xref: /aosp_15_r20/external/pdfium/testing/fuzzers/xfa_codec_fuzzer.h (revision 3ac0a46f773bac49fa9476ec2b1cf3f8da5ec3a4)
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/fxge/dib/cfx_dibitmap.h"
17 #include "third_party/base/containers/span.h"
18 
19 // Support up to 64 MB. This prevents trivial OOM when MSAN is on and
20 // time outs.
21 const int kXFACodecFuzzerPixelLimit = 64000000;
22 
23 class XFACodecFuzzer {
24  public:
Fuzz(const uint8_t * data,size_t size,FXCODEC_IMAGE_TYPE type)25   static int Fuzz(const uint8_t* data, size_t size, FXCODEC_IMAGE_TYPE type) {
26     auto decoder = std::make_unique<ProgressiveDecoder>();
27     auto source = pdfium::MakeRetain<CFX_ReadOnlySpanStream>(
28         pdfium::make_span(data, size));
29     CFX_DIBAttribute attr;
30     FXCODEC_STATUS status =
31         decoder->LoadImageInfo(std::move(source), type, &attr, true);
32     if (status != FXCODEC_STATUS::kFrameReady)
33       return 0;
34 
35     // Skipping very large images, since they will take a long time and may lead
36     // to OOM.
37     FX_SAFE_UINT32 bitmap_size = decoder->GetHeight();
38     bitmap_size *= decoder->GetWidth();
39     bitmap_size *= 4;  // From CFX_DIBitmap impl.
40     if (!bitmap_size.IsValid() ||
41         bitmap_size.ValueOrDie() > kXFACodecFuzzerPixelLimit) {
42       return 0;
43     }
44 
45     auto bitmap = pdfium::MakeRetain<CFX_DIBitmap>();
46     bitmap->Create(decoder->GetWidth(), decoder->GetHeight(),
47                    FXDIB_Format::kArgb);
48 
49     size_t frames;
50     std::tie(status, frames) = decoder->GetFrames();
51     if (status != FXCODEC_STATUS::kDecodeReady || frames == 0)
52       return 0;
53 
54     status = decoder->StartDecode(bitmap, 0, 0, bitmap->GetWidth(),
55                                   bitmap->GetHeight());
56     while (status == FXCODEC_STATUS::kDecodeToBeContinued)
57       status = decoder->ContinueDecode();
58 
59     return 0;
60   }
61 };
62 
63 #endif  // TESTING_FUZZERS_XFA_CODEC_FUZZER_H_
64