fix cases
This commit is contained in:
@@ -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
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user