KnownThings hard-required PresentationFramework, PresentationCore and
WindowsBase to be resolvable, so decompiling a WPF binary on a machine
without WPF (Linux/macOS) threw "Could not resolve known assembly" and
aborted the whole BAML decompile.
Mirror MinimalCorlib: when a well-known BAML assembly cannot be resolved,
BamlDecompilerTypeSystem substitutes a synthetic stand-in module that
upholds the invariant KnownThings assumes. The stand-in only materializes
the types the decompiler explicitly seeds, so it stays bounded to the
well-known set and references to other types keep degrading to
UnknownType exactly as before. For the WPF assemblies it also reproduces
the XmlnsDefinitionAttribute mapping so known types still serialize under
the presentation xmlns instead of a clr-namespace fallback.
Assisted-by: Claude:claude-opus-4-8:Claude Code
Browsing an embedded .baml resource runs it through BamlReader.ReadDocument,
whose post-parse defer pass walks the record list with NavigateTree. That walk
recursed on every nested StaticResourceStart/KeyElementStart record with no
depth cap and indexed the record list with no bound. A crafted resource could
therefore drive recursion into a StackOverflowException -- which is uncatchable
and kills the process despite the resource node's try/catch -- or walk the index
off the end of the list. Both are reachable from ordinary resource browsing, no
project export required.
Consolidate the duplicated defer walk into one bounded, depth-capped helper that
fails with a catchable InvalidDataException, so the existing UI catch turns a
malformed resource into a "BAML decompilation failed" message instead of a crash.
Reject an oversized signature length before it drives a multi-gigabyte allocation
(it is read before the MSBAML check), and resolve defer offsets with TryGetValue
so a bogus offset reports malformed data rather than escaping as a bare
KeyNotFoundException.
Assisted-by: Claude:claude-opus-4-8:Claude Code