use super::Maps;
impl Maps {
#[inline(always)]
pub fn memset(&mut self, addr: u64, b: u8, amount: usize) {
for i in 0..amount {
self.write_byte(addr + i as u64, b);
}
}
pub fn memcpy(&mut self, to: u64, from: u64, size: usize) -> bool {
let b = match self.read_bytes_option(from, size) {
None => return false,
Some(b) => b.to_vec(),
};
self.write_bytes(to, &b);
true
}
pub fn sizeof_wide(&self, unicode_str_ptr: u64) -> usize {
const MAX_STR_LEN: usize = 1_000_000;
let mut counter: usize = 0;
for i in (0..MAX_STR_LEN).step_by(2) {
let b = match self.read_word(unicode_str_ptr + i as u64) {
Some(w) => w,
None => return counter,
};
if b == 0 {
return counter;
}
counter += 1;
}
0
}
pub fn write_string(&mut self, to: u64, from: &str) {
let bs: Vec<u8> = from.bytes().collect();
self.write_bytes(to, &bs);
self.write_byte(to + bs.len() as u64, 0x00);
}
pub fn write_wide_string(&mut self, to: u64, from: &str) {
let Some(mem) = self.get_mem_by_addr_mut(to) else {
log::warn!("Cannot write wide string: no map at 0x{:x}", to);
return;
};
if !mem.can_write() {
log::warn!("Cannot write wide string: non-writable at 0x{:x}", to);
return;
}
mem.write_wide_string(to, from);
}
#[inline(always)]
pub fn write_buffer(&mut self, to: u64, from: &[u8]) {
self.write_bytes_slice(to, from);
}
pub fn read_bytes_buff(&self, buff: &mut [u8], addr: u64) {
let len = buff.len();
buff.copy_from_slice(self.read_bytes(addr, len));
}
#[inline(always)]
pub fn read_buffer(&mut self, from: u64, sz: usize) -> Vec<u8> {
self.read_bytes(from, sz).to_vec()
}
pub fn try_read_bytes(&self, addr: u64, sz: usize) -> Option<&[u8]> {
if sz == 0 {
return Some(&[]);
}
let end_addr = addr + sz as u64 - 1;
let mem = self.get_mem_by_addr(addr)?;
if !mem.inside(end_addr) || !mem.can_read() {
log::warn!(
"Reading {} bytes from unmapped or non-readable region at 0x{:x}",
sz,
addr
);
return None;
}
Some(mem.read_bytes(addr, sz))
}
pub fn read_bytes(&self, addr: u64, sz: usize) -> &[u8] {
match self.try_read_bytes(addr, sz) {
Some(s) => s,
None => {
if sz == 0 {
return &[];
}
Box::leak(vec![0u8; sz].into_boxed_slice())
}
}
}
#[inline(always)]
pub fn read_bytes_option(&self, addr: u64, sz: usize) -> Option<&[u8]> {
self.try_read_bytes(addr, sz)
}
pub fn read_bytes_array<const N: usize>(&self, addr: u64) -> [u8; N] {
match self.try_read_bytes(addr, N) {
Some(slice) if slice.len() == N => {
let mut out = [0u8; N];
out.copy_from_slice(slice);
out
}
_ => [0u8; N],
}
}
pub fn read_string_of_bytes(&mut self, addr: u64, sz: usize) -> String {
let mut svec: Vec<String> = Vec::new();
let bytes = match self.try_read_bytes(addr, sz) {
Some(b) => b,
None => return String::new(),
};
for bs in bytes.iter() {
svec.push(format!("{:02x} ", bs));
}
let s: String = svec.into_iter().collect();
s
}
pub fn read_string(&self, addr: u64) -> String {
if addr == 0 {
return "".to_string();
}
let mut bytes: Vec<char> = Vec::new();
let mut b: u8;
let mut i: u64 = 0;
loop {
b = match self.read_byte(addr + i) {
Some(v) => v,
None => break,
};
if b == 0x00 {
break;
}
i += 1;
bytes.push(b as char);
}
let s: String = bytes.into_iter().collect();
s
}
pub fn read_wide_string_nocrash(&self, addr: u64) -> String {
if addr == 0 {
return "".to_string();
}
let mem = match self.get_mem_by_addr(addr) {
Some(m) => m,
None => {
return "".to_string();
}
};
mem.read_wide_string(addr)
}
pub fn read_wide_string(&self, addr: u64) -> String {
if addr == 0 {
return "".to_string();
}
let Some(mem) = self.get_mem_by_addr(addr) else {
log::warn!("read_wide_string: no map at 0x{:x}", addr);
return String::new();
};
if !mem.can_read() {
log::warn!("read_wide_string: non-readable map at 0x{:x}", addr);
return String::new();
}
mem.read_wide_string(addr)
}
pub fn read_wide_string_n(&self, addr: u64, max_chars: usize) -> String {
if addr == 0 {
return "".to_string();
}
let Some(mem) = self.get_mem_by_addr(addr) else {
log::warn!("read_wide_string_n: no map at 0x{:x}", addr);
return String::new();
};
if !mem.can_read() {
log::warn!("read_wide_string_n: non-readable map at 0x{:x}", addr);
return String::new();
}
mem.read_wide_string_n(addr, max_chars)
}
pub fn filter_string(&self, s: &mut String) {
let valid = " 0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ!\"#$%&'()*+,-./:;<=>?@[\\]^_`{|}~ \t\x00".as_bytes();
s.retain(|c| valid.contains(&(c as u8)));
}
pub fn filter_replace_bytes(&self, s: &[u8]) -> Vec<u8> {
let mut sanitized: Vec<u8> = Vec::new();
let valid =
"0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ!\"#$%&'()*+,-./:;<=>?@[\\]^_`{|}~".as_bytes();
let mut p;
for si in s.iter() {
p = false;
for validj in valid.iter() {
if validj == si {
sanitized.push(*si);
p = true;
break;
}
}
if !p {
sanitized.push(b'.');
}
}
sanitized
}
pub fn filter_replace_string(&self, s: &str) -> String {
let valid =
"0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ!\"#$%&'()*+,-./:;<=>?@[\\]^_`{|}~".as_bytes();
let sb = s.as_bytes();
let mut p;
let mut dst: Vec<char> = Vec::new();
for i in 0..s.len() {
p = false;
for j in 0..valid.len() {
if sb[i] == valid[j] {
dst.push(sb[i] as char);
p = true;
break;
}
}
if !p {
dst.push('.');
}
}
let sdst: String = dst.into_iter().collect();
sdst
}
}