diff options
author | Samuel Huang <huangs@chromium.org> | 2019-03-25 15:28:52 +0000 |
---|---|---|
committer | Copybara-Service <copybara-worker@google.com> | 2021-07-25 20:53:23 -0700 |
commit | 036cb9d1e02c28cbcace59a7131667869c1f5714 (patch) | |
tree | 448a50a60c4337696ea27d97d8b498feecd3014d /disassembler_win32.cc | |
parent | 0047fda863b1ebb43d2dc015643d3b59ec5734af (diff) | |
download | zucchini-036cb9d1e02c28cbcace59a7131667869c1f5714.tar.gz |
[Zucchini] Restrict PE rel32 scan size to min(virtual_size, size_of_raw_data).
For PE files, rel32 scanning previously scans .text data spanning
|size_of_raw_data| bytes. However, it's possible for |virtual_size| <
|size_of_raw_data|. In this case, any rel32 references found in the
data beyond |virtual_size| would have an invalid RVA.
The problem does not cause crashes, but leads to bogus rel32 locations
to be emitted, if their bogus target happen to be valid.
This CL fixes the issue by reducing range of rel32 scan size to
|min(virtual_size, size_of_raw_data)|, thereby avoiding extracting
these invalid rel32 references.
A DCHECK is added to ParseAndStoreRel32() to validate extracted rel32
locations for {DisassemblerWin32, DisassemblerElfIntel}. This guards
against coding error (bad data should have been blocked).
Bug: 935283
Change-Id: I1587f62cb61f6cbda892b26e3d8c08cc31e0528e
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/1535753
Reviewed-by: Etienne Pierre-Doray <etiennep@chromium.org>
Commit-Queue: Samuel Huang <huangs@chromium.org>
Cr-Commit-Position: refs/heads/master@{#643848}
NOKEYCHECK=True
GitOrigin-RevId: 96528abcb3e87ac56ded12f935c3443f3c96eebf
Diffstat (limited to 'disassembler_win32.cc')
-rw-r--r-- | disassembler_win32.cc | 8 |
1 files changed, 7 insertions, 1 deletions
diff --git a/disassembler_win32.cc b/disassembler_win32.cc index 645ea07..da830bf 100644 --- a/disassembler_win32.cc +++ b/disassembler_win32.cc @@ -373,8 +373,13 @@ bool DisassemblerWin32<Traits>::ParseAndStoreRel32() { rva_t start_rva = section.virtual_address; rva_t end_rva = start_rva + section.virtual_size; + // |virtual_size < size_of_raw_data| is possible. In this case, disassembly + // should not proceed beyond |virtual_size|, so rel32 location RVAs remain + // translatable to file offsets. + uint32_t size_to_use = + std::min(section.virtual_size, section.size_of_raw_data); ConstBufferView region = - image_[{section.file_offset_of_raw_data, section.size_of_raw_data}]; + image_[{section.file_offset_of_raw_data, size_to_use}]; Abs32GapFinder gap_finder(image_, region, abs32_locations_, Traits::kVAWidth); typename Traits::RelFinder finder; @@ -388,6 +393,7 @@ bool DisassemblerWin32<Traits>::ParseAndStoreRel32() { rel32 = finder.GetNext()) { offset_t rel32_offset = offset_t(rel32->location - image_.begin()); rva_t rel32_rva = location_offset_to_rva.Convert(rel32_offset); + DCHECK_NE(rel32_rva, kInvalidRva); rva_t target_rva = rel32_rva + 4 + image_.read<uint32_t>(rel32_offset); if (target_rva_checker.IsValid(target_rva) && (rel32->can_point_outside_section || |