Fix a bug that occurs when an object has the same object number with the root object
[pdfium.git] / core / src / fpdfapi / fpdf_parser / fpdf_parser_parser.cpp
index 97e0d6f..9fa26d8 100644 (file)
@@ -28,10 +28,6 @@ FX_BOOL IsSignatureDict(const CPDF_Dictionary* pDict)
     }
     return FALSE;
 }
-static FX_INT32 _CompareDWord(const void* p1, const void* p2)
-{
-    return (*(FX_DWORD*)p1) - (*(FX_DWORD*)p2);
-}
 static int _CompareFileSize(const void* p1, const void* p2)
 {
     FX_FILESIZE ret = (*(FX_FILESIZE*)p1) - (*(FX_FILESIZE*)p2);
@@ -1007,7 +1003,15 @@ FX_BOOL CPDF_Parser::LoadCrossRefV5(FX_FILESIZE pos, FX_FILESIZE& prev, FX_BOOL
         return FALSE;
     }
     if (m_pDocument) {
-        m_pDocument->InsertIndirectObject(pStream->m_ObjNum, pStream);
+        CPDF_Dictionary * pDict = m_pDocument->GetRoot();
+        if (!pDict || pDict->GetObjNum() != pStream->m_ObjNum) {
+            m_pDocument->InsertIndirectObject(pStream->m_ObjNum, pStream);
+        } else {
+            if (pStream->GetType() == PDFOBJ_STREAM) {
+                pStream->Release();
+            }
+            return FALSE;
+        }
     }
     if (pStream->GetType() != PDFOBJ_STREAM) {
         return FALSE;
@@ -1027,26 +1031,21 @@ FX_BOOL CPDF_Parser::LoadCrossRefV5(FX_FILESIZE pos, FX_FILESIZE& prev, FX_BOOL
     } else {
         m_Trailers.Add((CPDF_Dictionary*)pStream->GetDict()->Clone());
     }
-    FX_DWORD nSegs = 0;
-    std::vector <std::pair <FX_INT32, FX_INT32>> arrIndex;
+    std::vector<std::pair<FX_INT32, FX_INT32> > arrIndex;
     CPDF_Array* pArray = pStream->GetDict()->GetArray(FX_BSTRC("Index"));
     if (pArray) {
         FX_DWORD nPairSize = pArray->GetCount() / 2;
-        CPDF_Object* pStartNumObj = NULL;
-        CPDF_Object* pCountObj = NULL;
         for (FX_DWORD i = 0; i < nPairSize; i++) {
-            pStartNumObj = pArray->GetElement(i * 2);
-            pCountObj = pArray->GetElement(i * 2 + 1);
+            CPDF_Object* pStartNumObj = pArray->GetElement(i * 2);
+            CPDF_Object* pCountObj = pArray->GetElement(i * 2 + 1);
             if (pStartNumObj && pStartNumObj->GetType() == PDFOBJ_NUMBER
                 && pCountObj && pCountObj->GetType() == PDFOBJ_NUMBER) {
                 arrIndex.push_back(std::make_pair(pStartNumObj->GetInteger(), pCountObj->GetInteger()));
             }
         }
-        nSegs = arrIndex.size();
-        if (nSegs == 0) {
-            arrIndex.push_back(std::make_pair(0, size));
-            nSegs = 1;
-        }
+    }
+    if (arrIndex.size() == 0) {
+        arrIndex.push_back(std::make_pair(0, size));
     }
     pArray = pStream->GetDict()->GetArray(FX_BSTRC("W"));
     if (pArray == NULL) {
@@ -1069,7 +1068,7 @@ FX_BOOL CPDF_Parser::LoadCrossRefV5(FX_FILESIZE pos, FX_FILESIZE& prev, FX_BOOL
     FX_LPCBYTE pData = acc.GetData();
     FX_DWORD dwTotalSize = acc.GetSize();
     FX_DWORD segindex = 0;
-    for (FX_DWORD i = 0; i < nSegs; i ++) {
+    for (FX_DWORD i = 0; i < arrIndex.size(); i ++) {
         FX_INT32 startnum = arrIndex[i].first;
         if (startnum < 0) {
             continue;
@@ -1317,8 +1316,8 @@ void CPDF_Parser::GetIndirectBinary(FX_DWORD objnum, FX_LPBYTE& pBuffer, FX_DWOR
             m_Syntax.RestorePos(SavedPos);
             return;
         }
-        FX_DWORD real_objnum = FXSYS_atoi(word);
-        if (real_objnum && real_objnum != objnum) {
+        FX_DWORD parser_objnum = FXSYS_atoi(word);
+        if (parser_objnum && parser_objnum != objnum) {
             m_Syntax.RestorePos(SavedPos);
             return;
         }
@@ -1382,8 +1381,8 @@ CPDF_Object* CPDF_Parser::ParseIndirectObjectAt(CPDF_IndirectObjects* pObjList,
     }
     FX_FILESIZE objOffset = m_Syntax.SavePos();
     objOffset -= word.GetLength();
-    FX_DWORD real_objnum = FXSYS_atoi(word);
-    if (objnum && real_objnum != objnum) {
+    FX_DWORD parser_objnum = FXSYS_atoi(word);
+    if (objnum && parser_objnum != objnum) {
         m_Syntax.RestorePos(SavedPos);
         return NULL;
     }
@@ -1392,21 +1391,23 @@ CPDF_Object* CPDF_Parser::ParseIndirectObjectAt(CPDF_IndirectObjects* pObjList,
         m_Syntax.RestorePos(SavedPos);
         return NULL;
     }
-    FX_DWORD gennum = FXSYS_atoi(word);
+    FX_DWORD parser_gennum = FXSYS_atoi(word);
     if (m_Syntax.GetKeyword() != FX_BSTRC("obj")) {
         m_Syntax.RestorePos(SavedPos);
         return NULL;
     }
-    CPDF_Object* pObj = m_Syntax.GetObject(pObjList, objnum, gennum, 0, pContext);
+    CPDF_Object* pObj = m_Syntax.GetObject(pObjList, objnum, parser_gennum, 0, pContext);
     FX_FILESIZE endOffset = m_Syntax.SavePos();
     CFX_ByteString bsWord = m_Syntax.GetKeyword();
     if (bsWord == FX_BSTRC("endobj")) {
         endOffset = m_Syntax.SavePos();
     }
     m_Syntax.RestorePos(SavedPos);
-    if (pObj && !objnum) {
-        pObj->m_ObjNum = real_objnum;
-        pObj->m_GenNum = gennum;
+    if (pObj) {
+        if (!objnum) {
+            pObj->m_ObjNum = parser_objnum;
+        }
+        pObj->m_GenNum = parser_gennum;
     }
     return pObj;
 }
@@ -1421,8 +1422,8 @@ CPDF_Object* CPDF_Parser::ParseIndirectObjectAtByStrict(CPDF_IndirectObjects* pO
         m_Syntax.RestorePos(SavedPos);
         return NULL;
     }
-    FX_DWORD real_objnum = FXSYS_atoi(word);
-    if (objnum && real_objnum != objnum) {
+    FX_DWORD parser_objnum = FXSYS_atoi(word);
+    if (objnum && parser_objnum != objnum) {
         m_Syntax.RestorePos(SavedPos);
         return NULL;
     }
@@ -1684,11 +1685,7 @@ CPDF_SyntaxParser::CPDF_SyntaxParser()
     m_pFileBuf = NULL;
     m_MetadataObjnum = 0;
     m_dwWordPos = 0;
-#if defined(_FPDFAPI_MINI_)
-    m_bFileStream = TRUE;
-#else
     m_bFileStream = FALSE;
-#endif
 }
 CPDF_SyntaxParser::~CPDF_SyntaxParser()
 {
@@ -2195,9 +2192,7 @@ CPDF_Object* CPDF_SyntaxParser::GetObject(CPDF_IndirectObjects* pObjList, FX_DWO
             if (pObj == NULL) {
                 continue;
             }
-            if (key.GetLength() == 1) {
-                pDict->SetAt(CFX_ByteStringC(((FX_LPCSTR)key) + 1, key.GetLength() - 1), pObj);
-            } else {
+            if (key.GetLength() >= 1) {
                 if (nKeys < 32) {
                     pDict->SetAt(CFX_ByteStringC(((FX_LPCSTR)key) + 1, key.GetLength() - 1), pObj);
                 } else {
@@ -2438,16 +2433,13 @@ CPDF_Stream* CPDF_SyntaxParser::ReadStream(CPDF_Dictionary* pDict, PARSE_CONTEXT
         pContext->m_DataStart = m_Pos;
     }
 
-    base::CheckedNumeric<FX_FILESIZE> pos = m_Pos;
-    pos += len;
-    if (pos.IsValid() && pos.ValueOrDie() < m_FileLen) {
-        m_Pos = pos.ValueOrDie();
-    } else {
-        return NULL;
-    }
-
     CPDF_CryptoHandler* pCryptoHandler = objnum == (FX_DWORD)m_MetadataObjnum ? NULL : m_pCryptoHandler;
     if (pCryptoHandler == NULL) {
+        base::CheckedNumeric<FX_FILESIZE> pos = m_Pos;
+        pos += len;
+        if (pos.IsValid() && pos.ValueOrDie() < m_FileLen) {
+            m_Pos = pos.ValueOrDie();
+        }
         GetNextWord();
         if (m_WordSize < 9 || FXSYS_memcmp32(m_WordBuffer, "endstream", 9)) {
             m_Pos = StreamStartPos;
@@ -2478,13 +2470,9 @@ CPDF_Stream* CPDF_SyntaxParser::ReadStream(CPDF_Dictionary* pDict, PARSE_CONTEXT
                 }
             }
         }
+        m_Pos = StreamStartPos;
     }
-    m_Pos = StreamStartPos;
     CPDF_Stream* pStream;
-#if defined(_FPDFAPI_MINI_) && !defined(_FXCORE_FEATURE_ALL_)
-    pStream = FX_NEW CPDF_Stream(m_pFileAccess, pCryptoHandler, m_HeaderOffset + m_Pos, len, pDict, gennum);
-    m_Pos += len;
-#else
     FX_LPBYTE pData = FX_Alloc(FX_BYTE, len);
     if (!pData) {
         return NULL;
@@ -2502,7 +2490,6 @@ CPDF_Stream* CPDF_SyntaxParser::ReadStream(CPDF_Dictionary* pDict, PARSE_CONTEXT
         dest_buf.DetachBuffer();
     }
     pStream = FX_NEW CPDF_Stream(pData, len, pDict);
-#endif
     if (pContext) {
         pContext->m_DataEnd = pContext->m_DataStart + len;
     }
@@ -2541,7 +2528,7 @@ FX_BOOL CPDF_SyntaxParser::IsWholeWord(FX_FILESIZE startpos, FX_FILESIZE limit,
     FX_BYTE type = _PDF_CharType[tag[0]];
     FX_BOOL bCheckLeft = type != 'D' && type != 'W';
     type = _PDF_CharType[tag[taglen - 1]];
-    FX_BOOL bCheckRight = type != 'D' || type != 'W';
+    FX_BOOL bCheckRight = type != 'D' && type != 'W';
     FX_BYTE ch;
     if (bCheckRight && startpos + (FX_INT32)taglen <= limit && GetCharAt(startpos + (FX_INT32)taglen, ch)) {
         FX_BYTE type = _PDF_CharType[ch];
@@ -3471,8 +3458,8 @@ CPDF_Object       * CPDF_DataAvail::ParseIndirectObjectAt(FX_FILESIZE pos, FX_DWORD ob
     if (!bIsNumber) {
         return NULL;
     }
-    FX_DWORD real_objnum = FXSYS_atoi(word);
-    if (objnum && real_objnum != objnum) {
+    FX_DWORD parser_objnum = FXSYS_atoi(word);
+    if (objnum && parser_objnum != objnum) {
         return NULL;
     }
     word = m_syntaxParser.GetNextWord(bIsNumber);
@@ -3841,6 +3828,9 @@ FX_BOOL CPDF_DataAvail::CheckTrailer(IFX_DownloadHints* pHints)
         CFX_SmartPointer<IFX_FileStream> file(FX_CreateMemoryStream(pBuf, (size_t)iSize, FALSE));
         m_syntaxParser.InitParser((IFX_FileStream*)file, 0);
         CPDF_Object *pTrailer = m_syntaxParser.GetObject(NULL, 0, 0, 0);
+        if (pTrailer->GetType() != PDFOBJ_DICTIONARY) {
+            return FALSE;
+        }
         if (!pTrailer) {
             m_Pos += m_syntaxParser.SavePos();
             pHints->AddSegment(m_Pos, iTrailerSize);