OLD | NEW |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 } |
OLD | NEW |