summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--core/fxcodec/codec/ccodec_gifmodule.cpp2
-rw-r--r--core/fxcodec/codec/ccodec_progressivedecoder.h2
-rw-r--r--core/fxcodec/codec/fx_codec_progress.cpp44
-rw-r--r--core/fxcodec/fx_codec_def.h1
-rw-r--r--core/fxcodec/lgif/cgifcontext.cpp2
-rw-r--r--core/fxcodec/lgif/cgifcontext.h2
-rw-r--r--core/fxcodec/lgif/fx_gif.cpp32
-rw-r--r--core/fxcodec/lgif/fx_gif.h7
-rw-r--r--testing/libfuzzer/xfa_codec_fuzzer.h2
-rw-r--r--xfa/fxfa/cxfa_ffimage.cpp3
-rw-r--r--xfa/fxfa/cxfa_ffpageview.cpp3
-rw-r--r--xfa/fxfa/cxfa_ffwidget.cpp38
12 files changed, 91 insertions, 47 deletions
diff --git a/core/fxcodec/codec/ccodec_gifmodule.cpp b/core/fxcodec/codec/ccodec_gifmodule.cpp
index f7e3546a8f..911323c3a1 100644
--- a/core/fxcodec/codec/ccodec_gifmodule.cpp
+++ b/core/fxcodec/codec/ccodec_gifmodule.cpp
@@ -36,7 +36,7 @@ GifDecodeStatus CCodec_GifModule::ReadHeader(Context* pContext,
*width = context->width;
*height = context->height;
- *pal_num = context->global_pal_num;
+ *pal_num = (2 << context->global_pal_exp);
*pal_pp = context->m_GlobalPalette.empty() ? nullptr
: context->m_GlobalPalette.data();
*bg_index = context->bc_index;
diff --git a/core/fxcodec/codec/ccodec_progressivedecoder.h b/core/fxcodec/codec/ccodec_progressivedecoder.h
index 87bed08fcf..05b7c92078 100644
--- a/core/fxcodec/codec/ccodec_progressivedecoder.h
+++ b/core/fxcodec/codec/ccodec_progressivedecoder.h
@@ -56,7 +56,7 @@ class CCodec_ProgressiveDecoder : public CCodec_BmpModule::Delegate,
int32_t GetBPC() const { return m_SrcBPC; }
void SetClipBox(FX_RECT* clip);
- FXCODEC_STATUS GetFrames(int32_t& frames);
+ FXCODEC_STATUS GetFrames(int32_t* frames);
FXCODEC_STATUS StartDecode(const RetainPtr<CFX_DIBitmap>& pDIBitmap,
int start_x,
int start_y,
diff --git a/core/fxcodec/codec/fx_codec_progress.cpp b/core/fxcodec/codec/fx_codec_progress.cpp
index 8b90d3ab84..f10523cc39 100644
--- a/core/fxcodec/codec/fx_codec_progress.cpp
+++ b/core/fxcodec/codec/fx_codec_progress.cpp
@@ -1791,7 +1791,7 @@ void CCodec_ProgressiveDecoder::Resample(
}
}
-FXCODEC_STATUS CCodec_ProgressiveDecoder::GetFrames(int32_t& frames) {
+FXCODEC_STATUS CCodec_ProgressiveDecoder::GetFrames(int32_t* frames) {
if (!(m_status == FXCODEC_STATUS_FRAME_READY ||
m_status == FXCODEC_STATUS_FRAME_TOBECONTINUE)) {
return FXCODEC_STATUS_ERROR;
@@ -1801,7 +1801,8 @@ FXCODEC_STATUS CCodec_ProgressiveDecoder::GetFrames(int32_t& frames) {
case FXCODEC_IMAGE_BMP:
case FXCODEC_IMAGE_PNG:
case FXCODEC_IMAGE_TIF:
- frames = m_FrameNumber = 1;
+ *frames = 1;
+ m_FrameNumber = 1;
m_status = FXCODEC_STATUS_DECODE_READY;
return m_status;
case FXCODEC_IMAGE_GIF: {
@@ -1822,7 +1823,7 @@ FXCODEC_STATUS CCodec_ProgressiveDecoder::GetFrames(int32_t& frames) {
pGifModule->LoadFrameInfo(m_pGifContext.get(), &m_FrameNumber);
}
if (readResult == GifDecodeStatus::Success) {
- frames = m_FrameNumber;
+ *frames = m_FrameNumber;
m_status = FXCODEC_STATUS_DECODE_READY;
return m_status;
}
@@ -2108,34 +2109,37 @@ FXCODEC_STATUS CCodec_ProgressiveDecoder::ContinueDecode() {
case FXCODEC_IMAGE_GIF: {
CCodec_GifModule* pGifModule = m_pCodecMgr->GetGifModule();
if (!pGifModule) {
+ m_pDeviceBitmap = nullptr;
+ m_pFile = nullptr;
m_status = FXCODEC_STATUS_ERR_MEMORY;
return m_status;
}
- while (true) {
- GifDecodeStatus readRes =
- pGifModule->LoadFrame(m_pGifContext.get(), m_FrameCur, nullptr);
- while (readRes == GifDecodeStatus::Unfinished) {
- FXCODEC_STATUS error_status = FXCODEC_STATUS_DECODE_FINISH;
- if (!GifReadMoreData(pGifModule, error_status)) {
- m_pDeviceBitmap = nullptr;
- m_pFile = nullptr;
- m_status = error_status;
- return m_status;
- }
- readRes =
- pGifModule->LoadFrame(m_pGifContext.get(), m_FrameCur, nullptr);
- }
- if (readRes == GifDecodeStatus::Success) {
+
+ GifDecodeStatus readRes =
+ pGifModule->LoadFrame(m_pGifContext.get(), m_FrameCur, nullptr);
+ while (readRes == GifDecodeStatus::Unfinished) {
+ FXCODEC_STATUS error_status = FXCODEC_STATUS_DECODE_FINISH;
+ if (!GifReadMoreData(pGifModule, error_status)) {
m_pDeviceBitmap = nullptr;
m_pFile = nullptr;
- m_status = FXCODEC_STATUS_DECODE_FINISH;
+ m_status = error_status;
return m_status;
}
+ readRes =
+ pGifModule->LoadFrame(m_pGifContext.get(), m_FrameCur, nullptr);
+ }
+
+ if (readRes == GifDecodeStatus::Success) {
m_pDeviceBitmap = nullptr;
m_pFile = nullptr;
- m_status = FXCODEC_STATUS_ERROR;
+ m_status = FXCODEC_STATUS_DECODE_FINISH;
return m_status;
}
+
+ m_pDeviceBitmap = nullptr;
+ m_pFile = nullptr;
+ m_status = FXCODEC_STATUS_ERROR;
+ return m_status;
}
case FXCODEC_IMAGE_BMP: {
CCodec_BmpModule* pBmpModule = m_pCodecMgr->GetBmpModule();
diff --git a/core/fxcodec/fx_codec_def.h b/core/fxcodec/fx_codec_def.h
index fd23d78fa5..04696a11dd 100644
--- a/core/fxcodec/fx_codec_def.h
+++ b/core/fxcodec/fx_codec_def.h
@@ -22,6 +22,7 @@ enum FXCODEC_STATUS {
FXCODEC_STATUS_ERR_FORMAT,
FXCODEC_STATUS_ERR_PARAMS
};
+
#define JP2_SPACE_INVALID -1
#define JPX_SPACE_INVALID -1
#define JP2_SPACE_bilevel1 0
diff --git a/core/fxcodec/lgif/cgifcontext.cpp b/core/fxcodec/lgif/cgifcontext.cpp
index e57e978218..4dc663644c 100644
--- a/core/fxcodec/lgif/cgifcontext.cpp
+++ b/core/fxcodec/lgif/cgifcontext.cpp
@@ -17,7 +17,7 @@ CGifContext::CGifContext(CCodec_GifModule* gif_module,
CCodec_GifModule::Delegate* pDelegate)
: m_pModule(gif_module),
m_pDelegate(pDelegate),
- global_pal_num(0),
+ global_pal_exp(0),
img_row_offset(0),
img_row_avail_size(0),
avail_in(0),
diff --git a/core/fxcodec/lgif/cgifcontext.h b/core/fxcodec/lgif/cgifcontext.h
index d85243711d..71cf2bc75e 100644
--- a/core/fxcodec/lgif/cgifcontext.h
+++ b/core/fxcodec/lgif/cgifcontext.h
@@ -40,7 +40,7 @@ class CGifContext : public CCodec_GifModule::Context {
UnownedPtr<CCodec_GifModule> m_pModule;
UnownedPtr<CCodec_GifModule::Delegate> m_pDelegate;
std::vector<GifPalette> m_GlobalPalette;
- int32_t global_pal_num;
+ uint8_t global_pal_exp;
uint32_t img_row_offset;
uint32_t img_row_avail_size;
uint32_t avail_in;
diff --git a/core/fxcodec/lgif/fx_gif.cpp b/core/fxcodec/lgif/fx_gif.cpp
index 18385c3bdd..ea78259420 100644
--- a/core/fxcodec/lgif/fx_gif.cpp
+++ b/core/fxcodec/lgif/fx_gif.cpp
@@ -147,6 +147,7 @@ GifDecodeStatus gif_decode_image_info(CGifContext* context) {
}
GifLF* gif_img_info_lf_ptr = (GifLF*)&gif_img_info_ptr->local_flag;
if (gif_img_info_lf_ptr->local_pal) {
+ gif_image->local_pallette_exp = gif_img_info_lf_ptr->pal_bits;
int32_t loc_pal_size = (2 << gif_img_info_lf_ptr->pal_bits) * 3;
uint8_t* loc_pal_ptr = nullptr;
if (!gif_read_data(context, &loc_pal_ptr, loc_pal_size)) {
@@ -162,7 +163,7 @@ GifDecodeStatus gif_decode_image_info(CGifContext* context) {
context->skip_size = skip_size_org;
return GifDecodeStatus::Unfinished;
}
- gif_image->image_code_size = *code_size_ptr;
+ gif_image->image_code_exp = *code_size_ptr;
context->RecordCurrentPosition(&gif_image->image_data_pos);
gif_image->image_data_pos += context->skip_size;
gif_image->m_ImageGCE = nullptr;
@@ -214,10 +215,13 @@ CGifLZWDecoder::CGifLZWDecoder(char* error_ptr)
CGifLZWDecoder::~CGifLZWDecoder() {}
-void CGifLZWDecoder::InitTable(uint8_t code_len) {
- code_size = code_len;
- ASSERT(code_size < 13);
- code_clear = 1 << code_size;
+void CGifLZWDecoder::InitTable(uint8_t color_exp, uint8_t code_exp) {
+ // TODO(rharrison): Refactor all of this, so that initializing the table with
+ // bad values will kill the decompress.
+ ASSERT(code_exp <= GIF_MAX_LZW_EXP);
+ code_color_end = std::min(2 << color_exp, 1 << code_exp);
+ code_size = code_exp;
+ code_clear = 1 << code_exp;
code_end = code_clear + 1;
bits_left = 0;
code_store = 0;
@@ -247,6 +251,9 @@ bool CGifLZWDecoder::DecodeString(uint16_t code) {
stack[GIF_MAX_LZW_CODE - 1 - stack_size++] = code_table[code].suffix;
code = code_table[code].prefix;
}
+ if (code >= code_color_end)
+ return false;
+
stack[GIF_MAX_LZW_CODE - 1 - stack_size++] = static_cast<uint8_t>(code);
code_first = static_cast<uint8_t>(code);
return true;
@@ -282,7 +289,7 @@ GifDecodeStatus CGifLZWDecoder::Decode(uint8_t* des_buf, uint32_t* des_size) {
}
ASSERT(err_msg_ptr);
while (i <= *des_size && (avail_in > 0 || bits_left >= code_size_cur)) {
- if (code_size_cur > 12) {
+ if (code_size_cur > GIF_MAX_LZW_EXP) {
strncpy(err_msg_ptr, "Code Length Out Of Range", GIF_MAX_ERROR_SIZE - 1);
return GifDecodeStatus::Error;
}
@@ -383,9 +390,9 @@ GifDecodeStatus gif_read_header(CGifContext* context) {
return GifDecodeStatus::Unfinished;
}
if (reinterpret_cast<GifGF*>(&gif_lsd_ptr->global_flag)->global_pal) {
- context->global_pal_num =
- 2 << reinterpret_cast<GifGF*>(&gif_lsd_ptr->global_flag)->pal_bits;
- int32_t global_pal_size = context->global_pal_num * 3;
+ context->global_pal_exp =
+ reinterpret_cast<GifGF*>(&gif_lsd_ptr->global_flag)->pal_bits;
+ int32_t global_pal_size = (2 << context->global_pal_exp) * 3;
uint8_t* global_pal_ptr = nullptr;
if (!gif_read_data(context, &global_pal_ptr, global_pal_size)) {
context->skip_size = skip_size_org;
@@ -558,7 +565,7 @@ GifDecodeStatus gif_load_frame(CGifContext* context, int32_t frame_num) {
return GifDecodeStatus::Error;
}
}
- if (gif_image_ptr->image_code_size >= 13) {
+ if (gif_image_ptr->image_code_exp > GIF_MAX_LZW_EXP) {
gif_image_ptr->m_ImageRowBuf.clear();
context->AddError("Error Invalid Code Size");
return GifDecodeStatus::Error;
@@ -566,7 +573,10 @@ GifDecodeStatus gif_load_frame(CGifContext* context, int32_t frame_num) {
if (!context->m_ImgDecoder.get())
context->m_ImgDecoder =
pdfium::MakeUnique<CGifLZWDecoder>(context->m_szLastError);
- context->m_ImgDecoder->InitTable(gif_image_ptr->image_code_size);
+ context->m_ImgDecoder->InitTable(!gif_image_ptr->m_LocalPalettes.empty()
+ ? gif_image_ptr->local_pallette_exp
+ : context->global_pal_exp,
+ gif_image_ptr->image_code_exp);
context->img_row_offset = 0;
context->img_row_avail_size = 0;
context->img_pass_num = 0;
diff --git a/core/fxcodec/lgif/fx_gif.h b/core/fxcodec/lgif/fx_gif.h
index fd95aba17a..bddb22b30c 100644
--- a/core/fxcodec/lgif/fx_gif.h
+++ b/core/fxcodec/lgif/fx_gif.h
@@ -21,6 +21,7 @@ class CGifContext;
#define GIF_BLOCK_CE 0xFE
#define GIF_BLOCK_AE 0xFF
#define GIF_BLOCK_TERMINAL 0x00
+#define GIF_MAX_LZW_EXP 12
#define GIF_MAX_LZW_CODE 4096
#define GIF_DATA_BLOCK 255
#define GIF_MAX_ERROR_SIZE 256
@@ -116,7 +117,8 @@ class GifImage {
std::vector<GifPalette> m_LocalPalettes;
std::vector<uint8_t> m_ImageRowBuf;
GifImageInfo m_ImageInfo;
- uint8_t image_code_size;
+ uint8_t local_pallette_exp;
+ uint8_t image_code_exp;
uint32_t image_data_pos;
int32_t image_row_num;
};
@@ -131,7 +133,7 @@ class CGifLZWDecoder {
explicit CGifLZWDecoder(char* error_ptr);
~CGifLZWDecoder();
- void InitTable(uint8_t code_len);
+ void InitTable(uint8_t color_exp, uint8_t code_exp);
GifDecodeStatus Decode(uint8_t* des_buf, uint32_t* des_size);
void Input(uint8_t* src_buf, uint32_t src_size);
uint32_t GetAvailInput();
@@ -143,6 +145,7 @@ class CGifLZWDecoder {
uint8_t code_size;
uint8_t code_size_cur;
+ uint16_t code_color_end;
uint16_t code_clear;
uint16_t code_end;
uint16_t code_next;
diff --git a/testing/libfuzzer/xfa_codec_fuzzer.h b/testing/libfuzzer/xfa_codec_fuzzer.h
index 0d6b43e7b8..5193a8930f 100644
--- a/testing/libfuzzer/xfa_codec_fuzzer.h
+++ b/testing/libfuzzer/xfa_codec_fuzzer.h
@@ -37,7 +37,7 @@ class XFACodecFuzzer {
bitmap->Create(decoder->GetWidth(), decoder->GetHeight(), FXDIB_Argb);
int32_t frames;
- if (decoder->GetFrames(frames) != FXCODEC_STATUS_DECODE_READY ||
+ if (decoder->GetFrames(&frames) != FXCODEC_STATUS_DECODE_READY ||
frames == 0) {
return 0;
}
diff --git a/xfa/fxfa/cxfa_ffimage.cpp b/xfa/fxfa/cxfa_ffimage.cpp
index 757867f076..9903e6b25d 100644
--- a/xfa/fxfa/cxfa_ffimage.cpp
+++ b/xfa/fxfa/cxfa_ffimage.cpp
@@ -26,8 +26,7 @@ bool CXFA_FFImage::LoadWidget() {
if (GetDataAcc()->GetImageImage())
return true;
- GetDataAcc()->LoadImageImage();
- return CXFA_FFDraw::LoadWidget();
+ return GetDataAcc()->LoadImageImage() ? CXFA_FFDraw::LoadWidget() : false;
}
void CXFA_FFImage::UnloadWidget() {
diff --git a/xfa/fxfa/cxfa_ffpageview.cpp b/xfa/fxfa/cxfa_ffpageview.cpp
index 1de900c2f7..0e0db8dae0 100644
--- a/xfa/fxfa/cxfa_ffpageview.cpp
+++ b/xfa/fxfa/cxfa_ffpageview.cpp
@@ -208,7 +208,8 @@ CXFA_FFWidget* CXFA_FFPageWidgetIterator::GetWidget(
if (!pWidget->IsLoaded() &&
!!(pWidget->GetStatus() & XFA_WidgetStatus_Visible)) {
- pWidget->LoadWidget();
+ if (!pWidget->LoadWidget())
+ return nullptr;
}
return pWidget;
}
diff --git a/xfa/fxfa/cxfa_ffwidget.cpp b/xfa/fxfa/cxfa_ffwidget.cpp
index 7763a19972..859287388f 100644
--- a/xfa/fxfa/cxfa_ffwidget.cpp
+++ b/xfa/fxfa/cxfa_ffwidget.cpp
@@ -899,6 +899,17 @@ void XFA_DrawBox(CXFA_Box box,
XFA_BOX_Stroke(box, strokes, pGS, rtWidget, matrix, dwFlags);
}
+bool IsFXCodecErrorStatus(FXCODEC_STATUS status) {
+ return (status == FXCODEC_STATUS_ERROR ||
+#ifdef PDF_ENABLE_XFA
+ status == FXCODEC_STATUS_ERR_MEMORY ||
+#endif // PDF_ENABLE_XFA
+ status == FXCODEC_STATUS_ERR_READ ||
+ status == FXCODEC_STATUS_ERR_FLUSH ||
+ status == FXCODEC_STATUS_ERR_FORMAT ||
+ status == FXCODEC_STATUS_ERR_PARAMS);
+}
+
} // namespace
CXFA_FFWidget::CXFA_FFWidget(CXFA_WidgetAcc* pDataAcc)
@@ -2001,14 +2012,29 @@ RetainPtr<CFX_DIBitmap> XFA_LoadImageFromBuffer(
pBitmap->Create(pProgressiveDecoder->GetWidth(),
pProgressiveDecoder->GetHeight(), dibFormat);
pBitmap->Clear(0xffffffff);
+
int32_t nFrames;
- if ((pProgressiveDecoder->GetFrames(nFrames) ==
- FXCODEC_STATUS_DECODE_READY) &&
- (nFrames > 0)) {
- pProgressiveDecoder->StartDecode(pBitmap, 0, 0, pBitmap->GetWidth(),
- pBitmap->GetHeight());
- pProgressiveDecoder->ContinueDecode();
+ if (pProgressiveDecoder->GetFrames(&nFrames) != FXCODEC_STATUS_DECODE_READY ||
+ nFrames <= 0) {
+ pBitmap = nullptr;
+ return pBitmap;
+ }
+
+ FXCODEC_STATUS status = pProgressiveDecoder->StartDecode(
+ pBitmap, 0, 0, pBitmap->GetWidth(), pBitmap->GetHeight());
+ if (IsFXCodecErrorStatus(status)) {
+ pBitmap = nullptr;
+ return pBitmap;
}
+
+ while (status == FXCODEC_STATUS_DECODE_TOBECONTINUE) {
+ status = pProgressiveDecoder->ContinueDecode();
+ if (IsFXCodecErrorStatus(status)) {
+ pBitmap = nullptr;
+ return pBitmap;
+ }
+ }
+
return pBitmap;
}