blob: 3021d76887a39be24e6d5f2cc1da892be6736a46 [file] [log] [blame]
kumarashishg826308d2023-06-23 13:21:22 +00001// Copyright 2016 The PDFium Authors
Haibo Huang49cc9302020-04-27 16:14:24 -07002// 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>
Haibo Huang49cc9302020-04-27 16:14:24 -07007
8#include "core/fpdfapi/page/cpdf_colorspace.h"
9#include "core/fxcodec/jpx/cjpx_decoder.h"
Haibo Huang49cc9302020-04-27 16:14:24 -070010#include "core/fxcrt/fx_safe_types.h"
11#include "core/fxge/dib/cfx_dibitmap.h"
kumarashishg826308d2023-06-23 13:21:22 +000012#include "core/fxge/dib/fx_dib.h"
Haibo Huang49cc9302020-04-27 16:14:24 -070013
14namespace {
15
16const uint32_t kMaxJPXFuzzSize = 100 * 1024 * 1024; // 100 MB
17
18bool 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;
kumarashishg826308d2023-06-23 13:21:22 +000022 mem *= image_info.channels;
Haibo Huang49cc9302020-04-27 16:14:24 -070023 return mem.IsValid() && mem.ValueOrDie() <= kMemLimitBytes;
24}
25
26} // namespace
27
28extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) {
kumarashishg826308d2023-06-23 13:21:22 +000029 if (size < 2)
Haibo Huang49cc9302020-04-27 16:14:24 -070030 return 0;
31
kumarashishg826308d2023-06-23 13:21:22 +000032 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]);
Haibo Huang49cc9302020-04-27 16:14:24 -070035 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;
kumarashishg826308d2023-06-23 13:21:22 +000053 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;
Haibo Huang49cc9302020-04-27 16:14:24 -070059 } else {
kumarashishg826308d2023-06-23 13:21:22 +000060 image_info.width = (image_info.width * image_info.channels + 2) / 3;
61 format = FXDIB_Format::kRgb;
Haibo Huang49cc9302020-04-27 16:14:24 -070062 }
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
kumarashishg826308d2023-06-23 13:21:22 +000072 decoder->Decode(bitmap->GetBuffer(), bitmap->GetPitch(), /*swap_rgb=*/false,
73 GetCompsFromFormat(format));
Haibo Huang49cc9302020-04-27 16:14:24 -070074
75 return 0;
76}