| OLD | NEW |
| 1 // Copyright 2016 PDFium Authors. All rights reserved. | 1 // Copyright 2016 PDFium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 // Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com | 5 // Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com |
| 6 | 6 |
| 7 #include "core/fpdfapi/page/cpdf_streamparser.h" | 7 #include "core/fpdfapi/page/cpdf_streamparser.h" |
| 8 | 8 |
| 9 #include <limits.h> | 9 #include <limits.h> |
| 10 | 10 |
| (...skipping 11 matching lines...) Expand all Loading... |
| 22 #include "core/fpdfapi/parser/cpdf_number.h" | 22 #include "core/fpdfapi/parser/cpdf_number.h" |
| 23 #include "core/fpdfapi/parser/cpdf_stream.h" | 23 #include "core/fpdfapi/parser/cpdf_stream.h" |
| 24 #include "core/fpdfapi/parser/cpdf_string.h" | 24 #include "core/fpdfapi/parser/cpdf_string.h" |
| 25 #include "core/fpdfapi/parser/fpdf_parser_decode.h" | 25 #include "core/fpdfapi/parser/fpdf_parser_decode.h" |
| 26 #include "core/fpdfapi/parser/fpdf_parser_utility.h" | 26 #include "core/fpdfapi/parser/fpdf_parser_utility.h" |
| 27 #include "core/fxcodec/fx_codec.h" | 27 #include "core/fxcodec/fx_codec.h" |
| 28 #include "core/fxcrt/fx_ext.h" | 28 #include "core/fxcrt/fx_ext.h" |
| 29 | 29 |
| 30 namespace { | 30 namespace { |
| 31 | 31 |
| 32 const uint32_t kMaxNestedArrayLevel = 512; | 32 const uint32_t kMaxNestedParsingLevel = 512; |
| 33 const uint32_t kMaxWordBuffer = 256; | 33 const uint32_t kMaxWordBuffer = 256; |
| 34 const FX_STRSIZE kMaxStringLength = 32767; | 34 const FX_STRSIZE kMaxStringLength = 32767; |
| 35 | 35 |
| 36 uint32_t DecodeAllScanlines(std::unique_ptr<CCodec_ScanlineDecoder> pDecoder, | 36 uint32_t DecodeAllScanlines(std::unique_ptr<CCodec_ScanlineDecoder> pDecoder, |
| 37 uint8_t*& dest_buf, | 37 uint8_t*& dest_buf, |
| 38 uint32_t& dest_size) { | 38 uint32_t& dest_size) { |
| 39 if (!pDecoder) | 39 if (!pDecoder) |
| 40 return FX_INVALID_OFFSET; | 40 return FX_INVALID_OFFSET; |
| 41 int ncomps = pDecoder->CountComps(); | 41 int ncomps = pDecoder->CountComps(); |
| 42 int bpc = pDecoder->GetBPC(); | 42 int bpc = pDecoder->GetBPC(); |
| (...skipping 206 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 249 return EndOfData; | 249 return EndOfData; |
| 250 | 250 |
| 251 ch = m_pBuf[m_Pos++]; | 251 ch = m_pBuf[m_Pos++]; |
| 252 if (PDFCharIsLineEnding(ch)) | 252 if (PDFCharIsLineEnding(ch)) |
| 253 break; | 253 break; |
| 254 } | 254 } |
| 255 } | 255 } |
| 256 | 256 |
| 257 if (PDFCharIsDelimiter(ch) && ch != '/') { | 257 if (PDFCharIsDelimiter(ch) && ch != '/') { |
| 258 m_Pos--; | 258 m_Pos--; |
| 259 m_pLastObj = ReadNextObject(false, 0); | 259 m_pLastObj = ReadNextObject(false, false, 0); |
| 260 return Others; | 260 return Others; |
| 261 } | 261 } |
| 262 | 262 |
| 263 bool bIsNumber = true; | 263 bool bIsNumber = true; |
| 264 while (1) { | 264 while (1) { |
| 265 if (m_WordSize < kMaxWordBuffer) | 265 if (m_WordSize < kMaxWordBuffer) |
| 266 m_WordBuffer[m_WordSize++] = ch; | 266 m_WordBuffer[m_WordSize++] = ch; |
| 267 | 267 |
| 268 if (!PDFCharIsNumeric(ch)) | 268 if (!PDFCharIsNumeric(ch)) |
| 269 bIsNumber = false; | 269 bIsNumber = false; |
| (...skipping 29 matching lines...) Expand all Loading... |
| 299 if (memcmp(m_WordBuffer, "false", 5) == 0) { | 299 if (memcmp(m_WordBuffer, "false", 5) == 0) { |
| 300 m_pLastObj = pdfium::MakeUnique<CPDF_Boolean>(false); | 300 m_pLastObj = pdfium::MakeUnique<CPDF_Boolean>(false); |
| 301 return Others; | 301 return Others; |
| 302 } | 302 } |
| 303 } | 303 } |
| 304 return Keyword; | 304 return Keyword; |
| 305 } | 305 } |
| 306 | 306 |
| 307 std::unique_ptr<CPDF_Object> CPDF_StreamParser::ReadNextObject( | 307 std::unique_ptr<CPDF_Object> CPDF_StreamParser::ReadNextObject( |
| 308 bool bAllowNestedArray, | 308 bool bAllowNestedArray, |
| 309 uint32_t dwInArrayLevel) { | 309 bool bInArray, |
| 310 uint32_t dwRecursionLevel) { |
| 310 bool bIsNumber; | 311 bool bIsNumber; |
| 312 // Must get the next word before returning to avoid infinite loops. |
| 311 GetNextWord(bIsNumber); | 313 GetNextWord(bIsNumber); |
| 312 if (!m_WordSize) | 314 if (!m_WordSize || dwRecursionLevel > kMaxNestedParsingLevel) |
| 313 return nullptr; | 315 return nullptr; |
| 314 | 316 |
| 315 if (bIsNumber) { | 317 if (bIsNumber) { |
| 316 m_WordBuffer[m_WordSize] = 0; | 318 m_WordBuffer[m_WordSize] = 0; |
| 317 return pdfium::MakeUnique<CPDF_Number>( | 319 return pdfium::MakeUnique<CPDF_Number>( |
| 318 CFX_ByteStringC(m_WordBuffer, m_WordSize)); | 320 CFX_ByteStringC(m_WordBuffer, m_WordSize)); |
| 319 } | 321 } |
| 320 | 322 |
| 321 int first_char = m_WordBuffer[0]; | 323 int first_char = m_WordBuffer[0]; |
| 322 if (first_char == '/') { | 324 if (first_char == '/') { |
| (...skipping 15 matching lines...) Expand all Loading... |
| 338 while (1) { | 340 while (1) { |
| 339 GetNextWord(bIsNumber); | 341 GetNextWord(bIsNumber); |
| 340 if (m_WordSize == 2 && m_WordBuffer[0] == '>') | 342 if (m_WordSize == 2 && m_WordBuffer[0] == '>') |
| 341 break; | 343 break; |
| 342 | 344 |
| 343 if (!m_WordSize || m_WordBuffer[0] != '/') | 345 if (!m_WordSize || m_WordBuffer[0] != '/') |
| 344 return nullptr; | 346 return nullptr; |
| 345 | 347 |
| 346 CFX_ByteString key = | 348 CFX_ByteString key = |
| 347 PDF_NameDecode(CFX_ByteStringC(m_WordBuffer + 1, m_WordSize - 1)); | 349 PDF_NameDecode(CFX_ByteStringC(m_WordBuffer + 1, m_WordSize - 1)); |
| 348 std::unique_ptr<CPDF_Object> pObj = ReadNextObject(true, 0); | 350 std::unique_ptr<CPDF_Object> pObj = |
| 351 ReadNextObject(true, bInArray, dwRecursionLevel + 1); |
| 349 if (!pObj) | 352 if (!pObj) |
| 350 return nullptr; | 353 return nullptr; |
| 351 | 354 |
| 352 if (!key.IsEmpty()) | 355 if (!key.IsEmpty()) |
| 353 pDict->SetFor(key, std::move(pObj)); | 356 pDict->SetFor(key, std::move(pObj)); |
| 354 } | 357 } |
| 355 return std::move(pDict); | 358 return std::move(pDict); |
| 356 } | 359 } |
| 357 | 360 |
| 358 if (first_char == '[') { | 361 if (first_char == '[') { |
| 359 if ((!bAllowNestedArray && dwInArrayLevel) || | 362 if ((!bAllowNestedArray && bInArray)) |
| 360 dwInArrayLevel > kMaxNestedArrayLevel) { | |
| 361 return nullptr; | 363 return nullptr; |
| 362 } | |
| 363 | 364 |
| 364 auto pArray = pdfium::MakeUnique<CPDF_Array>(); | 365 auto pArray = pdfium::MakeUnique<CPDF_Array>(); |
| 365 while (1) { | 366 while (1) { |
| 366 std::unique_ptr<CPDF_Object> pObj = | 367 std::unique_ptr<CPDF_Object> pObj = |
| 367 ReadNextObject(bAllowNestedArray, dwInArrayLevel + 1); | 368 ReadNextObject(bAllowNestedArray, true, dwRecursionLevel + 1); |
| 368 if (pObj) { | 369 if (pObj) { |
| 369 pArray->Add(std::move(pObj)); | 370 pArray->Add(std::move(pObj)); |
| 370 continue; | 371 continue; |
| 371 } | 372 } |
| 372 if (!m_WordSize || m_WordBuffer[0] == ']') | 373 if (!m_WordSize || m_WordBuffer[0] == ']') |
| 373 break; | 374 break; |
| 374 } | 375 } |
| 375 return std::move(pArray); | 376 return std::move(pArray); |
| 376 } | 377 } |
| 377 | 378 |
| (...skipping 219 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 597 | 598 |
| 598 if (buf.GetLength() > kMaxStringLength) | 599 if (buf.GetLength() > kMaxStringLength) |
| 599 return CFX_ByteString(buf.GetBuffer(), kMaxStringLength); | 600 return CFX_ByteString(buf.GetBuffer(), kMaxStringLength); |
| 600 | 601 |
| 601 return buf.MakeString(); | 602 return buf.MakeString(); |
| 602 } | 603 } |
| 603 | 604 |
| 604 bool CPDF_StreamParser::PositionIsInBounds() const { | 605 bool CPDF_StreamParser::PositionIsInBounds() const { |
| 605 return m_Pos < m_Size; | 606 return m_Pos < m_Size; |
| 606 } | 607 } |
| OLD | NEW |