1 // Copyright 2016 The PDFium Authors 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_FUZZERS_XFA_CODEC_FUZZER_H_ 6 #define TESTING_FUZZERS_XFA_CODEC_FUZZER_H_ 7 8 #include <memory> 9 #include <utility> 10 11 #include "core/fxcodec/fx_codec.h" 12 #include "core/fxcodec/progressive_decoder.h" 13 #include "core/fxcrt/cfx_read_only_span_stream.h" 14 #include "core/fxcrt/fx_safe_types.h" 15 #include "core/fxcrt/retain_ptr.h" 16 #include "core/fxcrt/span.h" 17 #include "core/fxge/dib/cfx_dibitmap.h" 18 #include "core/fxge/dib/fx_dib.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 decoder = std::make_unique<ProgressiveDecoder>(); 28 auto source = pdfium::MakeRetain<CFX_ReadOnlySpanStream>( 29 pdfium::make_span(data, size)); 30 CFX_DIBAttribute attr; 31 FXCODEC_STATUS status = 32 decoder->LoadImageInfo(std::move(source), type, &attr, true); 33 if (status != FXCODEC_STATUS::kFrameReady) { 34 return 0; 35 } 36 37 // Skipping very large images, since they will take a long time and may lead 38 // to OOM. 39 FX_SAFE_UINT32 bitmap_size = decoder->GetHeight(); 40 bitmap_size *= decoder->GetWidth(); 41 bitmap_size *= GetCompsFromFormat(decoder->GetBitmapFormat()); 42 if (!bitmap_size.IsValid() || bitmap_size.ValueOrDie() == 0 || 43 bitmap_size.ValueOrDie() > kXFACodecFuzzerPixelLimit) { 44 return 0; 45 } 46 47 auto bitmap = pdfium::MakeRetain<CFX_DIBitmap>(); 48 if (!bitmap->Create(decoder->GetWidth(), decoder->GetHeight(), 49 decoder->GetBitmapFormat())) { 50 return 0; 51 } 52 53 size_t frames; 54 std::tie(status, frames) = decoder->GetFrames(); 55 if (status != FXCODEC_STATUS::kDecodeReady || frames == 0) { 56 return 0; 57 } 58 59 status = decoder->StartDecode(std::move(bitmap)); 60 while (status == FXCODEC_STATUS::kDecodeToBeContinued) { 61 status = decoder->ContinueDecode(); 62 } 63 64 return 0; 65 } 66 }; 67 68 #endif // TESTING_FUZZERS_XFA_CODEC_FUZZER_H_ 69