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

Side by Side Diff: core/fpdfapi/fpdf_page/fpdf_page_parser_old.cpp

Issue 1930743003: Fix stack overflow from nested arrays. (Closed) Base URL: https://pdfium.googlesource.com/pdfium@master
Patch Set: unsigned Created 4 years, 7 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/fpdf_page/fpdf_page_parser.cpp ('k') | core/fpdfapi/fpdf_page/pageint.h » ('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 2014 PDFium Authors. All rights reserved. 1 // Copyright 2014 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/fpdf_page/pageint.h" 7 #include "core/fpdfapi/fpdf_page/pageint.h"
8 8
9 #include <limits.h> 9 #include <limits.h>
10 10
(...skipping 13 matching lines...) Expand all
24 #include "core/fpdfapi/fpdf_parser/include/cpdf_number.h" 24 #include "core/fpdfapi/fpdf_parser/include/cpdf_number.h"
25 #include "core/fpdfapi/fpdf_parser/include/cpdf_stream.h" 25 #include "core/fpdfapi/fpdf_parser/include/cpdf_stream.h"
26 #include "core/fpdfapi/fpdf_parser/include/cpdf_stream_acc.h" 26 #include "core/fpdfapi/fpdf_parser/include/cpdf_stream_acc.h"
27 #include "core/fpdfapi/fpdf_parser/include/cpdf_string.h" 27 #include "core/fpdfapi/fpdf_parser/include/cpdf_string.h"
28 #include "core/fpdfapi/fpdf_parser/include/fpdf_parser_decode.h" 28 #include "core/fpdfapi/fpdf_parser/include/fpdf_parser_decode.h"
29 #include "core/fpdfapi/include/cpdf_modulemgr.h" 29 #include "core/fpdfapi/include/cpdf_modulemgr.h"
30 #include "core/fxcodec/include/fx_codec.h" 30 #include "core/fxcodec/include/fx_codec.h"
31 #include "core/fxcrt/include/fx_ext.h" 31 #include "core/fxcrt/include/fx_ext.h"
32 #include "core/fxcrt/include/fx_safe_types.h" 32 #include "core/fxcrt/include/fx_safe_types.h"
33 33
34 namespace {
35
36 const uint32_t kMaxNestedArrayLevel = 512;
37 const uint32_t kMaxWordBuffer = 256;
38 const FX_STRSIZE kMaxStringLength = 32767;
39
40 } // namespace
41
34 CPDF_StreamParser::CPDF_StreamParser(const uint8_t* pData, uint32_t dwSize) { 42 CPDF_StreamParser::CPDF_StreamParser(const uint8_t* pData, uint32_t dwSize) {
35 m_pBuf = pData; 43 m_pBuf = pData;
36 m_Size = dwSize; 44 m_Size = dwSize;
37 m_Pos = 0; 45 m_Pos = 0;
38 m_pLastObj = NULL; 46 m_pLastObj = NULL;
39 } 47 }
40 48
41 CPDF_StreamParser::~CPDF_StreamParser() { 49 CPDF_StreamParser::~CPDF_StreamParser() {
42 if (m_pLastObj) { 50 if (m_pLastObj) {
43 m_pLastObj->Release(); 51 m_pLastObj->Release();
(...skipping 179 matching lines...) Expand 10 before | Expand all | Expand 10 after
223 } 231 }
224 m_Pos = dwSavePos; 232 m_Pos = dwSavePos;
225 pData = FX_Alloc(uint8_t, dwStreamSize); 233 pData = FX_Alloc(uint8_t, dwStreamSize);
226 FXSYS_memcpy(pData, m_pBuf + m_Pos, dwStreamSize); 234 FXSYS_memcpy(pData, m_pBuf + m_Pos, dwStreamSize);
227 m_Pos += dwStreamSize; 235 m_Pos += dwStreamSize;
228 } 236 }
229 pDict->SetAtInteger("Length", (int)dwStreamSize); 237 pDict->SetAtInteger("Length", (int)dwStreamSize);
230 return new CPDF_Stream(pData, dwStreamSize, pDict); 238 return new CPDF_Stream(pData, dwStreamSize, pDict);
231 } 239 }
232 240
233 #define MAX_WORD_BUFFER 256
234 #define MAX_STRING_LENGTH 32767
235
236 CPDF_StreamParser::SyntaxType CPDF_StreamParser::ParseNextElement() { 241 CPDF_StreamParser::SyntaxType CPDF_StreamParser::ParseNextElement() {
237 if (m_pLastObj) { 242 if (m_pLastObj) {
238 m_pLastObj->Release(); 243 m_pLastObj->Release();
239 m_pLastObj = nullptr; 244 m_pLastObj = nullptr;
240 } 245 }
241 246
242 m_WordSize = 0; 247 m_WordSize = 0;
243 FX_BOOL bIsNumber = TRUE; 248 FX_BOOL bIsNumber = TRUE;
244 if (!PositionIsInBounds()) 249 if (!PositionIsInBounds())
245 return EndOfData; 250 return EndOfData;
(...skipping 15 matching lines...) Expand all
261 return EndOfData; 266 return EndOfData;
262 267
263 ch = m_pBuf[m_Pos++]; 268 ch = m_pBuf[m_Pos++];
264 if (PDFCharIsLineEnding(ch)) 269 if (PDFCharIsLineEnding(ch))
265 break; 270 break;
266 } 271 }
267 } 272 }
268 273
269 if (PDFCharIsDelimiter(ch) && ch != '/') { 274 if (PDFCharIsDelimiter(ch) && ch != '/') {
270 m_Pos--; 275 m_Pos--;
271 m_pLastObj = ReadNextObject(); 276 m_pLastObj = ReadNextObject(false, 0);
272 return Others; 277 return Others;
273 } 278 }
274 279
275 while (1) { 280 while (1) {
276 if (m_WordSize < MAX_WORD_BUFFER) 281 if (m_WordSize < kMaxWordBuffer)
277 m_WordBuffer[m_WordSize++] = ch; 282 m_WordBuffer[m_WordSize++] = ch;
278 283
279 if (!PDFCharIsNumeric(ch)) 284 if (!PDFCharIsNumeric(ch))
280 bIsNumber = FALSE; 285 bIsNumber = FALSE;
281 286
282 if (!PositionIsInBounds()) 287 if (!PositionIsInBounds())
283 break; 288 break;
284 289
285 ch = m_pBuf[m_Pos++]; 290 ch = m_pBuf[m_Pos++];
286 291
(...skipping 21 matching lines...) Expand all
308 } 313 }
309 } else if (m_WordSize == 5) { 314 } else if (m_WordSize == 5) {
310 if (memcmp(m_WordBuffer, "false", 5) == 0) { 315 if (memcmp(m_WordBuffer, "false", 5) == 0) {
311 m_pLastObj = new CPDF_Boolean(FALSE); 316 m_pLastObj = new CPDF_Boolean(FALSE);
312 return Others; 317 return Others;
313 } 318 }
314 } 319 }
315 return Keyword; 320 return Keyword;
316 } 321 }
317 322
318 CPDF_Object* CPDF_StreamParser::ReadNextObject(FX_BOOL bAllowNestedArray, 323 CPDF_Object* CPDF_StreamParser::ReadNextObject(bool bAllowNestedArray,
319 FX_BOOL bInArray) { 324 uint32_t dwInArrayLevel) {
320 FX_BOOL bIsNumber; 325 FX_BOOL bIsNumber;
321 GetNextWord(bIsNumber); 326 GetNextWord(bIsNumber);
322 if (m_WordSize == 0) { 327 if (!m_WordSize)
323 return NULL; 328 return nullptr;
324 } 329
325 if (bIsNumber) { 330 if (bIsNumber) {
326 m_WordBuffer[m_WordSize] = 0; 331 m_WordBuffer[m_WordSize] = 0;
327 return new CPDF_Number(CFX_ByteStringC(m_WordBuffer, m_WordSize)); 332 return new CPDF_Number(CFX_ByteStringC(m_WordBuffer, m_WordSize));
328 } 333 }
334
329 int first_char = m_WordBuffer[0]; 335 int first_char = m_WordBuffer[0];
330 if (first_char == '/') { 336 if (first_char == '/') {
331 return new CPDF_Name( 337 return new CPDF_Name(
332 PDF_NameDecode(CFX_ByteStringC(m_WordBuffer + 1, m_WordSize - 1))); 338 PDF_NameDecode(CFX_ByteStringC(m_WordBuffer + 1, m_WordSize - 1)));
333 } 339 }
334 if (first_char == '(') { 340
341 if (first_char == '(')
335 return new CPDF_String(ReadString(), FALSE); 342 return new CPDF_String(ReadString(), FALSE);
336 } 343
337 if (first_char == '<') { 344 if (first_char == '<') {
338 if (m_WordSize == 1) { 345 if (m_WordSize == 1)
339 return new CPDF_String(ReadHexString(), TRUE); 346 return new CPDF_String(ReadHexString(), TRUE);
340 } 347
341 CPDF_Dictionary* pDict = new CPDF_Dictionary; 348 CPDF_Dictionary* pDict = new CPDF_Dictionary;
342 while (1) { 349 while (1) {
343 GetNextWord(bIsNumber); 350 GetNextWord(bIsNumber);
344 if (m_WordSize == 0) { 351 if (m_WordSize == 2 && m_WordBuffer[0] == '>')
352 break;
353
354 if (!m_WordSize || m_WordBuffer[0] != '/') {
345 pDict->Release(); 355 pDict->Release();
346 return nullptr; 356 return nullptr;
347 } 357 }
348 if (m_WordSize == 2 && m_WordBuffer[0] == '>') { 358
349 break;
350 }
351 if (m_WordBuffer[0] != '/') {
352 pDict->Release();
353 return nullptr;
354 }
355 CFX_ByteString key = 359 CFX_ByteString key =
356 PDF_NameDecode(CFX_ByteStringC(m_WordBuffer + 1, m_WordSize - 1)); 360 PDF_NameDecode(CFX_ByteStringC(m_WordBuffer + 1, m_WordSize - 1));
357 CPDF_Object* pObj = ReadNextObject(TRUE); 361 CPDF_Object* pObj = ReadNextObject(true, 0);
358 if (!pObj) { 362 if (!pObj) {
359 pDict->Release(); 363 pDict->Release();
360 return nullptr; 364 return nullptr;
361 } 365 }
362 if (!key.IsEmpty()) { 366
367 if (key.IsEmpty())
368 pObj->Release();
369 else
363 pDict->SetAt(key, pObj); 370 pDict->SetAt(key, pObj);
364 } else {
365 pObj->Release();
366 }
367 } 371 }
368 return pDict; 372 return pDict;
369 } 373 }
374
370 if (first_char == '[') { 375 if (first_char == '[') {
371 if (!bAllowNestedArray && bInArray) { 376 if ((!bAllowNestedArray && dwInArrayLevel) ||
372 return NULL; 377 dwInArrayLevel > kMaxNestedArrayLevel) {
378 return nullptr;
373 } 379 }
380
374 CPDF_Array* pArray = new CPDF_Array; 381 CPDF_Array* pArray = new CPDF_Array;
375 while (1) { 382 while (1) {
376 CPDF_Object* pObj = ReadNextObject(bAllowNestedArray, TRUE); 383 CPDF_Object* pObj = ReadNextObject(bAllowNestedArray, dwInArrayLevel + 1);
377 if (pObj) { 384 if (pObj) {
378 pArray->Add(pObj); 385 pArray->Add(pObj);
379 continue; 386 continue;
380 } 387 }
381 388
382 if (m_WordSize == 0 || m_WordBuffer[0] == ']') 389 if (!m_WordSize || m_WordBuffer[0] == ']')
383 break; 390 break;
384 } 391 }
385 return pArray; 392 return pArray;
386 } 393 }
394
395 if (m_WordSize == 5 && !memcmp(m_WordBuffer, "false", 5))
396 return new CPDF_Boolean(FALSE);
397
387 if (m_WordSize == 4) { 398 if (m_WordSize == 4) {
388 if (memcmp(m_WordBuffer, "true", 4) == 0) { 399 if (memcmp(m_WordBuffer, "true", 4) == 0)
389 return new CPDF_Boolean(TRUE); 400 return new CPDF_Boolean(TRUE);
390 } 401
391 if (memcmp(m_WordBuffer, "null", 4) == 0) { 402 if (memcmp(m_WordBuffer, "null", 4) == 0)
392 return new CPDF_Null; 403 return new CPDF_Null;
393 }
394 } else if (m_WordSize == 5) {
395 if (memcmp(m_WordBuffer, "false", 5) == 0) {
396 return new CPDF_Boolean(FALSE);
397 }
398 } 404 }
399 return NULL; 405
406 return nullptr;
400 } 407 }
401 408
402 void CPDF_StreamParser::GetNextWord(FX_BOOL& bIsNumber) { 409 void CPDF_StreamParser::GetNextWord(FX_BOOL& bIsNumber) {
403 m_WordSize = 0; 410 m_WordSize = 0;
404 bIsNumber = TRUE; 411 bIsNumber = TRUE;
405 if (!PositionIsInBounds()) 412 if (!PositionIsInBounds())
406 return; 413 return;
407 414
408 int ch = m_pBuf[m_Pos++]; 415 int ch = m_pBuf[m_Pos++];
409 while (1) { 416 while (1) {
(...skipping 22 matching lines...) Expand all
432 if (ch == '/') { 439 if (ch == '/') {
433 while (1) { 440 while (1) {
434 if (!PositionIsInBounds()) 441 if (!PositionIsInBounds())
435 return; 442 return;
436 ch = m_pBuf[m_Pos++]; 443 ch = m_pBuf[m_Pos++];
437 if (!PDFCharIsOther(ch) && !PDFCharIsNumeric(ch)) { 444 if (!PDFCharIsOther(ch) && !PDFCharIsNumeric(ch)) {
438 m_Pos--; 445 m_Pos--;
439 return; 446 return;
440 } 447 }
441 448
442 if (m_WordSize < MAX_WORD_BUFFER) 449 if (m_WordSize < kMaxWordBuffer)
443 m_WordBuffer[m_WordSize++] = ch; 450 m_WordBuffer[m_WordSize++] = ch;
444 } 451 }
445 } else if (ch == '<') { 452 } else if (ch == '<') {
446 if (!PositionIsInBounds()) 453 if (!PositionIsInBounds())
447 return; 454 return;
448 ch = m_pBuf[m_Pos++]; 455 ch = m_pBuf[m_Pos++];
449 if (ch == '<') 456 if (ch == '<')
450 m_WordBuffer[m_WordSize++] = ch; 457 m_WordBuffer[m_WordSize++] = ch;
451 else 458 else
452 m_Pos--; 459 m_Pos--;
453 } else if (ch == '>') { 460 } else if (ch == '>') {
454 if (!PositionIsInBounds()) 461 if (!PositionIsInBounds())
455 return; 462 return;
456 ch = m_pBuf[m_Pos++]; 463 ch = m_pBuf[m_Pos++];
457 if (ch == '>') 464 if (ch == '>')
458 m_WordBuffer[m_WordSize++] = ch; 465 m_WordBuffer[m_WordSize++] = ch;
459 else 466 else
460 m_Pos--; 467 m_Pos--;
461 } 468 }
462 return; 469 return;
463 } 470 }
464 471
465 while (1) { 472 while (1) {
466 if (m_WordSize < MAX_WORD_BUFFER) 473 if (m_WordSize < kMaxWordBuffer)
467 m_WordBuffer[m_WordSize++] = ch; 474 m_WordBuffer[m_WordSize++] = ch;
468 if (!PDFCharIsNumeric(ch)) 475 if (!PDFCharIsNumeric(ch))
469 bIsNumber = FALSE; 476 bIsNumber = FALSE;
470 477
471 if (!PositionIsInBounds()) 478 if (!PositionIsInBounds())
472 return; 479 return;
473 ch = m_pBuf[m_Pos++]; 480 ch = m_pBuf[m_Pos++];
474 if (PDFCharIsDelimiter(ch) || PDFCharIsWhitespace(ch)) { 481 if (PDFCharIsDelimiter(ch) || PDFCharIsWhitespace(ch)) {
475 m_Pos--; 482 m_Pos--;
476 break; 483 break;
477 } 484 }
478 } 485 }
479 } 486 }
480 487
481 CFX_ByteString CPDF_StreamParser::ReadString() { 488 CFX_ByteString CPDF_StreamParser::ReadString() {
482 if (!PositionIsInBounds()) 489 if (!PositionIsInBounds())
483 return CFX_ByteString(); 490 return CFX_ByteString();
484 491
485 uint8_t ch = m_pBuf[m_Pos++]; 492 uint8_t ch = m_pBuf[m_Pos++];
486 CFX_ByteTextBuf buf; 493 CFX_ByteTextBuf buf;
487 int parlevel = 0; 494 int parlevel = 0;
488 int status = 0; 495 int status = 0;
489 int iEscCode = 0; 496 int iEscCode = 0;
490 while (1) { 497 while (1) {
491 switch (status) { 498 switch (status) {
492 case 0: 499 case 0:
493 if (ch == ')') { 500 if (ch == ')') {
494 if (parlevel == 0) { 501 if (parlevel == 0) {
495 if (buf.GetLength() > MAX_STRING_LENGTH) { 502 if (buf.GetLength() > kMaxStringLength) {
496 return CFX_ByteString(buf.GetBuffer(), MAX_STRING_LENGTH); 503 return CFX_ByteString(buf.GetBuffer(), kMaxStringLength);
497 } 504 }
498 return buf.AsStringC(); 505 return buf.AsStringC();
499 } 506 }
500 parlevel--; 507 parlevel--;
501 buf.AppendChar(')'); 508 buf.AppendChar(')');
502 } else if (ch == '(') { 509 } else if (ch == '(') {
503 parlevel++; 510 parlevel++;
504 buf.AppendChar('('); 511 buf.AppendChar('(');
505 } else if (ch == '\\') { 512 } else if (ch == '\\') {
506 status = 1; 513 status = 1;
(...skipping 57 matching lines...) Expand 10 before | Expand all | Expand 10 after
564 break; 571 break;
565 } 572 }
566 if (!PositionIsInBounds()) 573 if (!PositionIsInBounds())
567 break; 574 break;
568 575
569 ch = m_pBuf[m_Pos++]; 576 ch = m_pBuf[m_Pos++];
570 } 577 }
571 if (PositionIsInBounds()) 578 if (PositionIsInBounds())
572 ++m_Pos; 579 ++m_Pos;
573 580
574 if (buf.GetLength() > MAX_STRING_LENGTH) { 581 if (buf.GetLength() > kMaxStringLength) {
575 return CFX_ByteString(buf.GetBuffer(), MAX_STRING_LENGTH); 582 return CFX_ByteString(buf.GetBuffer(), kMaxStringLength);
576 } 583 }
577 return buf.AsStringC(); 584 return buf.AsStringC();
578 } 585 }
579 586
580 CFX_ByteString CPDF_StreamParser::ReadHexString() { 587 CFX_ByteString CPDF_StreamParser::ReadHexString() {
581 if (!PositionIsInBounds()) 588 if (!PositionIsInBounds())
582 return CFX_ByteString(); 589 return CFX_ByteString();
583 590
584 CFX_ByteTextBuf buf; 591 CFX_ByteTextBuf buf;
585 bool bFirst = true; 592 bool bFirst = true;
(...skipping 12 matching lines...) Expand all
598 code = val * 16; 605 code = val * 16;
599 } else { 606 } else {
600 code += val; 607 code += val;
601 buf.AppendByte((uint8_t)code); 608 buf.AppendByte((uint8_t)code);
602 } 609 }
603 bFirst = !bFirst; 610 bFirst = !bFirst;
604 } 611 }
605 if (!bFirst) 612 if (!bFirst)
606 buf.AppendChar((char)code); 613 buf.AppendChar((char)code);
607 614
608 if (buf.GetLength() > MAX_STRING_LENGTH) 615 if (buf.GetLength() > kMaxStringLength)
609 return CFX_ByteString(buf.GetBuffer(), MAX_STRING_LENGTH); 616 return CFX_ByteString(buf.GetBuffer(), kMaxStringLength);
610 617
611 return buf.AsStringC(); 618 return buf.AsStringC();
612 } 619 }
613 620
614 bool CPDF_StreamParser::PositionIsInBounds() const { 621 bool CPDF_StreamParser::PositionIsInBounds() const {
615 return m_Pos < m_Size; 622 return m_Pos < m_Size;
616 } 623 }
617 624
618 CPDF_ContentParser::CPDF_ContentParser() 625 CPDF_ContentParser::CPDF_ContentParser()
619 : m_Status(Ready), 626 : m_Status(Ready),
(...skipping 193 matching lines...) Expand 10 before | Expand all | Expand 10 after
813 } 820 }
814 m_Status = Done; 821 m_Status = Done;
815 return; 822 return;
816 } 823 }
817 steps++; 824 steps++;
818 if (pPause && pPause->NeedToPauseNow()) { 825 if (pPause && pPause->NeedToPauseNow()) {
819 break; 826 break;
820 } 827 }
821 } 828 }
822 } 829 }
OLDNEW
« no previous file with comments | « core/fpdfapi/fpdf_page/fpdf_page_parser.cpp ('k') | core/fpdfapi/fpdf_page/pageint.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698