summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorthestig <thestig@chromium.org>2016-09-26 16:14:28 -0700
committerCommit bot <commit-bot@chromium.org>2016-09-26 16:14:28 -0700
commit2ab466e3a59d845422e06e50bc38d4bf31ac1adf (patch)
treef34d7121c70042306739281445f2c19e83185fed
parent2c065322f1b14ca3ff145dc068ab2361704f9e4b (diff)
downloadpdfium-2ab466e3a59d845422e06e50bc38d4bf31ac1adf.tar.xz
Clean up fx_codec_fax.cpp.
Review-Url: https://codereview.chromium.org/2357173005
-rw-r--r--core/fpdfapi/fpdf_parser/fpdf_parser_decode.cpp85
-rw-r--r--core/fxcodec/codec/ccodec_faxmodule.h12
-rw-r--r--core/fxcodec/codec/ccodec_scanlinedecoder.h7
-rw-r--r--core/fxcodec/codec/fx_codec.cpp19
-rw-r--r--core/fxcodec/codec/fx_codec_fax.cpp473
-rw-r--r--testing/libfuzzer/pdf_codec_fax_fuzzer.cc13
6 files changed, 297 insertions, 312 deletions
diff --git a/core/fpdfapi/fpdf_parser/fpdf_parser_decode.cpp b/core/fpdfapi/fpdf_parser/fpdf_parser_decode.cpp
index 1b5bd024f8..eaf1e04193 100644
--- a/core/fpdfapi/fpdf_parser/fpdf_parser_decode.cpp
+++ b/core/fpdfapi/fpdf_parser/fpdf_parser_decode.cpp
@@ -7,6 +7,8 @@
#include "core/fpdfapi/fpdf_parser/include/fpdf_parser_decode.h"
#include <limits.h>
+
+#include <algorithm>
#include <utility>
#include <vector>
@@ -18,7 +20,26 @@
#include "core/fxcrt/include/fx_ext.h"
#include "third_party/base/stl_util.h"
-#define _STREAM_MAX_SIZE_ 20 * 1024 * 1024
+namespace {
+
+const uint32_t kMaxStreamSize = 20 * 1024 * 1024;
+
+bool CheckFlateDecodeParams(int Colors, int BitsPerComponent, int Columns) {
+ if (Colors < 0 || BitsPerComponent < 0 || Columns < 0)
+ return false;
+
+ int check = Columns;
+ if (check > 0 && Colors > INT_MAX / check)
+ return false;
+
+ check *= Colors;
+ if (check > 0 && BitsPerComponent > INT_MAX / check)
+ return false;
+
+ return check * BitsPerComponent <= INT_MAX - 7;
+}
+
+} // namespace
const uint16_t PDFDocEncoding[256] = {
0x0000, 0x0001, 0x0002, 0x0003, 0x0004, 0x0005, 0x0006, 0x0007, 0x0008,
@@ -171,31 +192,34 @@ uint32_t RunLengthDecode(const uint8_t* src_buf,
uint8_t*& dest_buf,
uint32_t& dest_size) {
uint32_t i = 0;
- uint32_t old;
dest_size = 0;
while (i < src_size) {
+ if (src_buf[i] == 128)
+ break;
+
+ uint32_t old = dest_size;
if (src_buf[i] < 128) {
- old = dest_size;
dest_size += src_buf[i] + 1;
if (dest_size < old)
return FX_INVALID_OFFSET;
i += src_buf[i] + 2;
- } else if (src_buf[i] > 128) {
- old = dest_size;
+ } else {
dest_size += 257 - src_buf[i];
if (dest_size < old)
return FX_INVALID_OFFSET;
i += 2;
- } else {
- break;
}
}
- if (dest_size >= _STREAM_MAX_SIZE_)
+ if (dest_size >= kMaxStreamSize)
return FX_INVALID_OFFSET;
+
dest_buf = FX_Alloc(uint8_t, dest_size);
i = 0;
int dest_count = 0;
while (i < src_size) {
+ if (src_buf[i] == 128)
+ break;
+
if (src_buf[i] < 128) {
uint32_t copy_len = src_buf[i] + 1;
uint32_t buf_left = src_size - i - 1;
@@ -207,7 +231,7 @@ uint32_t RunLengthDecode(const uint8_t* src_buf,
FXSYS_memcpy(dest_buf + dest_count, src_buf + i + 1, copy_len);
dest_count += src_buf[i] + 1;
i += src_buf[i] + 2;
- } else if (src_buf[i] > 128) {
+ } else {
int fill = 0;
if (i < src_size - 1) {
fill = src_buf[i + 1];
@@ -215,15 +239,10 @@ uint32_t RunLengthDecode(const uint8_t* src_buf,
FXSYS_memset(dest_buf + dest_count, fill, 257 - src_buf[i]);
dest_count += 257 - src_buf[i];
i += 2;
- } else {
- break;
}
}
- uint32_t ret = i + 1;
- if (ret > src_size) {
- ret = src_size;
- }
- return ret;
+
+ return std::min(i + 1, src_size);
}
CCodec_ScanlineDecoder* FPDFAPI_CreateFaxDecoder(
@@ -233,16 +252,16 @@ CCodec_ScanlineDecoder* FPDFAPI_CreateFaxDecoder(
int height,
const CPDF_Dictionary* pParams) {
int K = 0;
- FX_BOOL EndOfLine = FALSE;
- FX_BOOL ByteAlign = FALSE;
- FX_BOOL BlackIs1 = FALSE;
+ bool EndOfLine = false;
+ bool ByteAlign = false;
+ bool BlackIs1 = false;
int Columns = 1728;
int Rows = 0;
if (pParams) {
K = pParams->GetIntegerFor("K");
- EndOfLine = pParams->GetIntegerFor("EndOfLine");
- ByteAlign = pParams->GetIntegerFor("EncodedByteAlign");
- BlackIs1 = pParams->GetIntegerFor("BlackIs1");
+ EndOfLine = !!pParams->GetIntegerFor("EndOfLine");
+ ByteAlign = !!pParams->GetIntegerFor("EncodedByteAlign");
+ BlackIs1 = !!pParams->GetIntegerFor("BlackIs1");
Columns = pParams->GetIntegerFor("Columns", 1728);
Rows = pParams->GetIntegerFor("Rows");
if (Rows > USHRT_MAX) {
@@ -254,28 +273,6 @@ CCodec_ScanlineDecoder* FPDFAPI_CreateFaxDecoder(
Columns, Rows);
}
-static FX_BOOL CheckFlateDecodeParams(int Colors,
- int BitsPerComponent,
- int Columns) {
- if (Columns < 0) {
- return FALSE;
- }
- int check = Columns;
- if (Colors < 0 || (check > 0 && Colors > INT_MAX / check)) {
- return FALSE;
- }
- check *= Colors;
- if (BitsPerComponent < 0 ||
- (check > 0 && BitsPerComponent > INT_MAX / check)) {
- return FALSE;
- }
- check *= BitsPerComponent;
- if (check > INT_MAX - 7) {
- return FALSE;
- }
- return TRUE;
-}
-
CCodec_ScanlineDecoder* FPDFAPI_CreateFlateDecoder(
const uint8_t* src_buf,
uint32_t src_size,
diff --git a/core/fxcodec/codec/ccodec_faxmodule.h b/core/fxcodec/codec/ccodec_faxmodule.h
index ad7e9b6063..27d4b9abdd 100644
--- a/core/fxcodec/codec/ccodec_faxmodule.h
+++ b/core/fxcodec/codec/ccodec_faxmodule.h
@@ -18,17 +18,11 @@ class CCodec_FaxModule {
int width,
int height,
int K,
- FX_BOOL EndOfLine,
- FX_BOOL EncodedByteAlign,
- FX_BOOL BlackIs1,
+ bool EndOfLine,
+ bool EncodedByteAlign,
+ bool BlackIs1,
int Columns,
int Rows);
- FX_BOOL Encode(const uint8_t* src_buf,
- int width,
- int height,
- int pitch,
- uint8_t*& dest_buf,
- uint32_t& dest_size);
};
#endif // CORE_FXCODEC_CODEC_CCODEC_FAXMODULE_H_
diff --git a/core/fxcodec/codec/ccodec_scanlinedecoder.h b/core/fxcodec/codec/ccodec_scanlinedecoder.h
index cd18c8d76e..23ecb9582a 100644
--- a/core/fxcodec/codec/ccodec_scanlinedecoder.h
+++ b/core/fxcodec/codec/ccodec_scanlinedecoder.h
@@ -14,6 +14,13 @@ class IFX_Pause;
class CCodec_ScanlineDecoder {
public:
CCodec_ScanlineDecoder();
+ CCodec_ScanlineDecoder(int nOrigWidth,
+ int nOrigHeight,
+ int nOutputWidth,
+ int nOutputHeight,
+ int nComps,
+ int nBpc,
+ uint32_t nPitch);
virtual ~CCodec_ScanlineDecoder();
const uint8_t* GetScanline(int line);
diff --git a/core/fxcodec/codec/fx_codec.cpp b/core/fxcodec/codec/fx_codec.cpp
index 1995784dcd..7f0c8ad225 100644
--- a/core/fxcodec/codec/fx_codec.cpp
+++ b/core/fxcodec/codec/fx_codec.cpp
@@ -34,7 +34,24 @@ CCodec_ModuleMgr::CCodec_ModuleMgr()
CCodec_ModuleMgr::~CCodec_ModuleMgr() {}
CCodec_ScanlineDecoder::CCodec_ScanlineDecoder()
- : m_NextLine(-1), m_pLastScanline(nullptr) {}
+ : CCodec_ScanlineDecoder(0, 0, 0, 0, 0, 0, 0) {}
+
+CCodec_ScanlineDecoder::CCodec_ScanlineDecoder(int nOrigWidth,
+ int nOrigHeight,
+ int nOutputWidth,
+ int nOutputHeight,
+ int nComps,
+ int nBpc,
+ uint32_t nPitch)
+ : m_OrigWidth(nOrigWidth),
+ m_OrigHeight(nOrigHeight),
+ m_OutputWidth(nOutputWidth),
+ m_OutputHeight(nOutputHeight),
+ m_nComps(nComps),
+ m_bpc(nBpc),
+ m_Pitch(nPitch),
+ m_NextLine(-1),
+ m_pLastScanline(nullptr) {}
CCodec_ScanlineDecoder::~CCodec_ScanlineDecoder() {}
diff --git a/core/fxcodec/codec/fx_codec_fax.cpp b/core/fxcodec/codec/fx_codec_fax.cpp
index 11c42ade28..91e6f9a7be 100644
--- a/core/fxcodec/codec/fx_codec_fax.cpp
+++ b/core/fxcodec/codec/fx_codec_fax.cpp
@@ -4,6 +4,9 @@
// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com
+#include <algorithm>
+#include <vector>
+
#include "core/fxcodec/codec/codec_int.h"
#include "core/fxcodec/include/fx_codec.h"
@@ -39,103 +42,92 @@ const uint8_t ZeroLeadPos[256] = {
// Limit of image dimension, an arbitrary large number.
const int kMaxImageDimension = 0x01FFFF;
-int FindBit(const uint8_t* data_buf, int max_pos, int start_pos, int bit) {
+int FindBit(const std::vector<uint8_t>& data_buf,
+ int max_pos,
+ int start_pos,
+ int bit) {
ASSERT(start_pos >= 0);
- if (start_pos >= max_pos) {
+ if (start_pos >= max_pos)
return max_pos;
- }
+
const uint8_t* leading_pos = bit ? OneLeadPos : ZeroLeadPos;
if (start_pos % 8) {
uint8_t data = data_buf[start_pos / 8];
- if (bit) {
+ if (bit)
data &= 0xff >> (start_pos % 8);
- } else {
+ else
data |= 0xff << (8 - start_pos % 8);
- }
- if (leading_pos[data] < 8) {
+
+ if (leading_pos[data] < 8)
return start_pos / 8 * 8 + leading_pos[data];
- }
+
start_pos += 7;
}
uint8_t skip = bit ? 0x00 : 0xff;
int byte_pos = start_pos / 8;
int max_byte = (max_pos + 7) / 8;
while (byte_pos < max_byte) {
- if (data_buf[byte_pos] != skip) {
+ if (data_buf[byte_pos] != skip)
break;
- }
- byte_pos++;
+
+ ++byte_pos;
}
- if (byte_pos == max_byte) {
+ if (byte_pos == max_byte)
return max_pos;
- }
- int pos = leading_pos[data_buf[byte_pos]] + byte_pos * 8;
- if (pos > max_pos) {
- pos = max_pos;
- }
- return pos;
+
+ return std::min(leading_pos[data_buf[byte_pos]] + byte_pos * 8, max_pos);
}
-void FaxG4FindB1B2(const uint8_t* ref_buf,
+void FaxG4FindB1B2(const std::vector<uint8_t>& ref_buf,
int columns,
int a0,
bool a0color,
- int& b1,
- int& b2) {
+ int* b1,
+ int* b2) {
uint8_t first_bit =
(a0 < 0) ? 1 : ((ref_buf[a0 / 8] & (1 << (7 - a0 % 8))) != 0);
- b1 = FindBit(ref_buf, columns, a0 + 1, !first_bit);
- if (b1 >= columns) {
- b1 = b2 = columns;
+ *b1 = FindBit(ref_buf, columns, a0 + 1, !first_bit);
+ if (*b1 >= columns) {
+ *b1 = *b2 = columns;
return;
}
if (first_bit == !a0color) {
- b1 = FindBit(ref_buf, columns, b1 + 1, first_bit);
+ *b1 = FindBit(ref_buf, columns, *b1 + 1, first_bit);
first_bit = !first_bit;
}
- if (b1 >= columns) {
- b1 = b2 = columns;
+ if (*b1 >= columns) {
+ *b1 = *b2 = columns;
return;
}
- b2 = FindBit(ref_buf, columns, b1 + 1, first_bit);
+ *b2 = FindBit(ref_buf, columns, *b1 + 1, first_bit);
}
void FaxFillBits(uint8_t* dest_buf, int columns, int startpos, int endpos) {
- if (startpos < 0) {
- startpos = 0;
- }
- if (endpos < 0) {
- endpos = 0;
- }
- if (endpos >= columns) {
- endpos = columns;
- }
- if (startpos >= endpos) {
+ startpos = std::max(startpos, 0);
+ endpos = std::min(std::max(endpos, 0), columns);
+ if (startpos >= endpos)
return;
- }
+
int first_byte = startpos / 8;
int last_byte = (endpos - 1) / 8;
if (first_byte == last_byte) {
- for (int i = startpos % 8; i <= (endpos - 1) % 8; i++) {
+ for (int i = startpos % 8; i <= (endpos - 1) % 8; ++i)
dest_buf[first_byte] -= 1 << (7 - i);
- }
return;
}
- int i;
- for (i = startpos % 8; i < 8; i++) {
+
+ for (int i = startpos % 8; i < 8; ++i)
dest_buf[first_byte] -= 1 << (7 - i);
- }
- for (i = 0; i <= (endpos - 1) % 8; i++) {
+ for (int i = 0; i <= (endpos - 1) % 8; ++i)
dest_buf[last_byte] -= 1 << (7 - i);
- }
- if (last_byte > first_byte + 1) {
+
+ if (last_byte > first_byte + 1)
FXSYS_memset(dest_buf + first_byte + 1, 0, last_byte - first_byte - 1);
- }
}
-#define NEXTBIT \
- src_buf[bitpos / 8] & (1 << (7 - bitpos % 8)); \
- bitpos++;
+#define NEXTBIT() \
+ src_buf[*bitpos / 8] & (1 << (7 - *bitpos % 8)); \
+ ++(*bitpos);
const uint8_t FaxBlackRunIns[] = {
0, 2, 0x02, 3, 0, 0x03,
@@ -254,23 +246,23 @@ const uint8_t FaxWhiteRunIns[] = {
int FaxGetRun(const uint8_t* ins_array,
const uint8_t* src_buf,
- int& bitpos,
+ int* bitpos,
int bitsize) {
uint32_t code = 0;
int ins_off = 0;
while (1) {
uint8_t ins = ins_array[ins_off++];
- if (ins == 0xff) {
+ if (ins == 0xff)
return -1;
- }
- if (bitpos >= bitsize) {
+
+ if (*bitpos >= bitsize)
return -1;
- }
+
code <<= 1;
- if (src_buf[bitpos / 8] & (1 << (7 - bitpos % 8))) {
- code++;
- }
- bitpos++;
+ if (src_buf[*bitpos / 8] & (1 << (7 - *bitpos % 8)))
+ ++code;
+
+ ++(*bitpos);
int next_off = ins_off + ins * 3;
for (; ins_off < next_off; ins_off += 3) {
if (ins_array[ins_off] == code) {
@@ -282,34 +274,34 @@ int FaxGetRun(const uint8_t* ins_array,
FX_BOOL FaxG4GetRow(const uint8_t* src_buf,
int bitsize,
- int& bitpos,
+ int* bitpos,
uint8_t* dest_buf,
- const uint8_t* ref_buf,
+ const std::vector<uint8_t>& ref_buf,
int columns) {
int a0 = -1;
bool a0color = true;
while (1) {
- if (bitpos >= bitsize) {
+ if (*bitpos >= bitsize)
return FALSE;
- }
- int a1, a2, b1, b2;
- FaxG4FindB1B2(ref_buf, columns, a0, a0color, b1, b2);
- FX_BOOL bit = NEXTBIT;
+
+ int a1;
+ int a2;
+ int b1;
+ int b2;
+ FaxG4FindB1B2(ref_buf, columns, a0, a0color, &b1, &b2);
+ FX_BOOL bit = NEXTBIT();
int v_delta = 0;
- if (bit) {
- } else {
- if (bitpos >= bitsize) {
+ if (!bit) {
+ if (*bitpos >= bitsize)
return FALSE;
- }
- FX_BOOL bit1 = NEXTBIT;
- if (bitpos >= bitsize) {
+
+ FX_BOOL bit1 = NEXTBIT();
+ if (*bitpos >= bitsize)
return FALSE;
- }
- FX_BOOL bit2 = NEXTBIT;
- if (bit1 && bit2) {
- v_delta = 1;
- } else if (bit1) {
- v_delta = -1;
+
+ FX_BOOL bit2 = NEXTBIT();
+ if (bit1) {
+ v_delta = bit2 ? 1 : -1;
} else if (bit2) {
int run_len1 = 0;
while (1) {
@@ -320,13 +312,13 @@ FX_BOOL FaxG4GetRow(const uint8_t* src_buf,
break;
}
}
- if (a0 < 0) {
- run_len1++;
- }
+ if (a0 < 0)
+ ++run_len1;
+
a1 = a0 + run_len1;
- if (!a0color) {
+ if (!a0color)
FaxFillBits(dest_buf, columns, a0, a1);
- }
+
int run_len2 = 0;
while (1) {
int run = FaxGetRun(a0color ? FaxBlackRunIns : FaxWhiteRunIns,
@@ -337,111 +329,104 @@ FX_BOOL FaxG4GetRow(const uint8_t* src_buf,
}
}
a2 = a1 + run_len2;
- if (a0color) {
+ if (a0color)
FaxFillBits(dest_buf, columns, a1, a2);
- }
+
a0 = a2;
- if (a0 < columns) {
+ if (a0 < columns)
continue;
- }
+
return TRUE;
} else {
- if (bitpos >= bitsize) {
+ if (*bitpos >= bitsize)
return FALSE;
- }
- bit = NEXTBIT;
+
+ bit = NEXTBIT();
if (bit) {
- if (!a0color) {
+ if (!a0color)
FaxFillBits(dest_buf, columns, a0, b2);
- }
- if (b2 >= columns) {
+
+ if (b2 >= columns)
return TRUE;
- }
+
a0 = b2;
continue;
- } else {
- if (bitpos >= bitsize) {
+ }
+
+ if (*bitpos >= bitsize)
+ return FALSE;
+
+ FX_BOOL next_bit1 = NEXTBIT();
+ if (*bitpos >= bitsize)
+ return FALSE;
+
+ FX_BOOL next_bit2 = NEXTBIT();
+ if (next_bit1) {
+ v_delta = next_bit2 ? 2 : -2;
+ } else if (next_bit2) {
+ if (*bitpos >= bitsize)
return FALSE;
- }
- FX_BOOL next_bit1 = NEXTBIT;
- if (bitpos >= bitsize) {
+
+ bit = NEXTBIT();
+ v_delta = bit ? 3 : -3;
+ } else {
+ if (*bitpos >= bitsize)
return FALSE;
+
+ bit = NEXTBIT();
+ if (bit) {
+ *bitpos += 3;
+ continue;
}
- FX_BOOL next_bit2 = NEXTBIT;
- if (next_bit1 && next_bit2) {
- v_delta = 2;
- } else if (next_bit1) {
- v_delta = -2;
- } else if (next_bit2) {
- if (bitpos >= bitsize) {
- return FALSE;
- }
- bit = NEXTBIT;
- if (bit) {
- v_delta = 3;
- } else {
- v_delta = -3;
- }
- } else {
- if (bitpos >= bitsize) {
- return FALSE;
- }
- bit = NEXTBIT;
- if (bit) {
- bitpos += 3;
- continue;
- } else {
- bitpos += 5;
- return TRUE;
- }
- }
+ *bitpos += 5;
+ return TRUE;
}
}
}
a1 = b1 + v_delta;
- if (!a0color) {
+ if (!a0color)
FaxFillBits(dest_buf, columns, a0, a1);
- }
- if (a1 >= columns) {
+
+ if (a1 >= columns)
return TRUE;
- }
+
a0 = a1;
a0color = !a0color;
}
}
-FX_BOOL FaxSkipEOL(const uint8_t* src_buf, int bitsize, int& bitpos) {
- int startbit = bitpos;
- while (bitpos < bitsize) {
- int bit = NEXTBIT;
- if (bit) {
- if (bitpos - startbit <= 11) {
- bitpos = startbit;
- }
- return TRUE;
- }
+FX_BOOL FaxSkipEOL(const uint8_t* src_buf, int bitsize, int* bitpos) {
+ int startbit = *bitpos;
+ while (*bitpos < bitsize) {
+ int bit = NEXTBIT();
+ if (!bit)
+ continue;
+
+ if (*bitpos - startbit <= 11)
+ *bitpos = startbit;
+ return TRUE;
}
return FALSE;
}
FX_BOOL FaxGet1DLine(const uint8_t* src_buf,
int bitsize,
- int& bitpos,
- uint8_t* dest_buf,
+ int* bitpos,
+ std::vector<uint8_t>* dest_buf,
int columns) {
bool color = true;
int startpos = 0;
while (1) {
- if (bitpos >= bitsize) {
+ if (*bitpos >= bitsize)
return FALSE;
- }
+
int run_len = 0;
while (1) {
int run = FaxGetRun(color ? FaxWhiteRunIns : FaxBlackRunIns, src_buf,
bitpos, bitsize);
if (run < 0) {
- while (bitpos < bitsize) {
- int bit = NEXTBIT;
+ while (*bitpos < bitsize) {
+ int bit = NEXTBIT();
if (bit) {
return TRUE;
}
@@ -453,13 +438,13 @@ FX_BOOL FaxGet1DLine(const uint8_t* src_buf,
break;
}
}
- if (!color) {
- FaxFillBits(dest_buf, columns, startpos, startpos + run_len);
- }
+ if (!color)
+ FaxFillBits(dest_buf->data(), columns, startpos, startpos + run_len);
+
startpos += run_len;
- if (startpos >= columns) {
+ if (startpos >= columns)
break;
- }
+
color = !color;
}
return TRUE;
@@ -473,125 +458,109 @@ class CCodec_FaxDecoder : public CCodec_ScanlineDecoder {
uint32_t src_size,
int width,
int height,
+ uint32_t pitch,
int K,
- FX_BOOL EndOfLine,
- FX_BOOL EncodedByteAlign,
- FX_BOOL BlackIs1,
- int Columns,
- int Rows);
+ bool EndOfLine,
+ bool EncodedByteAlign,
+ bool BlackIs1);
~CCodec_FaxDecoder() override;
-
// CCodec_ScanlineDecoder
FX_BOOL v_Rewind() override;
uint8_t* v_GetNextLine() override;
uint32_t GetSrcOffset() override;
- int m_Encoding, m_bEndOfLine, m_bByteAlign, m_bBlack;
- int bitpos;
- const uint8_t* m_pSrcBuf;
- uint32_t m_SrcSize;
- uint8_t* m_pScanlineBuf;
- uint8_t* m_pRefBuf;
+ private:
+ const int m_Encoding;
+ int m_bitpos;
+ bool m_bByteAlign;
+ const bool m_bEndOfLine;
+ const bool m_bBlack;
+ const uint32_t m_SrcSize;
+ const uint8_t* const m_pSrcBuf;
+ std::vector<uint8_t> m_ScanlineBuf;
+ std::vector<uint8_t> m_RefBuf;
};
CCodec_FaxDecoder::CCodec_FaxDecoder(const uint8_t* src_buf,
uint32_t src_size,
int width,
int height,
+ uint32_t pitch,
int K,
- FX_BOOL EndOfLine,
- FX_BOOL EncodedByteAlign,
- FX_BOOL BlackIs1,
- int Columns,
- int Rows) {
- m_Encoding = K;
- m_bEndOfLine = EndOfLine;
- m_bByteAlign = EncodedByteAlign;
- m_bBlack = BlackIs1;
- m_OrigWidth = Columns;
- m_OrigHeight = Rows;
- if (m_OrigWidth == 0)
- m_OrigWidth = width;
- if (m_OrigHeight == 0)
- m_OrigHeight = height;
- // Should not overflow. Checked by CCodec_FaxDecoder::CreateDecoder.
- m_Pitch = (static_cast<uint32_t>(m_OrigWidth) + 31) / 32 * 4;
- m_OutputWidth = m_OrigWidth;
- m_OutputHeight = m_OrigHeight;
- m_pScanlineBuf = FX_Alloc(uint8_t, m_Pitch);
- m_pRefBuf = FX_Alloc(uint8_t, m_Pitch);
- m_pSrcBuf = src_buf;
- m_SrcSize = src_size;
- m_nComps = 1;
- m_bpc = 1;
-}
+ bool EndOfLine,
+ bool EncodedByteAlign,
+ bool BlackIs1)
+ : CCodec_ScanlineDecoder(width, height, width, height, 1, 1, pitch),
+ m_Encoding(K),
+ m_bitpos(0),
+ m_bByteAlign(EncodedByteAlign),
+ m_bEndOfLine(EndOfLine),
+ m_bBlack(BlackIs1),
+ m_SrcSize(src_size),
+ m_pSrcBuf(src_buf),
+ m_ScanlineBuf(pitch),
+ m_RefBuf(pitch) {}
-CCodec_FaxDecoder::~CCodec_FaxDecoder() {
- FX_Free(m_pScanlineBuf);
- FX_Free(m_pRefBuf);
-}
+CCodec_FaxDecoder::~CCodec_FaxDecoder() {}
FX_BOOL CCodec_FaxDecoder::v_Rewind() {
- FXSYS_memset(m_pRefBuf, 0xff, m_Pitch);
- bitpos = 0;
+ FXSYS_memset(m_RefBuf.data(), 0xff, m_RefBuf.size());
+ m_bitpos = 0;
return TRUE;
}
+
uint8_t* CCodec_FaxDecoder::v_GetNextLine() {
int bitsize = m_SrcSize * 8;
- FaxSkipEOL(m_pSrcBuf, bitsize, bitpos);
- if (bitpos >= bitsize) {
+ FaxSkipEOL(m_pSrcBuf, bitsize, &m_bitpos);
+ if (m_bitpos >= bitsize)
return nullptr;
- }
- FXSYS_memset(m_pScanlineBuf, 0xff, m_Pitch);
+
+ FXSYS_memset(m_ScanlineBuf.data(), 0xff, m_ScanlineBuf.size());
if (m_Encoding < 0) {
- FaxG4GetRow(m_pSrcBuf, bitsize, bitpos, m_pScanlineBuf, m_pRefBuf,
+ FaxG4GetRow(m_pSrcBuf, bitsize, &m_bitpos, m_ScanlineBuf.data(), m_RefBuf,
m_OrigWidth);
- FXSYS_memcpy(m_pRefBuf, m_pScanlineBuf, m_Pitch);
+ m_RefBuf = m_ScanlineBuf;
} else if (m_Encoding == 0) {
- FaxGet1DLine(m_pSrcBuf, bitsize, bitpos, m_pScanlineBuf, m_OrigWidth);
+ FaxGet1DLine(m_pSrcBuf, bitsize, &m_bitpos, &m_ScanlineBuf, m_OrigWidth);
} else {
- FX_BOOL bNext1D = m_pSrcBuf[bitpos / 8] & (1 << (7 - bitpos % 8));
- bitpos++;
+ FX_BOOL bNext1D = m_pSrcBuf[m_bitpos / 8] & (1 << (7 - m_bitpos % 8));
+ ++m_bitpos;
if (bNext1D) {
- FaxGet1DLine(m_pSrcBuf, bitsize, bitpos, m_pScanlineBuf, m_OrigWidth);
+ FaxGet1DLine(m_pSrcBuf, bitsize, &m_bitpos, &m_ScanlineBuf, m_OrigWidth);
} else {
- FaxG4GetRow(m_pSrcBuf, bitsize, bitpos, m_pScanlineBuf, m_pRefBuf,
+ FaxG4GetRow(m_pSrcBuf, bitsize, &m_bitpos, m_ScanlineBuf.data(), m_RefBuf,
m_OrigWidth);
}
- FXSYS_memcpy(m_pRefBuf, m_pScanlineBuf, m_Pitch);
- }
- if (m_bEndOfLine) {
- FaxSkipEOL(m_pSrcBuf, bitsize, bitpos);
+ m_RefBuf = m_ScanlineBuf;
}
- if (m_bByteAlign && bitpos < bitsize) {
- int bitpos0 = bitpos;
- int bitpos1 = (bitpos + 7) / 8 * 8;
+ if (m_bEndOfLine)
+ FaxSkipEOL(m_pSrcBuf, bitsize, &m_bitpos);
+
+ if (m_bByteAlign && m_bitpos < bitsize) {
+ int bitpos0 = m_bitpos;
+ int bitpos1 = (m_bitpos + 7) / 8 * 8;
while (m_bByteAlign && bitpos0 < bitpos1) {
int bit = m_pSrcBuf[bitpos0 / 8] & (1 << (7 - bitpos0 % 8));
if (bit != 0) {
- m_bByteAlign = FALSE;
+ m_bByteAlign = false;
} else {
- bitpos0++;
+ ++bitpos0;
}
}
- if (m_bByteAlign) {
- bitpos = bitpos1;
- }
+ if (m_bByteAlign)
+ m_bitpos = bitpos1;
}
if (m_bBlack) {
- for (uint32_t i = 0; i < m_Pitch; i++) {
- m_pScanlineBuf[i] = ~m_pScanlineBuf[i];
+ for (uint32_t i = 0; i < m_Pitch; ++i) {
+ m_ScanlineBuf[i] = ~m_ScanlineBuf[i];
}
}
- return m_pScanlineBuf;
+ return m_ScanlineBuf.data();
}
+
uint32_t CCodec_FaxDecoder::GetSrcOffset() {
- uint32_t ret = (bitpos + 7) / 8;
- if (ret > m_SrcSize) {
- ret = m_SrcSize;
- }
- return ret;
+ return std::min(static_cast<uint32_t>((m_bitpos + 7) / 8), m_SrcSize);
}
void FaxG4Decode(const uint8_t* src_buf,
@@ -601,40 +570,42 @@ void FaxG4Decode(const uint8_t* src_buf,
int width,
int height,
int pitch) {
- if (pitch == 0) {
+ if (pitch == 0)
pitch = (width + 7) / 8;
- }
- uint8_t* ref_buf = FX_Alloc(uint8_t, pitch);
- FXSYS_memset(ref_buf, 0xff, pitch);
+
+ std::vector<uint8_t> ref_buf(pitch, 0xff);
int bitpos = *pbitpos;
for (int iRow = 0; iRow < height; iRow++) {
uint8_t* line_buf = dest_buf + iRow * pitch;
FXSYS_memset(line_buf, 0xff, pitch);
- FaxG4GetRow(src_buf, src_size << 3, bitpos, line_buf, ref_buf, width);
- FXSYS_memcpy(ref_buf, line_buf, pitch);
+ FaxG4GetRow(src_buf, src_size << 3, &bitpos, line_buf, ref_buf, width);
+ FXSYS_memcpy(ref_buf.data(), line_buf, pitch);
}
- FX_Free(ref_buf);
*pbitpos = bitpos;
}
-CCodec_ScanlineDecoder* CCodec_FaxModule::CreateDecoder(
- const uint8_t* src_buf,
- uint32_t src_size,
- int width,
- int height,
- int K,
- FX_BOOL EndOfLine,
- FX_BOOL EncodedByteAlign,
- FX_BOOL BlackIs1,
- int Columns,
- int Rows) {
+CCodec_ScanlineDecoder* CCodec_FaxModule::CreateDecoder(const uint8_t* src_buf,
+ uint32_t src_size,
+ int width,
+ int height,
+ int K,
+ bool EndOfLine,
+ bool EncodedByteAlign,
+ bool BlackIs1,
+ int Columns,
+ int Rows) {
+ int actual_width = Columns ? Columns : width;
+ int actual_height = Rows ? Rows : height;
+
// Reject invalid values.
- if (width <= 0 || height < 0 || Columns < 0 || Rows < 0)
+ if (actual_width <= 0 || actual_height <= 0)
return nullptr;
+
// Reject unreasonable large input.
- if (width > kMaxImageDimension || height > kMaxImageDimension ||
- Columns > kMaxImageDimension || Rows > kMaxImageDimension)
+ if (actual_width > kMaxImageDimension || actual_height > kMaxImageDimension)
return nullptr;
- return new CCodec_FaxDecoder(src_buf, src_size, width, height, K, EndOfLine,
- EncodedByteAlign, BlackIs1, Columns, Rows);
+
+ uint32_t pitch = (static_cast<uint32_t>(actual_width) + 31) / 32 * 4;
+ return new CCodec_FaxDecoder(src_buf, src_size, actual_width, actual_height,
+ pitch, K, EndOfLine, EncodedByteAlign, BlackIs1);
}
diff --git a/testing/libfuzzer/pdf_codec_fax_fuzzer.cc b/testing/libfuzzer/pdf_codec_fax_fuzzer.cc
index 60e2c9ff19..f6cc1e7200 100644
--- a/testing/libfuzzer/pdf_codec_fax_fuzzer.cc
+++ b/testing/libfuzzer/pdf_codec_fax_fuzzer.cc
@@ -22,17 +22,16 @@ extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) {
int K = GetInteger(data + 8);
int Columns = GetInteger(data + 12);
int Rows = GetInteger(data + 16);
- FX_BOOL EndOfLine = (data[20] & 0x01) == 0;
- FX_BOOL ByteAlign = (data[20] & 0x02) == 0;
- FX_BOOL BlackIs1 = (data[20] & 0x04) == 0;
+ bool EndOfLine = !(data[20] & 0x01);
+ bool ByteAlign = !(data[20] & 0x02);
+ bool BlackIs1 = !(data[20] & 0x04);
data += kParameterSize;
size -= kParameterSize;
CCodec_FaxModule fax_module;
- std::unique_ptr<CCodec_ScanlineDecoder> decoder;
- decoder.reset(fax_module.CreateDecoder(data, size, width, height, K,
- EndOfLine, ByteAlign, BlackIs1,
- Columns, Rows));
+ std::unique_ptr<CCodec_ScanlineDecoder> decoder(
+ fax_module.CreateDecoder(data, size, width, height, K, EndOfLine,
+ ByteAlign, BlackIs1, Columns, Rows));
if (decoder) {
int line = 0;