From b6e0117285a918f4f2f3a350b8a648d2247d3d8e Mon Sep 17 00:00:00 2001 From: Ryan Harrison Date: Wed, 20 Jun 2018 13:43:04 +0000 Subject: Add in a size guard to JPX fuzzer Setting an upper limit to the size of images being processed in the JPX fuzzer to reduce timeouts due to images just being really big. Also cleaned the types for passing pitch down to reduce the signedness conversions. BUG=chromium:834561 Change-Id: I28b7a2537a922ed7a9ca2f8ed049ae78dd471f49 Reviewed-on: https://pdfium-review.googlesource.com/35570 Reviewed-by: Henrique Nakashima Commit-Queue: Ryan Harrison --- core/fxcodec/codec/ccodec_jpxmodule.h | 2 +- core/fxcodec/codec/cjpx_decoder.h | 2 +- core/fxcodec/codec/fx_codec_jpx_opj.cpp | 19 +++++++++---------- testing/fuzzers/pdf_jpx_fuzzer.cc | 9 +++++++++ 4 files changed, 20 insertions(+), 12 deletions(-) diff --git a/core/fxcodec/codec/ccodec_jpxmodule.h b/core/fxcodec/codec/ccodec_jpxmodule.h index c57002722e..2a949862ca 100644 --- a/core/fxcodec/codec/ccodec_jpxmodule.h +++ b/core/fxcodec/codec/ccodec_jpxmodule.h @@ -29,7 +29,7 @@ class CCodec_JpxModule { uint32_t* components); bool Decode(CJPX_Decoder* pDecoder, uint8_t* dest_data, - int pitch, + uint32_t pitch, const std::vector& offsets); }; diff --git a/core/fxcodec/codec/cjpx_decoder.h b/core/fxcodec/codec/cjpx_decoder.h index c68969301c..9de9d6c4ab 100644 --- a/core/fxcodec/codec/cjpx_decoder.h +++ b/core/fxcodec/codec/cjpx_decoder.h @@ -24,7 +24,7 @@ class CJPX_Decoder { bool Init(const unsigned char* src_data, uint32_t src_size); void GetInfo(uint32_t* width, uint32_t* height, uint32_t* components); bool Decode(uint8_t* dest_buf, - int pitch, + uint32_t pitch, const std::vector& offsets); private: diff --git a/core/fxcodec/codec/fx_codec_jpx_opj.cpp b/core/fxcodec/codec/fx_codec_jpx_opj.cpp index c828167315..e5ba37cc06 100644 --- a/core/fxcodec/codec/fx_codec_jpx_opj.cpp +++ b/core/fxcodec/codec/fx_codec_jpx_opj.cpp @@ -567,13 +567,12 @@ void CJPX_Decoder::GetInfo(uint32_t* width, } bool CJPX_Decoder::Decode(uint8_t* dest_buf, - int pitch, + uint32_t pitch, const std::vector& offsets) { if (m_Image->comps[0].w != m_Image->x1 || m_Image->comps[0].h != m_Image->y1) return false; - if (pitch(m_Image->comps[0].w * 8 * m_Image->numcomps + 31)>> - 5 << 2) { + if (pitch<(m_Image->comps[0].w * 8 * m_Image->numcomps + 31)>> 5 << 2) { return false; } @@ -591,14 +590,14 @@ bool CJPX_Decoder::Decode(uint8_t* dest_buf, } } } - int width = m_Image->comps[0].w; - int height = m_Image->comps[0].h; + uint32_t width = m_Image->comps[0].w; + uint32_t height = m_Image->comps[0].h; for (uint32_t channel = 0; channel < m_Image->numcomps; ++channel) { uint8_t* pChannel = channel_bufs[channel]; if (adjust_comps[channel] < 0) { - for (int row = 0; row < height; ++row) { + for (uint32_t row = 0; row < height; ++row) { uint8_t* pScanline = pChannel + row * pitch; - for (int col = 0; col < width; ++col) { + for (uint32_t col = 0; col < width; ++col) { uint8_t* pPixel = pScanline + col * m_Image->numcomps; if (!m_Image->comps[channel].data) continue; @@ -615,9 +614,9 @@ bool CJPX_Decoder::Decode(uint8_t* dest_buf, } } } else { - for (int row = 0; row < height; ++row) { + for (uint32_t row = 0; row < height; ++row) { uint8_t* pScanline = pChannel + row * pitch; - for (int col = 0; col < width; ++col) { + for (uint32_t col = 0; col < width; ++col) { uint8_t* pPixel = pScanline + col * m_Image->numcomps; if (!m_Image->comps[channel].data) continue; @@ -662,7 +661,7 @@ void CCodec_JpxModule::GetImageInfo(CJPX_Decoder* pDecoder, bool CCodec_JpxModule::Decode(CJPX_Decoder* pDecoder, uint8_t* dest_data, - int pitch, + uint32_t pitch, const std::vector& offsets) { return pDecoder->Decode(dest_data, pitch, offsets); } diff --git a/testing/fuzzers/pdf_jpx_fuzzer.cc b/testing/fuzzers/pdf_jpx_fuzzer.cc index da65bc2d9a..b74957bb14 100644 --- a/testing/fuzzers/pdf_jpx_fuzzer.cc +++ b/testing/fuzzers/pdf_jpx_fuzzer.cc @@ -14,6 +14,10 @@ CCodec_JpxModule g_module; +namespace { +const uint32_t kMaxJPXFuzzSize = 100 * 1024 * 1024; // 100 MB +} // namespace + extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) { std::unique_ptr decoder = g_module.CreateDecoder(data, size, nullptr); @@ -47,6 +51,11 @@ extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) { if (!bitmap->Create(width, height, format)) return 0; + if (bitmap->GetHeight() <= 0 || + kMaxJPXFuzzSize / bitmap->GetPitch() < + static_cast(bitmap->GetHeight())) + return 0; + std::vector output_offsets(components); for (uint32_t i = 0; i < components; ++i) output_offsets[i] = i; -- cgit v1.2.3