Load minidumps whose writer left out a stream - #725
Conversation
|
THIS MESSAGE WAS GENERATED BY AN AUTOMATED PROCESS Validation record for head
The tests get a dump with a missing stream by reading a real one and marking that stream's directory entry Origin of the change: a corpus sweep loaded 5,250 minidumps through Caveats:
Re-keyed 2026-08-28. The figures above were measured at |
|
Corpus decompilation diffs can be found at angr/dec-snapshots@master...angr/cle_725 |
376d41f to
9f41442
Compare
9f41442 to
c9d2bf5
Compare
A minidump's stream directory lists only the streams its writer chose to emit; the header and the directory are the only mandatory parts of the file. The backend read four of them and handled a missing one three different ways: the memory list was required, the module and thread lists were dereferenced unguarded and produced an AttributeError from the middle of a loop, and only the system information stream raised a considered error. A dump with no memory list now loads with no memory, and one with no module or thread list loads with no sections or with no threads. The module list is read on the architecture path as well, where a 64-bit dump without one failed before any of that. MinidumpMissingStreamError, which the missing system information stream still raises when no architecture was passed either, now derives from CLEError and hands its explanation to the base class. It was invisible to except CLEError, and str() on it was empty because the explanation only ever reached an attribute. A module whose image the dump did not capture is still rejected twenty lines further down; #715 covers that half.
c9d2bf5 to
0885272
Compare
|
THIS MESSAGE WAS GENERATED BY AN AUTOMATED PROCESS Full load report for four minidumps before and after this change. Each case takes a real fixture — Before — three of the four dumps die mid-load on a cle at the merge base, 46a3733After — the three load with whatever the dump did record, and the missing with this change, 0885272 |
THIS MESSAGE WAS GENERATED BY AN AUTOMATED PROCESS
Problem
A minidump's directory lists only the streams its writer emitted, and the backend could not cope when one was absent. Striking
ModuleListStreamout of the directory oftests/x86_64/windows/breakpad/tiny-exe-with-cet-xsave.dmp— which is exactly what a reader sees when the writer never collected it:The whole load goes with it: the memory the dump did capture, the register state of the threads it did record, and the section table built from its modules. And the one deliberate rejection was unusable — a missing
SystemInfoStreamraisedMinidumpMissingStreamErrorwithstr(e)=''andisinstance(cle.CLEError) = False.Root cause
Minidump.__init__reaches into stream objects theminidumppackage leaves asNone, at three sites — thewow64.dllscan above,for module in self._mdf.modules.modules:andfor thread in self._mdf.threads.threads:— and a fourth treats a dump that captured no memory as invalid outright:A minidump's only mandatory parts are its header and its stream directory, so each of these fires on a real dump. The error class compounded it:
class MinidumpMissingStreamError(Exception)callingsuper().__init__()with no arguments, so the explanation was stashed on an attributestr()never reached and the exception sat outside theCLEErrorhierarchy.Fix
modulesandthreadsare read once and default to[]when the stream is absent, so such a dump loads with no sections or no threads, and a dump with no memory list loads withsegments = [].MinidumpMissingStreamErrorderives fromCLEErrorand passes its explanation to the base class.A missing
SystemInfoStreamstill raises, because the architecture is the one thing the backend cannot infer, and a module whose image the dump did not capture is still rejected a few lines below.Testing
tests/test_minidump.pygains a test per absent stream:test_minidump_without_module_listassertsld.main_object.threads == [0x5BC]on a dump whose module list is gone,test_minidump_without_thread_listpins the 30 sections that survive ontests/x86/windows/jusched_x86.dmp,test_minidump_without_captured_memorypins the empty segment list, andtest_minidump_without_system_infopins the message and theCLEErrorbase. Each takes a real dump and strikes a stream out of its directory in a temporary copy; both fixtures are onangr/binariesmaster. #715 reworks the same function, so whichever lands second needs a rebase.Validation: #725 (comment)
session: sharpen