Bound infrastructure payload string fallbacks

This commit is contained in:
Jan Petykiewicz 2026-04-18 13:52:18 -07:00
commit 1873db0b08
3 changed files with 51 additions and 33 deletions

View file

@ -3966,6 +3966,7 @@ fn build_infrastructure_asset_trace_report(
"direct disassembly now also shows 0x00493be0 iterating live-entry ordinals through 0x00518380(ordinal, 0), converting each ordinal to a live id, then resolving that live id through 0x00518140 before handing the resulting payload pointer to 0x0048dcf0".to_string(),
"direct disassembly now shows 0x00518680 loading the non-direct collection header, tombstone bitset, and live-id-bound-scaled 12-byte tables for the non-direct path before 0x00493be0 starts iterating".to_string(),
"direct disassembly now also shows the shared child payload callback 0x00455fc0 opening 0x55f1, parsing three len-prefixed strings through 0x531380, opening 0x55f2, seeding the child through 0x455b70, dispatching slot +0x48, and then opening 0x55f3".to_string(),
"direct disassembly now also shows 0x00455b70 storing those three payload strings into [this+0x206/+0x20a/+0x20e], defaulting the second lane through a fixed literal when absent and defaulting the third lane back to the first string when absent".to_string(),
format!(
"current save-side probe reports {} embedded 0x55f1 rows with a third decoded string",
side_buffer
@ -3980,7 +3981,6 @@ fn build_infrastructure_asset_trace_report(
blockers: vec![
"how the payload streams reached through 0x00518380 -> 0x00518140 align with the embedded 0x55f1 name-pair groups and compact-prefix regimes surfaced by the save-side probe".to_string(),
"which tagged values inside each payload stream correspond to the child count, optional primary-child ordinal, and the per-child shared tagged callback sequence consumed by 0x0048dcf0".to_string(),
"whether the third 0x55f1 string parsed by 0x00455fc0 is absent on grounded saves, stored under a different framing than the current probe, or only populated on a narrower infrastructure subset".to_string(),
"which restored child fields or grouped rows retain the 0x38a5 embedded name-pair semantics before route/local-runtime follow-ons take over".to_string(),
],
},
@ -12546,6 +12546,26 @@ fn parse_save_len_prefixed_ascii_name(bytes: &[u8]) -> Option<String> {
Some(text.to_string())
}
fn parse_save_varlen_ascii_name_at(bytes: &[u8], offset: usize) -> Option<(String, usize)> {
let first = *bytes.get(offset)?;
if first == 0 {
return None;
}
let (len, header_len) = if first <= 0x7f {
(first as usize, 1usize)
} else {
let second = *bytes.get(offset + 1)? as usize;
((((first as usize) & 0x7f) << 8) | second, 2usize)
};
let start = offset + header_len;
let end = start.checked_add(len)?;
let text = std::str::from_utf8(bytes.get(start..end)?)
.ok()?
.trim_end_matches('\0')
.to_string();
Some((text, end))
}
fn parse_save_len_prefixed_ascii_name_pair(bytes: &[u8]) -> Option<(String, String)> {
let (first, second, _) = parse_save_len_prefixed_ascii_name_triplet(bytes)?;
Some((first, second))
@ -12554,42 +12574,22 @@ fn parse_save_len_prefixed_ascii_name_pair(bytes: &[u8]) -> Option<(String, Stri
fn parse_save_len_prefixed_ascii_name_triplet(
bytes: &[u8],
) -> Option<(String, String, Option<String>)> {
let first_len = *bytes.first()? as usize;
let first_end = 1 + first_len;
let first = std::str::from_utf8(bytes.get(1..first_end)?)
.ok()?
.trim_end_matches('\0')
.to_string();
let (first, first_end) = parse_save_varlen_ascii_name_at(bytes, 0)?;
let mut second_len_offset = first_end;
while matches!(bytes.get(second_len_offset), Some(0)) {
second_len_offset += 1;
}
let second_len = *bytes.get(second_len_offset)? as usize;
let second_start = second_len_offset + 1;
let second = std::str::from_utf8(bytes.get(second_start..second_start + second_len)?)
.ok()?
.trim_end_matches('\0')
.to_string();
let (second, second_end) = parse_save_varlen_ascii_name_at(bytes, second_len_offset)?;
if first.is_empty() || second.is_empty() {
return None;
}
let mut third_len_offset = second_start + second_len;
let mut third_len_offset = second_end;
while matches!(bytes.get(third_len_offset), Some(0)) {
third_len_offset += 1;
}
let third = bytes
.get(third_len_offset)
.copied()
.filter(|len| *len != 0)
.and_then(|third_len| {
let third_len = third_len as usize;
let third_start = third_len_offset + 1;
let text = std::str::from_utf8(bytes.get(third_start..third_start + third_len)?)
.ok()?
.trim_end_matches('\0')
.to_string();
(!text.is_empty()).then_some(text)
});
let third = parse_save_varlen_ascii_name_at(bytes, third_len_offset)
.map(|(text, _)| text)
.filter(|text| !text.is_empty());
Some((first, second, third))
}
@ -20409,6 +20409,18 @@ mod tests {
assert_eq!(parsed.2.as_deref(), Some("Third"));
}
#[test]
fn parses_save_len_prefixed_ascii_name_triplet_with_extended_length_prefix() {
let mut bytes = Vec::new();
bytes.extend_from_slice(&[0x80, 0x03, b'A', b'B', b'C']);
bytes.extend_from_slice(&[0, 1, b'X']);
let parsed = parse_save_len_prefixed_ascii_name_triplet(&bytes)
.expect("triplet parser should decode extended-length prefix");
assert_eq!(parsed.0, "ABC");
assert_eq!(parsed.1, "X");
assert_eq!(parsed.2, None);
}
#[test]
fn aligns_placed_structure_dynamic_side_buffer_name_pairs_with_triplets() {
let side_buffer = SmpSavePlacedStructureDynamicSideBufferProbe {