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