mirror of
https://github.com/Cesarus85/ringfall-mjolnir-vr.git
synced 2026-10-23 01:00:30 +02:00
125 lines
6.0 KiB
Markdown
125 lines
6.0 KiB
Markdown
# `_data_decode_memory` legal-C codegen research
|
|
|
|
## Result
|
|
|
|
The residual is closed by removing the fallback assignment
|
|
`memory_size = count;` after `system_exit(-1)` in the invalid-element-size
|
|
switch arm. With that one source change, XDK 3911 emits the January section
|
|
exactly:
|
|
|
|
- padded size: 304 / 304 bytes;
|
|
- relocations: 19 / 19, including identity and order;
|
|
- normalized SHA-256:
|
|
`eb39377415e6c3e07f763e8f0f42f6ecafaf61acc0fab30fbc06062b9dc465d8`;
|
|
- normalized byte differences: zero;
|
|
- all 15 sibling functions remain strict exact.
|
|
|
|
This was independently reproduced from a generated copy of the complete
|
|
translation unit under this research directory. Production source was not
|
|
edited by this research lane; the one-line candidate was already present as
|
|
another lane's uncommitted edit when the matrix ran.
|
|
|
|
## Reproduction environment and command
|
|
|
|
- Compiler: XDK 3911 `CL.Exe`, banner version 13.00.9254.1 for x86.
|
|
- Flags: `/nologo /c /O2 /Oy- /DDEBUG /Dxbox` plus the same repository include
|
|
roots as the generated campaign build.
|
|
- Target: `build/split/source/memory/data_encoding.obj` from the January 14,
|
|
2002 executable.
|
|
- Comparator: the current hardened `tools/coff_compare.py` implementation,
|
|
using `section_infos_equal` for size, relocation count/identity, normalized
|
|
bytes, and section ownership.
|
|
|
|
Run from the `closure-wave` worktree:
|
|
|
|
```powershell
|
|
& "C:\Users\isabe\.cache\codex-runtimes\codex-primary-runtime\dependencies\python\python.exe" `
|
|
research\data_decode_memory_codegen\run_matrix.py
|
|
```
|
|
|
|
The script creates only ignored disposable sources, objects, and
|
|
`results.json` below `research/data_decode_memory_codegen`. It compiles each
|
|
candidate as the complete translation unit and checks every one of the 16 code
|
|
owners, so a locally improved decoder cannot hide a sibling regression.
|
|
|
|
## Why the source shape matters
|
|
|
|
The fallback assignment keeps `memory_size` semantically live on the default
|
|
edge. VC7 then allocates `state`, `memory`, and `memory_size` to the wrong
|
|
callee-saved register permutation for the January object. With the assignment
|
|
absent, the allocator coalesces the invalid-path value with the `count`
|
|
parameter and produces the January ESI/EDI/EBX allocation, including the
|
|
partial-BX switch and the post-`system_exit` reload:
|
|
|
|
```asm
|
|
call _system_exit
|
|
mov ebx, [ebp+0Ch]
|
|
add esp, 14h
|
|
```
|
|
|
|
That is a general codegen lesson: a statement on a nominally unreachable
|
|
error edge can change live ranges and register allocation across an entire
|
|
function even though normal inputs never execute it.
|
|
|
|
## Original-bug note
|
|
|
|
`system_exit` is intended to terminate, but its current C declaration is an
|
|
ordinary returning `void` function. If it were ever to return for an invalid
|
|
`element_size`, the exact source leaves `memory_size` indeterminate and its
|
|
subsequent use is undefined behavior. The January machine code itself reloads
|
|
`count` on this path, but C does not guarantee that result.
|
|
|
|
The matching source should therefore carry a plain-English bug comment. The
|
|
safe, nonmatching fix is to restore `memory_size = count;` before `break;` (or
|
|
to repair the termination contract project-wide); restoring it currently
|
|
produces the old nonexact hash and must not be mistaken for an exact source.
|
|
|
|
## Bounded experiment matrix
|
|
|
|
All variants used the complete TU and the campaign compiler/flags. `Diffs`
|
|
counts normalized bytes in `_data_decode_memory`; every row retained 19
|
|
relocations.
|
|
|
|
| ID | Source shape | Size | Diffs / first | Nonexact functions | Verdict |
|
|
|---|---|---:|---:|---:|---|
|
|
| v00 | no default fallback assignment | 304 | 0 / none | 0 | **strict exact** |
|
|
| v01 | `byte *memory` | 304 | 0 / none | 0 | code-neutral exact spelling |
|
|
| v02 | `char *memory` | 304 | 0 / none | 0 | code-neutral exact spelling |
|
|
| v03 | buffer pointer born before switch | 288 | 163 / +0x5 | 4 | reject; regresses three siblings |
|
|
| v04 | current pointer born before switch | 304 | 211 / +0x8 | 4 | reject; regresses three siblings |
|
|
| v05 | offset born before switch | 304 | 209 / +0x8 | 3 | reject; regresses two siblings |
|
|
| v06 | split result base-load and offset-add | 304 | 0 / none | 0 | code-neutral exact spelling |
|
|
| v07 | failure-first final gate | 304 | 0 / none | 0 | code-neutral exact spelling |
|
|
| v08 | named final-gate boolean | 304 | 0 / none | 0 | code-neutral exact spelling |
|
|
| v09 | 32-bit count alias live across switch | 288 | 176 / +0x5 | 1 | reject |
|
|
| v10 | initialize `memory_size = 0` | 288 | 114 / +0x8 | 1 | safe but nonexact |
|
|
| v11 | initialize `memory_size = count` | 320 | 279 / +0x8 | 1 | safe but nonexact |
|
|
| v12 | assign zero after `system_exit` | 304 | 94 / +0x5 | 1 | safe but nonexact |
|
|
| v13 | `return NULL` after `system_exit` | 304 | 166 / +0x8 | 1 | safe but nonexact |
|
|
| v14 | restore `memory_size = count` after `system_exit` | 304 | 114 / +0x4 | 1 | old baseline; nonexact |
|
|
|
|
The exact spellings v01/v02/v06/v07/v08 are not recommended changes: they add
|
|
no evidence beyond showing that those local spellings are optimizer-neutral.
|
|
The least invasive exact source is v00.
|
|
|
|
## Do not repeat
|
|
|
|
In addition to v01-v14 above, the prior closeout log already exhausts E01-E17:
|
|
declaration order, split/redundant initializers, `register` hints on locals and
|
|
parameters, short aliases, multiplication/shift spellings, predecessor-TU
|
|
perturbations, `const`, and a `state` alias. It also rules out volatile,
|
|
pragmas, flag changes, inline assembly, aliasing violations, and byte forcing.
|
|
See `docs/object_matching_logs/data_encoding_obj.md` for the measured hashes
|
|
and sibling regressions.
|
|
|
|
## Recommended admission gate
|
|
|
|
Rebuild the real TU, compare all 16 code owners plus all 14 January-owned
|
|
non-code sections with `tools/coff_compare.py`, run the whole-TU regression
|
|
gate and consolidated build, add the bug/fix comment, then mark the object
|
|
Matching only if all strict checks remain green. No fuzzy acceptance is
|
|
permitted: the candidate is genuinely byte- and relocation-exact. Because
|
|
objdiff represents the local jump-table labels differently, the progress
|
|
ledger still needs a fail-closed semantic bookkeeping entry that re-runs the
|
|
hardened comparison on every progress build.
|