Summary
In the minimal-PE path, the synthetic string-coverage section is added with no overlap or lower-bound check (PeSynthesizer.py:~415-440):
str_vaddr = align_down(min_s, section_alignment)
str_size = align_up(max_s, section_alignment) - str_vaddr
regions.append({"name": ".rdata", "vaddr": str_vaddr, ...})
The .smdaIAT path immediately above (:~397) does check overlaps before appending its region, so the asymmetry looks unintentional rather than deliberate.
Consequences when a string ref sits low in the image:
align_down of a low RVA (e.g. 0x200) yields RVA 0, which is below SizeOfHeaders. A section overlapping the headers is invalid per the PE spec and Windows rejects it.
- The resulting range can fully contain
.text and .smdaIAT, so strings planted under .text's range are silently lost on mapping.
With string refs at base+0x200 and base+0x50000, LIEF reports .rdata va=00000000 vs=00051000 containing both .text va=00001000 and .smdaIAT va=00003000.
Note on verification
Unlike the sibling issues I filed alongside this one, I confirmed this one by reading the code and by the asymmetry with the .smdaIAT overlap check rather than by re-running it end to end — my attempts to drive the minimal-PE path on the repo fixtures kept landing in the full-PE path, which has a different layout routine. Flagging that explicitly so you can weigh it accordingly; the mechanism is straightforward but I would not call it reproduced by me.
Suggested direction
Mirror the .smdaIAT overlap check, and clamp str_vaddr to at least SizeOfHeaders (or the first section's RVA) so the coverage section can never start at 0 or straddle an existing region.
Related, same subsystem
PeSynthesizer._buildOptionalHeader (:~296-316) copies the original optional header wholesale, so the export/resource/reloc/TLS/debug/IAT/delay-import directory RVAs survive while their targets are now zero-filled; only the IMPORT entry is rewritten. Parsers that follow those directories read zeroed structures instead of failing cleanly. Same subsystem, same "output parses but is not internally consistent" theme.
Found during a whole-repo audit of src/smda/**. Synthesis is documented as experimental, so filing rather than patching.
Summary
In the minimal-PE path, the synthetic string-coverage section is added with no overlap or lower-bound check (
PeSynthesizer.py:~415-440):The
.smdaIATpath immediately above (:~397) does checkoverlapsbefore appending its region, so the asymmetry looks unintentional rather than deliberate.Consequences when a string ref sits low in the image:
align_downof a low RVA (e.g. 0x200) yields RVA 0, which is belowSizeOfHeaders. A section overlapping the headers is invalid per the PE spec and Windows rejects it..textand.smdaIAT, so strings planted under.text's range are silently lost on mapping.With string refs at
base+0x200andbase+0x50000, LIEF reports.rdata va=00000000 vs=00051000containing both.text va=00001000and.smdaIAT va=00003000.Note on verification
Unlike the sibling issues I filed alongside this one, I confirmed this one by reading the code and by the asymmetry with the
.smdaIAToverlap check rather than by re-running it end to end — my attempts to drive the minimal-PE path on the repo fixtures kept landing in the full-PE path, which has a different layout routine. Flagging that explicitly so you can weigh it accordingly; the mechanism is straightforward but I would not call it reproduced by me.Suggested direction
Mirror the
.smdaIAToverlap check, and clampstr_vaddrto at leastSizeOfHeaders(or the first section's RVA) so the coverage section can never start at 0 or straddle an existing region.Related, same subsystem
PeSynthesizer._buildOptionalHeader(:~296-316) copies the original optional header wholesale, so the export/resource/reloc/TLS/debug/IAT/delay-import directory RVAs survive while their targets are now zero-filled; only the IMPORT entry is rewritten. Parsers that follow those directories read zeroed structures instead of failing cleanly. Same subsystem, same "output parses but is not internally consistent" theme.Found during a whole-repo audit of
src/smda/**. Synthesis is documented as experimental, so filing rather than patching.