• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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