Remove |offsets| parameter from CJPX_Decoder::Decode().
The decoder does not need this level of flexibility. Replace it with
a |swap_rgb| parameter and calculate the offsets internally in a
foolproof manner.
Also rename a local variable in one caller to better describe what it
represents and to avoid Hungarian notation.
Change-Id: I6948517dd4af03d942be08e3e597c1c667e71396
Reviewed-on: https://pdfium-review.googlesource.com/c/pdfium/+/65791
Commit-Queue: Lei Zhang <thestig@chromium.org>
Reviewed-by: Tom Sepez <tsepez@chromium.org>
diff --git a/core/fpdfapi/page/cpdf_dib.cpp b/core/fpdfapi/page/cpdf_dib.cpp
index 4dbb815..6976a0d 100644
--- a/core/fpdfapi/page/cpdf_dib.cpp
+++ b/core/fpdfapi/page/cpdf_dib.cpp
@@ -8,7 +8,6 @@
#include <algorithm>
#include <memory>
-#include <numeric>
#include <utility>
#include <vector>
@@ -641,6 +640,7 @@
break;
case JpxDecodeAction::kUseRgb:
+ DCHECK(image_info.components >= 3);
swap_rgb = true;
m_pColorSpace = nullptr;
break;
@@ -671,18 +671,13 @@
format = FXDIB_Rgb;
}
- auto pCachedBitmap = pdfium::MakeRetain<CFX_DIBitmap>();
- if (!pCachedBitmap->Create(image_info.width, image_info.height, format))
+ auto result_bitmap = pdfium::MakeRetain<CFX_DIBitmap>();
+ if (!result_bitmap->Create(image_info.width, image_info.height, format))
return nullptr;
- pCachedBitmap->Clear(0xFFFFFFFF);
- // Fill |output_offsets| with 0, 1, ... N.
- std::vector<uint8_t> output_offsets(image_info.components);
- std::iota(output_offsets.begin(), output_offsets.end(), 0);
- if (swap_rgb)
- std::swap(output_offsets[0], output_offsets[2]);
- if (!decoder->Decode(pCachedBitmap->GetBuffer(), pCachedBitmap->GetPitch(),
- output_offsets)) {
+ result_bitmap->Clear(0xFFFFFFFF);
+ if (!decoder->Decode(result_bitmap->GetBuffer(), result_bitmap->GetPitch(),
+ swap_rgb)) {
return nullptr;
}
@@ -690,7 +685,7 @@
m_bpc < 8) {
int scale = 8 - m_bpc;
for (uint32_t row = 0; row < image_info.height; ++row) {
- uint8_t* scanline = pCachedBitmap->GetWritableScanline(row);
+ uint8_t* scanline = result_bitmap->GetWritableScanline(row);
for (uint32_t col = 0; col < image_info.width; ++col) {
*scanline = (*scanline) >> scale;
++scanline;
@@ -698,7 +693,7 @@
}
}
m_bpc = 8;
- return pCachedBitmap;
+ return result_bitmap;
}
CPDF_DIB::LoadState CPDF_DIB::StartLoadMask() {
diff --git a/core/fxcodec/jpx/cjpx_decoder.cpp b/core/fxcodec/jpx/cjpx_decoder.cpp
index 986d2f1..95f76ff 100644
--- a/core/fxcodec/jpx/cjpx_decoder.cpp
+++ b/core/fxcodec/jpx/cjpx_decoder.cpp
@@ -9,7 +9,6 @@
#include <algorithm>
#include <limits>
#include <utility>
-#include <vector>
#include "core/fxcodec/jpx/jpx_decode_utils.h"
#include "core/fxcrt/fx_safe_types.h"
@@ -493,21 +492,21 @@
return {m_Image->x1, m_Image->y1, m_Image->numcomps};
}
-bool CJPX_Decoder::Decode(uint8_t* dest_buf,
- uint32_t pitch,
- pdfium::span<const uint8_t> offsets) {
+bool CJPX_Decoder::Decode(uint8_t* dest_buf, uint32_t pitch, bool swap_rgb) {
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;
- }
+
+ if (swap_rgb && m_Image->numcomps < 3)
+ return false;
memset(dest_buf, 0xff, m_Image->y1 * pitch);
std::vector<uint8_t*> channel_bufs(m_Image->numcomps);
std::vector<int> adjust_comps(m_Image->numcomps);
for (uint32_t i = 0; i < m_Image->numcomps; i++) {
- channel_bufs[i] = dest_buf + offsets[i];
+ channel_bufs[i] = dest_buf + i;
adjust_comps[i] = m_Image->comps[i].prec - 8;
if (i > 0) {
if (m_Image->comps[i].dx != m_Image->comps[i - 1].dx ||
@@ -517,6 +516,9 @@
}
}
}
+ if (swap_rgb)
+ std::swap(channel_bufs[0], channel_bufs[2]);
+
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) {
diff --git a/core/fxcodec/jpx/cjpx_decoder.h b/core/fxcodec/jpx/cjpx_decoder.h
index 0fdccb9..4d9883c 100644
--- a/core/fxcodec/jpx/cjpx_decoder.h
+++ b/core/fxcodec/jpx/cjpx_decoder.h
@@ -8,6 +8,7 @@
#define CORE_FXCODEC_JPX_CJPX_DECODER_H_
#include <memory>
+#include <vector>
#include "core/fxcrt/unowned_ptr.h"
#include "third_party/base/span.h"
@@ -44,9 +45,9 @@
bool Init(pdfium::span<const uint8_t> src_data);
JpxImageInfo GetInfo() const;
bool StartDecode();
- bool Decode(uint8_t* dest_buf,
- uint32_t pitch,
- pdfium::span<const uint8_t> offsets);
+
+ // |swap_rgb| can only be set for images with 3 or more components.
+ bool Decode(uint8_t* dest_buf, uint32_t pitch, bool swap_rgb);
private:
const ColorSpaceOption m_ColorSpaceOption;
diff --git a/testing/fuzzers/pdf_jpx_fuzzer.cc b/testing/fuzzers/pdf_jpx_fuzzer.cc
index 89705dd..3986ae2 100644
--- a/testing/fuzzers/pdf_jpx_fuzzer.cc
+++ b/testing/fuzzers/pdf_jpx_fuzzer.cc
@@ -71,10 +71,8 @@
static_cast<uint32_t>(bitmap->GetHeight()))
return 0;
- std::vector<uint8_t> output_offsets(image_info.components);
- for (uint32_t i = 0; i < image_info.components; ++i)
- output_offsets[i] = i;
+ decoder->Decode(bitmap->GetBuffer(), bitmap->GetPitch(),
+ /*swap_rgb=*/false);
- decoder->Decode(bitmap->GetBuffer(), bitmap->GetPitch(), output_offsets);
return 0;
}