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; }