| Index: core/src/fpdfapi/fpdf_parser/fpdf_parser_parser.cpp
|
| diff --git a/core/src/fpdfapi/fpdf_parser/fpdf_parser_parser.cpp b/core/src/fpdfapi/fpdf_parser/fpdf_parser_parser.cpp
|
| index 1b62b06749c5d92224e9d484b703b8d985c957eb..97e0d6f5e36a596a660772e5a988518f3bbb2acd 100644
|
| --- a/core/src/fpdfapi/fpdf_parser/fpdf_parser_parser.cpp
|
| +++ b/core/src/fpdfapi/fpdf_parser/fpdf_parser_parser.cpp
|
| @@ -9,7 +9,9 @@
|
| #include "../../../include/fpdfapi/fpdf_page.h"
|
| #include "../../../../third_party/numerics/safe_math.h"
|
| #include "../fpdf_page/pageint.h"
|
| -#include <limits.h>
|
| +#include <utility>
|
| +#include <vector>
|
| +
|
| #define _PARSER_OBJECT_LEVLE_ 64
|
| extern const FX_LPCSTR _PDF_CharType;
|
| FX_BOOL IsSignatureDict(const CPDF_Dictionary* pDict)
|
| @@ -1025,62 +1027,71 @@ FX_BOOL CPDF_Parser::LoadCrossRefV5(FX_FILESIZE pos, FX_FILESIZE& prev, FX_BOOL
|
| } else {
|
| m_Trailers.Add((CPDF_Dictionary*)pStream->GetDict()->Clone());
|
| }
|
| - CFX_DWordArray IndexArray, WidthArray;
|
| FX_DWORD nSegs = 0;
|
| + std::vector <std::pair <FX_INT32, FX_INT32>> arrIndex;
|
| CPDF_Array* pArray = pStream->GetDict()->GetArray(FX_BSTRC("Index"));
|
| - if (pArray == NULL) {
|
| - IndexArray.Add(0);
|
| - IndexArray.Add(size);
|
| - nSegs = 1;
|
| - } else {
|
| - for (FX_DWORD i = 0; i < pArray->GetCount(); i ++) {
|
| - IndexArray.Add(pArray->GetInteger(i));
|
| + 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);
|
| + 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;
|
| }
|
| - nSegs = pArray->GetCount() / 2;
|
| }
|
| pArray = pStream->GetDict()->GetArray(FX_BSTRC("W"));
|
| if (pArray == NULL) {
|
| pStream->Release();
|
| return FALSE;
|
| }
|
| - FX_DWORD totalwidth = 0;
|
| - FX_DWORD i;
|
| - for (i = 0; i < pArray->GetCount(); i ++) {
|
| + CFX_DWordArray WidthArray;
|
| + FX_SAFE_DWORD dwAccWidth = 0;
|
| + for (FX_DWORD i = 0; i < pArray->GetCount(); i ++) {
|
| WidthArray.Add(pArray->GetInteger(i));
|
| - if (totalwidth + WidthArray[i] < totalwidth) {
|
| - pStream->Release();
|
| - return FALSE;
|
| - }
|
| - totalwidth += WidthArray[i];
|
| + dwAccWidth += WidthArray[i];
|
| }
|
| - if (totalwidth == 0 || WidthArray.GetSize() < 3) {
|
| + if (!dwAccWidth.IsValid() || WidthArray.GetSize() < 3) {
|
| pStream->Release();
|
| return FALSE;
|
| }
|
| + FX_DWORD totalWidth = dwAccWidth.ValueOrDie();
|
| CPDF_StreamAcc acc;
|
| acc.LoadAllData(pStream);
|
| FX_LPCBYTE pData = acc.GetData();
|
| FX_DWORD dwTotalSize = acc.GetSize();
|
| FX_DWORD segindex = 0;
|
| - for (i = 0; i < nSegs; i ++) {
|
| - FX_INT32 startnum = IndexArray[i * 2];
|
| + for (FX_DWORD i = 0; i < nSegs; i ++) {
|
| + FX_INT32 startnum = arrIndex[i].first;
|
| if (startnum < 0) {
|
| continue;
|
| }
|
| - m_dwXrefStartObjNum = startnum;
|
| - FX_DWORD count = IndexArray[i * 2 + 1];
|
| - if (segindex + count < segindex || segindex + count == 0 ||
|
| - (FX_DWORD)totalwidth >= UINT_MAX / (segindex + count) || (segindex + count) * (FX_DWORD)totalwidth > dwTotalSize) {
|
| + m_dwXrefStartObjNum = base::checked_cast<FX_DWORD, FX_INT32> (startnum);
|
| + FX_DWORD count = base::checked_cast<FX_DWORD, FX_INT32> (arrIndex[i].second);
|
| + FX_SAFE_DWORD dwCaculatedSize = segindex;
|
| + dwCaculatedSize += count;
|
| + dwCaculatedSize *= totalWidth;
|
| + if (!dwCaculatedSize.IsValid() || dwCaculatedSize.ValueOrDie() > dwTotalSize) {
|
| continue;
|
| }
|
| - FX_LPCBYTE segstart = pData + segindex * (FX_DWORD)totalwidth;
|
| - if ((FX_DWORD)startnum + count < (FX_DWORD)startnum ||
|
| - (FX_DWORD)startnum + count > (FX_DWORD)m_V5Type.GetSize()) {
|
| + FX_LPCBYTE segstart = pData + segindex * totalWidth;
|
| + FX_SAFE_DWORD dwMaxObjNum = startnum;
|
| + dwMaxObjNum += count;
|
| + FX_DWORD dwV5Size = base::checked_cast<FX_DWORD, FX_INT32> (m_V5Type.GetSize());
|
| + if (!dwMaxObjNum.IsValid() || dwMaxObjNum.ValueOrDie() > dwV5Size) {
|
| continue;
|
| }
|
| for (FX_DWORD j = 0; j < count; j ++) {
|
| FX_INT32 type = 1;
|
| - FX_LPCBYTE entrystart = segstart + j * totalwidth;
|
| + FX_LPCBYTE entrystart = segstart + j * totalWidth;
|
| if (WidthArray[0]) {
|
| type = _GetVarInt(entrystart, WidthArray[0]);
|
| }
|
|
|