qvm: execute original string helpers
Browse files- docs/FINDINGS.md +3 -0
- docs/PROVISIONAL_TODO.md +3 -0
- docs/RESEARCH_LEDGER.md +5 -0
- docs/REVERSE_ENGINEERING_TODO.md +3 -0
- docs/research/QVM_STRING_MEMORY.md +7 -0
- docs/research/README.md +3 -0
- docs/research/qvm-resumer-audit.json +38 -2
- docs/research/qvm-string-memory.json +0 -0
- scripts/analyze_qvm_string_memory.py +17 -0
- scripts/qvm_string_memory_support.py +38 -0
- scripts/test_qvm_string_memory.py +18 -0
- xtask/checks.tsv +5 -0
docs/FINDINGS.md
CHANGED
|
@@ -1409,3 +1409,6 @@ RE-791–800 adds exact Rust source-sort/ranking parity, mixed count/prefix sema
|
|
| 1409 |
|
| 1410 |
|
| 1411 |
**RE-803:** Both bounded resumers now support validated child byte writes, coherent word mirroring and explicit word/byte/return precedence. [Evidence](research/QVM_CHILD_BYTE_EFFECTS.md).
|
|
|
|
|
|
|
|
|
|
|
|
| 1409 |
|
| 1410 |
|
| 1411 |
**RE-803:** Both bounded resumers now support validated child byte writes, coherent word mirroring and explicit word/byte/return precedence. [Evidence](research/QVM_CHILD_BYTE_EFFECTS.md).
|
| 1412 |
+
|
| 1413 |
+
|
| 1414 |
+
**RE-804:** Actual strlen36038 and strcpy36185 execute against coherent bytes, preserving destination guards; bounded copy69338 retains an explicit native strncpy model. [Evidence](research/QVM_STRING_MEMORY.md).
|
docs/PROVISIONAL_TODO.md
CHANGED
|
@@ -1416,3 +1416,6 @@ RE-802: Bounded tracing can now preserve byte/word coherence and execute unalign
|
|
| 1416 |
|
| 1417 |
|
| 1418 |
RE-803: Both bounded resumers now support validated child byte writes, coherent word mirroring and explicit word/byte/return precedence. Full runtime completion remains open. [Evidence](research/QVM_CHILD_BYTE_EFFECTS.md).
|
|
|
|
|
|
|
|
|
|
|
|
| 1416 |
|
| 1417 |
|
| 1418 |
RE-803: Both bounded resumers now support validated child byte writes, coherent word mirroring and explicit word/byte/return precedence. Full runtime completion remains open. [Evidence](research/QVM_CHILD_BYTE_EFFECTS.md).
|
| 1419 |
+
|
| 1420 |
+
|
| 1421 |
+
RE-804: Actual strlen36038 and strcpy36185 execute against coherent bytes, preserving destination guards; bounded copy69338 retains an explicit native strncpy model. Full runtime completion remains open. [Evidence](research/QVM_STRING_MEMORY.md).
|
docs/RESEARCH_LEDGER.md
CHANGED
|
@@ -1681,3 +1681,8 @@ Bounded tracing can now preserve byte/word coherence and execute unaligned byte
|
|
| 1681 |
## 2026-10-26 — RE-803 Explicit child byte effects and read-only shared byte views
|
| 1682 |
|
| 1683 |
Both bounded resumers now support validated child byte writes, coherent word mirroring and explicit word/byte/return precedence. Focused `cargo xtask test-group child-byte-effects` passes (6 Python tests); selected reports regenerate twice deterministically, with storage, documentation links and whitespace guards. Full suite deferred to task ten. Original assets unchanged; source fixtures do not establish complete native/runtime parity.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1681 |
## 2026-10-26 — RE-803 Explicit child byte effects and read-only shared byte views
|
| 1682 |
|
| 1683 |
Both bounded resumers now support validated child byte writes, coherent word mirroring and explicit word/byte/return precedence. Focused `cargo xtask test-group child-byte-effects` passes (6 Python tests); selected reports regenerate twice deterministically, with storage, documentation links and whitespace guards. Full suite deferred to task ten. Original assets unchanged; source fixtures do not establish complete native/runtime parity.
|
| 1684 |
+
|
| 1685 |
+
|
| 1686 |
+
## 2026-10-26 — RE-804 Actual QVM string helpers across aligned and unaligned memory
|
| 1687 |
+
|
| 1688 |
+
Actual strlen36038 and strcpy36185 execute against coherent bytes, preserving destination guards; bounded copy69338 retains an explicit native strncpy model. Focused `cargo xtask test-group string-memory` passes (6 Python tests); selected reports regenerate twice deterministically, with storage, documentation links and whitespace guards. Full suite deferred to task ten. Original assets unchanged; source fixtures do not establish complete native/runtime parity.
|
docs/REVERSE_ENGINEERING_TODO.md
CHANGED
|
@@ -1459,3 +1459,6 @@ Purpose: turn the supplied installation into an evidence-backed specification of
|
|
| 1459 |
|
| 1460 |
|
| 1461 |
- [x] RE-803 Explicit child byte effects and read-only shared byte views ([evidence](research/QVM_CHILD_BYTE_EFFECTS.md)).
|
|
|
|
|
|
|
|
|
|
|
|
| 1459 |
|
| 1460 |
|
| 1461 |
- [x] RE-803 Explicit child byte effects and read-only shared byte views ([evidence](research/QVM_CHILD_BYTE_EFFECTS.md)).
|
| 1462 |
+
|
| 1463 |
+
|
| 1464 |
+
- [x] RE-804 Actual QVM string helpers across aligned and unaligned memory ([evidence](research/QVM_STRING_MEMORY.md)).
|
docs/research/QVM_STRING_MEMORY.md
ADDED
|
@@ -0,0 +1,7 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# Actual QVM string helpers across aligned and unaligned memory
|
| 2 |
+
|
| 3 |
+
RE-804. Reproduce with `python3 scripts/analyze_qvm_string_memory.py`; focused validation: `cargo xtask test-group string-memory`. [Machine report](qvm-string-memory.json).
|
| 4 |
+
|
| 5 |
+
128 original-instruction fixtures vary source/destination alignment, NUL positions, long names and non-UTF8 bytes.32 wrapper cases verify valid capacities1/2/4/32 and exact terminal NUL. Independent byte-string oracles check lengths, return pointers and all destination guard bytes. Source word lookahead is given initialized padding; overlap and native ABI/error paths are not claimed.
|
| 6 |
+
|
| 7 |
+
Original executable/native runtime and complete Linux/macOS Rust/Bevy/Solari acceptance remain unverified.
|
docs/research/README.md
CHANGED
|
@@ -999,3 +999,6 @@ The extension collector adds five focused tests for native tail calls, command-r
|
|
| 999 |
|
| 1000 |
|
| 1001 |
[RE-803: Explicit child byte effects and read-only shared byte views](QVM_CHILD_BYTE_EFFECTS.md).
|
|
|
|
|
|
|
|
|
|
|
|
| 999 |
|
| 1000 |
|
| 1001 |
[RE-803: Explicit child byte effects and read-only shared byte views](QVM_CHILD_BYTE_EFFECTS.md).
|
| 1002 |
+
|
| 1003 |
+
|
| 1004 |
+
[RE-804: Actual QVM string helpers across aligned and unaligned memory](QVM_STRING_MEMORY.md).
|
docs/research/qvm-resumer-audit.json
CHANGED
|
@@ -9371,6 +9371,42 @@
|
|
| 9371 |
"repeated_calls_opt_in": true,
|
| 9372 |
"repeated_calls_setting": "literal_true"
|
| 9373 |
},
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 9374 |
{
|
| 9375 |
"backward_conditional_branches": [],
|
| 9376 |
"calls": [
|
|
@@ -9432,8 +9468,8 @@
|
|
| 9432 |
}
|
| 9433 |
},
|
| 9434 |
"summary": {
|
| 9435 |
-
"call_expressions":
|
| 9436 |
-
"files":
|
| 9437 |
"legacy_expressions": 158,
|
| 9438 |
"nonliteral_ranges": 24,
|
| 9439 |
"unresolved_mode_expressions": 3
|
|
|
|
| 9371 |
"repeated_calls_opt_in": true,
|
| 9372 |
"repeated_calls_setting": "literal_true"
|
| 9373 |
},
|
| 9374 |
+
{
|
| 9375 |
+
"backward_conditional_branches": [],
|
| 9376 |
+
"calls": [
|
| 9377 |
+
{
|
| 9378 |
+
"dynamic_store_requires_review": false,
|
| 9379 |
+
"implicit_local_offset": null,
|
| 9380 |
+
"instruction": 69348,
|
| 9381 |
+
"stores_result": false,
|
| 9382 |
+
"target": 5096
|
| 9383 |
+
},
|
| 9384 |
+
{
|
| 9385 |
+
"dynamic_store_requires_review": false,
|
| 9386 |
+
"implicit_local_offset": null,
|
| 9387 |
+
"instruction": 69359,
|
| 9388 |
+
"stores_result": false,
|
| 9389 |
+
"target": 5096
|
| 9390 |
+
},
|
| 9391 |
+
{
|
| 9392 |
+
"dynamic_store_requires_review": false,
|
| 9393 |
+
"implicit_local_offset": null,
|
| 9394 |
+
"instruction": 69373,
|
| 9395 |
+
"stores_result": false,
|
| 9396 |
+
"target": -103
|
| 9397 |
+
}
|
| 9398 |
+
],
|
| 9399 |
+
"explicit_result_offsets": null,
|
| 9400 |
+
"helper": "qvm_trace_support.resume",
|
| 9401 |
+
"line": 36,
|
| 9402 |
+
"literal_range": [
|
| 9403 |
+
69339,
|
| 9404 |
+
69384
|
| 9405 |
+
],
|
| 9406 |
+
"path": "scripts/qvm_string_memory_support.py",
|
| 9407 |
+
"repeated_calls_opt_in": true,
|
| 9408 |
+
"repeated_calls_setting": "literal_true"
|
| 9409 |
+
},
|
| 9410 |
{
|
| 9411 |
"backward_conditional_branches": [],
|
| 9412 |
"calls": [
|
|
|
|
| 9468 |
}
|
| 9469 |
},
|
| 9470 |
"summary": {
|
| 9471 |
+
"call_expressions": 189,
|
| 9472 |
+
"files": 147,
|
| 9473 |
"legacy_expressions": 158,
|
| 9474 |
"nonliteral_ranges": 24,
|
| 9475 |
"unresolved_mode_expressions": 3
|
docs/research/qvm-string-memory.json
ADDED
|
The diff for this file is too large to render.
See raw diff
|
|
|
scripts/analyze_qvm_string_memory.py
ADDED
|
@@ -0,0 +1,17 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
#!/usr/bin/env python3
|
| 2 |
+
import itertools
|
| 3 |
+
from pathlib import Path
|
| 4 |
+
from qvm_research_support import source
|
| 5 |
+
from qvm_string_memory_support import strlen,strcpy,copy_bounded,L
|
| 6 |
+
from qvm_byte_memory_support import read_bytes
|
| 7 |
+
from analyze_qvm import write_json
|
| 8 |
+
S=L+0x4000;D=S+0x1000
|
| 9 |
+
|
| 10 |
+
def main():
|
| 11 |
+
q,raw,h,ins=source();rows=[];copies=[];names=[b'',b'A',b'AB',b'x'*31,b'x'*32,b'x'*63,b'AB\0suffix',bytes([255,254,253])]
|
| 12 |
+
for sa,da,name in itertools.product(range(4),range(4),names):
|
| 13 |
+
b={S+sa+j:v for j,v in enumerate(name+b'\0'+b'\xcc'*4)};b.update({D+j:0x7e for j in range(96)});m,n,e=strlen(ins,{}, {8:S+sa},b);m,value,c=strcpy(ins,m,{8:D+da,12:S+sa},b);out=read_bytes(m,{**b,**c['child_memory_bytes']},D,96);rows.append({'source_alignment':sa,'dest_alignment':da,'source_hex':name.hex(),'length':n,'result_pointer':value-D,'buffer_hex':out.hex(),'strlen_execution':e['execution'],'strcpy_execution':c['execution']})
|
| 14 |
+
for name,cap in itertools.product(names,[1,2,4,32]):
|
| 15 |
+
b={S+j:v for j,v in enumerate(name+b'\0'+b'\xcc'*4)};b.update({D+j:0x7e for j in range(40)});m,v,e=copy_bounded(ins,{}, {8:D,12:S,16:cap},b);out=read_bytes(m,{**b,**e['child_memory_bytes']},D,40);copies.append({'source_hex':name.hex(),'capacity':cap,'buffer_hex':out.hex(),'wrapper_trace_sha256':e['wrapper_trace_sha256']})
|
| 16 |
+
write_json(Path('docs/research/qvm-string-memory.json'),{'source':q['source'],'sha256':q['sha256'],'probes':rows,'bounded_copies':copies,'limits':'Actual36038 strlen and36185 strcpy over128 aligned/unaligned byte fixtures, plus actual69338 valid wrapper over32 cases with modeled native-103 strncpy. Source word lookahead requires initialized padding; strcpy fixtures are disjoint with initialized destination guards. Native copy/error/overlap ABI parity remains open.'})
|
| 17 |
+
if __name__=='__main__':main()
|
scripts/qvm_string_memory_support.py
ADDED
|
@@ -0,0 +1,38 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
"""Actual36038/36185 and69338 with explicit modeled native strncpy bytes."""
|
| 2 |
+
from qvm_health_effects_support import H
|
| 3 |
+
from qvm_byte_memory_support import read_byte,read_bytes
|
| 4 |
+
from analyze_deferred_auth import trace_slice
|
| 5 |
+
from analyze_bsp_references import trace_fields
|
| 6 |
+
from qvm_trace_support import resume
|
| 7 |
+
L=H+0x680000
|
| 8 |
+
C=L+0x1000
|
| 9 |
+
W=L+0x2000
|
| 10 |
+
|
| 11 |
+
def cstring(m,b,address,limit=32768):
|
| 12 |
+
out=bytearray()
|
| 13 |
+
for j in range(limit):
|
| 14 |
+
v=read_byte(m,b,address+j)
|
| 15 |
+
if v==0:return bytes(out)
|
| 16 |
+
out.append(v)
|
| 17 |
+
raise ValueError('bounded string missing NUL')
|
| 18 |
+
|
| 19 |
+
def strlen(ins,m,args,b):
|
| 20 |
+
m=dict(m);m[L+28]=args[8];t=trace_slice(ins,36039,36121,m,{},byte_memory=b,local_base=L,coherent_memory=True,capture_stack=True,halt_on_leave=True,limit=32768)
|
| 21 |
+
return t['memory'],t['stack'][-1],{'execution':trace_fields(t,False),'actual_strlen':True}
|
| 22 |
+
|
| 23 |
+
def strcpy(ins,m,args,b):
|
| 24 |
+
n=len(cstring(m,b,args[12],1025));m=dict(m);m[C+32]=args[8];m[C+36]=args[12];t=trace_slice(ins,36186,36304,m,{},byte_memory=b,local_base=C,coherent_memory=True,capture_stack=True,halt_on_leave=True,limit=32768)
|
| 25 |
+
cells={args[8]+j:read_byte(t['memory'],t['byte_memory'],args[8]+j) for j in range(n+1)}
|
| 26 |
+
return t['memory'],t['stack'][-1],{'execution':trace_fields(t,False),'child_memory_bytes':cells,'actual_strcpy':True}
|
| 27 |
+
|
| 28 |
+
def copy_bounded(ins,m,args,b):
|
| 29 |
+
if args[12]==0 or not 1<=args[16]<=1024:raise ValueError('unsupported bounded copy domain')
|
| 30 |
+
m=dict(m)
|
| 31 |
+
for o,v in args.items():m[W+20+o]=v
|
| 32 |
+
def native(i,m,a,bs):
|
| 33 |
+
if not 0<=a[16]<=1023:raise ValueError('unsupported native copy count')
|
| 34 |
+
raw=cstring(m,bs,a[12]);data=raw[:a[16]].ljust(a[16],b'\0')
|
| 35 |
+
return m,a[8],{'native_strncpy_modeled':True,'child_memory_bytes':{a[8]+j:v for j,v in enumerate(data)}}
|
| 36 |
+
m,e=resume(ins,69339,69384,m,W,handlers={-103:native},byte_inputs=b,repeated_calls=True,sync_child_words=True,coherent_memory=True,byte_handlers=True,capture_byte_memory=True)
|
| 37 |
+
cells={args[8]+j:read_byte(m,e['byte_memory'],args[8]+j) for j in range(args[16])}
|
| 38 |
+
return m,0,{'child_memory_bytes':cells,'wrapper_trace_sha256':e['trace_sha256'],'native_strncpy_modeled':True}
|
scripts/test_qvm_string_memory.py
ADDED
|
@@ -0,0 +1,18 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
import json,unittest
|
| 2 |
+
from pathlib import Path
|
| 3 |
+
from qvm_string_memory_support import cstring,copy_bounded
|
| 4 |
+
class StringMemoryTests(unittest.TestCase):
|
| 5 |
+
@classmethod
|
| 6 |
+
def setUpClass(cls):cls.r=json.loads(Path('docs/research/qvm-string-memory.json').read_text())
|
| 7 |
+
def test_actual_strlen_strcpy_and_preserved_post_nul_guards(self):
|
| 8 |
+
self.assertEqual(len(self.r['probes']),128)
|
| 9 |
+
for p in self.r['probes']:
|
| 10 |
+
text=bytes.fromhex(p['source_hex']).split(b'\0')[0];out=bytearray(b'~'*96);start=p['dest_alignment'];out[start:start+len(text)+1]=text+b'\0';self.assertEqual(p['length'],len(text));self.assertEqual(p['result_pointer'],start);self.assertEqual(p['buffer_hex'],out.hex())
|
| 11 |
+
def test_actual_wrapper_terminator_and_native_copy_model(self):
|
| 12 |
+
self.assertEqual(len(self.r['bounded_copies']),32)
|
| 13 |
+
for p in self.r['bounded_copies']:
|
| 14 |
+
raw=bytes.fromhex(p['source_hex']).split(b'\0')[0];cap=p['capacity'];out=bytearray(b'~'*40);out[:cap]=raw[:cap-1].ljust(cap-1,b'\0')+b'\0';self.assertEqual(p['buffer_hex'],out.hex())
|
| 15 |
+
def test_unterminated_and_invalid_domains_reject(self):
|
| 16 |
+
with self.assertRaisesRegex(ValueError,'missing NUL'):cstring({},dict(enumerate(b'abc')),0,3)
|
| 17 |
+
with self.assertRaises(ValueError):copy_bounded([],{},{8:4,12:8,16:0},{})
|
| 18 |
+
if __name__=='__main__':unittest.main()
|
xtask/checks.tsv
CHANGED
|
@@ -1898,3 +1898,8 @@ report scripts/analyze_qvm_child_byte_effects.py docs/research/qvm-child-byte-ef
|
|
| 1898 |
edge docs/research/qvm-child-byte-effects.json scripts/test_qvm_child_byte_effects.py
|
| 1899 |
group child-byte-effects scripts/analyze_qvm_child_byte_effects.py
|
| 1900 |
edge scripts/analyze_qvm_child_byte_effects.py scripts/analyze_qvm_resumer_audit.py
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1898 |
edge docs/research/qvm-child-byte-effects.json scripts/test_qvm_child_byte_effects.py
|
| 1899 |
group child-byte-effects scripts/analyze_qvm_child_byte_effects.py
|
| 1900 |
edge scripts/analyze_qvm_child_byte_effects.py scripts/analyze_qvm_resumer_audit.py
|
| 1901 |
+
report scripts/analyze_qvm_string_memory.py docs/research/qvm-string-memory.json
|
| 1902 |
+
edge docs/research/qvm-string-memory.json scripts/test_qvm_string_memory.py
|
| 1903 |
+
group string-memory scripts/analyze_qvm_string_memory.py
|
| 1904 |
+
edge scripts/analyze_qvm_string_memory.py scripts/analyze_qvm_resumer_audit.py
|
| 1905 |
+
edge scripts/qvm_string_memory_support.py scripts/analyze_qvm_resumer_audit.py
|