fix: обработка выхода за пределы индекса сортировки в архиве и улучшение декодирования LZSS с поддержкой XOR
All checks were successful
Test / Lint (push) Successful in 47s
Test / Test (push) Successful in 41s

This commit is contained in:
2026-02-10 08:57:00 +00:00
parent 842f4a8569
commit ba1789f106
4 changed files with 116 additions and 21 deletions

View File

@@ -111,7 +111,9 @@ impl Archive {
let mut high = self.entries.len();
while low < high {
let mid = low + (high - low) / 2;
let target_idx = self.entries[mid].meta.sort_index as usize;
let Ok(target_idx) = usize::try_from(self.entries[mid].meta.sort_index) else {
break;
};
if target_idx >= self.entries.len() {
break;
}
@@ -396,7 +398,10 @@ fn parse_archive(bytes: &[u8], raw_mode: bool) -> Result<(Vec<EntryRecord>, u64)
name
},
};
return Ok((vec![entry], bytes.len() as u64));
return Ok((
vec![entry],
u64::try_from(bytes.len()).map_err(|_| Error::IntegerOverflow)?,
));
}
if bytes.len() < 16 {

View File

@@ -609,6 +609,52 @@ fn nres_synthetic_read_find_and_edit() {
let _ = fs::remove_file(&path);
}
#[test]
fn nres_find_falls_back_when_sort_index_is_out_of_range() {
let mut bytes = build_nres_bytes(&[
SyntheticEntry {
kind: 1,
attr1: 0,
attr2: 0,
attr3: 0,
name: "Alpha",
data: b"a",
},
SyntheticEntry {
kind: 2,
attr1: 0,
attr2: 0,
attr3: 0,
name: "Beta",
data: b"b",
},
SyntheticEntry {
kind: 3,
attr1: 0,
attr2: 0,
attr3: 0,
name: "Gamma",
data: b"c",
},
]);
let entry_count = 3usize;
let directory_offset = bytes
.len()
.checked_sub(entry_count * 64)
.expect("directory offset underflow");
let mid_entry_sort_index = directory_offset + 64 + 60;
bytes[mid_entry_sort_index..mid_entry_sort_index + 4].copy_from_slice(&u32::MAX.to_le_bytes());
let archive = Archive::open_bytes(Arc::from(bytes.into_boxed_slice()), OpenOptions::default())
.expect("open archive with corrupted sort index failed");
assert_eq!(archive.find("alpha"), Some(EntryId(0)));
assert_eq!(archive.find("BETA"), Some(EntryId(1)));
assert_eq!(archive.find("gamma"), Some(EntryId(2)));
assert_eq!(archive.find("missing"), None);
}
#[test]
fn nres_validation_error_cases() {
let valid = build_nres_bytes(&[SyntheticEntry {