|
Download docs/research/CLIENT_MASKS.md from nmarshall/urt-rs: direct link, hf CLI and curl.
- Browser
- Download file 5.47 kB
-
https://huggingface.co/nmarshall/urt-rs/resolve/main/docs/research/CLIENT_MASKS.md
- Command line
-
hf download hf://nmarshall/urt-rs/docs/research/CLIENT_MASKS.md
-
curl -L -o CLIENT_MASKS.md https://huggingface.co/nmarshall/urt-rs/resolve/main/docs/research/CLIENT_MASKS.md
5.47 kB
| # Client snapshot area-mask parsing | |
| Reproduce with `python3 scripts/analyze_client_masks.py`; validate with `python3 scripts/test_client_masks.py`. [client-masks.json](client-masks.json) retains three hash-verified graphs from the Linux ELF64 client: CL_ParseSnapshot, MSG_ReadByte and MSG_ReadData. This follows the server [mask serialization requests](SNAPSHOT_AREAS.md). | |
| These are bounded synthetic instruction evaluations. Original processes and every native callee remain unexecuted. Frame PUSH/POP instructions are explicitly omitted, virtual stack addresses supplied, and caller registers retained across stopped helpers. MSG_ReadBits return words and post-call readcounts are supplied; neither real packet decoding nor Huffman/cursor behavior is established. Only the Linux client is sampled, not dedicated-server equivalence or other platforms. | |
| ## CLIENT-001 — Reset, unsigned length guards and destination (RE-337) | |
| At entry 0x4207d2, the parser requests memset of its temporary snapshot: destination virtual stack, value zero, size 0x21c (540 bytes). Three PUSH instructions are omitted for this argument probe, and the pre-subtraction stack pointer is supplied explicitly. The memset call itself does not execute. Data compositions supply its zero-fill effects, retaining outside canaries. | |
| Two paths read the mask-length byte and test it against 32: comparisons at 0x42088f and 0x4208ed use unsigned JBE/JA respectively. Twenty-two probes accept 0,1,7,31,32 and reject 33,127,128,255,0xffffffff,0x80000000 on both paths. Rejected paths request Com_Error with error code 1, the supplied length word and the verified string `CL_ParseSnapshot: Invalid size %d for areamask.` The error function is not executed. | |
| Both accepted paths request MSG_ReadData(message, temporary_snapshot +0x18, length) at 0x4208fc. Length zero remains accepted. The byte-reader EOF word 0xffffffff fails this unsigned guard. These offsets describe this native Linux layout, not the server's different frame layout or a Rust ABI. | |
| ## CLIENT-002 — Byte-reader cursor boundary (RE-338) | |
| MSG_ReadByte at 0x44dec4 requests MSG_ReadBits(message,8). Its post-call slice compares message.readcount at +0x20 against message.cursize at +0x1c using signed CMOVLEL. If readcount <= cursize, it returns the supplied result's low eight bits, zero-extended; otherwise it returns 0xffffffff. The POP is explicitly omitted; evaluation stops before RET. | |
| Two hundred ten probes cover sizes 0,1,32,0x7fffffff,0xffffffff; cursors 0,1,2,32,33,0x80000000,0xffffffff; and six return words including 0x1234 and 0xffffffff. Equality is accepted. Negative signed cursor/size fixtures characterize the comparison locally; they do not establish legal message states. Low-byte 0xff is distinguishable from EOF 0xffffffff at this helper's return boundary. | |
| ## CLIENT-003 — Exact requested copy and truncation (RE-339) | |
| MSG_ReadData at 0x45307a uses a signed length <=0 early exit. For positive lengths, it requests eight bits once per destination byte through an initial byte, peeled remainder and four-byte unrolled loop. Each lane compares the supplied post-read cursor with cursize; on overflow it stores 0xff, otherwise the returned low byte. It continues requesting and storing the entire length after overflow rather than exiting at the first failed read. | |
| Fifty-three compositions cover lengths -1,0,1 through 9,16,17,31,32 with sizes drawn from zero, one, length-minus-one and length. Supplied post-readcounts are 1 through length, and supplied result words cycle through 0,127,128,255,0x1234,0xffffffff. Negative/zero lengths issue no requests or writes. Every positive fixture has exactly length requests `(message,8)`; overflow bytes become 0xff. The unused mask tail retains the supplied reset's zeros, and frame canaries remain unchanged. | |
| The server requests only its mask's used byte span; the client guard caps that span at 32 and targets a zero-initialized temporary buffer. This establishes compatible bounded pointer/count relationships, not a server-to-client wire round trip. Real MSG_ReadBits can use compressed bit cursors, so the supplied ordinal readcounts are explicit test inputs, not a recovered cursor update formula. Complete post-copy bad-message checks, delta validity and snapshot publication remain open. | |
| ## Validation and next work | |
| Eight independent tests cover reset arguments, both unsigned guards and error arguments, signed cursor/low-byte return, exact copy requests and bytes, continued EOF requests, canaries/tails/unrolled lengths, stopped CALL boundaries, and restricted evaluator CMOVLEL/BL semantics with unknown-flag rejection. Reports include source/disassembly hashes and native trace addresses or hashes. The evaluator extension adds only signed conditional move and the BL register alias. | |
| RE-340: recover actual bit/Huffman encoding and readcount updates, message overflow/bad-read handling, all snapshot/delta/player/entity validation and publication, mask renderer interpretation and map-area validity; compose real encoded packets and original-runtime/all-platform fixtures. Implement Rust protocol/Bevy/Solari integration only against a complete validated contract. | |
| Bit-reader follow-up: [message modes and assembly](MESSAGE_BITS.md) recovers bounded OOB reads, raw bit instructions and compressed cursor/sign-tail behavior (RE-341–343). Huffman symbols/code lengths remain supplied; real packet decoding and full snapshot validation remain open. | |