1 // Copyright 2016 The PDFium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 
5 #ifndef TESTING_LIBFUZZER_XFA_CODEC_FUZZER_H_
6 #define TESTING_LIBFUZZER_XFA_CODEC_FUZZER_H_
7 
8 #include <memory>
9 
10 #include "core/fxcodec/codec/ccodec_bmpmodule.h"
11 #include "core/fxcodec/codec/ccodec_gifmodule.h"
12 #include "core/fxcodec/codec/ccodec_pngmodule.h"
13 #include "core/fxcodec/codec/ccodec_progressivedecoder.h"
14 #include "core/fxcodec/codec/ccodec_tiffmodule.h"
15 #include "core/fxcodec/fx_codec.h"
16 #include "core/fxge/dib/cfx_dibitmap.h"
17 #include "testing/fx_string_testhelpers.h"
18 #include "third_party/base/ptr_util.h"
19 
20 // Support up to 64 MB. This prevents trivial OOM when MSAN is on and
21 // time outs.
22 const int kXFACodecFuzzerPixelLimit = 64000000;
23 
24 class XFACodecFuzzer {
25  public:
Fuzz(const uint8_t * data,size_t size,FXCODEC_IMAGE_TYPE type)26   static int Fuzz(const uint8_t* data, size_t size, FXCODEC_IMAGE_TYPE type) {
27     auto mgr = pdfium::MakeUnique<CCodec_ModuleMgr>();
28     mgr->SetBmpModule(pdfium::MakeUnique<CCodec_BmpModule>());
29     mgr->SetGifModule(pdfium::MakeUnique<CCodec_GifModule>());
30     mgr->SetPngModule(pdfium::MakeUnique<CCodec_PngModule>());
31     mgr->SetTiffModule(pdfium::MakeUnique<CCodec_TiffModule>());
32 
33     std::unique_ptr<CCodec_ProgressiveDecoder> decoder =
34         mgr->CreateProgressiveDecoder();
35     auto source = pdfium::MakeRetain<CFX_BufferSeekableReadStream>(data, size);
36     FXCODEC_STATUS status = decoder->LoadImageInfo(source, type, nullptr, true);
37     if (status != FXCODEC_STATUS_FRAME_READY)
38       return 0;
39 
40     // Skipping very large images, since they will take a long time and may lead
41     // to OOM.
42     FX_SAFE_UINT32 bitmap_size = decoder->GetHeight();
43     bitmap_size *= decoder->GetWidth();
44     bitmap_size *= 4;  // From CFX_DIBitmap impl.
45     if (!bitmap_size.IsValid() ||
46         bitmap_size.ValueOrDie() > kXFACodecFuzzerPixelLimit) {
47       return 0;
48     }
49 
50     auto bitmap = pdfium::MakeRetain<CFX_DIBitmap>();
51     bitmap->Create(decoder->GetWidth(), decoder->GetHeight(), FXDIB_Argb);
52 
53     size_t frames;
54     std::tie(status, frames) = decoder->GetFrames();
55     if (status != FXCODEC_STATUS_DECODE_READY || frames == 0)
56       return 0;
57 
58     status = decoder->StartDecode(bitmap, 0, 0, bitmap->GetWidth(),
59                                   bitmap->GetHeight());
60     while (status == FXCODEC_STATUS_DECODE_TOBECONTINUE)
61       status = decoder->ContinueDecode();
62 
63     return 0;
64   }
65 };
66 
67 #endif  // TESTING_LIBFUZZER_XFA_CODEC_FUZZER_H_
68