53 lines
3.4 KiB
Markdown
53 lines
3.4 KiB
Markdown
# Independent cross-check: RecordObservedTech
|
|
|
|
GPT-6 Astra, local instruction stream from fingerprinted `dumps/sots.exe`, 2026-09-09.
|
|
MD5 `9969481c39f4b33a8a21c48b62abee4c` exactly matches the analyst's ReVa program metadata;
|
|
the same local file's SHA-256 is `970b7de729956a53094c7eb98aba4270aee98e2fed5daf0d39e290013c90c841`.
|
|
This closes the previously reported missing ReVa/local fingerprint linkage.
|
|
|
|
Fresh disassembly: `verify/results/research-callback/record-observed-tech-objdump.txt`.
|
|
|
|
## Corrections to the first analyst pass
|
|
|
|
- The constructor/push path is **name not found**, NOT vector full capacity. The function scans
|
|
first at observer+0x274 through last at +0x278; +0x27c capacity is not read in this wrapper.
|
|
Empty list or exhausted search reaches 0x007ba274. Capacity handling belongs to 0x007b7320.
|
|
- The observer is stack argument 1 (`[ebp+8]`), not argument 2. Stack argument 2 (`[ebp+0xc]`)
|
|
supplies observation eligibility bytes and the field used to select the with-mask bit.
|
|
- Stack argument 3 is a TechDef-like object whose string starts at **object+4**. It is not a
|
|
bare string pointer: source length is object+0x14 and capacity object+0x18. The comparison uses
|
|
destination string at record+0x0c. Confirm semantic TechDef identity using the caller/schema.
|
|
|
|
## Pinned instructions / static callable boundary
|
|
|
|
Wrapper 0x007ba1a0 uses this in ECX, three stack arguments, returns with **ret 0x0c** at 0x007ba32b.
|
|
Its ECX-derived object supplies the 16-bit turn at +0x0c. The owner callback caller prepares ECX
|
|
from player+8 minus four and pushes (technology, player, player) in reverse argument order.
|
|
|
|
Before searching it requires three non-null arguments and rejects a subject with
|
|
`NPC && !RebAI` (offsets +0xfb/+0xfc, names cross-checked with the existing serializer/address
|
|
contract). It then calls 0x0057e6d0 on argument 3; a nonzero result suppresses recording.
|
|
|
|
Fresh disassembly now resolves that helper: read the technology's name string at def+4,
|
|
find its **first underscore**, and compare the suffix with **`_Root` using `_stricmp`**.
|
|
The literal is at 0x00a00040; imported comparator IAT is 0x009dd328 (MSVCR100.dll entry 115).
|
|
Thus root technologies are excluded, case-insensitively. It is not a costly master-tree query;
|
|
ECX is unused in this helper. Capture: observed-tech-exclusion-objdump.txt and
|
|
observed-tech-exclusion-literal.txt. The underscore scan has no terminator check in the binary;
|
|
valid tech-name syntax is a precondition, not evidence of safe arbitrary-string handling.
|
|
|
|
Search increments by **0x2c**, compares full names via 0x004236a0, and preserves an existing
|
|
element if found. On absence it constructs a stack temporary (0x008562a0), appends via 0x007b7320,
|
|
then operates on the newly appended element at last-0x2c:
|
|
|
|
- first/last turns are 16-bit offsets **+4/+6**;
|
|
- name assignment targets the string at **+0x0c** via 0x00425430;
|
|
- both new and existing paths update last turn **+6** and OR a bit into **+0x28**, using
|
|
subject+0x28 as the x86 shift count;
|
|
- existing-path first-turn/name stay unchanged in this wrapper.
|
|
|
|
Append is followed by conditional destruction of the TEMPORARY string when capacity >=16.
|
|
The temporary lifetime does not permit stealing its buffer into the appended element. Copy/
|
|
reallocation/destruction inside 0x007b7320 must be recovered before implementation.
|
|
|
|
These facts are static ABI/ordering evidence. They do not prove live allocation safety.
|