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 #include <cstdint>
6 #include <memory>
7
8 #include "core/fpdfapi/page/cpdf_colorspace.h"
9 #include "core/fxcodec/jpx/cjpx_decoder.h"
10 #include "core/fxcrt/fx_safe_types.h"
11 #include "core/fxge/dib/cfx_dibitmap.h"
12 #include "core/fxge/dib/fx_dib.h"
13
14 namespace {
15
16 const uint32_t kMaxJPXFuzzSize = 100 * 1024 * 1024; // 100 MB
17
CheckImageSize(const CJPX_Decoder::JpxImageInfo & image_info)18 bool CheckImageSize(const CJPX_Decoder::JpxImageInfo& image_info) {
19 static constexpr uint32_t kMemLimitBytes = 1024 * 1024 * 1024; // 1 GB.
20 FX_SAFE_UINT32 mem = image_info.width;
21 mem *= image_info.height;
22 mem *= image_info.channels;
23 return mem.IsValid() && mem.ValueOrDie() <= kMemLimitBytes;
24 }
25
26 } // namespace
27
LLVMFuzzerTestOneInput(const uint8_t * data,size_t size)28 extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) {
29 if (size < 2)
30 return 0;
31
32 std::unique_ptr<CJPX_Decoder> decoder = CJPX_Decoder::Create(
33 {data + 2, size - 2},
34 static_cast<CJPX_Decoder::ColorSpaceOption>(data[0] % 3), data[1]);
35 if (!decoder)
36 return 0;
37
38 // A call to StartDecode could be too expensive if image size is very big, so
39 // check size before calling StartDecode().
40 CJPX_Decoder::JpxImageInfo image_info = decoder->GetInfo();
41 if (!CheckImageSize(image_info))
42 return 0;
43
44 if (!decoder->StartDecode())
45 return 0;
46
47 // StartDecode() could change image size, so check again.
48 image_info = decoder->GetInfo();
49 if (!CheckImageSize(image_info))
50 return 0;
51
52 FXDIB_Format format;
53 if (image_info.channels == 1) {
54 format = FXDIB_Format::k8bppRgb;
55 } else if (image_info.channels <= 3) {
56 format = FXDIB_Format::kRgb;
57 } else if (image_info.channels == 4) {
58 format = FXDIB_Format::kRgb32;
59 } else {
60 image_info.width = (image_info.width * image_info.channels + 2) / 3;
61 format = FXDIB_Format::kRgb;
62 }
63 auto bitmap = pdfium::MakeRetain<CFX_DIBitmap>();
64 if (!bitmap->Create(image_info.width, image_info.height, format))
65 return 0;
66
67 if (bitmap->GetHeight() <= 0 ||
68 kMaxJPXFuzzSize / bitmap->GetPitch() <
69 static_cast<uint32_t>(bitmap->GetHeight()))
70 return 0;
71
72 decoder->Decode(bitmap->GetWritableBuffer(), bitmap->GetPitch(),
73 /*swap_rgb=*/false, GetCompsFromFormat(format));
74
75 return 0;
76 }
77