7#include "core/fpdfapi/page/cpdf_streamparser.h"
15#include "constants/stream_dict_common.h"
16#include "core/fpdfapi/page/cpdf_docpagedata.h"
17#include "core/fpdfapi/parser/cpdf_array.h"
18#include "core/fpdfapi/parser/cpdf_boolean.h"
19#include "core/fpdfapi/parser/cpdf_dictionary.h"
20#include "core/fpdfapi/parser/cpdf_name.h"
21#include "core/fpdfapi/parser/cpdf_null.h"
22#include "core/fpdfapi/parser/cpdf_number.h"
23#include "core/fpdfapi/parser/cpdf_stream.h"
24#include "core/fpdfapi/parser/cpdf_string.h"
25#include "core/fpdfapi/parser/fpdf_parser_decode.h"
26#include "core/fpdfapi/parser/fpdf_parser_utility.h"
27#include "core/fxcodec/data_and_bytes_consumed.h"
28#include "core/fxcodec/jpeg/jpegmodule.h"
29#include "core/fxcodec/scanlinedecoder.h"
30#include "core/fxcrt/check.h"
31#include "core/fxcrt/data_vector.h"
32#include "core/fxcrt/fx_extension.h"
33#include "core/fxcrt/fx_safe_types.h"
34#include "core/fxcrt/span_util.h"
35#include "core/fxge/calculate_pitch.h"
39const uint32_t kMaxNestedParsingLevel = 512;
40const size_t kMaxStringLength = 32767;
42const char kTrue[] =
"true";
43const char kFalse[] =
"false";
44const char kNull[] =
"null";
46uint32_t DecodeAllScanlines(std::unique_ptr<ScanlineDecoder> pDecoder) {
50 int ncomps = pDecoder->CountComps();
51 int bpc = pDecoder->GetBPC();
52 int width = pDecoder->GetWidth();
53 int height = pDecoder->GetHeight();
54 if (width <= 0 || height <= 0)
57 std::optional<uint32_t> maybe_size =
58 fxge::CalculatePitch8(bpc, ncomps, width);
59 if (!maybe_size.has_value())
64 if (size.ValueOrDefault(0) == 0)
67 for (
int row = 0; row < height; ++row) {
68 if (pDecoder->GetScanline(row).empty())
71 return pDecoder->GetSrcOffset();
74uint32_t DecodeInlineStream(pdfium::span<
const uint8_t> src_span,
89 if (decoder
== "FlateDecode") {
90 return FlateOrLZWDecode(
false, src_span, pParam.Get(),
94 if (decoder
== "LZWDecode") {
95 return FlateOrLZWDecode(
96 true, src_span, pParam.Get(),
100 if (decoder
== "DCTDecode") {
101 std::unique_ptr<ScanlineDecoder> pDecoder = JpegModule::CreateDecoder(
102 src_span, width, height, 0,
103 !pParam || pParam->GetIntegerFor(
"ColorTransform", 1));
104 return DecodeAllScanlines(std::move(pDecoder));
106 if (decoder
== "CCITTFaxDecode") {
107 std::unique_ptr<ScanlineDecoder> pDecoder =
108 CreateFaxDecoder(src_span, width, height, pParam.Get());
109 return DecodeAllScanlines(std::move(pDecoder));
112 if (decoder
== "ASCII85Decode") {
113 return A85Decode(src_span).bytes_consumed;
115 if (decoder
== "ASCIIHexDecode") {
116 return HexDecode(src_span).bytes_consumed;
118 if (decoder
== "RunLengthDecode") {
119 return RunLengthDecode(src_span).bytes_consumed;
131 const WeakPtr<ByteStringPool>& pPool)
140 if (m_Pos < m_pBuf.size() && PDFCharIsWhitespace(m_pBuf[m_Pos]))
143 if (m_Pos == m_pBuf.size())
150 const CPDF_Array* pArray = pFilter->AsArray();
152 decoder = pArray->GetByteStringAt(0);
154 pDict->GetArrayFor(pdfium::stream::kDecodeParms);
156 pParam = pParams->GetDictAt(0);
158 decoder = pFilter->GetString();
162 uint32_t width = pDict->GetIntegerFor(
"Width");
163 uint32_t height = pDict->GetIntegerFor(
"Height");
165 uint32_t nComponents = 1;
168 CPDF_DocPageData::FromDocument(pDoc)->GetColorSpace(pCSObj,
nullptr);
169 nComponents = pCS ? pCS->ComponentCount() : 3;
170 bpc = pDict->GetIntegerFor(
"BitsPerComponent");
172 std::optional<uint32_t> maybe_size =
173 fxge::CalculatePitch8(bpc, nComponents, width);
174 if (!maybe_size.has_value())
182 uint32_t dwOrigSize = size.ValueOrDie();
183 DataVector<uint8_t> data;
184 uint32_t dwStreamSize;
185 if (decoder.IsEmpty()) {
186 dwOrigSize = std::min<uint32_t>(dwOrigSize, m_pBuf.size() - m_Pos);
187 auto src_span = m_pBuf.subspan(m_Pos, dwOrigSize);
188 data = DataVector<uint8_t>(src_span.begin(), src_span.end());
189 dwStreamSize = dwOrigSize;
192 dwStreamSize = DecodeInlineStream(m_pBuf.subspan(m_Pos), width, height,
193 decoder, std::move(pParam), dwOrigSize);
194 if (!
pdfium::IsValueInRangeForNumericType<
int>(dwStreamSize)) {
198 uint32_t dwSavePos = m_Pos;
199 m_Pos += dwStreamSize;
201 uint32_t dwPrevPos = m_Pos;
207 dwStreamSize += m_Pos - dwPrevPos;
210 if (GetWord() ==
"EI") {
214 dwStreamSize += m_Pos - dwPrevPos;
217 auto src_span = m_pBuf.subspan(m_Pos, dwStreamSize);
218 data = DataVector<uint8_t>(src_span.begin(), src_span.end());
219 m_Pos += dwStreamSize;
221 pDict->SetNewFor<CPDF_Number>(
"Length",
static_cast<
int>(dwStreamSize));
222 return pdfium::MakeRetain<CPDF_Stream>(
std::move(data),
std::move(pDict));
228 if (!PositionIsInBounds())
231 uint8_t ch = m_pBuf[m_Pos++];
234 if (!PositionIsInBounds())
237 ch = m_pBuf[m_Pos++];
244 if (!PositionIsInBounds())
247 ch = m_pBuf[m_Pos++];
255 m_pLastObj = ReadNextObject(
false,
false, 0);
259 bool bIsNumber =
true;
261 if (m_WordSize < kMaxWordLength)
262 m_WordBuffer[m_WordSize++] = ch;
267 if (!PositionIsInBounds())
270 ch = m_pBuf[m_Pos++];
278 m_WordBuffer[m_WordSize] = 0;
282 if (m_WordBuffer[0] ==
'/')
285 if (m_WordSize == 4) {
286 if (GetWord() == kTrue) {
287 m_pLastObj = pdfium::MakeRetain<CPDF_Boolean>(
true);
290 if (GetWord() == kNull) {
291 m_pLastObj = pdfium::MakeRetain<CPDF_Null>();
294 }
else if (m_WordSize == 5) {
295 if (GetWord() == kFalse) {
296 m_pLastObj = pdfium::MakeRetain<CPDF_Boolean>(
false);
304 bool bAllowNestedArray,
306 uint32_t dwRecursionLevel) {
309 GetNextWord(bIsNumber);
310 if (!m_WordSize || dwRecursionLevel > kMaxNestedParsingLevel)
314 m_WordBuffer[m_WordSize] = 0;
315 return pdfium::MakeRetain<CPDF_Number>(GetWord());
318 int first_char = m_WordBuffer[0];
319 if (first_char ==
'/') {
320 ByteString name = PDF_NameDecode(GetWord().Substr(1));
321 return pdfium::MakeRetain<CPDF_Name>(m_pPool, name);
324 if (first_char ==
'(') {
325 return pdfium::MakeRetain<CPDF_String>(m_pPool, ReadString());
328 if (first_char ==
'<') {
329 if (m_WordSize == 1) {
330 return pdfium::MakeRetain<CPDF_String>(m_pPool, ReadHexString(),
331 CPDF_String::DataType::kIsHex);
334 auto pDict = pdfium::MakeRetain<CPDF_Dictionary>(m_pPool);
336 GetNextWord(bIsNumber);
337 if (m_WordSize == 2 && m_WordBuffer[0] ==
'>')
340 if (!m_WordSize || m_WordBuffer[0] !=
'/')
343 ByteString key = PDF_NameDecode(GetWord().Substr(1));
345 ReadNextObject(
true, bInArray, dwRecursionLevel + 1);
349 pDict->SetFor(key,
std::move(pObj));
354 if (first_char ==
'[') {
355 if ((!bAllowNestedArray && bInArray))
361 ReadNextObject(bAllowNestedArray,
true, dwRecursionLevel + 1);
363 pArray->Append(
std::move(pObj));
366 if (!m_WordSize || m_WordBuffer[0] ==
']')
372 if (GetWord() == kFalse)
373 return pdfium::MakeRetain<CPDF_Boolean>(
false);
374 if (GetWord() == kTrue)
375 return pdfium::MakeRetain<CPDF_Boolean>(
true);
376 if (GetWord() == kNull)
377 return pdfium::MakeRetain<CPDF_Null>();
385 if (!PositionIsInBounds())
388 uint8_t ch = m_pBuf[m_Pos++];
391 if (!PositionIsInBounds()) {
394 ch = m_pBuf[m_Pos++];
401 if (!PositionIsInBounds())
403 ch = m_pBuf[m_Pos++];
411 m_WordBuffer[m_WordSize++] = ch;
414 if (!PositionIsInBounds())
416 ch = m_pBuf[m_Pos++];
421 if (m_WordSize < kMaxWordLength)
422 m_WordBuffer[m_WordSize++] = ch;
424 }
else if (ch ==
'<') {
425 if (!PositionIsInBounds())
427 ch = m_pBuf[m_Pos++];
429 m_WordBuffer[m_WordSize++] = ch;
432 }
else if (ch ==
'>') {
433 if (!PositionIsInBounds())
435 ch = m_pBuf[m_Pos++];
437 m_WordBuffer[m_WordSize++] = ch;
445 if (m_WordSize < kMaxWordLength)
446 m_WordBuffer[m_WordSize++] = ch;
449 if (!PositionIsInBounds())
452 ch = m_pBuf[m_Pos++];
461 if (!PositionIsInBounds())
468 uint8_t ch = m_pBuf[m_Pos++];
474 return buf.First(
std::min(buf.GetLength(), kMaxStringLength));
478 }
else if (ch ==
'(') {
481 }
else if (ch ==
'\\') {
484 buf
+= static_cast<
char>(ch);
499 }
else if (ch ==
'n') {
501 }
else if (ch ==
'r') {
503 }
else if (ch ==
't') {
505 }
else if (ch ==
'b') {
507 }
else if (ch ==
'f') {
510 buf
+= static_cast<
char>(ch);
520 buf
+= static_cast<
char>(iEscCode);
529 buf
+= static_cast<
char>(iEscCode);
532 buf
+= static_cast<
char>(iEscCode);
543 if (!PositionIsInBounds())
544 return buf.First(
std::min(buf.GetLength(), kMaxStringLength));
546 ch = m_pBuf[m_Pos++];
551 if (!PositionIsInBounds()) {
552 return DataVector<uint8_t>();
556 DataVector<uint8_t> buf;
559 while (PositionIsInBounds()) {
560 uint8_t ch = m_pBuf[m_Pos++];
580 if (buf.size() > kMaxStringLength) {
581 buf.resize(kMaxStringLength);
587 return m_Pos < m_pBuf.size();
fxcrt::ByteString ByteString
std::vector< RetainPtr< CPDF_Object > >::const_iterator const_iterator
std::map< ByteString, RetainPtr< CPDF_Object >, std::less<> > DictMap
ElementType ParseNextElement()
RetainPtr< CPDF_Object > ReadNextObject(bool bAllowNestedArray, bool bInArray, uint32_t dwRecursionLevel)
RetainPtr< CPDF_Stream > ReadInlineStream(CPDF_Document *pDoc, RetainPtr< CPDF_Dictionary > pDict, const CPDF_Object *pCSObj)
CPDF_StreamParser(pdfium::span< const uint8_t > span, const WeakPtr< ByteStringPool > &pPool)
CPDF_StreamParser(pdfium::span< const uint8_t > span)
ByteString & operator+=(char ch)
bool operator==(const char *ptr) const
bool PDFCharIsWhitespace(uint8_t c)
bool PDFCharIsOther(uint8_t c)
bool PDFCharIsNumeric(uint8_t c)
bool PDFCharIsDelimiter(uint8_t c)
bool PDFCharIsLineEnding(uint8_t c)
int FXSYS_DecimalCharToInt(char c)
bool FXSYS_IsOctalDigit(char c)
int FXSYS_HexCharToInt(char c)
#define FX_INVALID_OFFSET
pdfium::CheckedNumeric< uint32_t > FX_SAFE_UINT32
const char kDecodeParms[]