Add a PE fixture whose TLS zero fill is larger than the image - #233
Add a PE fixture whose TLS zero fill is larger than the image#233zardus wants to merge 1 commit into
Conversation
TLS_huge_zero_fill.exe is a byte copy of the tracked TLS.exe with one field changed: the little-endian dword at file offset 0x68ec, IMAGE_TLS_DIRECTORY32.SizeOfZeroFill, goes from 0 to 0xf0000000. On disk that is a single byte, 0x68ef, from 0x00 to 0xf0; the two files are otherwise identical and the same length. cle takes that field at face value, so the fixture asks it for a 3.75 GiB thread local storage block out of a 124 KiB image. tests_src/tls_huge_zero_fill/build.sh records the edit and reproduces the object byte for byte.
|
THIS MESSAGE WAS GENERATED BY AN AUTOMATED PROCESS Validation record for head The fixture is the tracked file plus one byte$ cmp -l tests/x86/windows/TLS.exe tests/x86/windows/TLS_huge_zero_fill.exe
26864 0 360
$ sha256sum tests/x86/windows/TLS.exe tests/x86/windows/TLS_huge_zero_fill.exe
5a9327f87f994a76c84c986a498e105be183a558b520fe6004ceb6e498a7489d tests/x86/windows/TLS.exe
f34b38135cd3bd947061ae4d1880a479a990bf12e463179b60b7b73b64ba8c9b tests/x86/windows/TLS_huge_zero_fill.exe
Shape scan over the tracked objectsHow many tracked PEs declare a TLS block larger than their own Loaded with cle at master
|
tls_data_size |
tls_block_size |
new_thread() |
|
|---|---|---|---|
TLS.exe |
520 | 520 | returns <PETLSObject Object cle##tls, maps [0x600000:0x600607]> |
TLS_huge_zero_fill.exe |
520 | 4,026,532,360 | MemoryError |
Loader succeeds on both. This repository runs no CI, so there is no job to cite.
|
THIS MESSAGE WAS GENERATED BY AN AUTOMATED PROCESS The shape the consumer needs, counted over every tracked file, before and Before — no tracked object has it, so the consumer has nothing to assert on: merge base fc07821After — one does, and it is the tracked this head e2394bdThe two extra tracked files are the fixture and |
THIS MESSAGE WAS GENERATED BY AN AUTOMATED PROCESS
Problem
SizeOfZeroFillin a PE's TLS directory says how much zero fill follows amodule's initial thread-local data. cle adds it to the data size to get
tls_block_sizeand then materialises the whole block. It is a raw 32-bitheader field and nothing bounds it, so a file can ask cle for up to 4 GiB of
zeroes whatever its own size is.
No object this repository tracks can show that. All 1,851 tracked files were
walked at
fc07821: 30 parse as PE and carry a TLS directory, and every oneof the 30 has
SizeOfZeroFill == 0. The largest TLS block among them is 520bytes, in
tests/x86/windows/TLS.exe. The 58 ELF objects with aPT_TLSsegment top out at 4,104 bytes of
p_memsz.Root cause
Nothing here exercises a large
SizeOfZeroFillbecause nothing here has one.The consumer needs an object whose declared TLS block does not fit in its own
SizeOfImage, and atfc07821no tracked file has that shape.Fix
tests/x86/windows/TLS_huge_zero_fill.exeis a byte copy of the trackedtests/x86/windows/TLS.exewith that one field changed: the little-endian dwordat file offset
0x68ecgoes from0to0xf0000000. The low three bytes arealready zero in the original, so on disk this is one byte, and the two files
are the same length:
tests/x86/windows/TLS.exe5a9327f87f994a76c84c986a498e105be183a558b520fe6004ceb6e498a7489dtests/x86/windows/TLS_huge_zero_fill.exef34b38135cd3bd947061ae4d1880a479a990bf12e463179b60b7b73b64ba8c9btests_src/tls_huge_zero_fill/build.shrecords the edit and rebuilds the objectfrom the tracked
TLS.exe. Deleting the fixture and rerunning that scriptreproduces the sha256 above, so there is no provenance to argue about: every byte
either comes from a file this repository already tracks or is the one documented
edit.
Testing
This repository runs no CI. Loaded with cle at master
0e77ade3, the pairbehaves as follows, under
ulimit -v 2621440:tls_data_sizetls_block_sizeloader.tls.new_thread()TLS.exe(control)TLS_huge_zero_fill.exeMemoryErrorLoader(...)itself succeeds on both. The allocation happens later, in theljust(obj.tls_block_size, b"\0")atcle/backends/tls/tls_object.py:46, andthat is where the
MemoryErrorabove is raised — before the second copyClemory.add_backerwould make of the result.The fixture is a hand edit rather than compiler output, and it is committed
rather than made at test time because a test that patches a copy at run time
still loads an object nothing tracks.
The consumer is a cle change that bounds the field and keeps a regression test
over this pair — the control asserts that nothing about a well-formed TLS
directory changes. Its description will reference this pull request, so CI
resolves the fixture from here, and it cannot merge first. Validation: #233 (comment)
session: sharpen