Fix the issue that pdfium swallows 'fi' or 'ff' in some pdf files
authorJun Fang <jun_fang@foxitsoftware.com>
Sat, 26 Sep 2015 03:32:46 +0000 (20:32 -0700)
committerJun Fang <jun_fang@foxitsoftware.com>
Sat, 26 Sep 2015 03:32:46 +0000 (20:32 -0700)
Pdfium swallows 'fi' or 'ff' in some tested files because it doesn't load the embedded font file correctly. The root cause is that there is incorrect keyword like 'ngendstream' in the stream of the embedded font file. Pdfium tries to find another correct keyword but uses wrong offset rather than accumulated offset.

BUG=524043
R=thestig@chromium.org, tsepez@chromium.org

Review URL: https://codereview.chromium.org/1307353005 .

19 files changed:
core/include/fpdfapi/fpdf_parser.h
core/src/fpdfapi/fpdf_page/fpdf_page_parser.cpp
core/src/fpdfapi/fpdf_page/fpdf_page_parser_old.cpp
core/src/fpdfapi/fpdf_page/pageint.h
core/src/fpdfapi/fpdf_parser/fpdf_parser_parser.cpp
testing/resources/pixel/bug_524043_1.in [new file with mode: 0644]
testing/resources/pixel/bug_524043_1_expected.pdf.0.png [new file with mode: 0644]
testing/resources/pixel/bug_524043_2.in [new file with mode: 0644]
testing/resources/pixel/bug_524043_2_expected.pdf.0.png [new file with mode: 0644]
testing/resources/pixel/bug_524043_3.in [new file with mode: 0644]
testing/resources/pixel/bug_524043_3_expected.pdf.0.png [new file with mode: 0644]
testing/resources/pixel/bug_524043_4.in [new file with mode: 0644]
testing/resources/pixel/bug_524043_4_expected.pdf.0.png [new file with mode: 0644]
testing/resources/pixel/bug_524043_5.in [new file with mode: 0644]
testing/resources/pixel/bug_524043_5_expected.pdf.0.png [new file with mode: 0644]
testing/resources/pixel/bug_524043_6.in [new file with mode: 0644]
testing/resources/pixel/bug_524043_6_expected.pdf.0.png [new file with mode: 0644]
testing/resources/pixel/bug_524043_7.in [new file with mode: 0644]
testing/resources/pixel/bug_524043_7_expected.pdf.0.png [new file with mode: 0644]

index 03ae4cf..6194247 100644 (file)
@@ -294,7 +294,8 @@ class CPDF_SyntaxParser {
   FX_BOOL IsWholeWord(FX_FILESIZE startpos,
                       FX_FILESIZE limit,
                       const uint8_t* tag,
-                      FX_DWORD taglen);
+                      FX_DWORD taglen,
+                      FX_BOOL checkKeyword);
 
   CFX_ByteString ReadString();
 
index 059dd4c..4e5ef1c 100644 (file)
@@ -11,7 +11,6 @@
 
 #define REQUIRE_PARAMS(count)  \
   if (m_ParamCount != count) { \
-    m_bAbort = TRUE;           \
     return;                    \
   }
 
@@ -34,7 +33,6 @@ CPDF_StreamContentParser::CPDF_StreamContentParser(
       m_Level(level),
       m_ParamStartPos(0),
       m_ParamCount(0),
-      m_bAbort(FALSE),
       m_pCurStates(new CPDF_AllStates),
       m_pLastTextObject(nullptr),
       m_DefFontSize(0),
index 48e9b98..c9bcff6 100644 (file)
@@ -9,27 +9,7 @@
 #include "../../../include/fxcodec/fx_codec.h"
 #include "pageint.h"
 #include <limits.h>
-const FX_CHAR* const _PDF_OpCharType =
-    "IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII"
-    "IIVIIIIVIIVIIIIIVVIIIIIIIIIIIIII"
-    "IIVVVVVVIVVVVVVIVVVVVIIVVIIIIIII"
-    "IIVVVVVVVVVVVVVVIVVVIIVVIVVIIIII"
-    "IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII"
-    "IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII"
-    "IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII"
-    "IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII";
-FX_BOOL _PDF_HasInvalidOpChar(const FX_CHAR* op) {
-  if (!op) {
-    return FALSE;
-  }
-  uint8_t ch;
-  while ((ch = *op++)) {
-    if (_PDF_OpCharType[ch] == 'I') {
-      return TRUE;
-    }
-  }
-  return FALSE;
-}
+
 class CPDF_StreamParserAutoClearer {
  public:
   CPDF_StreamParserAutoClearer(CPDF_StreamParser** scoped_variable,
@@ -61,13 +41,7 @@ FX_DWORD CPDF_StreamContentParser::Parse(const uint8_t* pData,
       case CPDF_StreamParser::EndOfData:
         return m_pSyntax->GetPos();
       case CPDF_StreamParser::Keyword:
-        if (!OnOperator((char*)syntax.GetWordBuf()) &&
-            _PDF_HasInvalidOpChar((char*)syntax.GetWordBuf())) {
-          m_bAbort = TRUE;
-        }
-        if (m_bAbort) {
-          return m_pSyntax->GetPos();
-        }
+        OnOperator((char*)syntax.GetWordBuf());
         ClearAllParams();
         break;
       case CPDF_StreamParser::Number:
@@ -1126,10 +1100,6 @@ void CPDF_ContentParser::Continue(IFX_Pause* pPause) {
         m_CurrentOffset +=
             m_pParser->Parse(m_pData + m_CurrentOffset,
                              m_Size - m_CurrentOffset, PARSE_STEP_LIMIT);
-        if (m_pParser->ShouldAbort()) {
-          m_InternalStage = PAGEPARSE_STAGE_CHECKCLIP;
-          continue;
-        }
       }
     }
     if (m_InternalStage == PAGEPARSE_STAGE_CHECKCLIP) {
index 6bec072..c85523b 100644 (file)
@@ -162,7 +162,6 @@ class CPDF_StreamContentParser {
                            int level);
   ~CPDF_StreamContentParser();
 
-  FX_BOOL ShouldAbort() const { return m_bAbort; }
   CPDF_PageObjects* GetObjectList() const { return m_pObjectList; }
   CPDF_AllStates* GetCurStates() const { return m_pCurStates.get(); }
   FX_BOOL IsColored() const { return m_bColored; }
@@ -305,7 +304,6 @@ class CPDF_StreamContentParser {
   _ContentParam m_ParamBuf1[PARAM_BUF_SIZE];
   FX_DWORD m_ParamStartPos;
   FX_DWORD m_ParamCount;
-  FX_BOOL m_bAbort;
   CPDF_StreamParser* m_pSyntax;
   nonstd::unique_ptr<CPDF_AllStates> m_pCurStates;
   CPDF_ContentMark m_CurContentMark;
index 7482f0b..cd923f3 100644 (file)
@@ -2455,8 +2455,8 @@ CPDF_Stream* CPDF_SyntaxParser::ReadStream(CPDF_Dictionary* pDict,
     len = pLenObj->GetInteger();
   }
   // Check whether end of line markers follow the keyword 'stream'.
-  unsigned int numMarkers = ReadEOLMarkers(m_Pos);
-  m_Pos += numMarkers;
+  // The stream starts after end of line markers.
+  m_Pos += ReadEOLMarkers(m_Pos);
   FX_FILESIZE streamStartPos = m_Pos;
   if (pContext) {
     pContext->m_DataStart = streamStartPos;
@@ -2467,19 +2467,18 @@ CPDF_Stream* CPDF_SyntaxParser::ReadStream(CPDF_Dictionary* pDict,
       objnum == (FX_DWORD)m_MetadataObjnum ? nullptr : m_pCryptoHandler;
   if (!pCryptoHandler) {
     FX_BOOL bSearchForKeyword = TRUE;
-    unsigned int prevMarkers = 0;
-    unsigned int nextMarkers = 0;
     if (len >= 0) {
       pdfium::base::CheckedNumeric<FX_FILESIZE> pos = m_Pos;
       pos += len;
       if (pos.IsValid() && pos.ValueOrDie() < m_FileLen) {
         m_Pos = pos.ValueOrDie();
       }
-      prevMarkers = ReadEOLMarkers(m_Pos);
+      m_Pos += ReadEOLMarkers(m_Pos);
+      FXSYS_memset(m_WordBuffer, 0, ENDSTREAM_LEN + 1);
       GetNextWord();
-      nextMarkers = ReadEOLMarkers(m_Pos);
-      if (m_WordSize == ENDSTREAM_LEN && prevMarkers != 0 && nextMarkers != 0 &&
-          FXSYS_memcmp(m_WordBuffer, "endstream", ENDSTREAM_LEN) == 0) {
+      if (FXSYS_memcmp(m_WordBuffer, "endstream", ENDSTREAM_LEN) == 0 &&
+          IsWholeWord(m_Pos - ENDSTREAM_LEN, m_FileLen,
+                      FX_BSTRC("endstream").GetPtr(), ENDSTREAM_LEN, TRUE)) {
         bSearchForKeyword = FALSE;
       }
     }
@@ -2494,22 +2493,12 @@ CPDF_Stream* CPDF_SyntaxParser::ReadStream(CPDF_Dictionary* pDict,
           // Can't find any "endstream".
           break;
         }
-        prevMarkers = ReadEOLMarkers(streamStartPos + endStreamOffset - 1);
-        nextMarkers =
-            ReadEOLMarkers(streamStartPos + endStreamOffset + ENDSTREAM_LEN);
-        if (prevMarkers != 0 && nextMarkers != 0) {
+        if (IsWholeWord(m_Pos - ENDSTREAM_LEN, m_FileLen,
+                        FX_BSTRC("endstream").GetPtr(), ENDSTREAM_LEN, TRUE)) {
           // Stop searching when the keyword "endstream" is found.
+          endStreamOffset = m_Pos - streamStartPos - ENDSTREAM_LEN;
           break;
-        } else {
-          unsigned char ch = 0x00;
-          GetCharAt(streamStartPos + endStreamOffset + ENDSTREAM_LEN, ch);
-          if (ch == 0x09 || ch == 0x20) {
-            //"endstream" is treated as a keyword
-            // when it is followed by a tab or whitespace
-            break;
-          }
         }
-        m_Pos += ENDSTREAM_LEN;
       }
       m_Pos = streamStartPos;
       FX_FILESIZE endObjOffset = 0;
@@ -2519,14 +2508,12 @@ CPDF_Stream* CPDF_SyntaxParser::ReadStream(CPDF_Dictionary* pDict,
           // Can't find any "endobj".
           break;
         }
-        prevMarkers = ReadEOLMarkers(streamStartPos + endObjOffset - 1);
-        nextMarkers =
-            ReadEOLMarkers(streamStartPos + endObjOffset + ENDOBJ_LEN);
-        if (prevMarkers != 0 && nextMarkers != 0) {
+        if (IsWholeWord(m_Pos - ENDOBJ_LEN, m_FileLen,
+                        FX_BSTRC("endobj").GetPtr(), ENDOBJ_LEN, TRUE)) {
           // Stop searching when the keyword "endobj" is found.
+          endObjOffset = m_Pos - streamStartPos - ENDOBJ_LEN;
           break;
         }
-        m_Pos += ENDOBJ_LEN;
       }
       if (endStreamOffset < 0 && endObjOffset < 0) {
         // Can't find "endstream" or "endobj".
@@ -2542,7 +2529,7 @@ CPDF_Stream* CPDF_SyntaxParser::ReadStream(CPDF_Dictionary* pDict,
         endStreamOffset = endObjOffset;
       }
       len = endStreamOffset;
-      numMarkers = ReadEOLMarkers(streamStartPos + endStreamOffset - 2);
+      int numMarkers = ReadEOLMarkers(streamStartPos + endStreamOffset - 2);
       if (numMarkers == 2) {
         len -= 2;
       } else {
@@ -2579,8 +2566,9 @@ CPDF_Stream* CPDF_SyntaxParser::ReadStream(CPDF_Dictionary* pDict,
     pContext->m_DataEnd = pContext->m_DataStart + len;
   }
   streamStartPos = m_Pos;
+  FXSYS_memset(m_WordBuffer, 0, ENDOBJ_LEN + 1);
   GetNextWord();
-  numMarkers = ReadEOLMarkers(m_Pos);
+  int numMarkers = ReadEOLMarkers(m_Pos);
   if (m_WordSize == ENDOBJ_LEN && numMarkers != 0 &&
       FXSYS_memcmp(m_WordBuffer, "endobj", ENDOBJ_LEN) == 0) {
     m_Pos = streamStartPos;
@@ -2611,7 +2599,8 @@ int32_t CPDF_SyntaxParser::GetDirectNum() {
 FX_BOOL CPDF_SyntaxParser::IsWholeWord(FX_FILESIZE startpos,
                                        FX_FILESIZE limit,
                                        const uint8_t* tag,
-                                       FX_DWORD taglen) {
+                                       FX_DWORD taglen,
+                                       FX_BOOL checkKeyword) {
   uint8_t type = PDF_CharType[tag[0]];
   FX_BOOL bCheckLeft = type != 'D' && type != 'W';
   type = PDF_CharType[tag[taglen - 1]];
@@ -2620,13 +2609,13 @@ FX_BOOL CPDF_SyntaxParser::IsWholeWord(FX_FILESIZE startpos,
   if (bCheckRight && startpos + (int32_t)taglen <= limit &&
       GetCharAt(startpos + (int32_t)taglen, ch)) {
     uint8_t type = PDF_CharType[ch];
-    if (type == 'N' || type == 'R') {
+    if (type == 'N' || type == 'R' || (checkKeyword && type == 'D')) {
       return FALSE;
     }
   }
   if (bCheckLeft && startpos > 0 && GetCharAt(startpos - 1, ch)) {
     uint8_t type = PDF_CharType[ch];
-    if (type == 'N' || type == 'R') {
+    if (type == 'N' || type == 'R' || (checkKeyword && type == 'D')) {
       return FALSE;
     }
   }
@@ -2682,7 +2671,8 @@ FX_BOOL CPDF_SyntaxParser::SearchWord(const CFX_ByteStringC& tag,
         }
       }
       FX_FILESIZE startpos = bForward ? pos - taglen + 1 : pos;
-      if (!bWholeWord || IsWholeWord(startpos, limit, tag.GetPtr(), taglen)) {
+      if (!bWholeWord ||
+          IsWholeWord(startpos, limit, tag.GetPtr(), taglen, FALSE)) {
         m_Pos = startpos;
         return TRUE;
       }
@@ -2739,7 +2729,7 @@ int32_t CPDF_SyntaxParser::SearchMultiWord(const CFX_ByteStringC& tags,
         if (pPatterns[i].m_Offset == pPatterns[i].m_Len) {
           if (!bWholeWord ||
               IsWholeWord(pos - pPatterns[i].m_Len, limit, pPatterns[i].m_pTag,
-                          pPatterns[i].m_Len)) {
+                          pPatterns[i].m_Len, FALSE)) {
             found = i;
             goto end;
           } else {
diff --git a/testing/resources/pixel/bug_524043_1.in b/testing/resources/pixel/bug_524043_1.in
new file mode 100644 (file)
index 0000000..61ac6f4
--- /dev/null
@@ -0,0 +1,61 @@
+{{header}}
+{{object 1 0}} <<
+  /Type /Catalog
+  /Pages 2 0 R
+>>
+{{object 2 0}} <<
+  /Type /Pages
+  /MediaBox [ 0 0 200 200 ]
+  /Count 1
+  /Kids [ 3 0 R ]
+>>
+endobj
+{{object 3 0}} <<
+  /Type /Page
+  /Parent 2 0 R
+  /Resources <<
+    /Font <<
+      /F1 4 0 R
+      /F2 5 0 R
+    >>
+  >>
+  /Contents 6 0 R
+>>
+endobj
+{{object 4 0}} <<
+  /Type /Font
+  /Subtype /Type1
+  /BaseFont /Times-Roman
+>>
+endobj
+{{object 5 0}} <<
+  /Type /Font
+  /Subtype /Type1
+  /BaseFont /Helvetica
+>>
+endobj
+% Case 1:
+%   /Length identifies intended end of stream, despite embedded keywords.
+%   Both should render as text.
+{{object 6 0}} <<
+  /Length 107
+>>
+stream
+BT
+20 50 Td
+/F1 12 Tf
+(endobj is text) Tj
+endstream
+0 50 Td
+/F2 13 Tf
+(endstream is text per /Length) Tj
+ET
+endstream
+endobj
+{{xref}}
+trailer <<
+  /Size 6
+  /Root 1 0 R
+>>
+{{startxref}}
+%%EOF
diff --git a/testing/resources/pixel/bug_524043_1_expected.pdf.0.png b/testing/resources/pixel/bug_524043_1_expected.pdf.0.png
new file mode 100644 (file)
index 0000000..a044bb0
Binary files /dev/null and b/testing/resources/pixel/bug_524043_1_expected.pdf.0.png differ
diff --git a/testing/resources/pixel/bug_524043_2.in b/testing/resources/pixel/bug_524043_2.in
new file mode 100644 (file)
index 0000000..0ee43da
--- /dev/null
@@ -0,0 +1,62 @@
+{{header}}
+{{object 1 0}} <<
+  /Type /Catalog
+  /Pages 2 0 R
+>>
+{{object 2 0}} <<
+  /Type /Pages
+  /MediaBox [ 0 0 200 200 ]
+  /Count 1
+  /Kids [ 3 0 R ]
+>>
+endobj
+{{object 3 0}} <<
+  /Type /Page
+  /Parent 2 0 R
+  /Resources <<
+    /Font <<
+      /F1 4 0 R
+      /F2 5 0 R
+    >>
+  >>
+  /Contents 6 0 R
+>>
+endobj
+{{object 4 0}} <<
+  /Type /Font
+  /Subtype /Type1
+  /BaseFont /Times-Roman
+>>
+endobj
+{{object 5 0}} <<
+  /Type /Font
+  /Subtype /Type1
+  /BaseFont /Helvetica
+>>
+endobj
+% Case 2:
+%   /Length incorrectly identifies middle of stream.
+%   The stream is blocked by the keyword "endstream"
+%   Only the text before the keyword can be rendered.
+{{object 6 0}} <<
+  /Length 87
+>>
+stream
+BT
+20 50 Td
+/F1 12 Tf
+(endobj is text) Tj
+endstream
+0 50 Td
+/F2 13 Tf
+(It's wrong when you see the text!) Tj
+ET
+endstream
+endobj
+{{xref}}
+trailer <<
+  /Size 6
+  /Root 1 0 R
+>>
+{{startxref}}
+%%EOF
diff --git a/testing/resources/pixel/bug_524043_2_expected.pdf.0.png b/testing/resources/pixel/bug_524043_2_expected.pdf.0.png
new file mode 100644 (file)
index 0000000..19de52a
Binary files /dev/null and b/testing/resources/pixel/bug_524043_2_expected.pdf.0.png differ
diff --git a/testing/resources/pixel/bug_524043_3.in b/testing/resources/pixel/bug_524043_3.in
new file mode 100644 (file)
index 0000000..716345e
--- /dev/null
@@ -0,0 +1,62 @@
+{{header}}
+{{object 1 0}} <<
+  /Type /Catalog
+  /Pages 2 0 R
+>>
+{{object 2 0}} <<
+  /Type /Pages
+  /MediaBox [ 0 0 200 200 ]
+  /Count 1
+  /Kids [ 3 0 R ]
+>>
+endobj
+{{object 3 0}} <<
+  /Type /Page
+  /Parent 2 0 R
+  /Resources <<
+    /Font <<
+      /F1 4 0 R
+      /F2 5 0 R
+    >>
+  >>
+  /Contents 6 0 R
+>>
+endobj
+{{object 4 0}} <<
+  /Type /Font
+  /Subtype /Type1
+  /BaseFont /Times-Roman
+>>
+endobj
+{{object 5 0}} <<
+  /Type /Font
+  /Subtype /Type1
+  /BaseFont /Helvetica
+>>
+endobj
+% Case 3:
+%   /Length incorrectly identifies middle of stream.
+%   "eendstream" shouldn't block the stream.
+%   Both should render as text.
+{{object 6 0}} <<
+  /Length 87
+>>
+stream
+BT
+20 50 Td
+/F1 12 Tf
+(endobj is text) Tj
+eendstream
+0 50 Td
+/F2 13 Tf
+(endstream is text per /Length) Tj
+ET
+endstream
+endobj
+{{xref}}
+trailer <<
+  /Size 6
+  /Root 1 0 R
+>>
+{{startxref}}
+%%EOF
diff --git a/testing/resources/pixel/bug_524043_3_expected.pdf.0.png b/testing/resources/pixel/bug_524043_3_expected.pdf.0.png
new file mode 100644 (file)
index 0000000..a044bb0
Binary files /dev/null and b/testing/resources/pixel/bug_524043_3_expected.pdf.0.png differ
diff --git a/testing/resources/pixel/bug_524043_4.in b/testing/resources/pixel/bug_524043_4.in
new file mode 100644 (file)
index 0000000..6cdb3d1
--- /dev/null
@@ -0,0 +1,61 @@
+{{header}}
+{{object 1 0}} <<
+  /Type /Catalog
+  /Pages 2 0 R
+>>
+{{object 2 0}} <<
+  /Type /Pages
+  /MediaBox [ 0 0 200 200 ]
+  /Count 1
+  /Kids [ 3 0 R ]
+>>
+endobj
+{{object 3 0}} <<
+  /Type /Page
+  /Parent 2 0 R
+  /Resources <<
+    /Font <<
+      /F1 4 0 R
+      /F2 5 0 R
+    >>
+  >>
+  /Contents 6 0 R
+>>
+endobj
+{{object 4 0}} <<
+  /Type /Font
+  /Subtype /Type1
+  /BaseFont /Times-Roman
+>>
+endobj
+{{object 5 0}} <<
+  /Type /Font
+  /Subtype /Type1
+  /BaseFont /Helvetica
+>>
+endobj
+% Case 4:
+%   /Length incorrectly identifies middle of stream.
+%   "endstream." shouldn't block the stream. 
+%   Both should render as text even "endstream" is missing.
+{{object 6 0}} <<
+  /Length 87
+>>
+stream
+BT
+20 50 Td
+/F1 12 Tf
+(endobj is text) Tj
+endstream.
+0 50 Td
+/F2 13 Tf
+(endstream is text per /Length) Tj
+ET
+endobj
+{{xref}}
+trailer <<
+  /Size 6
+  /Root 1 0 R
+>>
+{{startxref}}
+%%EOF
diff --git a/testing/resources/pixel/bug_524043_4_expected.pdf.0.png b/testing/resources/pixel/bug_524043_4_expected.pdf.0.png
new file mode 100644 (file)
index 0000000..a044bb0
Binary files /dev/null and b/testing/resources/pixel/bug_524043_4_expected.pdf.0.png differ
diff --git a/testing/resources/pixel/bug_524043_5.in b/testing/resources/pixel/bug_524043_5.in
new file mode 100644 (file)
index 0000000..7996746
--- /dev/null
@@ -0,0 +1,61 @@
+{{header}}
+{{object 1 0}} <<
+  /Type /Catalog
+  /Pages 2 0 R
+>>
+{{object 2 0}} <<
+  /Type /Pages
+  /MediaBox [ 0 0 200 200 ]
+  /Count 1
+  /Kids [ 3 0 R ]
+>>
+endobj
+{{object 3 0}} <<
+  /Type /Page
+  /Parent 2 0 R
+  /Resources <<
+    /Font <<
+      /F1 4 0 R
+      /F2 5 0 R
+    >>
+  >>
+  /Contents 6 0 R
+>>
+endobj
+{{object 4 0}} <<
+  /Type /Font
+  /Subtype /Type1
+  /BaseFont /Times-Roman
+>>
+endobj
+{{object 5 0}} <<
+  /Type /Font
+  /Subtype /Type1
+  /BaseFont /Helvetica
+>>
+endobj
+% Case 5:
+%   /Length incorrectly identifies middle of stream.
+%   "endstream%" shouldn't block the stream. 
+%   Both should render as text even "endobj" is missing.
+{{object 6 0}} <<
+  /Length 87
+>>
+stream
+BT
+20 50 Td
+/F1 12 Tf
+(endobj is text) Tj
+endstream%
+0 50 Td
+/F2 13 Tf
+(endstream is text per /Length) Tj
+ET
+endstream
+{{xref}}
+trailer <<
+  /Size 6
+  /Root 1 0 R
+>>
+{{startxref}}
+%%EOF
diff --git a/testing/resources/pixel/bug_524043_5_expected.pdf.0.png b/testing/resources/pixel/bug_524043_5_expected.pdf.0.png
new file mode 100644 (file)
index 0000000..a044bb0
Binary files /dev/null and b/testing/resources/pixel/bug_524043_5_expected.pdf.0.png differ
diff --git a/testing/resources/pixel/bug_524043_6.in b/testing/resources/pixel/bug_524043_6.in
new file mode 100644 (file)
index 0000000..318b207
--- /dev/null
@@ -0,0 +1,60 @@
+{{header}}
+{{object 1 0}} <<
+  /Type /Catalog
+  /Pages 2 0 R
+>>
+{{object 2 0}} <<
+  /Type /Pages
+  /MediaBox [ 0 0 200 200 ]
+  /Count 1
+  /Kids [ 3 0 R ]
+>>
+endobj
+{{object 3 0}} <<
+  /Type /Page
+  /Parent 2 0 R
+  /Resources <<
+    /Font <<
+      /F1 4 0 R
+      /F2 5 0 R
+    >>
+  >>
+  /Contents 6 0 R
+>>
+endobj
+{{object 4 0}} <<
+  /Type /Font
+  /Subtype /Type1
+  /BaseFont /Times-Roman
+>>
+endobj
+{{object 5 0}} <<
+  /Type /Font
+  /Subtype /Type1
+  /BaseFont /Helvetica
+>>
+endobj
+% Case 6:
+%   /Length incorrectly identifies middle of stream.
+%   "endstream+" shouldn't block the stream. 
+%   Nothing will be rendered when both "endstream" and "endobj" are missing.
+{{object 6 0}} <<
+  /Length 87
+>>
+stream
+BT
+20 50 Td
+/F1 12 Tf
+(endobj is text) Tj
+endstream+
+0 50 Td
+/F2 13 Tf
+(endstream is text per /Length) Tj
+ET
+{{xref}}
+trailer <<
+  /Size 6
+  /Root 1 0 R
+>>
+{{startxref}}
+%%EOF
diff --git a/testing/resources/pixel/bug_524043_6_expected.pdf.0.png b/testing/resources/pixel/bug_524043_6_expected.pdf.0.png
new file mode 100644 (file)
index 0000000..3edcc2d
Binary files /dev/null and b/testing/resources/pixel/bug_524043_6_expected.pdf.0.png differ
diff --git a/testing/resources/pixel/bug_524043_7.in b/testing/resources/pixel/bug_524043_7.in
new file mode 100644 (file)
index 0000000..c95f2d9
--- /dev/null
@@ -0,0 +1,61 @@
+{{header}}
+{{object 1 0}} <<
+  /Type /Catalog
+  /Pages 2 0 R
+>>
+{{object 2 0}} <<
+  /Type /Pages
+  /MediaBox [ 0 0 200 200 ]
+  /Count 1
+  /Kids [ 3 0 R ]
+>>
+endobj
+{{object 3 0}} <<
+  /Type /Page
+  /Parent 2 0 R
+  /Resources <<
+    /Font <<
+      /F1 4 0 R
+      /F2 5 0 R
+    >>
+  >>
+  /Contents 6 0 R
+>>
+endobj
+{{object 4 0}} <<
+  /Type /Font
+  /Subtype /Type1
+  /BaseFont /Times-Roman
+>>
+endobj
+{{object 5 0}} <<
+  /Type /Font
+  /Subtype /Type1
+  /BaseFont /Helvetica
+>>
+endobj
+% Case 7:
+%   /Length incorrectly identifies middle of stream.
+%   "endstream" will block the stream. 
+%   The text before the keyword "endstream" can be rendered although
+%   both "endstream" and "endobj" are missing at the end of stream.
+{{object 6 0}} <<
+  /Length 87
+>>
+stream
+BT
+20 50 Td
+/F1 12 Tf
+(endobj is text) Tj
+endstream
+0 50 Td
+/F2 13 Tf
+(endstream is text per /Length) Tj
+ET
+{{xref}}
+trailer <<
+  /Size 6
+  /Root 1 0 R
+>>
+{{startxref}}
+%%EOF
diff --git a/testing/resources/pixel/bug_524043_7_expected.pdf.0.png b/testing/resources/pixel/bug_524043_7_expected.pdf.0.png
new file mode 100644 (file)
index 0000000..19de52a
Binary files /dev/null and b/testing/resources/pixel/bug_524043_7_expected.pdf.0.png differ