Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(284)

Side by Side Diff: core/fpdfapi/page/cpdf_streamparser.cpp

Issue 2686193003: [M57] Limit parsing recursion levels in CPDF_StreamParser (Closed)
Patch Set: Created 3 years, 10 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « core/fpdfapi/page/cpdf_streamparser.h ('k') | testing/libfuzzer/pdf_streamparser_fuzzer.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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
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
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
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
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
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 }
OLDNEW
« no previous file with comments | « core/fpdfapi/page/cpdf_streamparser.h ('k') | testing/libfuzzer/pdf_streamparser_fuzzer.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698