M74: Avoid 0 byte reads in ParseAndAppendCrossRefSubsectionData().
The existing CPDF_Parser::ParseAndAppendCrossRefSubsectionData() code
does not handle reads properly when the read count is a multiple of the
block size. e.g. For a count of 2048 and a block size of 1024, it tries
to read 1024, 1024, and 0 bytes.
Commit cef91f11 added a check that causes 0 byte reads to fail, so the
existing behavior causes ParseAndAppendCrossRefSubsectionData() to fail
altogether. Fix how ParseAndAppendCrossRefSubsectionData() loops to
avoid the 0 byte read.
BUG=chromium:945624
TBR=tsepez@chromium.org
Change-Id: Ie309dd6c3e139720f19962ec2a094512282aa8ed
Reviewed-on: https://pdfium-review.googlesource.com/c/pdfium/+/52410
Reviewed-by: Tom Sepez <tsepez@chromium.org>
Commit-Queue: Lei Zhang <thestig@chromium.org>
(cherry picked from commit fabd13dc93f6cd9345f20f10456eb5a5ac8863e6)
Reviewed-on: https://pdfium-review.googlesource.com/c/pdfium/+/52652
Reviewed-by: Lei Zhang <thestig@chromium.org>
diff --git a/core/fpdfapi/parser/cpdf_parser.cpp b/core/fpdfapi/parser/cpdf_parser.cpp
index dc3d398..02cb08e 100644
--- a/core/fpdfapi/parser/cpdf_parser.cpp
+++ b/core/fpdfapi/parser/cpdf_parser.cpp
@@ -453,22 +453,20 @@
std::vector<char> buf(1024 * kEntryConstSize + 1);
buf.back() = '\0';
- int32_t nBlocks = count / 1024 + 1;
- for (int32_t block = 0; block < nBlocks; block++) {
- int32_t block_size = block == nBlocks - 1 ? count % 1024 : 1024;
+ uint32_t nBytesToRead = count;
+ while (nBytesToRead > 0) {
+ const uint32_t block_size = std::min(nBytesToRead, 1024u);
if (!m_pSyntax->ReadBlock(reinterpret_cast<uint8_t*>(buf.data()),
block_size * kEntryConstSize)) {
return false;
}
- for (int32_t i = 0; i < block_size; i++) {
+ for (uint32_t i = 0; i < block_size; i++) {
+ uint32_t iObjectIndex = count - nBytesToRead + i;
CrossRefObjData& obj_data =
- (*out_objects)[start_obj_index + block * 1024 + i];
-
- const uint32_t objnum = start_objnum + block * 1024 + i;
-
+ (*out_objects)[start_obj_index + iObjectIndex];
+ const uint32_t objnum = start_objnum + iObjectIndex;
obj_data.obj_num = objnum;
-
ObjectInfo& info = obj_data.info;
char* pEntry = &buf[i * kEntryConstSize];
@@ -496,6 +494,7 @@
info.type = ObjectType::kNotCompressed;
}
}
+ nBytesToRead -= block_size;
}
return true;
}