Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(2276)

Unified Diff: core/src/fpdfapi/fpdf_parser/fpdf_parser_parser.cpp

Issue 1523523002: Fix hint table loading issues. (Closed) Base URL: https://pdfium.googlesource.com/pdfium.git@master
Patch Set: im dumb Created 5 years ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « core/include/fxcrt/fx_basic.h ('k') | core/src/fpdfapi/fpdf_parser/parser_int.h » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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 bc5d3edc2bbc6bcacd66680a15110eaf64899e14..4f5d34ef2c777bbeec4cc1723eae14184ce7c262 100644
--- a/core/src/fpdfapi/fpdf_parser/fpdf_parser_parser.cpp
+++ b/core/src/fpdfapi/fpdf_parser/fpdf_parser_parser.cpp
@@ -75,6 +75,12 @@ int32_t GetStreamFirst(CPDF_StreamAcc* pObjStream) {
return pObjStream->GetDict()->GetInteger(FX_BSTRC("First"));
}
+bool CanReadFromBitStream(const CFX_BitStream* hStream,
jun_fang 2015/12/12 09:48:10 I don't think that we need to add an extra functio
+ const FX_SAFE_DWORD& num_bits) {
+ return (num_bits.IsValid() &&
+ hStream->BitsRemaining() >= num_bits.ValueOrDie());
+}
+
} // namespace
// TODO(thestig) Using unique_ptr with ReleaseDeleter is still not ideal.
@@ -4644,12 +4650,16 @@ FX_DWORD CPDF_HintTables::GetItemLength(int index,
return szArray[index + 1] - szArray[index];
}
FX_BOOL CPDF_HintTables::ReadPageHintTable(CFX_BitStream* hStream) {
- if (!hStream)
+ if (!hStream || hStream->IsEOF())
return FALSE;
int nStreamOffset = ReadPrimaryHintStreamOffset();
int nStreamLen = ReadPrimaryHintStreamLength();
if (nStreamOffset < 0 || nStreamLen < 1)
return FALSE;
+
+ const FX_DWORD kHeaderSize = 288;
+ if (hStream->BitsRemaining() < kHeaderSize)
+ return FALSE;
// Item 1: The least number of objects in a page.
FX_DWORD dwObjLeastNum = hStream->GetBits(32);
// Item 2: The location of the first page's page object.
@@ -4692,6 +4702,11 @@ FX_BOOL CPDF_HintTables::ReadPageHintTable(CFX_BitStream* hStream) {
int nPages = pPageNum ? pPageNum->GetInteger() : 0;
if (nPages < 1)
return FALSE;
+
+ FX_SAFE_DWORD required_bits = dwDeltaObjectsBits;
+ required_bits *= pdfium::base::checked_cast<FX_DWORD>(nPages);
+ if (!CanReadFromBitStream(hStream, required_bits))
jun_fang 2015/12/12 09:48:10 It means a failure if the return of CFX_BitStream:
Oliver Chang 2015/12/12 15:07:26 How do we distinguish between reading a value of 0
+ return FALSE;
for (int i = 0; i < nPages; ++i) {
FX_SAFE_DWORD safeDeltaObj = hStream->GetBits(dwDeltaObjectsBits);
safeDeltaObj += dwObjLeastNum;
@@ -4700,6 +4715,11 @@ FX_BOOL CPDF_HintTables::ReadPageHintTable(CFX_BitStream* hStream) {
m_dwDeltaNObjsArray.Add(safeDeltaObj.ValueOrDie());
}
hStream->ByteAlign();
+
+ required_bits = dwDeltaPageLenBits;
+ required_bits *= pdfium::base::checked_cast<FX_DWORD>(nPages);
+ if (!CanReadFromBitStream(hStream, required_bits))
+ return FALSE;
CFX_DWordArray dwPageLenArray;
for (int i = 0; i < nPages; ++i) {
FX_SAFE_DWORD safePageLen = hStream->GetBits(dwDeltaPageLenBits);
@@ -4739,41 +4759,64 @@ FX_BOOL CPDF_HintTables::ReadPageHintTable(CFX_BitStream* hStream) {
dwPageLenArray[nPages - 1]);
}
hStream->ByteAlign();
+
// number of shared objects
+ required_bits = dwSharedObjBits;
+ required_bits *= pdfium::base::checked_cast<FX_DWORD>(nPages);
+ if (!CanReadFromBitStream(hStream, required_bits))
+ return FALSE;
for (int i = 0; i < nPages; i++) {
m_dwNSharedObjsArray.Add(hStream->GetBits(dwSharedObjBits));
}
hStream->ByteAlign();
+
// array of identifier, sizes = nshared_objects
for (int i = 0; i < nPages; i++) {
+ required_bits = dwSharedIdBits;
+ required_bits *= m_dwNSharedObjsArray[i];
+ if (!CanReadFromBitStream(hStream, required_bits))
+ return FALSE;
for (int j = 0; j < m_dwNSharedObjsArray[i]; j++) {
m_dwIdentifierArray.Add(hStream->GetBits(dwSharedIdBits));
}
}
hStream->ByteAlign();
+
for (int i = 0; i < nPages; i++) {
FX_SAFE_DWORD safeSize = m_dwNSharedObjsArray[i];
safeSize *= dwSharedNumeratorBits;
- if (!safeSize.IsValid())
+ if (!CanReadFromBitStream(hStream, safeSize))
return FALSE;
hStream->SkipBits(safeSize.ValueOrDie());
}
hStream->ByteAlign();
+
FX_SAFE_DWORD safeTotalPageLen = pdfium::base::checked_cast<FX_DWORD>(nPages);
safeTotalPageLen *= dwDeltaPageLenBits;
- if (!safeTotalPageLen.IsValid())
+ if (!CanReadFromBitStream(hStream, safeTotalPageLen))
return FALSE;
hStream->SkipBits(safeTotalPageLen.ValueOrDie());
jun_fang 2015/12/12 09:48:10 We should add a return value for SkipBits() like:
hStream->ByteAlign();
return TRUE;
}
-FX_BOOL CPDF_HintTables::ReadSharedObjHintTable(CFX_BitStream* hStream) {
- if (!hStream)
+FX_BOOL CPDF_HintTables::ReadSharedObjHintTable(CFX_BitStream* hStream,
+ FX_DWORD offset) {
+ if (!hStream || hStream->IsEOF())
return FALSE;
int nStreamOffset = ReadPrimaryHintStreamOffset();
int nStreamLen = ReadPrimaryHintStreamLength();
if (nStreamOffset < 0 || nStreamLen < 1)
return FALSE;
+
+ FX_SAFE_DWORD bit_offset = offset;
+ bit_offset *= 8;
+ if (!bit_offset.IsValid() || hStream->GetPos() > bit_offset.ValueOrDie())
+ return FALSE;
+ hStream->SkipBits(bit_offset.ValueOrDie() - hStream->GetPos());
+
+ const FX_DWORD kHeaderSize = 192;
+ if (hStream->BitsRemaining() < kHeaderSize)
+ return FALSE;
// Item 1: The object number of the first object in the shared objects
// section.
FX_DWORD dwFirstSharedObjNum = hStream->GetBits(32);
@@ -4801,6 +4844,11 @@ FX_BOOL CPDF_HintTables::ReadSharedObjHintTable(CFX_BitStream* hStream) {
return FALSE;
FX_DWORD dwPrevObjLen = 0;
FX_DWORD dwCurObjLen = 0;
+ FX_SAFE_DWORD required_bits = dwSharedObjTotal;
+ required_bits *= dwDeltaGroupLen;
+ if (!CanReadFromBitStream(hStream, required_bits))
jun_fang 2015/12/12 09:48:10 To check the return value of hStream->GetBits().
+ return FALSE;
+
for (int i = 0; i < dwSharedObjTotal; ++i) {
dwPrevObjLen = dwCurObjLen;
FX_SAFE_DWORD safeObjLen = hStream->GetBits(dwDeltaGroupLen);
@@ -4838,6 +4886,8 @@ FX_BOOL CPDF_HintTables::ReadSharedObjHintTable(CFX_BitStream* hStream) {
m_szSharedObjOffsetArray.Add(safeLoc.ValueOrDie());
}
hStream->ByteAlign();
+ if (hStream->BitsRemaining() < dwSharedObjTotal)
+ return FALSE;
hStream->SkipBits(dwSharedObjTotal);
jun_fang 2015/12/12 09:48:10 To check the return value of SkipBits() after we a
hStream->ByteAlign();
return TRUE;
@@ -4899,6 +4949,8 @@ int32_t CPDF_HintTables::CheckPage(int index, IFX_DownloadHints* pHints) {
FX_DWORD dwObjNum = 0;
for (int j = 0; j < m_dwNSharedObjsArray[index]; ++j) {
dwIndex = m_dwIdentifierArray[offset + j];
+ if (dwIndex >= m_dwSharedObjNumArray.GetSize())
+ return IPDF_DataAvail::DataNotAvailable;
dwObjNum = m_dwSharedObjNumArray[dwIndex];
if (dwObjNum >= nFirstPageObjNum &&
dwObjNum < nFirstPageObjNum + m_nFirstPageSharedObjs) {
@@ -4920,6 +4972,7 @@ FX_BOOL CPDF_HintTables::LoadHintStream(CPDF_Stream* pHintStream) {
CPDF_Object* pOffset = pDict ? pDict->GetElement(FX_BSTRC("S")) : nullptr;
if (!pOffset || pOffset->GetType() != PDFOBJ_NUMBER)
return FALSE;
+ int shared_hint_table_offset = pOffset->GetInteger();
CPDF_StreamAcc acc;
acc.LoadAllData(pHintStream);
FX_DWORD size = acc.GetSize();
@@ -4927,13 +4980,15 @@ FX_BOOL CPDF_HintTables::LoadHintStream(CPDF_Stream* pHintStream) {
// The header section of shared object hint table is 24 bytes.
// Hint table has at least 60 bytes.
const FX_DWORD MIN_STREAM_LEN = 60;
- if (size < MIN_STREAM_LEN || size < pOffset->GetInteger() ||
- !pOffset->GetInteger()) {
+ if (size < MIN_STREAM_LEN || shared_hint_table_offset <= 0 ||
+ size < shared_hint_table_offset) {
return FALSE;
}
CFX_BitStream bs;
bs.Init(acc.GetData(), size);
- return ReadPageHintTable(&bs) && ReadSharedObjHintTable(&bs);
+ return ReadPageHintTable(&bs) &&
+ ReadSharedObjHintTable(&bs, pdfium::base::checked_cast<FX_DWORD>(
+ shared_hint_table_offset));
}
int CPDF_HintTables::ReadPrimaryHintStreamOffset() const {
if (!m_pLinearizedDict)
« no previous file with comments | « core/include/fxcrt/fx_basic.h ('k') | core/src/fpdfapi/fpdf_parser/parser_int.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698