fix cases

This commit is contained in:
Intege-rs
2024-11-19 19:55:34 -05:00
parent 0f3fe5e23f
commit 677167b97a
2 changed files with 47 additions and 41 deletions

View File

@@ -36,7 +36,7 @@ impl<'a, S: Scannable + ?Sized> Scanner<'a, S> {
let upper_limit = self.range.end;
while let Some(address) = scan_for_aob(self.bin, self.cursor..upper_limit, aob) {
self.cursor = address + 1;
if exec(self.bin, address, self.pat, saves, self.range.clone()) {
if exec(self.bin, address, self.pat, saves, self.range.clone()).is_some() {
return true;
}
}
@@ -46,7 +46,7 @@ impl<'a, S: Scannable + ?Sized> Scanner<'a, S> {
while self.range.contains(&self.cursor) {
let current_cursor = self.cursor;
self.cursor += 1;
if exec(self.bin, current_cursor, self.pat, saves, self.range.clone()) {
if exec(self.bin, current_cursor, self.pat, saves, self.range.clone()).is_some() {
return true;
}
}
@@ -63,7 +63,7 @@ pub fn exec<Binary: Scannable + ?Sized>(
pattern: Pattern,
saves: &mut [usize],
range: Range<usize>,
) -> bool {
) -> Option<usize> {
let mut cursor = address;
let mut pc = 0;
@@ -87,8 +87,8 @@ pub fn exec<Binary: Scannable + ?Sized>(
// Compare bytes
Atom::Byte(pat_byte) => {
let Some(byte) = read::<_, u8>(bin, cursor) else { return false; };
if byte & mask != pat_byte & mask { return false; }
let Some(byte) = read::<_, u8>(bin, cursor) else { return None; };
if byte & mask != pat_byte & mask { return None; }
cursor += 1;
mask = 0xFF;
}
@@ -105,9 +105,8 @@ pub fn exec<Binary: Scannable + ?Sized>(
let skip = if skip == 0 { SKIP_VA } else { skip };
// start running the pattern from pc...
if !exec(bin, cursor, &pattern[pc..], saves, range.clone()) {
return false;
}
exec(bin, cursor, &pattern[pc..], saves, range.clone())?;
cursor = cursor.wrapping_add(skip as usize);
mask = 0xff;
ext_range = 0;
@@ -119,7 +118,7 @@ pub fn exec<Binary: Scannable + ?Sized>(
match pattern.get(pc) {
Some(Atom::Push(_)) => counter += 1,
Some(Atom::Pop) => counter -= 1,
None => return true,
None => return Some(cursor),
_ => (/**/)
}
pc += 1;
@@ -127,7 +126,7 @@ pub fn exec<Binary: Scannable + ?Sized>(
}
Atom::Pop => {
return true;
return Some(cursor);
}
Atom::Fuzzy(pat_mask) => {
@@ -158,60 +157,60 @@ pub fn exec<Binary: Scannable + ?Sized>(
}
Atom::Jump1 => {
let Some(sbyte) = read::<_, i8>(bin, cursor) else { return false };
let Some(sbyte) = read::<_, i8>(bin, cursor) else { return None };
cursor = cursor.wrapping_add(sbyte as usize).wrapping_add(1);
}
Atom::Jump4 => {
let Some(sdword) = read::<_, i32>(bin, cursor) else { return false };
let Some(sdword) = read::<_, i32>(bin, cursor) else { return None };
cursor = cursor.wrapping_add(sdword as usize).wrapping_add(4);
}
Atom::Ptr => {
let Some(sptr) = read::<_, usize>(bin, cursor) else { return false };
let Some(sptr) = read::<_, usize>(bin, cursor) else { return None };
cursor = sptr;
}
Atom::Pir(slot) => {
let Some(sdword) = read::<_, i32>(bin, cursor) else { return false };
let Some(sdword) = read::<_, i32>(bin, cursor) else { return None };
let base = saves.get(slot as usize).cloned().unwrap_or(cursor);
cursor = base.wrapping_add(sdword as usize);
}
Atom::Check(slot) => {
if let Some(&rva) = saves.get(slot as usize) {
if rva != cursor { return false; }
if rva != cursor { return None; }
}
}
Atom::Aligned(align) => {
if cursor & ((1 << align) - 1) != 0 {
return false;
return None;
}
}
Atom::ReadU8(slot) => {
let Some(value) = read::<_, u8>(bin, cursor) else { return false };
let Some(value) = read::<_, u8>(bin, cursor) else { return None };
if let Some(slot) = saves.get_mut(slot as usize) { *slot = value as _ }
}
Atom::ReadI8(slot) => {
let Some(value) = read::<_, i8>(bin, cursor) else { return false };
let Some(value) = read::<_, i8>(bin, cursor) else { return None };
if let Some(slot) = saves.get_mut(slot as usize) { *slot = value as _ }
}
Atom::ReadU16(slot) => {
let Some(value) = read::<_, u16>(bin, cursor) else { return false };
let Some(value) = read::<_, u16>(bin, cursor) else { return None };
if let Some(slot) = saves.get_mut(slot as usize) { *slot = value as _ }
}
Atom::ReadI16(slot) => {
let Some(value) = read::<_, i16>(bin, cursor) else { return false };
let Some(value) = read::<_, i16>(bin, cursor) else { return None };
if let Some(slot) = saves.get_mut(slot as usize) { *slot = value as _ }
}
Atom::ReadU32(slot) => {
let Some(value) = read::<_, u32>(bin, cursor) else { return false };
let Some(value) = read::<_, u32>(bin, cursor) else { return None };
if let Some(slot) = saves.get_mut(slot as usize) { *slot = value as _ }
}
Atom::ReadI32(slot) => {
let Some(value) = read::<_, i32>(bin, cursor) else { return false };
let Some(value) = read::<_, i32>(bin, cursor) else { return None };
if let Some(slot) = saves.get_mut(slot as usize) { *slot = value as _ }
}
Atom::Zero(slot) => {
@@ -220,35 +219,40 @@ pub fn exec<Binary: Scannable + ?Sized>(
}
}
Atom::Case(next) => {
if exec(bin, cursor, pattern, saves, range.clone()) {
if let Some(nc) = exec(bin, cursor, &pattern[pc..], saves, range.clone()) {
cursor = nc;
// same as Push/Pop except we add the next from the break to the pc.
let mut counter = 1;
loop {
pc += 1;
match pattern.get(pc) {
Some(Atom::Case(_)) => counter += 1,
Some(Atom::Break(next)) => {
counter -= 1;
if counter == 0 {
pc += *next as usize
pc += *next as usize + 1;
break;
}
}
None => return true,
None => return Some(cursor),
_ => (/**/)
}
pc += 1;
}
// panic!("{pc}, {:X?} == {:02X}", pattern.get(pc), bin.chunk_at(cursor).unwrap([1]));
} else {
// if the case fails go to the location defined by next
pc += next as usize;
}
}
Atom::Break(_next) => {
return true;
return Some(cursor);
}
Atom::Nop => {}
}
}
true
Some(cursor)
}
@@ -260,13 +264,13 @@ pub fn exec_many<Binary: Scannable + ?Sized >(
saves: &mut [usize],
range: Range<usize>,
limit: u32,
) -> bool {
) -> Option<usize> {
let mut aob = <[u8; 0x10] as Pod>::uninit();
let aob = make_aob(pattern, &mut aob);
let Some(chunk) = bin.chunk_at(address) else {
// pattern fails before we even try (out of bounds)
return false;
return None;
};
match !aob.is_empty() {
@@ -275,21 +279,21 @@ pub fn exec_many<Binary: Scannable + ?Sized >(
let mut cursor = address;
while let Some(address) = scan_for_aob(bin, cursor..upper_limit, aob) {
cursor = address;
if exec(bin, cursor, pattern, saves, range.clone()) {
return true;
if let Some(cursor) = exec(bin, cursor, pattern, saves, range.clone()) {
return Some(cursor);
}
cursor += 1;
}
false
None
}
false => {
// try to reduce the limit just in-case we can squeeze some perf out of it
for i in 0..(limit as usize).min(chunk.len()) {
if exec(bin, address + i, pattern, saves, range.clone()) {
return true;
if let Some(cursor) = exec(bin, address + i, pattern, saves, range.clone()) {
return Some(cursor);
}
}
false
None
}
}
}

View File

@@ -4,14 +4,16 @@
#[test]
pub fn test_pattern() {
let pattern = x::pattern!("E8 [0-4] BB ");
let buffer: &[u8] = &[ 0xAA, 0xE8, 0xBB, 0xE8, 0x00, 0xBB, ];
let pattern = x::pattern!("E8 ( AA | CC | DD ) E8 ");
use x::xpat::Atom::*;
let pattern = &[Save(0), Byte(0xE8),
Case(2), Byte(0xCC), Break(8),
Case(2), Byte(0xAA), Break(5),
Case(2), Byte(0xCC), Break(2), Nop, Byte(0xDD), Byte(0xE8)];
let buffer: &[u8] = &[ 0xE8, 0xDD, 0xE8 ];
let mut scanner = x::Scanner::new(buffer, pattern, ..);
let mut saves = [0usize;8];
assert!(scanner.next(&mut saves));
assert_eq!(saves[0], 1);
assert!(scanner.next(&mut saves));
assert_eq!(saves[0], 3);
}