diff --git a/src/lib.rs b/src/lib.rs index 94693fb..c15cf94 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -116,6 +116,31 @@ pub fn maps_contain_addr(addr: usize, maps: &[MapRange]) -> bool { maps.iter().any(|map| map_contain_addr(map, addr)) } +/// Returns whether or not any MapRange contains the given address range. +/// Note: this will only work correctly on macOS and Linux. +pub fn maps_contain_addr_range(mut addr: usize, mut size: usize, maps: &[MapRange]) -> bool { + if size == 0 || addr.checked_add(size).is_none() { + return false; + } + + while size > 0 { + match maps.iter().find(|map| map_contain_addr(map, addr)) { + None => return false, + Some(map) => { + let end = map.start() + map.size(); + if addr + size <= end { + return true; + } else { + size -= end - addr; + addr = end; + } + } + } + } + + true +} + #[cfg(test)] mod tests { use crate::get_process_maps; diff --git a/src/linux_maps.rs b/src/linux_maps.rs index 578d051..1bfdbd1 100644 --- a/src/linux_maps.rs +++ b/src/linux_maps.rs @@ -187,3 +187,72 @@ fn test_parse_maps() { assert_eq!(super::maps_contain_addr(0x00400000, &vec), true); assert_eq!(super::maps_contain_addr(0x00300000, &vec), false); } + +#[test] +fn test_contains_addr_range() { + let vec = vec![ + MapRange { + range_start: 0x00400000, + range_end: 0x00500000, + offset: 0, + dev: "00:14".to_string(), + flags: "r-xp".to_string(), + inode: 205736, + pathname: Some(PathBuf::from("/usr/bin/fish")), + }, + MapRange { + range_start: 0x00600000, + range_end: 0x00700000, + offset: 0, + dev: "00:14".to_string(), + flags: "r--p".to_string(), + inode: 205736, + pathname: Some(PathBuf::from("/usr/bin/fish")), + }, + MapRange { + range_start: 0x00700000, + range_end: 0x00800000, + offset: 0, + dev: "00:14".to_string(), + flags: "r--p".to_string(), + inode: 205736, + pathname: Some(PathBuf::from("/usr/bin/fish")), + }, + ]; + + assert_eq!(super::maps_contain_addr_range(0x00400000, 0x1, &vec), true); + assert_eq!( + super::maps_contain_addr_range(0x00400000, 0x100000, &vec), + true + ); + assert_eq!( + super::maps_contain_addr_range(0x00500000 - 1, 1, &vec), + true + ); + assert_eq!( + super::maps_contain_addr_range(0x00600000, 0x100001, &vec), + true + ); + assert_eq!( + super::maps_contain_addr_range(0x00600000, 0x200000, &vec), + true + ); + + assert_eq!( + super::maps_contain_addr_range(0x00400000, 0x100001, &vec), + false + ); + assert_eq!( + super::maps_contain_addr_range(0x00400000, usize::MAX, &vec), + false + ); + assert_eq!(super::maps_contain_addr_range(0x00400000, 0, &vec), false); + assert_eq!( + super::maps_contain_addr_range(0x00400000, 0x00200000, &vec), + false + ); + assert_eq!( + super::maps_contain_addr_range(0x00400000, 0x00200001, &vec), + false + ); +}