From 746babded81e9de3fc132fd670386382c031fa74 Mon Sep 17 00:00:00 2001 From: Nicolas Pena Date: Wed, 3 May 2017 12:35:59 -0400 Subject: SetPos to at most the file length to avoid overflows MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This CL prevents arbitrary position setting which may cause integer overflows. In the bug in question, the PDF says the xrefs are located in a huge position. This then causes problems when calling CPDF_SyntaxParser methods. Bug: chromium:603545 Change-Id: I5f94c38f46a0217e9f12f1bf8b2f3bee3b03cb35 Reviewed-on: https://pdfium-review.googlesource.com/4813 Commit-Queue: Nicolás Peña Reviewed-by: Tom Sepez --- core/fpdfapi/parser/cpdf_parser.cpp | 108 ++++++++++++++++++------------------ 1 file changed, 54 insertions(+), 54 deletions(-) (limited to 'core/fpdfapi/parser/cpdf_parser.cpp') diff --git a/core/fpdfapi/parser/cpdf_parser.cpp b/core/fpdfapi/parser/cpdf_parser.cpp index 86428ab9d7..fc98be5f6e 100644 --- a/core/fpdfapi/parser/cpdf_parser.cpp +++ b/core/fpdfapi/parser/cpdf_parser.cpp @@ -155,12 +155,12 @@ CPDF_Parser::Error CPDF_Parser::StartParse( if (m_pSyntax->m_FileLen < m_pSyntax->m_HeaderOffset + 9) return FORMAT_ERROR; - m_pSyntax->RestorePos(m_pSyntax->m_FileLen - m_pSyntax->m_HeaderOffset - 9); + m_pSyntax->SetPos(m_pSyntax->m_FileLen - m_pSyntax->m_HeaderOffset - 9); m_pDocument = pDocument; bool bXRefRebuilt = false; if (m_pSyntax->SearchWord("startxref", true, false, 4096)) { - m_SortedOffset.insert(m_pSyntax->SavePos()); + m_SortedOffset.insert(m_pSyntax->GetPos()); m_pSyntax->GetKeyword(); bool bNumber; @@ -286,11 +286,11 @@ bool CPDF_Parser::VerifyCrossRefV4() { if (it.second.pos == 0) continue; // Find the first non-zero position. - FX_FILESIZE SavedPos = m_pSyntax->SavePos(); - m_pSyntax->RestorePos(it.second.pos); + FX_FILESIZE SavedPos = m_pSyntax->GetPos(); + m_pSyntax->SetPos(it.second.pos); bool is_num = false; CFX_ByteString num_str = m_pSyntax->GetNextWord(&is_num); - m_pSyntax->RestorePos(SavedPos); + m_pSyntax->SetPos(SavedPos); if (!is_num || num_str.IsEmpty() || FXSYS_atoui(num_str.c_str()) != it.first) { // If the object number read doesn't match the one stored, @@ -414,12 +414,12 @@ bool CPDF_Parser::LoadLinearizedCrossRefV4(FX_FILESIZE pos, uint32_t dwObjCount) { FX_FILESIZE dwStartPos = pos - m_pSyntax->m_HeaderOffset; - m_pSyntax->RestorePos(dwStartPos); + m_pSyntax->SetPos(dwStartPos); m_SortedOffset.insert(pos); uint32_t start_objnum = 0; uint32_t count = dwObjCount; - FX_FILESIZE SavedPos = m_pSyntax->SavePos(); + FX_FILESIZE SavedPos = m_pSyntax->GetPos(); const int32_t recordsize = 20; std::vector buf(1024 * recordsize + 1); @@ -465,14 +465,14 @@ bool CPDF_Parser::LoadLinearizedCrossRefV4(FX_FILESIZE pos, } } } - m_pSyntax->RestorePos(SavedPos + count * recordsize); + m_pSyntax->SetPos(SavedPos + count * recordsize); return true; } bool CPDF_Parser::LoadCrossRefV4(FX_FILESIZE pos, FX_FILESIZE streampos, bool bSkip) { - m_pSyntax->RestorePos(pos); + m_pSyntax->SetPos(pos); if (m_pSyntax->GetKeyword() != "xref") return false; @@ -481,14 +481,14 @@ bool CPDF_Parser::LoadCrossRefV4(FX_FILESIZE pos, m_SortedOffset.insert(streampos); while (1) { - FX_FILESIZE SavedPos = m_pSyntax->SavePos(); + FX_FILESIZE SavedPos = m_pSyntax->GetPos(); bool bIsNumber; CFX_ByteString word = m_pSyntax->GetNextWord(&bIsNumber); if (word.IsEmpty()) return false; if (!bIsNumber) { - m_pSyntax->RestorePos(SavedPos); + m_pSyntax->SetPos(SavedPos); break; } @@ -498,7 +498,7 @@ bool CPDF_Parser::LoadCrossRefV4(FX_FILESIZE pos, uint32_t count = m_pSyntax->GetDirectNum(); m_pSyntax->ToNextWord(); - SavedPos = m_pSyntax->SavePos(); + SavedPos = m_pSyntax->GetPos(); const int32_t recordsize = 20; m_dwXrefStartObjNum = start_objnum; @@ -541,7 +541,7 @@ bool CPDF_Parser::LoadCrossRefV4(FX_FILESIZE pos, } } } - m_pSyntax->RestorePos(SavedPos + count * recordsize); + m_pSyntax->SetPos(SavedPos + count * recordsize); } return !streampos || LoadCrossRefV5(&streampos, false); } @@ -736,7 +736,7 @@ bool CPDF_Parser::RebuildCrossRef() { } FX_FILESIZE offset = 0; - m_pSyntax->RestorePos(obj_pos); + m_pSyntax->SetPos(obj_pos); offset = m_pSyntax->FindTag("obj", 0); if (offset == -1) offset = 0; @@ -776,7 +776,7 @@ bool CPDF_Parser::RebuildCrossRef() { if (inside_index == 7) { if (PDFCharIsWhitespace(byte) || PDFCharIsDelimiter(byte)) { last_trailer = pos + i - 7; - m_pSyntax->RestorePos(pos + i - m_pSyntax->m_HeaderOffset); + m_pSyntax->SetPos(pos + i - m_pSyntax->m_HeaderOffset); std::unique_ptr pObj = m_pSyntax->GetObject(m_pDocument, 0, 0, true); @@ -813,7 +813,7 @@ bool CPDF_Parser::RebuildCrossRef() { m_pTrailer = ToDictionary(std::move(pObj)); } - FX_FILESIZE dwSavePos = m_pSyntax->SavePos(); + FX_FILESIZE dwSavePos = m_pSyntax->GetPos(); CFX_ByteString strWord = m_pSyntax->GetKeyword(); if (!strWord.Compare("startxref")) { bool bNumber; @@ -822,7 +822,7 @@ bool CPDF_Parser::RebuildCrossRef() { if (bNumber) m_LastXRefOffset = FXSYS_atoi(bsOffset.c_str()); } - m_pSyntax->RestorePos(dwSavePos); + m_pSyntax->SetPos(dwSavePos); } } } @@ -1135,7 +1135,7 @@ std::unique_ptr CPDF_Parser::ParseIndirectObject( if (it == m_ObjCache[pObjStream].end()) return nullptr; - syntax.RestorePos(offset + it->second); + syntax.SetPos(offset + it->second); return syntax.GetObject(pObjList, 0, 0, true); } @@ -1229,43 +1229,43 @@ void CPDF_Parser::GetIndirectBinary(uint32_t objnum, if (pos == 0) return; - FX_FILESIZE SavedPos = m_pSyntax->SavePos(); - m_pSyntax->RestorePos(pos); + FX_FILESIZE SavedPos = m_pSyntax->GetPos(); + m_pSyntax->SetPos(pos); bool bIsNumber; CFX_ByteString word = m_pSyntax->GetNextWord(&bIsNumber); if (!bIsNumber) { - m_pSyntax->RestorePos(SavedPos); + m_pSyntax->SetPos(SavedPos); return; } uint32_t parser_objnum = FXSYS_atoui(word.c_str()); if (parser_objnum && parser_objnum != objnum) { - m_pSyntax->RestorePos(SavedPos); + m_pSyntax->SetPos(SavedPos); return; } word = m_pSyntax->GetNextWord(&bIsNumber); if (!bIsNumber) { - m_pSyntax->RestorePos(SavedPos); + m_pSyntax->SetPos(SavedPos); return; } if (m_pSyntax->GetKeyword() != "obj") { - m_pSyntax->RestorePos(SavedPos); + m_pSyntax->SetPos(SavedPos); return; } auto it = m_SortedOffset.find(pos); if (it == m_SortedOffset.end() || ++it == m_SortedOffset.end()) { - m_pSyntax->RestorePos(SavedPos); + m_pSyntax->SetPos(SavedPos); return; } FX_FILESIZE nextoff = *it; bool bNextOffValid = false; if (nextoff != pos) { - m_pSyntax->RestorePos(nextoff); + m_pSyntax->SetPos(nextoff); word = m_pSyntax->GetNextWord(&bIsNumber); if (word == "xref") { bNextOffValid = true; @@ -1278,66 +1278,66 @@ void CPDF_Parser::GetIndirectBinary(uint32_t objnum, } if (!bNextOffValid) { - m_pSyntax->RestorePos(pos); + m_pSyntax->SetPos(pos); while (1) { if (m_pSyntax->GetKeyword() == "endobj") break; - if (m_pSyntax->SavePos() == m_pSyntax->m_FileLen) + if (m_pSyntax->GetPos() == m_pSyntax->m_FileLen) break; } - nextoff = m_pSyntax->SavePos(); + nextoff = m_pSyntax->GetPos(); } size = (uint32_t)(nextoff - pos); pBuffer = FX_Alloc(uint8_t, size); - m_pSyntax->RestorePos(pos); + m_pSyntax->SetPos(pos); m_pSyntax->ReadBlock(pBuffer, size); - m_pSyntax->RestorePos(SavedPos); + m_pSyntax->SetPos(SavedPos); } std::unique_ptr CPDF_Parser::ParseIndirectObjectAt( CPDF_IndirectObjectHolder* pObjList, FX_FILESIZE pos, uint32_t objnum) { - FX_FILESIZE SavedPos = m_pSyntax->SavePos(); - m_pSyntax->RestorePos(pos); + FX_FILESIZE SavedPos = m_pSyntax->GetPos(); + m_pSyntax->SetPos(pos); bool bIsNumber; CFX_ByteString word = m_pSyntax->GetNextWord(&bIsNumber); if (!bIsNumber) { - m_pSyntax->RestorePos(SavedPos); + m_pSyntax->SetPos(SavedPos); return nullptr; } - FX_FILESIZE objOffset = m_pSyntax->SavePos(); + FX_FILESIZE objOffset = m_pSyntax->GetPos(); objOffset -= word.GetLength(); uint32_t parser_objnum = FXSYS_atoui(word.c_str()); if (objnum && parser_objnum != objnum) { - m_pSyntax->RestorePos(SavedPos); + m_pSyntax->SetPos(SavedPos); return nullptr; } word = m_pSyntax->GetNextWord(&bIsNumber); if (!bIsNumber) { - m_pSyntax->RestorePos(SavedPos); + m_pSyntax->SetPos(SavedPos); return nullptr; } uint32_t parser_gennum = FXSYS_atoui(word.c_str()); if (m_pSyntax->GetKeyword() != "obj") { - m_pSyntax->RestorePos(SavedPos); + m_pSyntax->SetPos(SavedPos); return nullptr; } std::unique_ptr pObj = m_pSyntax->GetObject(pObjList, objnum, parser_gennum, true); - m_pSyntax->SavePos(); + m_pSyntax->GetPos(); CFX_ByteString bsWord = m_pSyntax->GetKeyword(); if (bsWord == "endobj") - m_pSyntax->SavePos(); + m_pSyntax->GetPos(); - m_pSyntax->RestorePos(SavedPos); + m_pSyntax->SetPos(SavedPos); if (pObj) { if (!objnum) pObj->m_ObjNum = parser_objnum; @@ -1351,31 +1351,31 @@ std::unique_ptr CPDF_Parser::ParseIndirectObjectAtByStrict( FX_FILESIZE pos, uint32_t objnum, FX_FILESIZE* pResultPos) { - FX_FILESIZE SavedPos = m_pSyntax->SavePos(); - m_pSyntax->RestorePos(pos); + FX_FILESIZE SavedPos = m_pSyntax->GetPos(); + m_pSyntax->SetPos(pos); bool bIsNumber; CFX_ByteString word = m_pSyntax->GetNextWord(&bIsNumber); if (!bIsNumber) { - m_pSyntax->RestorePos(SavedPos); + m_pSyntax->SetPos(SavedPos); return nullptr; } uint32_t parser_objnum = FXSYS_atoui(word.c_str()); if (objnum && parser_objnum != objnum) { - m_pSyntax->RestorePos(SavedPos); + m_pSyntax->SetPos(SavedPos); return nullptr; } word = m_pSyntax->GetNextWord(&bIsNumber); if (!bIsNumber) { - m_pSyntax->RestorePos(SavedPos); + m_pSyntax->SetPos(SavedPos); return nullptr; } uint32_t gennum = FXSYS_atoui(word.c_str()); if (m_pSyntax->GetKeyword() != "obj") { - m_pSyntax->RestorePos(SavedPos); + m_pSyntax->SetPos(SavedPos); return nullptr; } @@ -1385,7 +1385,7 @@ std::unique_ptr CPDF_Parser::ParseIndirectObjectAtByStrict( if (pResultPos) *pResultPos = m_pSyntax->m_Pos; - m_pSyntax->RestorePos(SavedPos); + m_pSyntax->SetPos(SavedPos); return pObj; } @@ -1417,9 +1417,9 @@ bool CPDF_Parser::IsLinearizedFile( const CFX_RetainPtr& pFileAccess, uint32_t offset) { m_pSyntax->InitParser(pFileAccess, offset); - m_pSyntax->RestorePos(m_pSyntax->m_HeaderOffset + 9); + m_pSyntax->SetPos(m_pSyntax->m_HeaderOffset + 9); - FX_FILESIZE SavedPos = m_pSyntax->SavePos(); + FX_FILESIZE SavedPos = m_pSyntax->GetPos(); bool bIsNumber; CFX_ByteString word = m_pSyntax->GetNextWord(&bIsNumber); if (!bIsNumber) @@ -1432,7 +1432,7 @@ bool CPDF_Parser::IsLinearizedFile( uint32_t gennum = FXSYS_atoui(word.c_str()); if (m_pSyntax->GetKeyword() != "obj") { - m_pSyntax->RestorePos(SavedPos); + m_pSyntax->SetPos(SavedPos); return false; } @@ -1465,7 +1465,7 @@ CPDF_Parser::Error CPDF_Parser::StartLinearizedParse( m_bHasParsed = true; m_pDocument = pDocument; - FX_FILESIZE dwFirstXRefOffset = m_pSyntax->SavePos(); + FX_FILESIZE dwFirstXRefOffset = m_pSyntax->GetPos(); bool bXRefRebuilt = false; bool bLoadV4 = LoadCrossRefV4(dwFirstXRefOffset, 0, false); if (!bLoadV4 && !LoadCrossRefV5(&dwFirstXRefOffset, true)) { @@ -1549,7 +1549,7 @@ CPDF_Parser::Error CPDF_Parser::LoadLinearizedMainXRefTable() { uint32_t dwSaveMetadataObjnum = m_pSyntax->m_MetadataObjnum; m_pSyntax->m_MetadataObjnum = 0; m_pTrailer.reset(); - m_pSyntax->RestorePos(m_LastXRefOffset - m_pSyntax->m_HeaderOffset); + m_pSyntax->SetPos(m_LastXRefOffset - m_pSyntax->m_HeaderOffset); uint8_t ch = 0; uint32_t dwCount = 0; @@ -1557,7 +1557,7 @@ CPDF_Parser::Error CPDF_Parser::LoadLinearizedMainXRefTable() { while (PDFCharIsWhitespace(ch)) { ++dwCount; if (m_pSyntax->m_FileLen <= - (FX_FILESIZE)(m_pSyntax->SavePos() + m_pSyntax->m_HeaderOffset)) { + (FX_FILESIZE)(m_pSyntax->GetPos() + m_pSyntax->m_HeaderOffset)) { break; } m_pSyntax->GetNextChar(ch); -- cgit v1.2.3