Revert "Revert "Fix the issue that pdfium swallows 'fi' or 'ff' in some pdf files""

This reverts commit fa9756f77ad6145940d3dc697814b84f5755ae17.

TBR=thestig@chromium.org
Review URL: https://codereview.chromium.org/1307353005/
diff --git a/core/include/fpdfapi/fpdf_parser.h b/core/include/fpdfapi/fpdf_parser.h
index 03ae4cf..6194247 100644
--- a/core/include/fpdfapi/fpdf_parser.h
+++ b/core/include/fpdfapi/fpdf_parser.h
@@ -294,7 +294,8 @@
   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();
 
diff --git a/core/src/fpdfapi/fpdf_page/fpdf_page_parser.cpp b/core/src/fpdfapi/fpdf_page/fpdf_page_parser.cpp
index 059dd4c..4e5ef1c 100644
--- a/core/src/fpdfapi/fpdf_page/fpdf_page_parser.cpp
+++ b/core/src/fpdfapi/fpdf_page/fpdf_page_parser.cpp
@@ -11,7 +11,6 @@
 
 #define REQUIRE_PARAMS(count)  \
   if (m_ParamCount != count) { \
-    m_bAbort = TRUE;           \
     return;                    \
   }
 
@@ -34,7 +33,6 @@
       m_Level(level),
       m_ParamStartPos(0),
       m_ParamCount(0),
-      m_bAbort(FALSE),
       m_pCurStates(new CPDF_AllStates),
       m_pLastTextObject(nullptr),
       m_DefFontSize(0),
diff --git a/core/src/fpdfapi/fpdf_page/fpdf_page_parser_old.cpp b/core/src/fpdfapi/fpdf_page/fpdf_page_parser_old.cpp
index 48e9b98..c9bcff6 100644
--- a/core/src/fpdfapi/fpdf_page/fpdf_page_parser_old.cpp
+++ b/core/src/fpdfapi/fpdf_page/fpdf_page_parser_old.cpp
@@ -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 @@
       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 @@
         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) {
diff --git a/core/src/fpdfapi/fpdf_page/pageint.h b/core/src/fpdfapi/fpdf_page/pageint.h
index 6bec072..c85523b 100644
--- a/core/src/fpdfapi/fpdf_page/pageint.h
+++ b/core/src/fpdfapi/fpdf_page/pageint.h
@@ -162,7 +162,6 @@
                            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 @@
   _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;
diff --git a/core/src/fpdfapi/fpdf_parser/fpdf_parser_parser.cpp b/core/src/fpdfapi/fpdf_parser/fpdf_parser_parser.cpp
index 7482f0b..cd923f3 100644
--- a/core/src/fpdfapi/fpdf_parser/fpdf_parser_parser.cpp
+++ b/core/src/fpdfapi/fpdf_parser/fpdf_parser_parser.cpp
@@ -2455,8 +2455,8 @@
     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 @@
       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 @@
           // 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 @@
           // 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 @@
         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 @@
     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 @@
 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 @@
   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_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 @@
         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
index 0000000..61ac6f4
--- /dev/null
+++ b/testing/resources/pixel/bug_524043_1.in
@@ -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
index 0000000..a044bb0
--- /dev/null
+++ b/testing/resources/pixel/bug_524043_1_expected.pdf.0.png
Binary files differ
diff --git a/testing/resources/pixel/bug_524043_2.in b/testing/resources/pixel/bug_524043_2.in
new file mode 100644
index 0000000..0ee43da
--- /dev/null
+++ b/testing/resources/pixel/bug_524043_2.in
@@ -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
index 0000000..19de52a
--- /dev/null
+++ b/testing/resources/pixel/bug_524043_2_expected.pdf.0.png
Binary files differ
diff --git a/testing/resources/pixel/bug_524043_3.in b/testing/resources/pixel/bug_524043_3.in
new file mode 100644
index 0000000..716345e
--- /dev/null
+++ b/testing/resources/pixel/bug_524043_3.in
@@ -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
index 0000000..a044bb0
--- /dev/null
+++ b/testing/resources/pixel/bug_524043_3_expected.pdf.0.png
Binary files differ
diff --git a/testing/resources/pixel/bug_524043_4.in b/testing/resources/pixel/bug_524043_4.in
new file mode 100644
index 0000000..6cdb3d1
--- /dev/null
+++ b/testing/resources/pixel/bug_524043_4.in
@@ -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
index 0000000..a044bb0
--- /dev/null
+++ b/testing/resources/pixel/bug_524043_4_expected.pdf.0.png
Binary files differ
diff --git a/testing/resources/pixel/bug_524043_5.in b/testing/resources/pixel/bug_524043_5.in
new file mode 100644
index 0000000..7996746
--- /dev/null
+++ b/testing/resources/pixel/bug_524043_5.in
@@ -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
index 0000000..a044bb0
--- /dev/null
+++ b/testing/resources/pixel/bug_524043_5_expected.pdf.0.png
Binary files differ
diff --git a/testing/resources/pixel/bug_524043_6.in b/testing/resources/pixel/bug_524043_6.in
new file mode 100644
index 0000000..318b207
--- /dev/null
+++ b/testing/resources/pixel/bug_524043_6.in
@@ -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
index 0000000..3edcc2d
--- /dev/null
+++ b/testing/resources/pixel/bug_524043_6_expected.pdf.0.png
Binary files differ
diff --git a/testing/resources/pixel/bug_524043_7.in b/testing/resources/pixel/bug_524043_7.in
new file mode 100644
index 0000000..c95f2d9
--- /dev/null
+++ b/testing/resources/pixel/bug_524043_7.in
@@ -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
index 0000000..19de52a
--- /dev/null
+++ b/testing/resources/pixel/bug_524043_7_expected.pdf.0.png
Binary files differ