Analyze keyed usercmd timestamps fields and compressed streams
Browse files- docs/ASSET_PIPELINE_TODO.md +2 -0
- docs/FINDINGS.md +6 -0
- docs/PROVISIONAL_TODO.md +2 -0
- docs/RESEARCH_LEDGER.md +6 -0
- docs/REVERSE_ENGINEERING_TODO.md +5 -0
- docs/research/MESSAGE_DELTA_KEY.md +2 -0
- docs/research/MESSAGE_USERCMD.md +51 -0
- docs/research/README.md +2 -0
- docs/research/message-usercmd.json +0 -0
- scripts/analyze_collision_composition.py +4 -4
- scripts/analyze_message_usercmd.py +83 -0
- scripts/test_message_usercmd.py +83 -0
docs/ASSET_PIPELINE_TODO.md
CHANGED
|
@@ -238,3 +238,5 @@ Research progress: [numeric message codecs](research/MESSAGE_NUMERIC.md) adds ra
|
|
| 238 |
Research progress: [scalar message deltas](research/MESSAGE_DELTA.md) adds integer/finite-float and modeled-tree compressed contracts (RE-385–387). RE-388 retains keyed/higher-level/caller/actual-packet/runtime/platform work; broad network conversion remains open.
|
| 239 |
|
| 240 |
Research progress: [keyed message deltas](research/MESSAGE_DELTA_KEY.md) adds integer mask/XOR and finite float compressed contracts (RE-389–391). RE-392 retains caller/index/runtime/higher-level/packet/platform work; broad networking conversion remains open.
|
|
|
|
|
|
|
|
|
| 238 |
Research progress: [scalar message deltas](research/MESSAGE_DELTA.md) adds integer/finite-float and modeled-tree compressed contracts (RE-385–387). RE-388 retains keyed/higher-level/caller/actual-packet/runtime/platform work; broad network conversion remains open.
|
| 239 |
|
| 240 |
Research progress: [keyed message deltas](research/MESSAGE_DELTA_KEY.md) adds integer mask/XOR and finite float compressed contracts (RE-389–391). RE-392 retains caller/index/runtime/higher-level/packet/platform work; broad networking conversion remains open.
|
| 241 |
+
|
| 242 |
+
Research progress: [keyed usercmd codecs](research/MESSAGE_USERCMD.md) completes bounded RE-393–395 (time/key dispatch, record fields/narrowing and 204 modeled-tree streams). RE-392/396 retain legal callers, packet baselines/higher-level codecs and actual runtime/platform work; broad networking and rendering milestones remain open.
|
docs/FINDINGS.md
CHANGED
|
@@ -444,3 +444,9 @@ Bounded qagame paths recover bomb-plant/inactivity correction requests, direct f
|
|
| 444 |
**F-152 — Observed keyed finite float delta:** numeric equality omits payload and preserves baseline bits; changed words XOR the full key before/after 32-bit transport, without the integer mask table. Nonfinite/control-state/caller/platform behavior remains open. [KEY-002](research/MESSAGE_DELTA_KEY.md).
|
| 445 |
|
| 446 |
**F-153 — Observed keyed compressed composition:** independent modeled-codeword packing agrees with native wrapper/bit/Huffman slices and paired bytes/cursors. Integer width-32 decode returns can differ for identical bytes due to actual adjacent file words; legal game-level reachability remains unverified. Native training/packet/overflow/EOF/runtime/platform contracts remain open. [KEY-003](research/MESSAGE_DELTA_KEY.md).
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 444 |
**F-152 — Observed keyed finite float delta:** numeric equality omits payload and preserves baseline bits; changed words XOR the full key before/after 32-bit transport, without the integer mask table. Nonfinite/control-state/caller/platform behavior remains open. [KEY-002](research/MESSAGE_DELTA_KEY.md).
|
| 445 |
|
| 446 |
**F-153 — Observed keyed compressed composition:** independent modeled-codeword packing agrees with native wrapper/bit/Huffman slices and paired bytes/cursors. Integer width-32 decode returns can differ for identical bytes due to actual adjacent file words; legal game-level reachability remains unverified. Native training/packet/overflow/EOF/runtime/platform contracts remain open. [KEY-003](research/MESSAGE_DELTA_KEY.md).
|
| 447 |
+
|
| 448 |
+
**F-154 — Usercmd time and key dispatch:** signed modulo-32 delta <=255 selects low-eight-bit timestamp encoding; larger positive deltas use a full time word. Field keys XOR writer new time / reader decoded time; synthetic negative deltas can separate these values. Legal caller behavior remains open. [CMD-001](research/MESSAGE_USERCMD.md).
|
| 449 |
+
|
| 450 |
+
**F-155 — Usercmd masks and stores:** eight fields in a 24-byte record use widths 16/8; movement sign-extends before XOR. Mask16's extra key bit survives full-word stores, while mask8's extra bit is discarded by byte stores. Unchanged aggregate copies the remaining 20 bytes; no keyed mask32 field appears in these graphs. Semantic names and legal high keys remain unverified. [CMD-002](research/MESSAGE_USERCMD.md).
|
| 451 |
+
|
| 452 |
+
**F-156 — Usercmd composition and accounting:** 204 synthetic modeled-tree streams agree with independent request/packing/full-record/cursor/diagnostic/canary oracles in both engines. Unchanged commands add seven to oldsize beyond requested widths. No original process/native callee, runtime traffic or full native training executes. [CMD-003](research/MESSAGE_USERCMD.md).
|
docs/PROVISIONAL_TODO.md
CHANGED
|
@@ -550,3 +550,5 @@ Research progress: [numeric message codecs](research/MESSAGE_NUMERIC.md) complet
|
|
| 550 |
Research progress: [scalar message deltas](research/MESSAGE_DELTA.md) completes bounded RE-385–387. RE-388 leaves keyed/usercmd/entity/player/snapshot and complete caller/overflow/EOF/floating/runtime/platform contracts open.
|
| 551 |
|
| 552 |
Research progress: [keyed message deltas](research/MESSAGE_DELTA_KEY.md) completes bounded RE-389–391. RE-392 leaves keyed caller/narrowing/index reachability, higher-level codecs and actual runtime/packet/platform contracts open.
|
|
|
|
|
|
|
|
|
| 550 |
Research progress: [scalar message deltas](research/MESSAGE_DELTA.md) completes bounded RE-385–387. RE-388 leaves keyed/usercmd/entity/player/snapshot and complete caller/overflow/EOF/floating/runtime/platform contracts open.
|
| 551 |
|
| 552 |
Research progress: [keyed message deltas](research/MESSAGE_DELTA_KEY.md) completes bounded RE-389–391. RE-392 leaves keyed caller/narrowing/index reachability, higher-level codecs and actual runtime/packet/platform contracts open.
|
| 553 |
+
|
| 554 |
+
Research progress: [keyed usercmd codecs](research/MESSAGE_USERCMD.md) completes bounded RE-393–395 (time/key dispatch, record fields/narrowing and 204 modeled-tree streams). RE-392/396 retain legal callers, packet baselines/higher-level codecs and actual runtime/platform work; broad networking and rendering milestones remain open.
|
docs/RESEARCH_LEDGER.md
CHANGED
|
@@ -253,3 +253,9 @@ Completed bounded RE-385–387 with `analyze_message_delta.py`: 22 verified grap
|
|
| 253 |
## 2026-10-11 — Keyed deltas, direct mask indexing and adjacent data
|
| 254 |
|
| 255 |
Completed bounded RE-389–391 with `analyze_message_delta_key.py`: 22 verified graphs across the Linux ELF64 engines, two symbol/file-backed 32-word mask tables plus adjacent entityStateFields words, 288 compressed keyed streams and 48 supplied-reader control probes. KEY-001–003/F-151–153 distinguish comparison before XOR from keyed payload encoding, direct width indexing from an inferred width-minus-one mask, extra returned key bits from caller-visible effects, and width-32 adjacent file reads from a valid mask entry. Identical encoded width-32 integer streams can return different words between images because the adjacent low words differ; legal caller/index/narrowing/runtime reachability remains unverified. Finite keyed float payloads XOR the complete word and recover changed values; numeric equality/signed zeros retain baseline bits without using the integer mask table. Independent flag/remainder/modeled-codeword packing, exact decode formula, cursor/accounting/XOR-range diagnostic and canary oracles validate the sampled instruction compositions. Source/disassembly and dependency identities/hashes are retained; compressed trees remain MODEL-DERIVED. Frame saves/restores/PUSH/POP are omitted, stopped helper/tail boundaries and caller-register restoration are explicit, and no original process or native callee executes. Eight tests verify table/symbol/adjacent file bytes, keyed decisions/requests, float behavior, independent packing/cursors, integer decode masks, supplied flags, accounting/diagnostics/dependencies and paired payloads with source-specific width-32 results. All 390 tests pass; new and preceding reports regenerate byte-identically, with storage/link/whitespace checks passing. RE-388 remains open; RE-392 tracks caller widths/keys/narrowing/index reachability/runtime adjacent effects, usercmd/entity/player/snapshot codecs, remaining scalar/overflow/EOF/nonfinite controls, native seeded codewords and actual packet/runtime/all-platform/renderer contracts before Rust mask compatibility decisions.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 253 |
## 2026-10-11 — Keyed deltas, direct mask indexing and adjacent data
|
| 254 |
|
| 255 |
Completed bounded RE-389–391 with `analyze_message_delta_key.py`: 22 verified graphs across the Linux ELF64 engines, two symbol/file-backed 32-word mask tables plus adjacent entityStateFields words, 288 compressed keyed streams and 48 supplied-reader control probes. KEY-001–003/F-151–153 distinguish comparison before XOR from keyed payload encoding, direct width indexing from an inferred width-minus-one mask, extra returned key bits from caller-visible effects, and width-32 adjacent file reads from a valid mask entry. Identical encoded width-32 integer streams can return different words between images because the adjacent low words differ; legal caller/index/narrowing/runtime reachability remains unverified. Finite keyed float payloads XOR the complete word and recover changed values; numeric equality/signed zeros retain baseline bits without using the integer mask table. Independent flag/remainder/modeled-codeword packing, exact decode formula, cursor/accounting/XOR-range diagnostic and canary oracles validate the sampled instruction compositions. Source/disassembly and dependency identities/hashes are retained; compressed trees remain MODEL-DERIVED. Frame saves/restores/PUSH/POP are omitted, stopped helper/tail boundaries and caller-register restoration are explicit, and no original process or native callee executes. Eight tests verify table/symbol/adjacent file bytes, keyed decisions/requests, float behavior, independent packing/cursors, integer decode masks, supplied flags, accounting/diagnostics/dependencies and paired payloads with source-specific width-32 results. All 390 tests pass; new and preceding reports regenerate byte-identically, with storage/link/whitespace checks passing. RE-388 remains open; RE-392 tracks caller widths/keys/narrowing/index reachability/runtime adjacent effects, usercmd/entity/player/snapshot codecs, remaining scalar/overflow/EOF/nonfinite controls, native seeded codewords and actual packet/runtime/all-platform/renderer contracts before Rust mask compatibility decisions.
|
| 256 |
+
|
| 257 |
+
## 2026-10-11 — Keyed usercmd timestamp, fields and compressed composition
|
| 258 |
+
|
| 259 |
+
Completed bounded RE-393–395 with `analyze_message_usercmd.py`: 18 verified graphs across the Linux ELF64 engines and 204 compressed usercmd streams. CMD-001–003/F-154–156 recover signed timestamp short/full dispatch, timestamp-derived keys, aggregate and eight per-field gates, the observed 24-byte layout, signed movement XOR and byte-versus-word narrowing. Synthetic negative deltas can separate decoded/new timestamps and therefore reader/writer keys; legal caller time/key behavior and field semantic confirmation remain open. Actual mask8/mask16 bytes and native/disassembly/dependency hashes are retained. Byte stores discard the extra key bit while full-word stores retain it. Unchanged commands add seven directly to oldsize beyond requested widths. Compositions stop at child boundaries, omit PUSH/POP/save/restores and explicitly preserve caller registers across disjoint synthetic frames; trees remain MODEL-DERIVED and no original process/native callee executes. Eight independent tests verify timestamp boundaries/wrap, aggregate/per-field requests, complete decoded records, raw/codeword packing/cursors, accounting/diagnostics/canaries/source retention, file/dependency identities, paired outcomes and low-byte XOR support. All 398 tests pass. RE-392 remains open; RE-396 tracks caller keys/timestamps/legal domains, packet bundling/baselines, semantic confirmation, entity/player/snapshot tables/codecs, alias/truncation/EOF/overflow/reset behavior, native training and actual packet/runtime/all-platform/renderer contracts before Rust compatibility decisions.
|
| 260 |
+
|
| 261 |
+
Validation: all preceding composition reports regenerated byte-identically; the new usercmd report reproduced twice byte-identically. Storage policy (including normal-Git size/filter setup), documentation links and whitespace checks pass.
|
docs/REVERSE_ENGINEERING_TODO.md
CHANGED
|
@@ -472,3 +472,8 @@ Purpose: turn the supplied installation into an evidence-backed specification of
|
|
| 472 |
- [x] RE-390 Recover keyed finite float comparisons, baseline retention and full-word XOR payloads ([KEY-002](research/MESSAGE_DELTA_KEY.md)).
|
| 473 |
- [x] RE-391 Compose modeled-tree keyed streams with independent packing/cursors and source-dependent integer width-32 return checks ([KEY-003](research/MESSAGE_DELTA_KEY.md)).
|
| 474 |
- [ ] RE-392 Recover keyed callers/widths/keys/narrowing and zero/negative/out-of-range mask-index reachability, runtime adjacent-data effects, usercmd/entity/player/snapshot codecs, remaining scalar/overflow/EOF/nonfinite/control-state behavior, native seeded codewords and actual packet/runtime/all-platform/renderer contracts; resolve caller evidence before Rust mask compatibility decisions.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 472 |
- [x] RE-390 Recover keyed finite float comparisons, baseline retention and full-word XOR payloads ([KEY-002](research/MESSAGE_DELTA_KEY.md)).
|
| 473 |
- [x] RE-391 Compose modeled-tree keyed streams with independent packing/cursors and source-dependent integer width-32 return checks ([KEY-003](research/MESSAGE_DELTA_KEY.md)).
|
| 474 |
- [ ] RE-392 Recover keyed callers/widths/keys/narrowing and zero/negative/out-of-range mask-index reachability, runtime adjacent-data effects, usercmd/entity/player/snapshot codecs, remaining scalar/overflow/EOF/nonfinite/control-state behavior, native seeded codewords and actual packet/runtime/all-platform/renderer contracts; resolve caller evidence before Rust mask compatibility decisions.
|
| 475 |
+
|
| 476 |
+
- [x] RE-393 Recover bounded native keyed usercmd timestamp short/full dispatch, signed delta and timestamp-derived key evidence; document synthetic negative/wrap effects without claiming legal traffic. [CMD-001](research/MESSAGE_USERCMD.md).
|
| 477 |
+
- [x] RE-394 Recover 24-byte record offsets, aggregate/eight field gates, widths, signed movement and byte/word mask narrowing from both Linux ELF64 engines. [CMD-002](research/MESSAGE_USERCMD.md).
|
| 478 |
+
- [x] RE-395 Compose 204 modeled-tree keyed usercmd streams; independently verify requests, payload/record/cursor/accounting/diagnostic/canary/paired results and low-byte XOR evaluator support. [CMD-003](research/MESSAGE_USERCMD.md).
|
| 479 |
+
- [ ] RE-396 Trace usercmd caller keys/timestamps/legal ranges, confirm semantic fields and packet baselines/bundling; recover entity/player/snapshot codecs and tables, alias/EOF/overflow/reset contracts, native seed and real packet/runtime/all-platform behavior before Rust compatibility decisions.
|
docs/research/MESSAGE_DELTA_KEY.md
CHANGED
|
@@ -54,3 +54,5 @@ Twenty-four reader control probes per engine supply flags 0/1/2/0xffffffff, thre
|
|
| 54 |
Eight independent tests verify symbol/file-backed table and adjacent bytes, integer decision/request XOR, finite float/signed-zero behavior, independent compressed packing/cursors, exact integer decode masks, supplied flags, accounting/XOR diagnostics/dependency hashes, and paired payloads with explicitly source-dependent width-32 results. No evaluator extension was needed.
|
| 55 |
|
| 56 |
RE-392: recover keyed delta caller widths/keys and narrowing, mask-index zero/negative/out-of-range reachability, runtime adjacent-data effects, usercmd/entity/player/snapshot codecs, remaining scalar/overflow/EOF/nonfinite/control-state behavior, native trained codewords and actual packet/runtime/all-platform/renderer contracts. Resolve caller evidence before normalizing or preserving the observed mask behavior in Rust.
|
|
|
|
|
|
|
|
|
| 54 |
Eight independent tests verify symbol/file-backed table and adjacent bytes, integer decision/request XOR, finite float/signed-zero behavior, independent compressed packing/cursors, exact integer decode masks, supplied flags, accounting/XOR diagnostics/dependency hashes, and paired payloads with explicitly source-dependent width-32 results. No evaluator extension was needed.
|
| 55 |
|
| 56 |
RE-392: recover keyed delta caller widths/keys and narrowing, mask-index zero/negative/out-of-range reachability, runtime adjacent-data effects, usercmd/entity/player/snapshot codecs, remaining scalar/overflow/EOF/nonfinite/control-state behavior, native trained codewords and actual packet/runtime/all-platform/renderer contracts. Resolve caller evidence before normalizing or preserving the observed mask behavior in Rust.
|
| 57 |
+
|
| 58 |
+
Follow-up: [keyed usercmd evidence](MESSAGE_USERCMD.md) resolves bounded field widths and store narrowing for this caller family, with timestamp-derived keys. It does not close the broader legal-index/caller/runtime tasks in RE-392.
|
docs/research/MESSAGE_USERCMD.md
ADDED
|
@@ -0,0 +1,51 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# Keyed user-command codec
|
| 2 |
+
|
| 3 |
+
Scope: RE-393–395 / F-154–156. Evidence: verified disassembly and file-backed mask bytes from both Linux ELF64 engines, recorded in [message-usercmd.json](message-usercmd.json). Reproduce with `python3 scripts/analyze_message_usercmd.py`; verify with `python3 scripts/test_message_usercmd.py`.
|
| 4 |
+
|
| 5 |
+
## CMD-001 — Timestamp dispatch and key derivation
|
| 6 |
+
|
| 7 |
+
`MSG_WriteDeltaUsercmdKey` subtracts baseline time from new time modulo 32 bits and compares the signed result with 255. Values at or below 255 emit a one-bit 1 followed by the low eight delta bits; greater values emit a one-bit 0 followed by the complete new 32-bit time. The reader adds an eight-bit delta to baseline time modulo 32 bits, or takes the full time. This is a signed comparison, not a verified requirement that deltas be nonnegative.
|
| 8 |
+
|
| 9 |
+
Synthetic -1 delta fixtures therefore decode baseline+255 rather than the supplied new timestamp. A wrap from 0xfffffffe to 1 produces delta 3 and recovers 1. These results describe instruction behavior; actual callers' monotonicity, reset and legal time ranges remain open.
|
| 10 |
+
|
| 11 |
+
After the timestamp, a one-bit aggregate flag controls the remaining fields. The writer derives the effective key from supplied key XOR **new** timestamp; the reader uses supplied key XOR **decoded** timestamp. Thus a synthetic short-time discrepancy can also change subsequent keyed fields. There are no calls to the scalar keyed-delta helpers in these graphs: field encoding is inlined through WriteBits/ReadBits.
|
| 12 |
+
|
| 13 |
+
Evidence anchors: writer entries dedicated `0x4422d2`, client `0x453c92`; signed delta comparisons `0x4422e9` / `0x453ca9`. Reader entries `0x44200c` / `0x4539cc`.
|
| 14 |
+
|
| 15 |
+
## CMD-002 — Record layout, flags and narrowing
|
| 16 |
+
|
| 17 |
+
The observed record spans 24 bytes. Semantic labels below are inferred user-command interpretations; offsets, sizes and wire order come directly from native loads/stores and child requests.
|
| 18 |
+
|
| 19 |
+
| Record offset | Stored bytes | Inferred field | Changed payload bits | Wire order after aggregate flag |
|
| 20 |
+
| --- | --- | --- | --- | --- |
|
| 21 |
+
| 0 | 4 | server time | 8-bit delta or full 32-bit time | Before aggregate flag |
|
| 22 |
+
| 4 | 4 | angle 0 | 16 | 1 |
|
| 23 |
+
| 8 | 4 | angle 1 | 16 | 2 |
|
| 24 |
+
| 12 | 4 | angle 2 | 16 | 3 |
|
| 25 |
+
| 21 | 1 | forward movement | 8 | 4 |
|
| 26 |
+
| 22 | 1 | right movement | 8 | 5 |
|
| 27 |
+
| 23 | 1 | up movement | 8 | 6 |
|
| 28 |
+
| 16 | 4 | buttons | 16 | 7 |
|
| 29 |
+
| 20 | 1 | weapon | 8 | 8 |
|
| 30 |
+
|
| 31 |
+
Aggregate equality compares the full word fields, the three movement bytes and the weapon byte. A word load at +20 clears its low byte through XORB to compare movement separately from weapon. Each field then has its own one-bit flag. Equality emits only 0 and copies the complete stored baseline field during reading. Changes emit 1 and the low width bits of new value XOR effective key. Movement bytes are sign-extended before XOR; weapon is zero-extended.
|
| 32 |
+
|
| 33 |
+
The reader uses actual `kbitmask[8]=0x1ff` and `kbitmask[16]=0x1ffff`, consistent with [keyed scalar findings](MESSAGE_DELTA_KEY.md). The word fields store a full 32-bit result, preserving the extra key bit at bit 16. Changed movement/weapon results store only a byte, discarding bit 8. None of these field paths index mask32; the full timestamp is read directly without the keyed mask. For matching decoded/new timestamps, changed word output is `(new & 0xffff) | (effective_key & 0x10000)`; changed bytes recover the supplied byte. This alone does not establish which high key bits are reachable during gameplay.
|
| 34 |
+
|
| 35 |
+
File-backed masks: dedicated addresses `0x6cf620` / `0x6cf640`, client `0x7a4680` / `0x7a46a0` for widths 8 / 16. Source identities, mask symbol and file offsets are in the report. If the aggregate flag is zero, the reader retains the decoded timestamp and copies all remaining 20 baseline bytes.
|
| 36 |
+
|
| 37 |
+
## CMD-003 — Bounded compressed compositions
|
| 38 |
+
|
| 39 |
+
Per engine, 102 streams cover deltas 0, 1, 255, 256 and -1; unchanged fields, each of eight individual field changes and all-field changes; keys 0 and 0x10100. Two additional wrap fixtures use keys 0 and 0xffffffff and start at bit 7. This is 204 streams total, using 18 verified graphs across the two images.
|
| 40 |
+
|
| 41 |
+
The script composes native usercmd, bit and Huffman instruction slices against relocated **MODEL-DERIVED** seeded trees. An independent test oracle builds the timestamp/aggregate/per-field requests, packs raw remainder bits and modeled codewords, and predicts the complete decoded record using separate writer/reader timestamp-derived keys. Checks cover exact bytes, final bit/size/readcount, unchanged source records, destination and buffer canaries, diagnostics and paired engine outcomes.
|
| 42 |
+
|
| 43 |
+
An unchanged command emits three requests (timestamp flag, timestamp payload, aggregate flag) and then adds seven directly to global `oldsize` (`0x44258a` / `0x453f4a`). A changed command emits eleven plus the number of changed fields. `oldsize` otherwise sums requested widths, rather than compressed lengths; XOR payloads and negative short deltas can increment the existing range diagnostic without setting message overflow in these ample-buffer fixtures.
|
| 44 |
+
|
| 45 |
+
The shared evaluator adds low-byte XORB support, preserving other register bytes and handling zero-flag dispatch. Its focused check exercises that instruction independently.
|
| 46 |
+
|
| 47 |
+
## Remaining work and compatibility limits
|
| 48 |
+
|
| 49 |
+
No original executable or native callee runs. PUSH/POP and stack save/restores are omitted; synthetic frames and explicit caller-register restoration compose stopped child boundaries. Training remains model-derived, not a complete native seed run. The fixtures use ample initialized buffers and disjoint records. They do not validate truncated/EOF/overflow packets, overlapping pointers, caller key provenance/time invariants, real multiplayer traffic, or other platforms.
|
| 50 |
+
|
| 51 |
+
RE-392 remains open for broader keyed callers. RE-396 must trace actual usercmd callers and key provenance, confirm field semantics against QVM/native consumers, recover packet bundling/baselines and entity/player/snapshot field tables, establish legal high-key/timestamp behavior, and compare runtime captures before Rust codec compatibility decisions. Bevy/Solari rendering and macOS/Linux game execution remain separate open milestones.
|
docs/research/README.md
CHANGED
|
@@ -151,3 +151,5 @@ The extension collector adds five focused tests for native tail calls, command-r
|
|
| 151 |
[Scalar delta flags and compressed compositions](MESSAGE_DELTA.md) adds RE-385–387: integer changes, finite float equality/signed zeros and modeled-tree byte/cursor composition. Reproduce with `python3 scripts/analyze_message_delta.py`; check with `python3 scripts/test_message_delta.py`. Keyed/higher-level/overflow/EOF/nonfinite and actual packet/runtime/platform contracts remain open.
|
| 152 |
|
| 153 |
[Keyed delta masks, XOR and compressed compositions](MESSAGE_DELTA_KEY.md) adds RE-389–391: actual integer table/bounds/adjacent reads, finite float XOR and modeled-tree payload/cursor checks. Reproduce with `python3 scripts/analyze_message_delta_key.py`; check with `python3 scripts/test_message_delta_key.py`. Caller/narrowing/index/higher-level and actual packet/runtime/platform contracts remain open.
|
|
|
|
|
|
|
|
|
| 151 |
[Scalar delta flags and compressed compositions](MESSAGE_DELTA.md) adds RE-385–387: integer changes, finite float equality/signed zeros and modeled-tree byte/cursor composition. Reproduce with `python3 scripts/analyze_message_delta.py`; check with `python3 scripts/test_message_delta.py`. Keyed/higher-level/overflow/EOF/nonfinite and actual packet/runtime/platform contracts remain open.
|
| 152 |
|
| 153 |
[Keyed delta masks, XOR and compressed compositions](MESSAGE_DELTA_KEY.md) adds RE-389–391: actual integer table/bounds/adjacent reads, finite float XOR and modeled-tree payload/cursor checks. Reproduce with `python3 scripts/analyze_message_delta_key.py`; check with `python3 scripts/test_message_delta_key.py`. Caller/narrowing/index/higher-level and actual packet/runtime/platform contracts remain open.
|
| 154 |
+
|
| 155 |
+
[Keyed user-command codecs](MESSAGE_USERCMD.md) adds RE-393–395. Reproduce with `python3 scripts/analyze_message_usercmd.py`; check with `python3 scripts/test_message_usercmd.py`. Caller/time/key provenance, packet/entity/player/snapshot and runtime/platform validation remain open.
|
docs/research/message-usercmd.json
ADDED
|
The diff for this file is too large to render.
See raw diff
|
|
|
scripts/analyze_collision_composition.py
CHANGED
|
@@ -124,11 +124,11 @@ def evaluate(graph,start,stops,memory,registers,limit=128,capture_registers=Fals
|
|
| 124 |
elif op=='sarq':
|
| 125 |
a,b=args.split(', ');v=read(b,8);v=v if v<2**63 else v-2**64
|
| 126 |
write(b,v>>(read(a,8)&63),8);equal=None;signed_le=signed_lt=negative=None;ge=greater=below=None
|
| 127 |
-
elif op in ['xorl','orl','orb','andl','subl','addl','addq','subq']:
|
| 128 |
-
width=8 if op in ['addq','subq'] else 1 if op
|
| 129 |
a,b=args.split(', ')
|
| 130 |
-
v,w=(0,0) if op
|
| 131 |
-
result=v^w if op
|
| 132 |
write(b,result,width);equal=(result&((1<<(width*8))-1))==0
|
| 133 |
signed_le=signed_lt=negative=None;ge=greater=below=None
|
| 134 |
elif op=='xorps':
|
|
|
|
| 124 |
elif op=='sarq':
|
| 125 |
a,b=args.split(', ');v=read(b,8);v=v if v<2**63 else v-2**64
|
| 126 |
write(b,v>>(read(a,8)&63),8);equal=None;signed_le=signed_lt=negative=None;ge=greater=below=None
|
| 127 |
+
elif op in ['xorl','xorb','orl','orb','andl','subl','addl','addq','subq']:
|
| 128 |
+
width=8 if op in ['addq','subq'] else 1 if op in ['orb','xorb'] else 4
|
| 129 |
a,b=args.split(', ')
|
| 130 |
+
v,w=(0,0) if op in ['xorl','xorb'] and a==b else (read(a,width),read(b,width))
|
| 131 |
+
result=v^w if op in ['xorl','xorb'] else v|w if op in ['orl','orb'] else v&w if op=='andl' else w-v if op in ['subl','subq'] else v+w
|
| 132 |
write(b,result,width);equal=(result&((1<<(width*8))-1))==0
|
| 133 |
signed_le=signed_lt=negative=None;ge=greater=below=None
|
| 134 |
elif op=='xorps':
|
scripts/analyze_message_usercmd.py
ADDED
|
@@ -0,0 +1,83 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
#!/usr/bin/env python3
|
| 2 |
+
"""Bounded keyed usercmd instruction compositions; no original code executes."""
|
| 3 |
+
import gzip
|
| 4 |
+
import hashlib
|
| 5 |
+
import json
|
| 6 |
+
from pathlib import Path
|
| 7 |
+
from analyze_native import elf
|
| 8 |
+
from analyze_bsp_loading import read_address
|
| 9 |
+
from analyze_bsp_references import global_address, trace_fields
|
| 10 |
+
from analyze_collision_composition import get_word, put_word
|
| 11 |
+
from analyze_engine_control import control_flow
|
| 12 |
+
from analyze_message_byte_codec import MSG, DATA, install_tree
|
| 13 |
+
from analyze_message_numeric import frame_graph
|
| 14 |
+
from analyze_message_widths import reader, run, writer
|
| 15 |
+
from analyze_message_wrappers import WRAPPER_STACK
|
| 16 |
+
from analyze_qvm import write_json
|
| 17 |
+
from analyze_vm_extensions import native_functions, verified
|
| 18 |
+
|
| 19 |
+
BASE=0xd0000
|
| 20 |
+
NEW=0xe0000
|
| 21 |
+
DEST=0xf0000
|
| 22 |
+
FIELDS=[(4,4,16),(8,4,16),(12,4,16),(21,1,8),(22,1,8),(23,1,8),(16,4,16),(20,1,8)]
|
| 23 |
+
|
| 24 |
+
|
| 25 |
+
def compose(graphs,m,key,reading=False):
|
| 26 |
+
name='MSG_ReadDeltaUsercmdKey' if reading else 'MSG_WriteDeltaUsercmdKey'
|
| 27 |
+
g,omitted=frame_graph(graphs[name]);rows=g['instructions'];calls={x['address']:i for i,x in enumerate(rows) if x['opcode']=='callq'};tails={x['address'] for x in rows if x['opcode']=='jmp' and '<MSG_WriteBits>' in x['operands']};ends={x['address'] for x in rows if x['opcode']=='retq'}
|
| 28 |
+
regs={'%rdi':MSG,'%rsi':key,'%rdx':BASE,'%rcx':DEST if reading else NEW,'%rsp':WRAPPER_STACK};pc=rows[0]['address'];requests=[];trace=[]
|
| 29 |
+
while True:
|
| 30 |
+
t=run(g,pc,list(calls)+list(tails)+list(ends),m,regs);m=t['memory'];regs=t['registers'];trace+=t['trace']
|
| 31 |
+
if t['stop'] in ends:break
|
| 32 |
+
request=[regs[k] for k in (['rdi','rsi'] if reading else ['rdi','rsi','rdx'])];requests.append(request)
|
| 33 |
+
if request[0]!=MSG:raise ValueError('usercmd pointer')
|
| 34 |
+
if reading:
|
| 35 |
+
m,value,error,child=reader(graphs,m,request[1]);regs['rax']=value
|
| 36 |
+
else:m,_,error,child=writer(graphs,m,request[2],request[1])
|
| 37 |
+
trace+=child
|
| 38 |
+
if error:raise ValueError('usercmd child error')
|
| 39 |
+
if t['stop'] in tails:break
|
| 40 |
+
pc=rows[calls[t['stop']]+1]['address']
|
| 41 |
+
if len(requests)>19:raise ValueError('usercmd request bound')
|
| 42 |
+
return m,requests,trace,omitted
|
| 43 |
+
|
| 44 |
+
|
| 45 |
+
def fixtures():
|
| 46 |
+
baseline=bytearray.fromhex('640000003412000078560000bc9a0000420000000780ff01')
|
| 47 |
+
for delta in [0,1,255,256,-1]:
|
| 48 |
+
for mutation in [-1,*range(8),8]:
|
| 49 |
+
new=bytearray(baseline);new[:4]=((100+delta)&0xffffffff).to_bytes(4,'little')
|
| 50 |
+
for i,(offset,size,_) in enumerate(FIELDS):
|
| 51 |
+
if mutation in [i,8]:new[offset:offset+size]=((int.from_bytes(new[offset:offset+size],'little')+1)&((1<<(8*size))-1)).to_bytes(size,'little')
|
| 52 |
+
for key in [0,0x10100]:yield delta,mutation,key,0,bytes(baseline),bytes(new)
|
| 53 |
+
b=bytearray(baseline);b[:4]=(0xfffffffe).to_bytes(4,'little');n=bytearray(b);n[:4]=(1).to_bytes(4,'little');n[4:8]=(0xffffffff).to_bytes(4,'little')
|
| 54 |
+
for key in [0,0xffffffff]:yield 'wrap',0,key,7,bytes(b),bytes(n)
|
| 55 |
+
|
| 56 |
+
|
| 57 |
+
def main():
|
| 58 |
+
cp=Path('docs/research/huffman-codebook.json');ip=Path('docs/research/huffman-initialization.json');code=json.loads(cp.read_text());initial=json.loads(ip.read_text())
|
| 59 |
+
out={'native':{},'codebook_report_sha256':hashlib.sha256(cp.read_bytes()).hexdigest(),'initialization_report_sha256':hashlib.sha256(ip.read_bytes()).hexdigest(),'field_layout':FIELDS,'limitations':'Synthetic Linux ELF64 instruction compositions only; no original process/native callee executes. Compressed trees MODEL-DERIVED, not full native training/captured packets. PUSH/POP and stack save/restores omitted; disjoint frames and explicit caller-register restoration. Ample zero-initialized buffers; selected timestamps/fields/keys only. Record field semantic names inferred separately. Negative timestamp and high key effects are synthetic reachability probes, not legal game traffic. No overflow/EOF/alias/full caller/runtime/platform conformance.'}
|
| 60 |
+
for label in ['linux--Quake3-UrT-Ded.x86_64','linux--Quake3-UrT.x86_64']:
|
| 61 |
+
r=json.loads(Path(f'docs/research/native/{label}.json').read_text());data=verified((Path('.cache/UrbanTerror43')/r['source']['path']).read_bytes(),r['source']['sha256']);meta,symbols=elf(data);a=r['artifacts']['disassembly.txt'];fs=native_functions(verified(gzip.open(a['path'],'rb').read(),a['uncompressed_sha256']).decode());names=['MSG_WriteDeltaUsercmdKey','MSG_ReadDeltaUsercmdKey','MSG_WriteBits','MSG_ReadBits','Huff_putBit','Huff_getBit','Huff_offsetTransmit','Huff_offsetReceive','send'];graphs={n:control_flow(fs[n]) for n in names}
|
| 62 |
+
for dep in [code,initial]:
|
| 63 |
+
if dep['native'][label]['source']!=r['source'] or dep['native'][label]['disassembly_sha256']!=a['uncompressed_sha256']:raise ValueError('dependency provenance')
|
| 64 |
+
mask=next(s for s in symbols if s['name']=='kbitmask');raw,offset=read_address(data,meta['sections'],mask['address'],128);template={mask['address']+i:v for i,v in enumerate(raw)};base=initial['native'][label]['entry_request']['huff_init_pointer'];state=code['model_derived_seed_training']['final_state'];install_tree(template,state,base);root=install_tree(template,state,base+0xc830)
|
| 65 |
+
for x in graphs['MSG_ReadBits']['instructions']:
|
| 66 |
+
if x['opcode']=='movq' and '(%rip)' in x['operands']:put_word(template,global_address(x),root,8)
|
| 67 |
+
g=graphs['MSG_WriteBits'];old=global_address(next(x for x in g['instructions'] if x['opcode']=='addl' and '(%rip)' in x['operands']));over=global_address(next(x for x in g['instructions'] if x['opcode']=='addl' and '$0x1,' in x['operands'] and '(%rip)' in x['operands']));streams=[]
|
| 68 |
+
for delta,mutation,key,bit,b,n in fixtures():
|
| 69 |
+
m=dict(template)
|
| 70 |
+
for i in range(256):m[DATA+i]=0
|
| 71 |
+
for ptr,record in [(BASE,b),(NEW,n),(DEST,bytes([0xa5]*24))]:
|
| 72 |
+
m[ptr-1]=m[ptr+24]=0x7b
|
| 73 |
+
for i,v in enumerate(record):m[ptr+i]=v
|
| 74 |
+
m[DATA-1]=m[DATA+256]=0x7b
|
| 75 |
+
for o,v in [(4,0),(8,0),(16,DATA),(24,256),(28,bit//8+1),(32,0),(36,bit)]:put_word(m,MSG+o,v,8 if o==16 else 4)
|
| 76 |
+
put_word(m,old,0);put_word(m,over,0);m,wq,trace,wo=compose(graphs,m,key);wb=get_word(m,MSG+36);size=get_word(m,MSG+28);payload=bytes(m[DATA+i] for i in range(size)).hex();account=get_word(m,old);counter=get_word(m,over)
|
| 77 |
+
put_word(m,MSG+36,bit);put_word(m,MSG+32,0);m,rq,child,ro=compose(graphs,m,key,True);trace+=child
|
| 78 |
+
streams.append({'delta_fixture':delta,'mutation':mutation,'key_word':key,'initial_bit':bit,'baseline_hex':b.hex(),'new_hex':n.hex(),'decoded_hex':bytes(m[DEST+i] for i in range(24)).hex(),'write_requests':wq,'read_requests':rq,'payload_hex':payload,'write_bit':wb,'write_size':size,'read_bit':get_word(m,MSG+36),'read_count':get_word(m,MSG+32),'oldsize_word':account,'range_counter':counter,'overflow_flag':get_word(m,MSG+4),'canaries':[m[p] for p in [DATA-1,DATA+256,BASE-1,BASE+24,NEW-1,NEW+24,DEST-1,DEST+24]],'inputs_unchanged':bytes(m[BASE+i] for i in range(24))==b and bytes(m[NEW+i] for i in range(24))==n,'writer_omitted':wo,'reader_omitted':ro,**trace_fields({'trace':trace},False)})
|
| 79 |
+
out['native'][label]={'source':r['source'],'disassembly_sha256':a['uncompressed_sha256'],'graphs':graphs,'mask_symbol':mask,'mask_file_offset':offset,'mask8':int.from_bytes(raw[32:36],'little'),'mask16':int.from_bytes(raw[64:68],'little'),'streams':streams}
|
| 80 |
+
write_json(Path('docs/research/message-usercmd.json'),out);print('Recovered keyed usercmd timestamp/field boundaries and modeled-tree compositions')
|
| 81 |
+
|
| 82 |
+
|
| 83 |
+
if __name__=='__main__':main()
|
scripts/test_message_usercmd.py
ADDED
|
@@ -0,0 +1,83 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
#!/usr/bin/env python3
|
| 2 |
+
"""Independent usercmd requests, packing, timestamp and field decode oracles."""
|
| 3 |
+
import hashlib
|
| 4 |
+
import json
|
| 5 |
+
from pathlib import Path
|
| 6 |
+
import unittest
|
| 7 |
+
from analyze_collision_composition import evaluate
|
| 8 |
+
|
| 9 |
+
FIELDS=[(4,4,16),(8,4,16),(12,4,16),(21,1,8),(22,1,8),(23,1,8),(16,4,16),(20,1,8)]
|
| 10 |
+
def word(b,o,s=4):return int.from_bytes(b[o:o+s],'little')
|
| 11 |
+
def signed(v):return v if v<2**31 else v-2**32
|
| 12 |
+
|
| 13 |
+
def oracle(p):
|
| 14 |
+
b=bytes.fromhex(p['baseline_hex']);n=bytes.fromhex(p['new_hex']);delta=(word(n,0)-word(b,0))&0xffffffff;short=signed(delta)<=255;time=(word(b,0)+(delta&255))&0xffffffff if short else word(n,0);changed=any(b[o:o+s]!=n[o:o+s] for o,s,w in FIELDS);q=[[0x90000,int(short),1],[0x90000,delta if short else word(n,0),8 if short else 32],[0x90000,int(changed),1]];result=bytearray(b);result[:4]=time.to_bytes(4,'little');wk=p['key_word']^word(n,0);rk=p['key_word']^time
|
| 15 |
+
if changed:
|
| 16 |
+
for o,s,w in FIELDS:
|
| 17 |
+
c=b[o:o+s]!=n[o:o+s];q.append([0x90000,int(c),1])
|
| 18 |
+
if c:
|
| 19 |
+
value=word(n,o,s)
|
| 20 |
+
if o in [21,22,23] and value>=128:value|=0xffffff00
|
| 21 |
+
encoded=value^wk;q.append([0x90000,encoded,w]);decoded=(encoded&((1<<w)-1))^(rk&((1<<(w+1))-1));result[o:o+s]=(decoded&((1<<(s*8))-1)).to_bytes(s,'little')
|
| 22 |
+
return q,bytes(result),short,changed
|
| 23 |
+
|
| 24 |
+
|
| 25 |
+
class MessageUsercmdTests(unittest.TestCase):
|
| 26 |
+
@classmethod
|
| 27 |
+
def setUpClass(cls):
|
| 28 |
+
cls.r=json.loads(Path('docs/research/message-usercmd.json').read_text());cls.codes={x['symbol']:x['bits'] for x in json.loads(Path('docs/research/huffman-codebook.json').read_text())['model_derived_seed_training']['codebook']}
|
| 29 |
+
|
| 30 |
+
def test_timestamp_signed_short_full_and_wrap(self):
|
| 31 |
+
for n in self.r['native'].values():
|
| 32 |
+
self.assertEqual(len(n['streams']),102)
|
| 33 |
+
for p in n['streams']:
|
| 34 |
+
q,result,short,_=oracle(p);self.assertEqual(p['write_requests'][:2],q[:2]);self.assertEqual(p['decoded_hex'][:8],result.hex()[:8]);self.assertEqual(short,p['delta_fixture']!=256)
|
| 35 |
+
if p['delta_fixture']==-1:self.assertNotEqual(p['decoded_hex'][:8],p['new_hex'][:8])
|
| 36 |
+
|
| 37 |
+
def test_aggregate_and_eight_field_requests(self):
|
| 38 |
+
for n in self.r['native'].values():
|
| 39 |
+
for p in n['streams']:
|
| 40 |
+
q,_,_,changed=oracle(p);self.assertEqual(p['write_requests'],q);self.assertEqual(p['read_requests'],[[ptr,width] for ptr,value,width in q]);self.assertEqual(changed,p['mutation']!=-1)
|
| 41 |
+
|
| 42 |
+
def test_full_record_decode_extra_word_bit_and_byte_narrowing(self):
|
| 43 |
+
saw_extra=False
|
| 44 |
+
for n in self.r['native'].values():
|
| 45 |
+
self.assertEqual(n['mask8'],0x1ff);self.assertEqual(n['mask16'],0x1ffff)
|
| 46 |
+
for p in n['streams']:
|
| 47 |
+
_,result,_,_=oracle(p);self.assertEqual(p['decoded_hex'],result.hex())
|
| 48 |
+
if p['key_word']==0x10100 and p['delta_fixture']==1 and p['mutation']==0:
|
| 49 |
+
self.assertEqual(word(result,4),word(bytes.fromhex(p['new_hex']),4)|0x10000);saw_extra=True
|
| 50 |
+
self.assertTrue(saw_extra)
|
| 51 |
+
|
| 52 |
+
def test_independent_compressed_payload_and_cursors(self):
|
| 53 |
+
for n in self.r['native'].values():
|
| 54 |
+
for p in n['streams']:
|
| 55 |
+
q,_,_,_=oracle(p);bits=[]
|
| 56 |
+
for ptr,value,width in q:
|
| 57 |
+
value&=(1<<width)-1;rem=width%8;bits += [(value>>i)&1 for i in range(rem)]
|
| 58 |
+
for i in range(width//8):bits+=self.codes[(value>>(rem+8*i))&255]
|
| 59 |
+
final=p['initial_bit']+len(bits);payload=bytearray(final//8+1)
|
| 60 |
+
for i,bit in enumerate(bits):pos=p['initial_bit']+i;payload[pos//8]|=bit<<(pos%8)
|
| 61 |
+
self.assertEqual(p['payload_hex'],payload.hex());self.assertEqual(p['write_bit'],final);self.assertEqual(p['read_bit'],final);self.assertEqual(p['write_size'],final//8+1);self.assertEqual(p['read_count'],final//8+1)
|
| 62 |
+
|
| 63 |
+
def test_accounting_diagnostics_and_canaries(self):
|
| 64 |
+
for n in self.r['native'].values():
|
| 65 |
+
for p in n['streams']:
|
| 66 |
+
q,_,_,changed=oracle(p);self.assertEqual(p['oldsize_word'],sum(w for ptr,v,w in q)+(0 if changed else 7));counter=sum(w!=32 and (signed(v)<0 or signed(v)>(1<<w)-1) for ptr,v,w in q);self.assertEqual(p['range_counter'],counter);self.assertEqual(p['overflow_flag'],0);self.assertEqual(p['canaries'],[0x7b]*8);self.assertTrue(p['inputs_unchanged'])
|
| 67 |
+
|
| 68 |
+
def test_dependency_and_mask_file_bytes(self):
|
| 69 |
+
for key,file in [('codebook_report_sha256','huffman-codebook.json'),('initialization_report_sha256','huffman-initialization.json')]:self.assertEqual(self.r[key],hashlib.sha256((Path('docs/research')/file).read_bytes()).hexdigest())
|
| 70 |
+
for n in self.r['native'].values():
|
| 71 |
+
data=(Path('.cache/UrbanTerror43')/n['source']['path']).read_bytes();self.assertEqual(hashlib.sha256(data).hexdigest(),n['source']['sha256']);offset=n['mask_file_offset'];self.assertEqual(data[offset+32:offset+36],bytes.fromhex('ff010000'));self.assertEqual(data[offset+64:offset+68],bytes.fromhex('ffff0100'))
|
| 72 |
+
|
| 73 |
+
def test_paired_outcomes(self):
|
| 74 |
+
a,b=self.r['native'].values()
|
| 75 |
+
def clean(rows):return [{k:v for k,v in p.items() if k not in ['trace_sha256','writer_omitted','reader_omitted']} for p in rows]
|
| 76 |
+
self.assertEqual(clean(a['streams']),clean(b['streams']))
|
| 77 |
+
|
| 78 |
+
def test_xorb_preserves_other_bytes_and_sets_zero(self):
|
| 79 |
+
g={'instructions':[{'address':1,'opcode':'xorb','operands':'%dil, %dil'},{'address':2,'opcode':'je','operands':'0x4'},{'address':3,'opcode':'nop','operands':''},{'address':4,'opcode':'nop','operands':''}]}
|
| 80 |
+
r=evaluate(g,1,[3,4],{}, {'%rdi':0x12345678},capture_registers=True);self.assertEqual(r['stop'],4);self.assertEqual(r['registers']['rdi'],0x12345600)
|
| 81 |
+
|
| 82 |
+
|
| 83 |
+
if __name__=='__main__':unittest.main()
|