summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLei Zhang <thestig@chromium.org>2015-12-22 13:41:54 -0800
committerLei Zhang <thestig@chromium.org>2015-12-22 13:41:54 -0800
commitf6dafc90ec1a0df8d618efc68c0223f0cdd80ffb (patch)
treebea547a227b6223178546c8cc17c6904ebb4ded6
parentf84fd2b1dac1fcca41db84d162995c38af650614 (diff)
downloadpdfium-f6dafc90ec1a0df8d618efc68c0223f0cdd80ffb.tar.xz
Convert CPDF_Parser::m_CrossRef to a std::map.
This improvements memory usage in case PDFs have sparse object numbers. The map holds a struct that currently has only one member. The struct will contain more members as other internal data structures get converted. BUG=pdfium:111 R=weili@chromium.org Review URL: https://codereview.chromium.org/1539573003 .
-rw-r--r--core/include/fpdfapi/fpdf_parser.h35
-rw-r--r--core/src/fpdfapi/fpdf_edit/fpdf_edit_create.cpp31
-rw-r--r--core/src/fpdfapi/fpdf_parser/fpdf_parser_parser.cpp136
-rw-r--r--core/src/fpdfapi/fpdf_parser/fpdf_parser_parser_unittest.cpp19
4 files changed, 111 insertions, 110 deletions
diff --git a/core/include/fpdfapi/fpdf_parser.h b/core/include/fpdfapi/fpdf_parser.h
index de0aa6196c..752df789da 100644
--- a/core/include/fpdfapi/fpdf_parser.h
+++ b/core/include/fpdfapi/fpdf_parser.h
@@ -394,10 +394,6 @@ class CPDF_Parser {
CFX_ByteString GetPassword() { return m_Password; }
- CPDF_SecurityHandler* GetSecurityHandler() {
- return m_pSecurityHandler.get();
- }
-
CPDF_CryptoHandler* GetCryptoHandler() {
return m_Syntax.m_pCryptoHandler.get();
}
@@ -405,44 +401,31 @@ class CPDF_Parser {
void SetSecurityHandler(CPDF_SecurityHandler* pSecurityHandler,
FX_BOOL bForced = FALSE);
- CFX_ByteString GetRecipient() { return m_bsRecipient; }
-
CPDF_Dictionary* GetTrailer() { return m_pTrailer; }
FX_FILESIZE GetLastXRefOffset() { return m_LastXRefOffset; }
CPDF_Document* GetDocument() { return m_pDocument; }
- CFX_ArrayTemplate<CPDF_Dictionary*>* GetOtherTrailers() {
- return &m_Trailers;
- }
-
FX_DWORD GetRootObjNum();
FX_DWORD GetInfoObjNum();
CPDF_Array* GetIDArray();
CPDF_Dictionary* GetEncryptDict() { return m_pEncryptDict; }
- FX_BOOL IsEncrypted() { return GetEncryptDict() != NULL; }
-
CPDF_Object* ParseIndirectObject(CPDF_IndirectObjects* pObjList,
FX_DWORD objnum,
PARSE_CONTEXT* pContext = NULL);
- FX_DWORD GetLastObjNum();
+ FX_DWORD GetLastObjNum() const;
+ bool IsValidObjectNumber(FX_DWORD objnum) const;
FX_BOOL IsFormStream(FX_DWORD objnum, FX_BOOL& bForm);
FX_FILESIZE GetObjectOffset(FX_DWORD objnum);
FX_FILESIZE GetObjectSize(FX_DWORD objnum);
- int GetObjectVersion(FX_DWORD objnum) { return m_ObjVersion[objnum]; }
-
void GetIndirectBinary(FX_DWORD objnum, uint8_t*& pBuffer, FX_DWORD& size);
- FX_BOOL GetFileStreamOption() { return m_Syntax.m_bFileStream; }
-
- void SetFileStreamOption(FX_BOOL b) { m_Syntax.m_bFileStream = b; }
-
IFX_FileRead* GetFileAccess() const { return m_Syntax.m_pFileAccess; }
int GetFileVersion() const { return m_FileVersion; }
@@ -523,13 +506,23 @@ class CPDF_Parser {
CFX_ByteString m_Password;
- CFX_FileSizeArray m_CrossRef;
+ struct ObjectInfo {
+ ObjectInfo() : pos(0) {}
+
+ FX_FILESIZE pos;
+// TODO(thestig): Use fields below in place of |m_V5Type| and |m_ObjVersion|
+#if 0
+ uint8_t type;
+ uint16_t gennum;
+#endif
+ };
+ std::map<FX_DWORD, ObjectInfo> m_ObjectInfo;
CFX_ByteArray m_V5Type;
+ CFX_WordArray m_ObjVersion;
CFX_FileSizeArray m_SortedOffset;
- CFX_WordArray m_ObjVersion;
CFX_ArrayTemplate<CPDF_Dictionary*> m_Trailers;
FX_BOOL m_bVersionUpdated;
diff --git a/core/src/fpdfapi/fpdf_edit/fpdf_edit_create.cpp b/core/src/fpdfapi/fpdf_edit/fpdf_edit_create.cpp
index 328728ef24..49ec0bae92 100644
--- a/core/src/fpdfapi/fpdf_edit/fpdf_edit_create.cpp
+++ b/core/src/fpdfapi/fpdf_edit/fpdf_edit_create.cpp
@@ -1319,16 +1319,19 @@ int32_t CPDF_Creator::WriteOldIndirectObject(FX_DWORD objnum) {
return 1;
}
int32_t CPDF_Creator::WriteOldObjs(IFX_Pause* pPause) {
- FX_DWORD nOldSize = m_pParser->m_CrossRef.GetSize();
+ FX_DWORD nLastObjNum = m_pParser->GetLastObjNum();
+ if (!m_pParser->IsValidObjectNumber(nLastObjNum))
+ return 0;
+
FX_DWORD objnum = (FX_DWORD)(uintptr_t)m_Pos;
- for (; objnum < nOldSize; objnum++) {
+ for (; objnum <= nLastObjNum; ++objnum) {
int32_t iRet = WriteOldIndirectObject(objnum);
- if (!iRet) {
- continue;
- }
- if (iRet < 0) {
+ if (iRet < 0)
return iRet;
- }
+
+ if (!iRet)
+ continue;
+
m_ObjectSize[objnum] = (FX_DWORD)(m_Offset - m_ObjectOffset[objnum]);
if (pPause && pPause->NeedToPauseNow()) {
m_Pos = (void*)(uintptr_t)(objnum + 1);
@@ -1389,7 +1392,6 @@ void CPDF_Creator::InitOldObjNumOffsets() {
void CPDF_Creator::InitNewObjNumOffsets() {
FX_BOOL bIncremental = (m_dwFlags & FPDFCREATE_INCREMENTAL) != 0;
FX_BOOL bNoOriginal = (m_dwFlags & FPDFCREATE_NO_ORIGINAL) != 0;
- FX_DWORD nOldSize = m_pParser ? m_pParser->m_CrossRef.GetSize() : 0;
FX_POSITION pos = m_pDocument->m_IndirectObjs.GetStartPosition();
while (pos) {
size_t key = 0;
@@ -1403,10 +1405,9 @@ void CPDF_Creator::InitNewObjNumOffsets() {
if (!pObj->IsModified()) {
continue;
}
- } else {
- if (objnum < nOldSize && m_pParser->m_V5Type[objnum] != 0) {
- continue;
- }
+ } else if (m_pParser->IsValidObjectNumber(objnum) &&
+ m_pParser->m_V5Type[objnum]) {
+ continue;
}
AppendNewObjNum(objnum);
}
@@ -1433,8 +1434,8 @@ void CPDF_Creator::InitNewObjNumOffsets() {
FX_BOOL bNewStart = FALSE;
for (; i < iCount; i++) {
FX_DWORD dwCurObjNum = m_NewObjNumArray.ElementAt(i);
- FX_BOOL bExist =
- (dwCurObjNum < nOldSize && m_ObjectOffset.GetPtrAt(dwCurObjNum));
+ bool bExist = m_pParser->IsValidObjectNumber(dwCurObjNum) &&
+ m_ObjectOffset.GetPtrAt(dwCurObjNum);
if (bExist || dwCurObjNum - dwLastObjNum > 1) {
if (!bNewStart) {
m_ObjectOffset.Add(dwStartObjNum, dwLastObjNum - dwStartObjNum + 1);
@@ -1555,7 +1556,7 @@ int32_t CPDF_Creator::WriteDoc_Stage1(IFX_Pause* pPause) {
m_pParser->m_V5Type[objnum] == 255) {
continue;
}
- m_ObjectOffset[objnum] = m_pParser->m_CrossRef[objnum];
+ m_ObjectOffset[objnum] = m_pParser->m_ObjectInfo[objnum].pos;
if (bObjStm) {
m_pXRefStream->AddObjectNumberToIndexArray(objnum);
}
diff --git a/core/src/fpdfapi/fpdf_parser/fpdf_parser_parser.cpp b/core/src/fpdfapi/fpdf_parser/fpdf_parser_parser.cpp
index 1b341f8692..d9697000e5 100644
--- a/core/src/fpdfapi/fpdf_parser/fpdf_parser_parser.cpp
+++ b/core/src/fpdfapi/fpdf_parser/fpdf_parser_parser.cpp
@@ -21,6 +21,14 @@
namespace {
+// A limit on the size of the xref table. Theoretical limits are higher, but
+// this may be large enough in practice.
+const int32_t kMaxXRefSize = 1048576;
+
+// A limit on the maximum object number in the xref table. Theoretical limits
+// are higher, but this may be large enough in practice.
+const FX_DWORD kMaxObjectNumber = 1048576;
+
struct SearchTagRecord {
const char* m_pTag;
FX_DWORD m_Len;
@@ -116,10 +124,15 @@ CPDF_Parser::CPDF_Parser() {
CPDF_Parser::~CPDF_Parser() {
CloseParser(FALSE);
}
-FX_DWORD CPDF_Parser::GetLastObjNum() {
- FX_DWORD dwSize = m_CrossRef.GetSize();
- return dwSize ? dwSize - 1 : 0;
+
+FX_DWORD CPDF_Parser::GetLastObjNum() const {
+ return m_ObjectInfo.empty() ? 0 : m_ObjectInfo.rbegin()->first;
+}
+
+bool CPDF_Parser::IsValidObjectNumber(FX_DWORD objnum) const {
+ return !m_ObjectInfo.empty() && objnum <= m_ObjectInfo.rbegin()->first;
}
+
void CPDF_Parser::SetEncryptDictionary(CPDF_Dictionary* pDict) {
m_pEncryptDict = pDict;
}
@@ -150,7 +163,7 @@ void CPDF_Parser::CloseParser(FX_BOOL bReParse) {
m_ObjCache.clear();
m_SortedOffset.RemoveAll();
- m_CrossRef.RemoveAll();
+ m_ObjectInfo.clear();
m_V5Type.RemoveAll();
m_ObjVersion.RemoveAll();
int32_t iLen = m_Trailers.GetSize();
@@ -331,14 +344,15 @@ void CPDF_Parser::ReleaseEncryptHandler() {
}
}
FX_FILESIZE CPDF_Parser::GetObjectOffset(FX_DWORD objnum) {
- if (objnum >= (FX_DWORD)m_CrossRef.GetSize()) {
+ if (!IsValidObjectNumber(objnum))
return 0;
- }
- if (m_V5Type[objnum] == 1) {
- return m_CrossRef[objnum];
- }
+
+ if (m_V5Type[objnum] == 1)
+ return m_ObjectInfo[objnum].pos;
+
if (m_V5Type[objnum] == 2) {
- return m_CrossRef[(int32_t)m_CrossRef[objnum]];
+ FX_FILESIZE pos = m_ObjectInfo[objnum].pos;
+ return m_ObjectInfo[pos].pos;
}
return 0;
}
@@ -352,10 +366,10 @@ FX_BOOL CPDF_Parser::LoadAllCrossRefV4(FX_FILESIZE xrefpos) {
return FALSE;
}
int32_t xrefsize = GetDirectInteger(m_pTrailer, "Size");
- if (xrefsize <= 0 || xrefsize > (1 << 20)) {
+ if (xrefsize <= 0 || xrefsize > kMaxXRefSize) {
return FALSE;
}
- m_CrossRef.SetSize(xrefsize);
+ m_ObjectInfo[0].pos = 0;
m_V5Type.SetSize(xrefsize);
CFX_FileSizeArray CrossRefList, XRefStreamList;
CrossRefList.Add(xrefpos);
@@ -458,7 +472,7 @@ FX_BOOL CPDF_Parser::LoadLinearizedCrossRefV4(FX_FILESIZE pos,
FX_DWORD objnum = start_objnum + block * 1024 + i;
char* pEntry = pBuf + i * recordsize;
if (pEntry[17] == 'f') {
- m_CrossRef.SetAtGrow(objnum, 0);
+ m_ObjectInfo[objnum].pos = 0;
m_V5Type.SetAtGrow(objnum, 0);
} else {
int32_t offset = FXSYS_atoi(pEntry);
@@ -468,18 +482,18 @@ FX_BOOL CPDF_Parser::LoadLinearizedCrossRefV4(FX_FILESIZE pos,
return FALSE;
}
}
- m_CrossRef.SetAtGrow(objnum, offset);
+ m_ObjectInfo[objnum].pos = offset;
int32_t version = FXSYS_atoi(pEntry + 11);
if (version >= 1) {
m_bVersionUpdated = TRUE;
}
m_ObjVersion.SetAtGrow(objnum, version);
- if (m_CrossRef[objnum] < m_Syntax.m_FileLen) {
+ if (m_ObjectInfo[objnum].pos < m_Syntax.m_FileLen) {
void* pResult = FXSYS_bsearch(
- &m_CrossRef[objnum], m_SortedOffset.GetData(),
+ &m_ObjectInfo[objnum].pos, m_SortedOffset.GetData(),
m_SortedOffset.GetSize(), sizeof(FX_FILESIZE), CompareFileSize);
if (!pResult) {
- m_SortedOffset.Add(m_CrossRef[objnum]);
+ m_SortedOffset.Add(m_ObjectInfo[objnum].pos);
}
}
m_V5Type.SetAtGrow(objnum, 1);
@@ -520,7 +534,7 @@ bool CPDF_Parser::LoadCrossRefV4(FX_FILESIZE pos,
break;
}
FX_DWORD start_objnum = FXSYS_atoi(word);
- if (start_objnum >= (1 << 20))
+ if (start_objnum >= kMaxObjectNumber)
return false;
FX_DWORD count = m_Syntax.GetDirectNum();
@@ -541,7 +555,7 @@ bool CPDF_Parser::LoadCrossRefV4(FX_FILESIZE pos,
FX_DWORD objnum = start_objnum + block * 1024 + i;
char* pEntry = pBuf + i * recordsize;
if (pEntry[17] == 'f') {
- m_CrossRef.SetAtGrow(objnum, 0);
+ m_ObjectInfo[objnum].pos = 0;
m_V5Type.SetAtGrow(objnum, 0);
} else {
FX_FILESIZE offset = (FX_FILESIZE)FXSYS_atoi64(pEntry);
@@ -551,15 +565,15 @@ bool CPDF_Parser::LoadCrossRefV4(FX_FILESIZE pos,
return false;
}
}
- m_CrossRef.SetAtGrow(objnum, offset);
+ m_ObjectInfo[objnum].pos = offset;
int32_t version = FXSYS_atoi(pEntry + 11);
if (version >= 1) {
m_bVersionUpdated = TRUE;
}
m_ObjVersion.SetAtGrow(objnum, version);
- if (m_CrossRef[objnum] < m_Syntax.m_FileLen &&
- !FindPosInOffsets(m_CrossRef[objnum])) {
- m_SortedOffset.Add(m_CrossRef[objnum]);
+ if (m_ObjectInfo[objnum].pos < m_Syntax.m_FileLen &&
+ !FindPosInOffsets(m_ObjectInfo[objnum].pos)) {
+ m_SortedOffset.Add(m_ObjectInfo[objnum].pos);
}
m_V5Type.SetAtGrow(objnum, 1);
}
@@ -592,7 +606,7 @@ FX_BOOL CPDF_Parser::LoadAllCrossRefV5(FX_FILESIZE xrefpos) {
}
FX_BOOL CPDF_Parser::RebuildCrossRef() {
- m_CrossRef.RemoveAll();
+ m_ObjectInfo.clear();
m_V5Type.RemoveAll();
m_SortedOffset.RemoveAll();
m_ObjVersion.RemoveAll();
@@ -794,18 +808,18 @@ FX_BOOL CPDF_Parser::RebuildCrossRef() {
} else {
i += (FX_DWORD)nLen;
}
- if (m_CrossRef.GetSize() > (int32_t)objnum &&
- m_CrossRef[objnum]) {
+ if (!m_ObjectInfo.empty() && IsValidObjectNumber(objnum) &&
+ m_ObjectInfo[objnum].pos) {
if (pObject) {
FX_DWORD oldgen = m_ObjVersion.GetAt(objnum);
- m_CrossRef[objnum] = obj_pos;
+ m_ObjectInfo[objnum].pos = obj_pos;
m_ObjVersion.SetAt(objnum, (int16_t)gennum);
if (oldgen != gennum) {
m_bVersionUpdated = TRUE;
}
}
} else {
- m_CrossRef.SetAtGrow(objnum, obj_pos);
+ m_ObjectInfo[objnum].pos = obj_pos;
m_V5Type.SetAtGrow(objnum, 1);
m_ObjVersion.SetAtGrow(objnum, (int16_t)gennum);
}
@@ -835,10 +849,8 @@ FX_BOOL CPDF_Parser::RebuildCrossRef() {
CPDF_Object* pRoot = pTrailer->GetElement("Root");
CPDF_Reference* pRef = ToReference(pRoot);
if (!pRoot ||
- (pRef &&
- (FX_DWORD)m_CrossRef.GetSize() >
- pRef->GetRefObjNum() &&
- m_CrossRef.GetAt(pRef->GetRefObjNum()) != 0)) {
+ (pRef && IsValidObjectNumber(pRef->GetRefObjNum()) &&
+ m_ObjectInfo[pRef->GetRefObjNum()].pos != 0)) {
FX_POSITION pos = pTrailer->GetStartPos();
while (pos) {
CFX_ByteString key;
@@ -964,7 +976,7 @@ FX_BOOL CPDF_Parser::RebuildCrossRef() {
m_SortedOffset.Add(offset);
}
FX_Free(buffer);
- return m_pTrailer && m_CrossRef.GetSize() > 0;
+ return m_pTrailer && !m_ObjectInfo.empty();
}
FX_BOOL CPDF_Parser::LoadCrossRefV5(FX_FILESIZE* pos, FX_BOOL bMainXRef) {
@@ -996,7 +1008,7 @@ FX_BOOL CPDF_Parser::LoadCrossRefV5(FX_FILESIZE* pos, FX_BOOL bMainXRef) {
}
if (bMainXRef) {
m_pTrailer = ToDictionary(pStream->GetDict()->Clone());
- m_CrossRef.SetSize(size);
+ m_ObjectInfo[0].pos = 0;
if (m_V5Type.SetSize(size)) {
FXSYS_memset(m_V5Type.GetData(), 0, size);
}
@@ -1076,7 +1088,7 @@ FX_BOOL CPDF_Parser::LoadCrossRefV5(FX_FILESIZE* pos, FX_BOOL bMainXRef) {
if (m_V5Type[startnum + j] == 255) {
FX_FILESIZE offset =
GetVarInt(entrystart + WidthArray[0], WidthArray[1]);
- m_CrossRef[startnum + j] = offset;
+ m_ObjectInfo[startnum + j].pos = offset;
void* pResult = FXSYS_bsearch(&offset, m_SortedOffset.GetData(),
m_SortedOffset.GetSize(),
sizeof(FX_FILESIZE), CompareFileSize);
@@ -1090,11 +1102,11 @@ FX_BOOL CPDF_Parser::LoadCrossRefV5(FX_FILESIZE* pos, FX_BOOL bMainXRef) {
}
m_V5Type[startnum + j] = type;
if (type == 0) {
- m_CrossRef[startnum + j] = 0;
+ m_ObjectInfo[startnum + j].pos = 0;
} else {
FX_FILESIZE offset =
GetVarInt(entrystart + WidthArray[0], WidthArray[1]);
- m_CrossRef[startnum + j] = offset;
+ m_ObjectInfo[startnum + j].pos = offset;
if (type == 1) {
void* pResult = FXSYS_bsearch(&offset, m_SortedOffset.GetData(),
m_SortedOffset.GetSize(),
@@ -1139,16 +1151,13 @@ FX_DWORD CPDF_Parser::GetInfoObjNum() {
}
FX_BOOL CPDF_Parser::IsFormStream(FX_DWORD objnum, FX_BOOL& bForm) {
bForm = FALSE;
- if (objnum >= (FX_DWORD)m_CrossRef.GetSize()) {
+ if (!IsValidObjectNumber(objnum))
return TRUE;
- }
- if (m_V5Type[objnum] == 0) {
+ if (m_V5Type[objnum] == 0)
return TRUE;
- }
- if (m_V5Type[objnum] == 2) {
+ if (m_V5Type[objnum] == 2)
return TRUE;
- }
- FX_FILESIZE pos = m_CrossRef[objnum];
+ FX_FILESIZE pos = m_ObjectInfo[objnum].pos;
void* pResult =
FXSYS_bsearch(&pos, m_SortedOffset.GetData(), m_SortedOffset.GetSize(),
sizeof(FX_FILESIZE), CompareFileSize);
@@ -1172,11 +1181,11 @@ FX_BOOL CPDF_Parser::IsFormStream(FX_DWORD objnum, FX_BOOL& bForm) {
CPDF_Object* CPDF_Parser::ParseIndirectObject(CPDF_IndirectObjects* pObjList,
FX_DWORD objnum,
PARSE_CONTEXT* pContext) {
- if (objnum >= (FX_DWORD)m_CrossRef.GetSize())
+ if (!IsValidObjectNumber(objnum))
return nullptr;
if (m_V5Type[objnum] == 1 || m_V5Type[objnum] == 255) {
- FX_FILESIZE pos = m_CrossRef[objnum];
+ FX_FILESIZE pos = m_ObjectInfo[objnum].pos;
if (pos <= 0)
return nullptr;
return ParseIndirectObjectAt(pObjList, pos, objnum, pContext);
@@ -1184,7 +1193,7 @@ CPDF_Object* CPDF_Parser::ParseIndirectObject(CPDF_IndirectObjects* pObjList,
if (m_V5Type[objnum] != 2)
return nullptr;
- CPDF_StreamAcc* pObjStream = GetObjectStream((FX_DWORD)m_CrossRef[objnum]);
+ CPDF_StreamAcc* pObjStream = GetObjectStream(m_ObjectInfo[objnum].pos);
if (!pObjStream)
return nullptr;
@@ -1227,14 +1236,14 @@ CPDF_StreamAcc* CPDF_Parser::GetObjectStream(FX_DWORD objnum) {
return pStreamAcc;
}
FX_FILESIZE CPDF_Parser::GetObjectSize(FX_DWORD objnum) {
- if (objnum >= (FX_DWORD)m_CrossRef.GetSize()) {
+ if (!IsValidObjectNumber(objnum))
return 0;
- }
+
if (m_V5Type[objnum] == 2) {
- objnum = (FX_DWORD)m_CrossRef[objnum];
+ objnum = m_ObjectInfo[objnum].pos;
}
if (m_V5Type[objnum] == 1 || m_V5Type[objnum] == 255) {
- FX_FILESIZE offset = m_CrossRef[objnum];
+ FX_FILESIZE offset = m_ObjectInfo[objnum].pos;
if (offset == 0) {
return 0;
}
@@ -1257,11 +1266,11 @@ void CPDF_Parser::GetIndirectBinary(FX_DWORD objnum,
FX_DWORD& size) {
pBuffer = NULL;
size = 0;
- if (objnum >= (FX_DWORD)m_CrossRef.GetSize()) {
+ if (!IsValidObjectNumber(objnum))
return;
- }
+
if (m_V5Type[objnum] == 2) {
- CPDF_StreamAcc* pObjStream = GetObjectStream((FX_DWORD)m_CrossRef[objnum]);
+ CPDF_StreamAcc* pObjStream = GetObjectStream(m_ObjectInfo[objnum].pos);
if (!pObjStream)
return;
@@ -1295,7 +1304,7 @@ void CPDF_Parser::GetIndirectBinary(FX_DWORD objnum,
if (m_V5Type[objnum] != 1)
return;
- FX_FILESIZE pos = m_CrossRef[objnum];
+ FX_FILESIZE pos = m_ObjectInfo[objnum].pos;
if (pos == 0) {
return;
}
@@ -1569,7 +1578,7 @@ FX_DWORD CPDF_Parser::StartAsynParse(IFX_FileRead* pFileAccess,
}
int32_t xrefsize = GetDirectInteger(m_pTrailer, "Size");
if (xrefsize > 0) {
- m_CrossRef.SetSize(xrefsize);
+ m_ObjectInfo[0].pos = 0;
m_V5Type.SetSize(xrefsize);
}
}
@@ -2964,17 +2973,14 @@ void CPDF_DataAvail::SetDocument(CPDF_Document* pDoc) {
}
FX_DWORD CPDF_DataAvail::GetObjectSize(FX_DWORD objnum, FX_FILESIZE& offset) {
CPDF_Parser* pParser = (CPDF_Parser*)(m_pDocument->GetParser());
- if (!pParser) {
- return 0;
- }
- if (objnum >= (FX_DWORD)pParser->m_CrossRef.GetSize()) {
+ if (!pParser || !pParser->IsValidObjectNumber(objnum))
return 0;
- }
+
if (pParser->m_V5Type[objnum] == 2) {
- objnum = (FX_DWORD)pParser->m_CrossRef[objnum];
- }
- if (pParser->m_V5Type[objnum] == 1 || pParser->m_V5Type[objnum] == 255) {
- offset = pParser->m_CrossRef[objnum];
+ objnum = pParser->m_ObjectInfo[objnum].pos;
+ } else if (pParser->m_V5Type[objnum] == 1 ||
+ pParser->m_V5Type[objnum] == 255) {
+ offset = pParser->m_ObjectInfo[objnum].pos;
if (offset == 0) {
return 0;
}
diff --git a/core/src/fpdfapi/fpdf_parser/fpdf_parser_parser_unittest.cpp b/core/src/fpdfapi/fpdf_parser/fpdf_parser_parser_unittest.cpp
index d3187c1ff4..3fd8dcf35a 100644
--- a/core/src/fpdfapi/fpdf_parser/fpdf_parser_parser_unittest.cpp
+++ b/core/src/fpdfapi/fpdf_parser/fpdf_parser_parser_unittest.cpp
@@ -267,7 +267,8 @@ TEST(fpdf_parser_parser, RebuildCrossRefCorrectly) {
ASSERT_TRUE(parser.RebuildCrossRef());
const FX_FILESIZE offsets[] = {0, 15, 61, 154, 296, 374, 450};
const FX_WORD versions[] = {0, 0, 2, 4, 6, 8, 0};
- ASSERT_TRUE(CompareArray(parser.m_CrossRef, offsets, FX_ArraySize(offsets)));
+ for (size_t i = 0; i < FX_ArraySize(offsets); ++i)
+ EXPECT_EQ(offsets[i], parser.m_ObjectInfo[i].pos);
ASSERT_TRUE(
CompareArray(parser.m_ObjVersion, versions, FX_ArraySize(versions)));
}
@@ -301,8 +302,8 @@ TEST(fpdf_parser_parser, LoadCrossRefV4) {
ASSERT_TRUE(parser.LoadCrossRefV4(0, 0, FALSE));
const FX_FILESIZE offsets[] = {0, 17, 81, 0, 331, 409};
const uint8_t types[] = {0, 1, 1, 0, 1, 1};
- ASSERT_TRUE(
- CompareArray(parser.m_CrossRef, offsets, FX_ArraySize(offsets)));
+ for (size_t i = 0; i < FX_ArraySize(offsets); ++i)
+ EXPECT_EQ(offsets[i], parser.m_ObjectInfo[i].pos);
ASSERT_TRUE(CompareArray(parser.m_V5Type, types, FX_ArraySize(types)));
}
{
@@ -326,8 +327,8 @@ TEST(fpdf_parser_parser, LoadCrossRefV4) {
const FX_FILESIZE offsets[] = {0, 0, 0, 25325, 0, 0, 0,
0, 25518, 25635, 0, 0, 25777};
const uint8_t types[] = {0, 0, 0, 1, 0, 0, 0, 0, 1, 1, 0, 0, 1};
- ASSERT_TRUE(
- CompareArray(parser.m_CrossRef, offsets, FX_ArraySize(offsets)));
+ for (size_t i = 0; i < FX_ArraySize(offsets); ++i)
+ EXPECT_EQ(offsets[i], parser.m_ObjectInfo[i].pos);
ASSERT_TRUE(CompareArray(parser.m_V5Type, types, FX_ArraySize(types)));
}
{
@@ -351,8 +352,8 @@ TEST(fpdf_parser_parser, LoadCrossRefV4) {
const FX_FILESIZE offsets[] = {0, 0, 0, 25325, 0, 0, 0,
0, 0, 25635, 0, 0, 25777};
const uint8_t types[] = {0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 0, 0, 1};
- ASSERT_TRUE(
- CompareArray(parser.m_CrossRef, offsets, FX_ArraySize(offsets)));
+ for (size_t i = 0; i < FX_ArraySize(offsets); ++i)
+ EXPECT_EQ(offsets[i], parser.m_ObjectInfo[i].pos);
ASSERT_TRUE(CompareArray(parser.m_V5Type, types, FX_ArraySize(types)));
}
{
@@ -374,8 +375,8 @@ TEST(fpdf_parser_parser, LoadCrossRefV4) {
ASSERT_TRUE(parser.LoadCrossRefV4(0, 0, FALSE));
const FX_FILESIZE offsets[] = {0, 23, 0, 0, 0, 45, 179};
const uint8_t types[] = {0, 1, 0, 0, 0, 1, 1};
- ASSERT_TRUE(
- CompareArray(parser.m_CrossRef, offsets, FX_ArraySize(offsets)));
+ for (size_t i = 0; i < FX_ArraySize(offsets); ++i)
+ EXPECT_EQ(offsets[i], parser.m_ObjectInfo[i].pos);
ASSERT_TRUE(CompareArray(parser.m_V5Type, types, FX_ArraySize(types)));
}
}