Unverified Commit a8574343 by van den Bosch Committed by GitHub

Macros and test changes (#380)

parent 2c766f5a
...@@ -79,12 +79,12 @@ fn main() -> Result<(), Error> { ...@@ -79,12 +79,12 @@ fn main() -> Result<(), Error> {
/// Return `Ok(file_path)` only if `file_path` points to an existing file. /// Return `Ok(file_path)` only if `file_path` points to an existing file.
fn check_file_existence(file_path: &str) -> Result<String, String> { fn check_file_existence(file_path: &str) -> Result<String, String> {
if std::fs::metadata(file_path) if std::fs::metadata(file_path)
.map_err(|err| format!("{}", err))? .map_err(|err| format!("{err}"))?
.is_file() .is_file()
{ {
Ok(file_path.to_string()) Ok(file_path.to_string())
} else { } else {
Err(format!("{} is not a file.", file_path)) Err(format!("{file_path} is not a file."))
} }
} }
...@@ -95,7 +95,7 @@ fn run_with_ghidra(args: &CmdlineArgs) -> Result<(), Error> { ...@@ -95,7 +95,7 @@ fn run_with_ghidra(args: &CmdlineArgs) -> Result<(), Error> {
// Only print the module versions and then quit. // Only print the module versions and then quit.
println!("[cwe_checker] module_versions:"); println!("[cwe_checker] module_versions:");
for module in modules.iter() { for module in modules.iter() {
println!("{}", module); println!("{module}");
} }
return Ok(()); return Ok(());
} }
...@@ -235,7 +235,7 @@ fn filter_modules_for_partial_run( ...@@ -235,7 +235,7 @@ fn filter_modules_for_partial_run(
} else if module_name.is_empty() { } else if module_name.is_empty() {
None None
} else { } else {
panic!("Error: {} is not a valid module name.", module_name) panic!("Error: {module_name} is not a valid module name.")
} }
}) })
.collect(); .collect();
......
...@@ -180,11 +180,12 @@ impl std::fmt::Display for BitvectorDomain { ...@@ -180,11 +180,12 @@ impl std::fmt::Display for BitvectorDomain {
} }
#[cfg(test)] #[cfg(test)]
mod tests { pub mod tests {
use super::*; use super::*;
use crate::bitvec;
fn bv(value: i64) -> BitvectorDomain { fn bv(value: i64) -> BitvectorDomain {
BitvectorDomain::Value(Bitvector::from_i64(value)) bitvec!(format!("{}:8", value)).into()
} }
#[test] #[test]
...@@ -211,11 +212,11 @@ mod tests { ...@@ -211,11 +212,11 @@ mod tests {
assert_eq!( assert_eq!(
sixteen.bin_op(IntEqual, &bv(16)), sixteen.bin_op(IntEqual, &bv(16)),
BitvectorDomain::Value(Bitvector::from_u8(true as u8)) BitvectorDomain::Value(bitvec!(format!("{}:1", true as u8)))
); );
assert_eq!( assert_eq!(
sixteen.bin_op(IntNotEqual, &bv(16)), sixteen.bin_op(IntNotEqual, &bv(16)),
BitvectorDomain::Value(Bitvector::from_u8(false as u8)) BitvectorDomain::Value(bitvec!(format!("{}:1", false as u8)))
); );
assert_eq!(sixteen.un_op(Int2Comp), bv(-16)); assert_eq!(sixteen.un_op(Int2Comp), bv(-16));
...@@ -223,27 +224,26 @@ mod tests { ...@@ -223,27 +224,26 @@ mod tests {
assert_eq!( assert_eq!(
sixteen.subpiece(ByteSize::new(0), ByteSize::new(4)), sixteen.subpiece(ByteSize::new(0), ByteSize::new(4)),
BitvectorDomain::Value(Bitvector::from_i32(16)) BitvectorDomain::Value(bitvec!("16:4"))
); );
assert_eq!( assert_eq!(
sixteen.subpiece(ByteSize::new(4), ByteSize::new(4)), sixteen.subpiece(ByteSize::new(4), ByteSize::new(4)),
BitvectorDomain::Value(Bitvector::from_i32(0)) BitvectorDomain::Value(bitvec!("0:4"))
); );
assert_eq!( assert_eq!(
BitvectorDomain::Value(Bitvector::from_i32(2)), BitvectorDomain::Value(bitvec!("2:4")),
BitvectorDomain::Value(Bitvector::from_i64(2 << 32)) bv(2 << 32).subpiece(ByteSize::new(4), ByteSize::new(4))
.subpiece(ByteSize::new(4), ByteSize::new(4))
); );
assert_eq!( assert_eq!(
BitvectorDomain::Value(Bitvector::from_i32(-1)) BitvectorDomain::Value(bitvec!("-1:4"))
.bin_op(Piece, &BitvectorDomain::Value(Bitvector::from_i32(-1))), .bin_op(Piece, &BitvectorDomain::Value(bitvec!("-1:4"))),
bv(-1) bv(-1)
); );
assert_eq!( assert_eq!(
BitvectorDomain::Value(Bitvector::from_i32(-1)).cast(PopCount, ByteSize::new(8)), BitvectorDomain::Value(bitvec!("-1:4")).cast(PopCount, ByteSize::new(8)),
bv(32) bv(32)
) )
} }
...@@ -262,26 +262,14 @@ mod tests { ...@@ -262,26 +262,14 @@ mod tests {
#[test] #[test]
fn arshift() { fn arshift() {
use BinOpType::IntSRight; use BinOpType::IntSRight;
let positive_x = BitvectorDomain::Value(Bitvector::from_i64(31)); let positive_x = bv(31);
let negative_x = BitvectorDomain::Value(Bitvector::from_i64(-31)); let negative_x = bv(-31);
let shift_3 = BitvectorDomain::Value(Bitvector::from_u8(3)); let shift_3 = BitvectorDomain::Value(bitvec!("3:1"));
let shift_70 = BitvectorDomain::Value(Bitvector::from_u8(70)); let shift_70 = BitvectorDomain::Value(bitvec!("70:1"));
assert_eq!( assert_eq!(positive_x.bin_op(IntSRight, &shift_3), bv(3));
positive_x.bin_op(IntSRight, &shift_3), assert_eq!(positive_x.bin_op(IntSRight, &shift_70), bv(0));
BitvectorDomain::Value(Bitvector::from_i64(3)) assert_eq!(negative_x.bin_op(IntSRight, &shift_3), bv(-4));
); assert_eq!(negative_x.bin_op(IntSRight, &shift_70), bv(-1));
assert_eq!(
positive_x.bin_op(IntSRight, &shift_70),
BitvectorDomain::Value(Bitvector::from_i64(0))
);
assert_eq!(
negative_x.bin_op(IntSRight, &shift_3),
BitvectorDomain::Value(Bitvector::from_i64(-4))
);
assert_eq!(
negative_x.bin_op(IntSRight, &shift_70),
BitvectorDomain::Value(Bitvector::from_i64(-1))
);
} }
#[test] #[test]
......
...@@ -197,7 +197,7 @@ impl fmt::Display for BricksDomain { ...@@ -197,7 +197,7 @@ impl fmt::Display for BricksDomain {
BricksDomain::Value(brick_domains) => { BricksDomain::Value(brick_domains) => {
write!(f, "Bricks: ")?; write!(f, "Bricks: ")?;
for brick_domain in brick_domains.iter() { for brick_domain in brick_domains.iter() {
write!(f, "{} ", brick_domain)?; write!(f, "{brick_domain} ")?;
} }
Ok(()) Ok(())
......
...@@ -169,7 +169,7 @@ impl fmt::Display for CharacterInclusionDomain { ...@@ -169,7 +169,7 @@ impl fmt::Display for CharacterInclusionDomain {
match self { match self {
CharacterInclusionDomain::Top => write!(f, "Top"), CharacterInclusionDomain::Top => write!(f, "Top"),
CharacterInclusionDomain::Value((certain_set, possible_set)) => { CharacterInclusionDomain::Value((certain_set, possible_set)) => {
write!(f, "Certain: {}, Possible: {}", certain_set, possible_set) write!(f, "Certain: {certain_set}, Possible: {possible_set}")
} }
} }
} }
...@@ -243,7 +243,7 @@ impl fmt::Display for CharacterSet { ...@@ -243,7 +243,7 @@ impl fmt::Display for CharacterSet {
match self { match self {
CharacterSet::Top => write!(f, "Top"), CharacterSet::Top => write!(f, "Top"),
CharacterSet::Value(char_set) => { CharacterSet::Value(char_set) => {
write!(f, "{:?}", char_set) write!(f, "{char_set:?}")
} }
} }
} }
......
...@@ -215,8 +215,8 @@ impl<T: RegisterDomain + Display> DataDomain<T> { ...@@ -215,8 +215,8 @@ impl<T: RegisterDomain + Display> DataDomain<T> {
if !self.relative_values.is_empty() { if !self.relative_values.is_empty() {
let target_iter = self.relative_values.iter().map(|(id, offset)| { let target_iter = self.relative_values.iter().map(|(id, offset)| {
( (
format!("{}", id), format!("{id}"),
serde_json::Value::String(format!("{}", offset)), serde_json::Value::String(format!("{offset}")),
) )
}); });
let targets = serde_json::Value::Object(target_iter.collect()); let targets = serde_json::Value::Object(target_iter.collect());
...@@ -226,8 +226,7 @@ impl<T: RegisterDomain + Display> DataDomain<T> { ...@@ -226,8 +226,7 @@ impl<T: RegisterDomain + Display> DataDomain<T> {
} }
if let Some(absolute_value) = &self.absolute_value { if let Some(absolute_value) = &self.absolute_value {
values.push(serde_json::Value::String(format!( values.push(serde_json::Value::String(format!(
"Value: {}", "Value: {absolute_value}"
absolute_value
))); )));
} }
if self.contains_top_values { if self.contains_top_values {
...@@ -248,6 +247,7 @@ impl<T: RegisterDomain + Display> DataDomain<T> { ...@@ -248,6 +247,7 @@ impl<T: RegisterDomain + Display> DataDomain<T> {
mod tests { mod tests {
use super::super::*; use super::super::*;
use super::*; use super::*;
use crate::{bitvec, variable};
impl<T: RegisterDomain> DataDomain<T> { impl<T: RegisterDomain> DataDomain<T> {
/// Return a new domain representing a set of relative values. /// Return a new domain representing a set of relative values.
...@@ -267,13 +267,13 @@ mod tests { ...@@ -267,13 +267,13 @@ mod tests {
} }
fn bv(value: i64) -> BitvectorDomain { fn bv(value: i64) -> BitvectorDomain {
BitvectorDomain::Value(Bitvector::from_i64(value)) bitvec!(format!("{}:8", value)).into()
} }
fn new_id(name: &str) -> AbstractIdentifier { fn new_id(name: &str) -> AbstractIdentifier {
AbstractIdentifier::new( AbstractIdentifier::new(
Tid::new("time0"), Tid::new("time0"),
AbstractLocation::Register(Variable::mock(name, ByteSize::new(8))), AbstractLocation::Register(variable!(format!("{}:8", name))),
) )
} }
......
...@@ -244,18 +244,18 @@ impl<T: RegisterDomain> std::ops::Sub for DataDomain<T> { ...@@ -244,18 +244,18 @@ impl<T: RegisterDomain> std::ops::Sub for DataDomain<T> {
mod tests { mod tests {
use super::super::*; use super::super::*;
use super::*; use super::*;
use crate::abstract_domain::*; use crate::{abstract_domain::*, bitvec, variable};
type Data = DataDomain<BitvectorDomain>; type Data = DataDomain<BitvectorDomain>;
fn bv(value: i64) -> BitvectorDomain { fn bv(value: i64) -> BitvectorDomain {
BitvectorDomain::Value(Bitvector::from_i64(value)) BitvectorDomain::Value(bitvec!(format!("{}:8", value)))
} }
fn new_id(name: &str) -> AbstractIdentifier { fn new_id(name: &str) -> AbstractIdentifier {
AbstractIdentifier::new( AbstractIdentifier::new(
Tid::new("time0"), Tid::new("time0"),
AbstractLocation::Register(Variable::mock(name, ByteSize::new(8))), AbstractLocation::Register(variable!(format!("{}:8", name))),
) )
} }
...@@ -313,7 +313,7 @@ mod tests { ...@@ -313,7 +313,7 @@ mod tests {
assert_eq!( assert_eq!(
three.subpiece(ByteSize::new(0), ByteSize::new(4)), three.subpiece(ByteSize::new(0), ByteSize::new(4)),
BitvectorDomain::Value(Bitvector::from_i32(3)).into() BitvectorDomain::Value(bitvec!("3:4")).into()
); );
assert_eq!( assert_eq!(
...@@ -321,8 +321,8 @@ mod tests { ...@@ -321,8 +321,8 @@ mod tests {
ByteSize::new(16) ByteSize::new(16)
); );
let one: Data = BitvectorDomain::Value(Bitvector::from_i32(1)).into(); let one: Data = BitvectorDomain::Value(bitvec!("1:4")).into();
let two: Data = BitvectorDomain::Value(Bitvector::from_i32(2)).into(); let two: Data = BitvectorDomain::Value(bitvec!("2:4")).into();
let concat = new_value((1 << 32) + 2); let concat = new_value((1 << 32) + 2);
assert_eq!(one.bin_op(Piece, &two), concat); assert_eq!(one.bin_op(Piece, &two), concat);
} }
......
...@@ -118,12 +118,12 @@ impl<T: SpecializeByConditional + RegisterDomain> SpecializeByConditional for Da ...@@ -118,12 +118,12 @@ impl<T: SpecializeByConditional + RegisterDomain> SpecializeByConditional for Da
#[cfg(test)] #[cfg(test)]
mod tests { mod tests {
use super::*; use super::*;
use crate::abstract_domain::*; use crate::{abstract_domain::*, variable};
fn new_id(name: &str) -> AbstractIdentifier { fn new_id(name: &str) -> AbstractIdentifier {
AbstractIdentifier::new( AbstractIdentifier::new(
Tid::new("time0"), Tid::new("time0"),
AbstractLocation::Register(Variable::mock(name, ByteSize::new(8))), AbstractLocation::Register(variable!(format!("{}:8", name))),
) )
} }
......
...@@ -109,18 +109,18 @@ impl<T: RegisterDomain + TryToInterval> TryToInterval for DataDomain<T> { ...@@ -109,18 +109,18 @@ impl<T: RegisterDomain + TryToInterval> TryToInterval for DataDomain<T> {
mod tests { mod tests {
use super::super::*; use super::super::*;
use super::*; use super::*;
use crate::abstract_domain::*; use crate::{abstract_domain::*, bitvec, variable};
type Data = DataDomain<BitvectorDomain>; type Data = DataDomain<BitvectorDomain>;
fn bv(value: i64) -> BitvectorDomain { fn bv(value: i64) -> BitvectorDomain {
BitvectorDomain::Value(Bitvector::from_i64(value)) BitvectorDomain::Value(bitvec!(format!("{}:8", value)))
} }
fn new_id(name: &str) -> AbstractIdentifier { fn new_id(name: &str) -> AbstractIdentifier {
AbstractIdentifier::new( AbstractIdentifier::new(
Tid::new("time0"), Tid::new("time0"),
AbstractLocation::Register(Variable::mock(name, ByteSize::new(8))), AbstractLocation::Register(variable!(format!("{}:8", name))),
) )
} }
......
...@@ -217,23 +217,22 @@ impl<K: Ord + Clone, V: AbstractDomain + HasTop> MapMergeStrategy<K, V> for Merg ...@@ -217,23 +217,22 @@ impl<K: Ord + Clone, V: AbstractDomain + HasTop> MapMergeStrategy<K, V> for Merg
#[cfg(test)] #[cfg(test)]
mod tests { mod tests {
use super::*; use super::*;
use crate::bitvec;
use std::collections::BTreeMap; use std::collections::BTreeMap;
use crate::intermediate_representation::Bitvector;
#[test] #[test]
fn test_merge_strategies() { fn test_merge_strategies() {
let map_left: BTreeMap<u64, DataDomain<BitvectorDomain>> = [ let map_left: BTreeMap<u64, DataDomain<BitvectorDomain>> = [
(0u64, Bitvector::from_i64(0).into()), (0u64, bitvec!("0:8").into()),
(1u64, Bitvector::from_i64(0).into()), (1u64, bitvec!("0:8").into()),
(5u64, DataDomain::new_top(ByteSize::new(8))), (5u64, DataDomain::new_top(ByteSize::new(8))),
] ]
.iter() .iter()
.cloned() .cloned()
.collect(); .collect();
let map_right: BTreeMap<u64, DataDomain<BitvectorDomain>> = [ let map_right: BTreeMap<u64, DataDomain<BitvectorDomain>> = [
(1u64, Bitvector::from_i64(1).into()), (1u64, bitvec!("1:8").into()),
(2u64, Bitvector::from_i64(1).into()), (2u64, bitvec!("1:8").into()),
(5u64, DataDomain::new_top(ByteSize::new(8))), (5u64, DataDomain::new_top(ByteSize::new(8))),
] ]
.iter() .iter()
...@@ -244,12 +243,12 @@ mod tests { ...@@ -244,12 +243,12 @@ mod tests {
let domain_map_left: DomainMap<_, _, UnionMergeStrategy> = map_left.clone().into(); let domain_map_left: DomainMap<_, _, UnionMergeStrategy> = map_left.clone().into();
let domain_map_right: DomainMap<_, _, UnionMergeStrategy> = map_right.clone().into(); let domain_map_right: DomainMap<_, _, UnionMergeStrategy> = map_right.clone().into();
let merged_map = domain_map_left.merge(&domain_map_right); let merged_map = domain_map_left.merge(&domain_map_right);
assert_eq!(merged_map.get(&0), Some(&Bitvector::from_i64(0).into())); assert_eq!(merged_map.get(&0), Some(&bitvec!("0:8").into()));
assert_eq!( assert_eq!(
merged_map.get(&1), merged_map.get(&1),
Some(&BitvectorDomain::new_top(ByteSize::new(8)).into()) Some(&BitvectorDomain::new_top(ByteSize::new(8)).into())
); );
assert_eq!(merged_map.get(&2), Some(&Bitvector::from_i64(1).into())); assert_eq!(merged_map.get(&2), Some(&bitvec!("1:8").into()));
assert_eq!( assert_eq!(
merged_map.get(&5), merged_map.get(&5),
Some(&DataDomain::new_top(ByteSize::new(8)).into()) Some(&DataDomain::new_top(ByteSize::new(8)).into())
...@@ -273,7 +272,7 @@ mod tests { ...@@ -273,7 +272,7 @@ mod tests {
let merged_map = domain_map_left.merge(&domain_map_right); let merged_map = domain_map_left.merge(&domain_map_right);
assert_eq!( assert_eq!(
merged_map.get(&0).unwrap().get_absolute_value(), merged_map.get(&0).unwrap().get_absolute_value(),
Some(&Bitvector::from_i64(0).into()) Some(&bitvec!("0:8").into())
); );
assert!(merged_map.get(&0).unwrap().contains_top()); assert!(merged_map.get(&0).unwrap().contains_top());
assert_eq!( assert_eq!(
...@@ -282,7 +281,7 @@ mod tests { ...@@ -282,7 +281,7 @@ mod tests {
); );
assert_eq!( assert_eq!(
merged_map.get(&2).unwrap().get_absolute_value(), merged_map.get(&2).unwrap().get_absolute_value(),
Some(&Bitvector::from_i64(1).into()) Some(&bitvec!("1:8").into())
); );
assert!(merged_map.get(&2).unwrap().contains_top()); assert!(merged_map.get(&2).unwrap().contains_top());
assert_eq!(merged_map.get(&5), None); assert_eq!(merged_map.get(&5), None);
......
...@@ -144,7 +144,7 @@ impl std::fmt::Display for AbstractIdentifier { ...@@ -144,7 +144,7 @@ impl std::fmt::Display for AbstractIdentifier {
} else { } else {
write!(formatter, "{}(", self.0.time)?; write!(formatter, "{}(", self.0.time)?;
for hint in &self.0.path_hints { for hint in &self.0.path_hints {
write!(formatter, "->{}", hint)?; write!(formatter, "->{hint}",)?;
} }
write!(formatter, ") @ {}", self.0.location) write!(formatter, ") @ {}", self.0.location)
} }
...@@ -185,10 +185,10 @@ impl std::fmt::Display for AbstractLocation { ...@@ -185,10 +185,10 @@ impl std::fmt::Display for AbstractLocation {
fn fmt(&self, formatter: &mut std::fmt::Formatter) -> std::fmt::Result { fn fmt(&self, formatter: &mut std::fmt::Formatter) -> std::fmt::Result {
match self { match self {
Self::Register(var) => write!(formatter, "{}", var.name), Self::Register(var) => write!(formatter, "{}", var.name),
Self::GlobalAddress { address, size: _ } => write!(formatter, "0x{:x}", address), Self::GlobalAddress { address, size: _ } => write!(formatter, "0x{address:x}"),
Self::Pointer(var, location) => write!(formatter, "{}->{}", var.name, location), Self::Pointer(var, location) => write!(formatter, "{}->{}", var.name, location),
Self::GlobalPointer(address, location) => { Self::GlobalPointer(address, location) => {
write!(formatter, "0x{:x}->{}", address, location) write!(formatter, "0x{address:x}->{location}")
} }
} }
} }
...@@ -275,8 +275,8 @@ impl AbstractMemoryLocation { ...@@ -275,8 +275,8 @@ impl AbstractMemoryLocation {
impl std::fmt::Display for AbstractMemoryLocation { impl std::fmt::Display for AbstractMemoryLocation {
fn fmt(&self, formatter: &mut std::fmt::Formatter) -> std::fmt::Result { fn fmt(&self, formatter: &mut std::fmt::Formatter) -> std::fmt::Result {
match self { match self {
Self::Location { offset, .. } => write!(formatter, "({})", offset), Self::Location { offset, .. } => write!(formatter, "({offset})"),
Self::Pointer { offset, target } => write!(formatter, "({})->{}", offset, target), Self::Pointer { offset, target } => write!(formatter, "({offset})->{target}"),
} }
} }
} }
...@@ -284,6 +284,7 @@ impl std::fmt::Display for AbstractMemoryLocation { ...@@ -284,6 +284,7 @@ impl std::fmt::Display for AbstractMemoryLocation {
#[cfg(test)] #[cfg(test)]
pub mod tests { pub mod tests {
use super::*; use super::*;
use crate::variable;
impl AbstractIdentifier { impl AbstractIdentifier {
/// Mock an abstract identifier with the given TID name and pointing to the value in the given register name. /// Mock an abstract identifier with the given TID name and pointing to the value in the given register name.
...@@ -294,7 +295,12 @@ pub mod tests { ...@@ -294,7 +295,12 @@ pub mod tests {
) -> AbstractIdentifier { ) -> AbstractIdentifier {
AbstractIdentifier::new( AbstractIdentifier::new(
Tid::new(tid.to_string()), Tid::new(tid.to_string()),
AbstractLocation::from_var(&Variable::mock(register, size_in_bytes)).unwrap(), AbstractLocation::from_var(&variable!(format!(
"{}:{}",
register.to_string(),
size_in_bytes
)))
.unwrap(),
) )
} }
} }
...@@ -311,7 +317,7 @@ pub mod tests { ...@@ -311,7 +317,7 @@ pub mod tests {
// Test uniqueness of TIDs in path hint array. // Test uniqueness of TIDs in path hint array.
let id = AbstractIdentifier::new( let id = AbstractIdentifier::new(
Tid::new("time_id"), Tid::new("time_id"),
AbstractLocation::from_var(&Variable::mock("var", 8)).unwrap(), AbstractLocation::from_var(&variable!("var:8")).unwrap(),
); );
let id = id.with_path_hint(Tid::new("first_hint")).unwrap(); let id = id.with_path_hint(Tid::new("first_hint")).unwrap();
let id = id.with_path_hint(Tid::new("second_hint")).unwrap(); let id = id.with_path_hint(Tid::new("second_hint")).unwrap();
...@@ -321,7 +327,7 @@ pub mod tests { ...@@ -321,7 +327,7 @@ pub mod tests {
#[test] #[test]
fn test_bytesize() { fn test_bytesize() {
let location = let location =
AbstractLocation::from_stack_position(&Variable::mock("RSP", 8), 10, ByteSize::new(4)); AbstractLocation::from_stack_position(&variable!("RSP:8"), 10, ByteSize::new(4));
let id = AbstractIdentifier::new(Tid::new("id"), location); let id = AbstractIdentifier::new(Tid::new("id"), location);
assert_eq!(id.bytesize(), ByteSize::new(4)); assert_eq!(id.bytesize(), ByteSize::new(4));
} }
......
use crate::bitvec;
use super::*; use super::*;
impl Interval { impl Interval {
pub fn mock(start: i64, end: i64) -> Interval { pub fn mock(start: i64, end: i64) -> Interval {
Interval::new(Bitvector::from_i64(start), Bitvector::from_i64(end), 1) Interval::new(
bitvec!(format!("{}:8", start)),
bitvec!(format!("{}:8", end)),
1,
)
} }
pub fn mock_i8(start: i8, end: i8) -> Interval { pub fn mock_i8(start: i8, end: i8) -> Interval {
Interval::new(Bitvector::from_i8(start), Bitvector::from_i8(end), 1) Interval::new(
bitvec!(format!("{}:1", start)),
bitvec!(format!("{}:1", end)),
1,
)
} }
pub fn with_stride(mut self, stride: u64) -> Interval { pub fn with_stride(mut self, stride: u64) -> Interval {
...@@ -92,7 +102,7 @@ fn subpiece_higher() { ...@@ -92,7 +102,7 @@ fn subpiece_higher() {
let val = Interval::mock(3, 21).with_stride(6); let val = Interval::mock(3, 21).with_stride(6);
assert_eq!( assert_eq!(
val.subpiece_higher(ByteSize::new(7)), val.subpiece_higher(ByteSize::new(7)),
Interval::from(Bitvector::from_i8(0)) Interval::from(bitvec!("0:1"))
) )
} }
...@@ -117,8 +127,8 @@ fn piece() { ...@@ -117,8 +127,8 @@ fn piece() {
assert_eq!( assert_eq!(
left.piece(&right), left.piece(&right),
Interval { Interval {
start: Bitvector::from_i16(256), start: bitvec!("256:2"),
end: Bitvector::from_i16(1278), end: bitvec!("1278:2"),
stride: 2, stride: 2,
} }
); );
...@@ -127,8 +137,8 @@ fn piece() { ...@@ -127,8 +137,8 @@ fn piece() {
assert_eq!( assert_eq!(
left.piece(&right), left.piece(&right),
Interval { Interval {
start: Bitvector::from_i16(259), start: bitvec!("259:2"),
end: Bitvector::from_i16(1039), end: bitvec!("1039:2"),
stride: 2, stride: 2,
} }
); );
...@@ -145,11 +155,11 @@ fn add_and_sub() { ...@@ -145,11 +155,11 @@ fn add_and_sub() {
#[test] #[test]
fn contains() { fn contains() {
let interval = Interval::mock(2, 10).with_stride(4); let interval = Interval::mock(2, 10).with_stride(4);
let elem = Bitvector::from_i64(4); let elem = bitvec!("4:8");
assert!(!interval.contains(&elem)); assert!(!interval.contains(&elem));
let elem = Bitvector::from_i64(6); let elem = bitvec!("6:8");
assert!(interval.contains(&elem)); assert!(interval.contains(&elem));
let elem = Bitvector::from_i64(14); let elem = bitvec!("14:8");
assert!(!interval.contains(&elem)); assert!(!interval.contains(&elem));
} }
......
use super::{create_computation, mock_context, NodeValue}; use super::{create_computation, mock_context, NodeValue};
use crate::def;
use crate::expr;
use crate::intermediate_representation::*; use crate::intermediate_representation::*;
use mock_context::Context;
use mock_context::StartEnd;
use std::collections::BTreeMap; use std::collections::BTreeMap;
use std::collections::BTreeSet; use std::collections::BTreeSet;
use std::iter::FromIterator; use std::iter::FromIterator;
use mock_context::Context;
use mock_context::StartEnd;
fn mock_program() -> Term<Program> { fn mock_program() -> Term<Program> {
let var = Variable { let def_term1 = def!["def1: RAX:8 = -(RAX:8)"];
name: String::from("RAX"), let def_term2 = def!["def2: RAX:8 = -(RAX:8)"];
size: ByteSize::new(8), let def_term3 = def!["def3: RAX:8 = -(RAX:8)"];
is_temp: false, let def_term4 = def!["def4: RAX:8 = -(RAX:8)"];
}; let def_term5 = def!["def5: RAX:8 = -(RAX:8)"];
let value = Expression::UnOp {
op: UnOpType::IntNegate,
arg: Box::new(Expression::Var(var.clone())),
};
let def_term1 = Term {
tid: Tid::new("def1".to_string()),
term: Def::Assign {
var: var.clone(),
value: value.clone(),
},
};
let def_term2 = Term {
tid: Tid::new("def2".to_string()),
term: Def::Assign {
var: var.clone(),
value: value.clone(),
},
};
let def_term3 = Term {
tid: Tid::new("def3".to_string()),
term: Def::Assign {
var: var.clone(),
value: value.clone(),
},
};
let def_term4 = Term {
tid: Tid::new("def4".to_string()),
term: Def::Assign {
var: var.clone(),
value: value.clone(),
},
};
let def_term5 = Term {
tid: Tid::new("def5".to_string()),
term: Def::Assign {
var: var.clone(),
value: value.clone(),
},
};
let call_term = Term { let call_term = Term {
tid: Tid::new("call".to_string()), tid: Tid::new("call".to_string()),
term: Jmp::Call { term: Jmp::Call {
...@@ -61,7 +24,7 @@ fn mock_program() -> Term<Program> { ...@@ -61,7 +24,7 @@ fn mock_program() -> Term<Program> {
}; };
let return_term = Term { let return_term = Term {
tid: Tid::new("return".to_string()), tid: Tid::new("return".to_string()),
term: Jmp::Return(Expression::Const(Bitvector::zero(64.into()))), // The return term does not matter term: Jmp::Return(expr!("0:8")), // The return term does not matter
}; };
let jmp = Jmp::Branch(Tid::new("sub1_blk1")); let jmp = Jmp::Branch(Tid::new("sub1_blk1"));
let jmp_term = Term { let jmp_term = Term {
...@@ -94,7 +57,7 @@ fn mock_program() -> Term<Program> { ...@@ -94,7 +57,7 @@ fn mock_program() -> Term<Program> {
}; };
let cond_jump = Jmp::CBranch { let cond_jump = Jmp::CBranch {
target: Tid::new("sub1_blk1"), target: Tid::new("sub1_blk1"),
condition: Expression::Const(Bitvector::from_u8(0)), condition: expr!("0:1"),
}; };
let cond_jump_term = Term { let cond_jump_term = Term {
tid: Tid::new("cond_jump"), tid: Tid::new("cond_jump"),
......
...@@ -127,25 +127,18 @@ pub fn remove_dead_var_assignments(project: &mut Project) { ...@@ -127,25 +127,18 @@ pub fn remove_dead_var_assignments(project: &mut Project) {
#[cfg(test)] #[cfg(test)]
mod tests { mod tests {
use super::*; use super::*;
use crate::defs;
fn def_assign_term(term_index: u64, input: &str, output: &str) -> Term<Def> {
Def::assign(
&format!("def_{}", term_index),
Variable::mock(output, 8),
Expression::Var(Variable::mock(input, 8)),
)
}
#[test] #[test]
fn dead_assignment_removal() { fn dead_assignment_removal() {
let defs = vec![ let defs = defs![
def_assign_term(1, "A", "B"), "def_1: B:8 = A:8",
def_assign_term(2, "B", "C"), "def_2: C:8 = B:8",
def_assign_term(3, "C", "RAX"), // dead assignment "def_3: RAX:8 = C:8",
def_assign_term(4, "B", "RAX"), "def_4: RAX:8 = B:8",
def_assign_term(5, "C", "RBX"), "def_5: RBX:8 = C:8",
def_assign_term(6, "A", "B"), // dead assignment, since the next assignment is dead "def_6: B:8 = A:8",
def_assign_term(7, "B", "C"), // dead assignment, since C is not a physical register "def_7: C:8 = B:8"
]; ];
let block = Term { let block = Term {
tid: Tid::new("block"), tid: Tid::new("block"),
...@@ -167,11 +160,11 @@ mod tests { ...@@ -167,11 +160,11 @@ mod tests {
project.program.term.subs.insert(sub.tid.clone(), sub); project.program.term.subs.insert(sub.tid.clone(), sub);
remove_dead_var_assignments(&mut project); remove_dead_var_assignments(&mut project);
let cleaned_defs = vec![ let cleaned_defs = defs![
def_assign_term(1, "A", "B"), "def_1: B:8 = A:8",
def_assign_term(2, "B", "C"), "def_2: C:8 = B:8",
def_assign_term(4, "B", "RAX"), "def_4: RAX:8 = B:8",
def_assign_term(5, "C", "RBX"), "def_5: RBX:8 = C:8"
]; ];
assert_eq!( assert_eq!(
&project.program.term.subs[&Tid::new("sub")].term.blocks[0] &project.program.term.subs[&Tid::new("sub")].term.blocks[0]
......
use super::*; use super::*;
use crate::intermediate_representation::{Def, Expression, Variable}; use crate::{defs, expr, intermediate_representation::Def, variable};
/// Creates a specific project containing three blocks for expression propagation tests. /// Creates a specific project containing three blocks for expression propagation tests.
/// ///
...@@ -12,11 +12,7 @@ fn mock_project() -> Project { ...@@ -12,11 +12,7 @@ fn mock_project() -> Project {
let callee_block = Term { let callee_block = Term {
tid: Tid::new("callee_block"), tid: Tid::new("callee_block"),
term: Blk { term: Blk {
defs: vec![Def::assign( defs: defs!["callee_def_1: Y:8 = Z:8"],
"callee_def_1",
Variable::mock("Y", 8),
Expression::var("Z", 8),
)],
jmps: Vec::new(), jmps: Vec::new(),
indirect_jmp_targets: Vec::new(), indirect_jmp_targets: Vec::new(),
}, },
...@@ -34,17 +30,9 @@ fn mock_project() -> Project { ...@@ -34,17 +30,9 @@ fn mock_project() -> Project {
let entry_jmp_block = Term { let entry_jmp_block = Term {
tid: Tid::new("entry_jmp_block"), tid: Tid::new("entry_jmp_block"),
term: Blk { term: Blk {
defs: vec![ defs: defs![
Def::assign( "entry_jmp_def_1: X:8 = ¬(Z:8)",
"entry_jmp_def_1", "entry_jmp_def_2: Z:8 = -(Z:8)"
Variable::mock("X", 8),
Expression::var("Z", 8).un_op(UnOpType::BoolNegate),
),
Def::assign(
"entry_jmp_def_2",
Variable::mock("Z", 8),
Expression::var("Z", 8).un_op(UnOpType::IntNegate),
),
], ],
jmps: vec![Term { jmps: vec![Term {
tid: Tid::new("call_to_called_function"), tid: Tid::new("call_to_called_function"),
...@@ -92,37 +80,13 @@ fn get_mock_entry_block() -> Term<Blk> { ...@@ -92,37 +80,13 @@ fn get_mock_entry_block() -> Term<Blk> {
Term { Term {
tid: Tid::new("entry_block"), tid: Tid::new("entry_block"),
term: Blk { term: Blk {
defs: vec![ defs: defs![
Def::assign( "tid_1: Z:8 = -(42:4)",
"tid_1", "tid_2: X:8 = -(Y:8)",
Variable::mock("Z", 8), "tid_3: Y:8 = X:8 + Y:8",
Expression::const_from_i32(42).un_op(UnOpType::IntNegate), "tid_4: X:8 = -(X:8)",
), "tid_5: Y:8 = -(Y:8)",
Def::assign( "tid_6: Y:8 = X:8 + Y:8"
"tid_2",
Variable::mock("X", 8),
Expression::var("Y", 8).un_op(UnOpType::IntNegate),
),
Def::assign(
"tid_3",
Variable::mock("Y", 8),
Expression::var("X", 8).plus(Expression::var("Y", 8)),
),
Def::assign(
"tid_4",
Variable::mock("X", 8),
Expression::var("X", 8).un_op(UnOpType::IntNegate),
),
Def::assign(
"tid_5",
Variable::mock("Y", 8),
Expression::var("Y", 8).un_op(UnOpType::IntNegate),
),
Def::assign(
"tid_6",
Variable::mock("Y", 8),
Expression::var("X", 8).plus(Expression::var("Y", 8)),
),
], ],
jmps: Vec::new(), jmps: Vec::new(),
indirect_jmp_targets: Vec::new(), indirect_jmp_targets: Vec::new(),
...@@ -149,17 +113,13 @@ fn inter_block_propagation() { ...@@ -149,17 +113,13 @@ fn inter_block_propagation() {
vec![ vec![
Def::assign( Def::assign(
"entry_jmp_def_1", "entry_jmp_def_1",
Variable::mock("X", 8), variable!("X:8"),
Expression::const_from_i32(42) expr!("-(42:4)").un_op(UnOpType::BoolNegate),
.un_op(UnOpType::IntNegate)
.un_op(UnOpType::BoolNegate),
), ),
Def::assign( Def::assign(
"entry_jmp_def_2", "entry_jmp_def_2",
Variable::mock("Z", 8), variable!("Z:8"),
Expression::const_from_i32(42) expr!("-(42:4)").un_op(UnOpType::IntNegate),
.un_op(UnOpType::IntNegate)
.un_op(UnOpType::IntNegate),
) )
] ]
) )
...@@ -181,11 +141,7 @@ fn no_propagation_on_calls() { ...@@ -181,11 +141,7 @@ fn no_propagation_on_calls() {
.unwrap() .unwrap()
.term .term
.defs, .defs,
vec![Def::assign( defs!["callee_def_1: Y:8 = Z:8"]
"callee_def_1",
Variable::mock("Y", 8),
Expression::var("Z", 8),
)]
) )
} }
#[test] #[test]
...@@ -214,10 +170,7 @@ fn insertion_table_update() { ...@@ -214,10 +170,7 @@ fn insertion_table_update() {
// Assignment is inserted into table, no other changes. // Assignment is inserted into table, no other changes.
assert_eq!( assert_eq!(
update.clone().unwrap(), update.clone().unwrap(),
HashMap::from([( HashMap::from([(variable!("Z:8"), expr!("-(42:4)"))])
Variable::mock("Z", 8),
Expression::const_from_i32(42).un_op(UnOpType::IntNegate)
)])
); );
let update = crate::analysis::forward_interprocedural_fixpoint::Context::update_def( let update = crate::analysis::forward_interprocedural_fixpoint::Context::update_def(
...@@ -229,14 +182,8 @@ fn insertion_table_update() { ...@@ -229,14 +182,8 @@ fn insertion_table_update() {
assert_eq!( assert_eq!(
update.clone().unwrap(), update.clone().unwrap(),
HashMap::from([ HashMap::from([
( (variable!("Z:8"), expr!("-(42:4)")),
Variable::mock("Z", 8), (variable!("X:8"), expr!("-(Y:8)"))
Expression::const_from_i32(42).un_op(UnOpType::IntNegate)
),
(
Variable::mock("X", 8),
Expression::var("Y", 8).un_op(UnOpType::IntNegate)
)
]) ])
); );
...@@ -248,10 +195,7 @@ fn insertion_table_update() { ...@@ -248,10 +195,7 @@ fn insertion_table_update() {
// Expression for X is removed and Assignment is not inserted. // Expression for X is removed and Assignment is not inserted.
assert_eq!( assert_eq!(
update.clone().unwrap(), update.clone().unwrap(),
HashMap::from([( HashMap::from([(variable!("Z:8"), expr!("-(42:4)")),])
Variable::mock("Z", 8),
Expression::const_from_i32(42).un_op(UnOpType::IntNegate)
),])
); );
let update = crate::analysis::forward_interprocedural_fixpoint::Context::update_def( let update = crate::analysis::forward_interprocedural_fixpoint::Context::update_def(
&context, &context,
...@@ -261,10 +205,7 @@ fn insertion_table_update() { ...@@ -261,10 +205,7 @@ fn insertion_table_update() {
// Expression for Y is removed and Assignment is not inserted. // Expression for Y is removed and Assignment is not inserted.
assert_eq!( assert_eq!(
update.clone().unwrap(), update.clone().unwrap(),
HashMap::from([( HashMap::from([(variable!("Z:8"), expr!("-(42:4)")),])
Variable::mock("Z", 8),
Expression::const_from_i32(42).un_op(UnOpType::IntNegate)
),])
); );
let update = crate::analysis::forward_interprocedural_fixpoint::Context::update_def( let update = crate::analysis::forward_interprocedural_fixpoint::Context::update_def(
...@@ -275,10 +216,7 @@ fn insertion_table_update() { ...@@ -275,10 +216,7 @@ fn insertion_table_update() {
// Assignment not inserted. // Assignment not inserted.
assert_eq!( assert_eq!(
update.clone().unwrap(), update.clone().unwrap(),
HashMap::from([( HashMap::from([(variable!("Z:8"), expr!("-(42:4)")),])
Variable::mock("Z", 8),
Expression::const_from_i32(42).un_op(UnOpType::IntNegate)
),])
); );
let update = crate::analysis::forward_interprocedural_fixpoint::Context::update_def( let update = crate::analysis::forward_interprocedural_fixpoint::Context::update_def(
...@@ -289,10 +227,7 @@ fn insertion_table_update() { ...@@ -289,10 +227,7 @@ fn insertion_table_update() {
// Assignment not inserted. // Assignment not inserted.
assert_eq!( assert_eq!(
update.clone().unwrap(), update.clone().unwrap(),
HashMap::from([( HashMap::from([(variable!("Z:8"), expr!("-(42:4)")),])
Variable::mock("Z", 8),
Expression::const_from_i32(42).un_op(UnOpType::IntNegate)
),])
); );
} }
#[test] #[test]
...@@ -300,35 +235,12 @@ fn insertion_table_update() { ...@@ -300,35 +235,12 @@ fn insertion_table_update() {
fn expressions_inserted() { fn expressions_inserted() {
let mut project = mock_project(); let mut project = mock_project();
propagate_input_expression(&mut project); propagate_input_expression(&mut project);
let result_def_entry_block = vec![ let result_def_entry_block = defs![
Def::assign( "tid_1: Z:8 = -(42:4)",
"tid_1", "tid_2: X:8 = -(Y:8)",
Variable::mock("Z", 8), "tid_3: Y:8 = -(Y:8) + Y:8",
Expression::const_from_i32(42).un_op(UnOpType::IntNegate), "tid_4: X:8 = -(X:8)",
), "tid_6: Y:8 = X:8 + -(Y:8)"
Def::assign(
"tid_2",
Variable::mock("X", 8),
Expression::var("Y", 8).un_op(UnOpType::IntNegate),
),
Def::assign(
"tid_3",
Variable::mock("Y", 8),
Expression::var("Y", 8)
.un_op(UnOpType::IntNegate)
.plus(Expression::var("Y", 8)),
),
Def::assign(
"tid_4",
Variable::mock("X", 8),
Expression::var("X", 8).un_op(UnOpType::IntNegate),
),
// tid_5 is removed by merge_def_assignments_to_same_var()
Def::assign(
"tid_6",
Variable::mock("Y", 8),
Expression::var("X", 8).plus(Expression::var("Y", 8).un_op(UnOpType::IntNegate)),
),
]; ];
assert_eq!( assert_eq!(
project project
...@@ -357,17 +269,13 @@ fn expressions_inserted() { ...@@ -357,17 +269,13 @@ fn expressions_inserted() {
vec![ vec![
Def::assign( Def::assign(
"entry_jmp_def_1", "entry_jmp_def_1",
Variable::mock("X", 8), variable!("X:8"),
Expression::const_from_i32(42) expr!("-(42:4)").un_op(UnOpType::BoolNegate),
.un_op(UnOpType::IntNegate)
.un_op(UnOpType::BoolNegate),
), ),
Def::assign( Def::assign(
"entry_jmp_def_2", "entry_jmp_def_2",
Variable::mock("Z", 8), variable!("Z:8"),
Expression::const_from_i32(42) expr!("-(42:4)").un_op(UnOpType::IntNegate)
.un_op(UnOpType::IntNegate)
.un_op(UnOpType::IntNegate)
) )
] ]
); );
...@@ -382,10 +290,6 @@ fn expressions_inserted() { ...@@ -382,10 +290,6 @@ fn expressions_inserted() {
.blocks[0] .blocks[0]
.term .term
.defs, .defs,
vec![Def::assign( defs!["callee_def_1: Y:8 = Z:8"]
"callee_def_1",
Variable::mock("Y", 8),
Expression::var("Z", 8),
)]
); );
} }
use super::*; use super::*;
use crate::{bitvec, variable};
use std::collections::HashSet; use std::collections::HashSet;
#[test] #[test]
...@@ -25,20 +26,20 @@ fn test_compute_return_values_of_call() { ...@@ -25,20 +26,20 @@ fn test_compute_return_values_of_call() {
&call, &call,
); );
let expected_val = DataDomain::from_target( let expected_val = DataDomain::from_target(
AbstractIdentifier::from_var(Tid::new("call_tid"), &Variable::mock("RAX", 8)), AbstractIdentifier::from_var(Tid::new("call_tid"), &variable!("RAX:8")),
Bitvector::from_i64(0).into(), bitvec!("0x0:8").into(),
); );
assert_eq!(return_values.iter().len(), 3); assert_eq!(return_values.iter().len(), 3);
assert_eq!(return_values[0], (&Variable::mock("RAX", 8), expected_val)); assert_eq!(return_values[0], (&variable!("RAX:8"), expected_val));
// Test returning a known value. // Test returning a known value.
let param_ref = DataDomain::from_target( let param_ref = DataDomain::from_target(
AbstractIdentifier::from_var(Tid::new("callee"), &Variable::mock("RDI", 8)), AbstractIdentifier::from_var(Tid::new("callee"), &variable!("RDI:8")),
Bitvector::from_i64(0).into(), bitvec!("0x0:8").into(),
); );
callee_state.set_register(&Variable::mock("RAX", 8), param_ref); callee_state.set_register(&variable!("RAX:8"), param_ref);
let expected_val = DataDomain::from_target( let expected_val = DataDomain::from_target(
AbstractIdentifier::from_var(Tid::new("caller"), &Variable::mock("RDI", 8)), AbstractIdentifier::from_var(Tid::new("caller"), &variable!("RDI:8")),
Bitvector::from_i64(0).into(), bitvec!("0x0:8").into(),
); );
let return_values = context.compute_return_values_of_call( let return_values = context.compute_return_values_of_call(
&mut caller_state, &mut caller_state,
...@@ -47,7 +48,7 @@ fn test_compute_return_values_of_call() { ...@@ -47,7 +48,7 @@ fn test_compute_return_values_of_call() {
&call, &call,
); );
assert_eq!(return_values.iter().len(), 3); assert_eq!(return_values.iter().len(), 3);
assert_eq!(return_values[0], (&Variable::mock("RAX", 8), expected_val)); assert_eq!(return_values[0], (&variable!("RAX:8"), expected_val));
} }
#[test] #[test]
...@@ -69,17 +70,17 @@ fn test_call_stub_handling() { ...@@ -69,17 +70,17 @@ fn test_call_stub_handling() {
assert_eq!( assert_eq!(
state.get_params_of_current_function(), state.get_params_of_current_function(),
vec![( vec![(
Arg::from_var(Variable::mock("r0", 4), None), Arg::from_var(variable!("r0:4"), None),
AccessPattern::new().with_read_flag() AccessPattern::new().with_read_flag()
)] )]
); );
assert_eq!( assert_eq!(
state.get_register(&Variable::mock("r0", 4)), state.get_register(&variable!("r0:4")),
DataDomain::from_target( DataDomain::from_target(
AbstractIdentifier::mock(call_tid, "r0", 4), AbstractIdentifier::mock(call_tid, "r0", 4),
Bitvector::from_i32(0).into() bitvec!("0x0:4").into()
) )
.merge(&Bitvector::zero(ByteSize::new(4).into()).into()) .merge(&bitvec!("0x0:4").into())
); );
// Test handling of sprintf call // Test handling of sprintf call
...@@ -89,7 +90,7 @@ fn test_call_stub_handling() { ...@@ -89,7 +90,7 @@ fn test_call_stub_handling() {
project.get_standard_calling_convention().unwrap(), project.get_standard_calling_convention().unwrap(),
); );
// Set the format string param register to a pointer to the string 'cat %s %s %s %s'. // Set the format string param register to a pointer to the string 'cat %s %s %s %s'.
state.set_register(&Variable::mock("r1", 4), Bitvector::from_i32(0x6000).into()); state.set_register(&variable!("r1:4"), bitvec!("0x6000:4").into());
let extern_symbol = ExternSymbol::mock_sprintf_symbol_arm(); let extern_symbol = ExternSymbol::mock_sprintf_symbol_arm();
let call_tid = Tid::new("call_sprintf"); let call_tid = Tid::new("call_sprintf");
context.handle_extern_symbol_call(&mut state, &extern_symbol, &call_tid); context.handle_extern_symbol_call(&mut state, &extern_symbol, &call_tid);
...@@ -97,14 +98,14 @@ fn test_call_stub_handling() { ...@@ -97,14 +98,14 @@ fn test_call_stub_handling() {
assert_eq!( assert_eq!(
params[0], params[0],
( (
Arg::from_var(Variable::mock("r0", 4), None), Arg::from_var(variable!("r0:4"), None),
AccessPattern::new_unknown_access() AccessPattern::new_unknown_access()
) )
); );
assert_eq!( assert_eq!(
params[1], params[1],
( (
Arg::from_var(Variable::mock("r2", 4), None), Arg::from_var(variable!("r2:4"), None),
AccessPattern::new() AccessPattern::new()
.with_read_flag() .with_read_flag()
.with_dereference_flag() .with_dereference_flag()
...@@ -121,15 +122,15 @@ fn test_get_global_mem_address() { ...@@ -121,15 +122,15 @@ fn test_get_global_mem_address() {
let context = Context::new(&project, &graph); let context = Context::new(&project, &graph);
// Check global address from abstract ID // Check global address from abstract ID
let global_address_id: DataDomain<BitvectorDomain> = DataDomain::from_target( let global_address_id: DataDomain<BitvectorDomain> = DataDomain::from_target(
AbstractIdentifier::from_global_address(&Tid::new("fn_tid"), &Bitvector::from_i32(0x2000)), AbstractIdentifier::from_global_address(&Tid::new("fn_tid"), &bitvec!("0x2000:4")),
Bitvector::from_i32(0x2).into(), bitvec!("0x2:4").into(),
); );
let result = context.get_global_mem_address(&global_address_id); let result = context.get_global_mem_address(&global_address_id);
assert_eq!(result, Some(Bitvector::from_i32(0x2002))); assert_eq!(result, Some(bitvec!("0x2002:4")));
// Check global address from absolute value // Check global address from absolute value
let global_address_const = Bitvector::from_i32(0x2003).into(); let global_address_const = bitvec!("0x2003:4").into();
let result = context.get_global_mem_address(&global_address_const); let result = context.get_global_mem_address(&global_address_const);
assert_eq!(result, Some(Bitvector::from_i32(0x2003))); assert_eq!(result, Some(bitvec!("0x2003:4")));
// Check global address not returned if it may not be unique // Check global address not returned if it may not be unique
let value = global_address_id.merge(&global_address_const); let value = global_address_id.merge(&global_address_const);
let result = context.get_global_mem_address(&value); let result = context.get_global_mem_address(&value);
......
...@@ -277,6 +277,7 @@ impl Default for FunctionSignature { ...@@ -277,6 +277,7 @@ impl Default for FunctionSignature {
#[cfg(test)] #[cfg(test)]
pub mod tests { pub mod tests {
use super::*; use super::*;
use crate::variable;
impl FunctionSignature { impl FunctionSignature {
/// Create a mock x64 function signature with 2 parameters, one of which is accessed mutably, /// Create a mock x64 function signature with 2 parameters, one of which is accessed mutably,
...@@ -287,11 +288,11 @@ pub mod tests { ...@@ -287,11 +288,11 @@ pub mod tests {
write_access_pattern.set_unknown_access_flags(); write_access_pattern.set_unknown_access_flags();
let parameters = HashMap::from_iter([ let parameters = HashMap::from_iter([
( (
Arg::from_var(Variable::mock("RDI", 8), None), Arg::from_var(variable!("RDI:8"), None),
AccessPattern::new(), AccessPattern::new(),
), ),
( (
Arg::from_var(Variable::mock("RSI", 8), None), Arg::from_var(variable!("RSI:8"), None),
write_access_pattern, write_access_pattern,
), ),
]); ]);
......
...@@ -444,7 +444,7 @@ impl State { ...@@ -444,7 +444,7 @@ impl State {
let regs = self let regs = self
.register .register
.iter() .iter()
.map(|(var, value)| (format!("{}", var), value.to_json_compact())) .map(|(var, value)| (format!("{var}"), value.to_json_compact()))
.collect(); .collect();
json_map.insert("Register".to_string(), serde_json::Value::Object(regs)); json_map.insert("Register".to_string(), serde_json::Value::Object(regs));
let access_patterns = self let access_patterns = self
...@@ -452,8 +452,8 @@ impl State { ...@@ -452,8 +452,8 @@ impl State {
.iter() .iter()
.map(|(id, pattern)| { .map(|(id, pattern)| {
( (
format!("{}", id), format!("{id}"),
serde_json::Value::String(format!("{}", pattern)), serde_json::Value::String(format!("{pattern}")),
) )
}) })
.collect(); .collect();
......
use super::*; use super::*;
use crate::{bitvec, expr, variable};
impl State { impl State {
/// Generate a mock state for an ARM-32 state. /// Generate a mock state for an ARM-32 state.
pub fn mock_arm32() -> State { pub fn mock_arm32() -> State {
State::new( State::new(
&Tid::new("mock_fn"), &Tid::new("mock_fn"),
&Variable::mock("sp", 4), &variable!("sp:4"),
&CallingConvention::mock_arm32(), &CallingConvention::mock_arm32(),
) )
} }
...@@ -14,7 +15,7 @@ impl State { ...@@ -14,7 +15,7 @@ impl State {
pub fn mock_x64(tid_name: &str) -> State { pub fn mock_x64(tid_name: &str) -> State {
State::new( State::new(
&Tid::new(tid_name), &Tid::new(tid_name),
&Variable::mock("RSP", 8), &variable!("RSP:8"),
&CallingConvention::mock_x64(), &CallingConvention::mock_x64(),
) )
} }
...@@ -22,7 +23,7 @@ impl State { ...@@ -22,7 +23,7 @@ impl State {
/// Mock an abstract ID representing the stack. /// Mock an abstract ID representing the stack.
fn mock_stack_id() -> AbstractIdentifier { fn mock_stack_id() -> AbstractIdentifier {
AbstractIdentifier::from_var(Tid::new("mock_fn"), &Variable::mock("sp", 4)) AbstractIdentifier::from_var(Tid::new("mock_fn"), &variable!("sp:4"))
} }
/// Mock an abstract ID of a stack parameter /// Mock an abstract ID of a stack parameter
...@@ -46,11 +47,8 @@ fn test_new() { ...@@ -46,11 +47,8 @@ fn test_new() {
// Assert that the register values are as expected // Assert that the register values are as expected
assert_eq!(state.register.len(), 7); // 6 parameter register plus stack pointer assert_eq!(state.register.len(), 7); // 6 parameter register plus stack pointer
assert_eq!( assert_eq!(
state.get_register(&Variable::mock("sp", 4)), state.get_register(&variable!("sp:4")),
DataDomain::from_target( DataDomain::from_target(mock_stack_id(), bitvec!("0x0:4").into())
mock_stack_id(),
Bitvector::zero(ByteSize::new(4).into()).into()
)
); );
// Check the generated tracked IDs // Check the generated tracked IDs
assert_eq!(state.tracked_ids.len(), 6); assert_eq!(state.tracked_ids.len(), 6);
...@@ -59,7 +57,7 @@ fn test_new() { ...@@ -59,7 +57,7 @@ fn test_new() {
state.get_register(id.unwrap_register()), state.get_register(id.unwrap_register()),
DataDomain::from_target( DataDomain::from_target(
id.clone(), id.clone(),
Bitvector::zero(id.unwrap_register().size.into()).into() bitvec!(format!("0:{}", id.unwrap_register().size)).into()
) )
); );
assert_eq!(access_pattern, &AccessPattern::new()); assert_eq!(access_pattern, &AccessPattern::new());
...@@ -69,21 +67,20 @@ fn test_new() { ...@@ -69,21 +67,20 @@ fn test_new() {
#[test] #[test]
fn test_store_and_load_from_stack() { fn test_store_and_load_from_stack() {
let mut state = State::mock_arm32(); let mut state = State::mock_arm32();
let address = DataDomain::from_target(mock_stack_id(), Bitvector::from_i32(-4).into()); let address = DataDomain::from_target(mock_stack_id(), bitvec!("-4:4").into());
let value: DataDomain<BitvectorDomain> = Bitvector::from_i32(0).into(); let value: DataDomain<BitvectorDomain> = bitvec!("0x0:4").into();
// write and load a value to the current stack frame // write and load a value to the current stack frame
state.write_value(address.clone(), value.clone()); state.write_value(address.clone(), value.clone());
assert_eq!(state.stack.iter().len(), 1); assert_eq!(state.stack.iter().len(), 1);
assert_eq!( assert_eq!(
state.stack.get(Bitvector::from_i32(-4), ByteSize::new(4)), state.stack.get(bitvec!("-4:4"), ByteSize::new(4)),
value.clone() value.clone()
); );
assert_eq!(state.load_value(address, ByteSize::new(4), None), value); assert_eq!(state.load_value(address, ByteSize::new(4), None), value);
// Load a parameter register and check that the parameter gets generated // Load a parameter register and check that the parameter gets generated
let address = DataDomain::from_target(mock_stack_id(), Bitvector::from_i32(4).into()); let address = DataDomain::from_target(mock_stack_id(), bitvec!("0x4:4").into());
let stack_param_id = mock_stack_param_id(4, 4); let stack_param_id = mock_stack_param_id(4, 4);
let stack_param = let stack_param = DataDomain::from_target(stack_param_id.clone(), bitvec!("0x0:4").into());
DataDomain::from_target(stack_param_id.clone(), Bitvector::from_i32(0).into());
assert_eq!(state.tracked_ids.iter().len(), 6); assert_eq!(state.tracked_ids.iter().len(), 6);
assert_eq!( assert_eq!(
state.load_value(address.clone(), ByteSize::new(4), None), state.load_value(address.clone(), ByteSize::new(4), None),
...@@ -104,22 +101,21 @@ fn test_store_and_load_from_stack() { ...@@ -104,22 +101,21 @@ fn test_store_and_load_from_stack() {
fn test_load_unsized_from_stack() { fn test_load_unsized_from_stack() {
let mut state = State::mock_arm32(); let mut state = State::mock_arm32();
// Load an existing stack param (generated by a sized load at the same address) // Load an existing stack param (generated by a sized load at the same address)
let address = DataDomain::from_target(mock_stack_id(), Bitvector::from_i32(0).into()); let address = DataDomain::from_target(mock_stack_id(), bitvec!("0x0:4").into());
let stack_param_id = mock_stack_param_id(0, 4); let stack_param_id = mock_stack_param_id(0, 4);
let stack_param = let stack_param = DataDomain::from_target(stack_param_id.clone(), bitvec!("0x0:4").into());
DataDomain::from_target(stack_param_id.clone(), Bitvector::from_i32(0).into());
state.load_value(address, ByteSize::new(4), None); state.load_value(address, ByteSize::new(4), None);
let unsized_load = state.load_unsized_value_from_stack(Bitvector::from_i32(0)); let unsized_load = state.load_unsized_value_from_stack(bitvec!("0x0:4").into());
assert_eq!(unsized_load, stack_param); assert_eq!(unsized_load, stack_param);
assert!(state.tracked_ids.get(&stack_param_id).is_some()); assert!(state.tracked_ids.get(&stack_param_id).is_some());
// Load a non-existing stack param // Load a non-existing stack param
let stack_param_id = mock_stack_param_id(4, 1); let stack_param_id = mock_stack_param_id(4, 1);
let stack_param = DataDomain::from_target(stack_param_id.clone(), Bitvector::from_i8(0).into()); let stack_param = DataDomain::from_target(stack_param_id.clone(), bitvec!("0x0:1").into());
let unsized_load = state.load_unsized_value_from_stack(Bitvector::from_i32(4)); let unsized_load = state.load_unsized_value_from_stack(bitvec!("0x4:4"));
assert_eq!(unsized_load, stack_param); assert_eq!(unsized_load, stack_param);
assert!(state.tracked_ids.get(&stack_param_id).is_some()); assert!(state.tracked_ids.get(&stack_param_id).is_some());
// Unsized load from the current stack frame // Unsized load from the current stack frame
let unsized_load = state.load_unsized_value_from_stack(Bitvector::from_i32(-4)); let unsized_load = state.load_unsized_value_from_stack(bitvec!("-4:4"));
assert_eq!(unsized_load, DataDomain::new_top(ByteSize::new(1))); assert_eq!(unsized_load, DataDomain::new_top(ByteSize::new(1)));
} }
...@@ -127,16 +123,16 @@ fn test_load_unsized_from_stack() { ...@@ -127,16 +123,16 @@ fn test_load_unsized_from_stack() {
fn test_eval() { fn test_eval() {
let mut state = State::mock_arm32(); let mut state = State::mock_arm32();
// Test the eval method // Test the eval method
let expr = Expression::Var(Variable::mock("sp", 4)).plus_const(42); let expr = expr!("sp:4 + 42:4");
assert_eq!( assert_eq!(
state.eval(&expr), state.eval(&expr),
DataDomain::from_target(mock_stack_id(), Bitvector::from_i32(42).into()) DataDomain::from_target(mock_stack_id(), bitvec!("42:4").into())
); );
// Test the eval_parameter_arg method // Test the eval_parameter_arg method
let arg = Arg::from_var(Variable::mock("sp", 4), None); let arg = Arg::from_var(variable!("sp:4"), None);
assert_eq!( assert_eq!(
state.eval_parameter_arg(&arg), state.eval_parameter_arg(&arg),
DataDomain::from_target(mock_stack_id(), Bitvector::from_i32(0).into()) DataDomain::from_target(mock_stack_id(), bitvec!("0x0:4").into())
); );
} }
...@@ -146,9 +142,8 @@ fn test_extern_symbol_handling() { ...@@ -146,9 +142,8 @@ fn test_extern_symbol_handling() {
let extern_symbol = ExternSymbol::mock_arm32("mock_symbol"); let extern_symbol = ExternSymbol::mock_arm32("mock_symbol");
let cconv = CallingConvention::mock_arm32(); let cconv = CallingConvention::mock_arm32();
let call_tid = Tid::new("call_tid"); let call_tid = Tid::new("call_tid");
let param_id = AbstractIdentifier::from_var(Tid::new("mock_fn"), &Variable::mock("r0", 4)); let param_id = AbstractIdentifier::from_var(Tid::new("mock_fn"), &variable!("r0:4"));
let return_val_id = let return_val_id = AbstractIdentifier::from_var(Tid::new("call_tid"), &variable!("r0:4"));
AbstractIdentifier::from_var(Tid::new("call_tid"), &Variable::mock("r0", 4));
// Test extern symbol handling. // Test extern symbol handling.
state.handle_generic_extern_symbol( state.handle_generic_extern_symbol(
&call_tid, &call_tid,
...@@ -164,7 +159,7 @@ fn test_extern_symbol_handling() { ...@@ -164,7 +159,7 @@ fn test_extern_symbol_handling() {
.is_mutably_dereferenced(), .is_mutably_dereferenced(),
true true
); );
let return_val = state.get_register(&Variable::mock("r0", 4)); let return_val = state.get_register(&variable!("r0:4"));
assert_eq!(return_val.get_relative_values().iter().len(), 2); assert_eq!(return_val.get_relative_values().iter().len(), 2);
assert_eq!( assert_eq!(
return_val.get_relative_values().get(&param_id).unwrap(), return_val.get_relative_values().get(&param_id).unwrap(),
...@@ -179,7 +174,7 @@ fn test_extern_symbol_handling() { ...@@ -179,7 +174,7 @@ fn test_extern_symbol_handling() {
.get_relative_values() .get_relative_values()
.get(&return_val_id) .get(&return_val_id)
.unwrap(), .unwrap(),
&Bitvector::from_i32(0).into() &bitvec!("0:4").into()
); );
} }
...@@ -189,16 +184,16 @@ fn test_substitute_global_mem_address() { ...@@ -189,16 +184,16 @@ fn test_substitute_global_mem_address() {
let global_memory = RuntimeMemoryImage::mock(); let global_memory = RuntimeMemoryImage::mock();
// Test that addresses into non-writeable memory do not get substituted. // Test that addresses into non-writeable memory do not get substituted.
let global_address: DataDomain<BitvectorDomain> = Bitvector::from_i32(0x1000).into(); let global_address: DataDomain<BitvectorDomain> = bitvec!("0x1000:4").into();
let substituted_address = let substituted_address =
state.substitute_global_mem_address(global_address.clone(), &global_memory); state.substitute_global_mem_address(global_address.clone(), &global_memory);
assert_eq!(global_address, substituted_address); assert_eq!(global_address, substituted_address);
// Test substitution for addresses into writeable global memory. // Test substitution for addresses into writeable global memory.
let global_address: DataDomain<BitvectorDomain> = Bitvector::from_i32(0x2000).into(); let global_address: DataDomain<BitvectorDomain> = bitvec!("0x2000:4").into();
let substituted_address = state.substitute_global_mem_address(global_address, &global_memory); let substituted_address = state.substitute_global_mem_address(global_address, &global_memory);
let expected_global_id = AbstractIdentifier::from_global_address( let expected_global_id = AbstractIdentifier::from_global_address(
state.get_current_function_tid(), state.get_current_function_tid(),
&Bitvector::from_i32(0x2000), &bitvec!("0x2000:4"),
); );
assert_eq!( assert_eq!(
state.tracked_ids.get(&expected_global_id), state.tracked_ids.get(&expected_global_id),
...@@ -206,6 +201,6 @@ fn test_substitute_global_mem_address() { ...@@ -206,6 +201,6 @@ fn test_substitute_global_mem_address() {
); );
assert_eq!( assert_eq!(
substituted_address, substituted_address,
DataDomain::from_target(expected_global_id, Bitvector::from_i32(0).into()) DataDomain::from_target(expected_global_id, bitvec!("0x0:4").into())
); );
} }
...@@ -89,7 +89,7 @@ impl<'a> Context<'a> { ...@@ -89,7 +89,7 @@ impl<'a> Context<'a> {
pub fn log_debug(&self, result: Result<(), Error>, location: Option<&Tid>) { pub fn log_debug(&self, result: Result<(), Error>, location: Option<&Tid>) {
if let Err(err) = result { if let Err(err) = result {
let mut log_message = let mut log_message =
LogMessage::new_debug(format!("{}", err)).source("Pointer Inference"); LogMessage::new_debug(format!("{err}")).source("Pointer Inference");
if let Some(loc) = location { if let Some(loc) = location {
log_message = log_message.location(loc.clone()); log_message = log_message.location(loc.clone());
}; };
...@@ -286,7 +286,7 @@ impl<'a> Context<'a> { ...@@ -286,7 +286,7 @@ impl<'a> Context<'a> {
name: "CWE476".to_string(), name: "CWE476".to_string(),
version: VERSION.to_string(), version: VERSION.to_string(),
addresses: vec![tid.address.clone()], addresses: vec![tid.address.clone()],
tids: vec![format!("{}", tid)], tids: vec![format!("{tid}")],
symbols: Vec::new(), symbols: Vec::new(),
other: Vec::new(), other: Vec::new(),
description: format!( description: format!(
......
...@@ -157,8 +157,7 @@ impl<'a> PointerInference<'a> { ...@@ -157,8 +157,7 @@ impl<'a> PointerInference<'a> {
if !self.computation.has_stabilized() { if !self.computation.has_stabilized() {
let worklist_size = self.computation.get_worklist().len(); let worklist_size = self.computation.get_worklist().len();
self.log_info(format!( self.log_info(format!(
"Fixpoint did not stabilize. Remaining worklist size: {}", "Fixpoint did not stabilize. Remaining worklist size: {worklist_size}"
worklist_size,
)); ));
} }
if print_stats { if print_stats {
...@@ -172,11 +171,10 @@ impl<'a> PointerInference<'a> { ...@@ -172,11 +171,10 @@ impl<'a> PointerInference<'a> {
for (node_index, value) in self.computation.node_values().iter() { for (node_index, value) in self.computation.node_values().iter() {
let node = graph.node_weight(*node_index).unwrap(); let node = graph.node_weight(*node_index).unwrap();
if let Ok(string) = serde_yaml::to_string(&(node, value)) { if let Ok(string) = serde_yaml::to_string(&(node, value)) {
println!("{}", string); println!("{string}");
} else { } else {
println!( println!(
"Serializing failed at {:?} with {:?}", "Serializing failed at {node_index:?} with {:?}",
node_index,
serde_yaml::to_string(value) serde_yaml::to_string(value)
); );
} }
...@@ -192,7 +190,7 @@ impl<'a> PointerInference<'a> { ...@@ -192,7 +190,7 @@ impl<'a> PointerInference<'a> {
for (node_index, node_value) in self.computation.node_values().iter() { for (node_index, node_value) in self.computation.node_values().iter() {
let node = graph.node_weight(*node_index).unwrap(); let node = graph.node_weight(*node_index).unwrap();
if let NodeValue::Value(value) = node_value { if let NodeValue::Value(value) = node_value {
json_nodes.insert(format!("{}", node), value.to_json_compact()); json_nodes.insert(format!("{node}"), value.to_json_compact());
} }
} }
serde_json::Value::Object(json_nodes) serde_json::Value::Object(json_nodes)
...@@ -237,8 +235,7 @@ impl<'a> PointerInference<'a> { ...@@ -237,8 +235,7 @@ impl<'a> PointerInference<'a> {
} }
} }
self.log_info(format!( self.log_info(format!(
"Blocks with state: {} / {}", "Blocks with state: {stateful_blocks} / {all_blocks}"
stateful_blocks, all_blocks
)); ));
} }
......
...@@ -216,7 +216,7 @@ impl AbstractObject { ...@@ -216,7 +216,7 @@ impl AbstractObject {
.inner .inner
.memory .memory
.iter() .iter()
.map(|(index, value)| (format!("{}", index), value.to_json_compact())); .map(|(index, value)| (format!("{index}"), value.to_json_compact()));
elements.push(( elements.push((
"memory".to_string(), "memory".to_string(),
serde_json::Value::Object(memory.collect()), serde_json::Value::Object(memory.collect()),
......
...@@ -174,7 +174,7 @@ impl AbstractObjectList { ...@@ -174,7 +174,7 @@ impl AbstractObjectList {
use serde_json::*; use serde_json::*;
let mut object_map = Map::new(); let mut object_map = Map::new();
for (id, object) in self.objects.iter() { for (id, object) in self.objects.iter() {
object_map.insert(format!("{}", id), object.to_json_compact()); object_map.insert(format!("{id}"), object.to_json_compact());
} }
Value::Object(object_map) Value::Object(object_map)
} }
......
...@@ -7,12 +7,11 @@ use crate::{ ...@@ -7,12 +7,11 @@ use crate::{
analysis::pointer_inference::PointerInference as PointerInferenceComputation, analysis::pointer_inference::PointerInference as PointerInferenceComputation,
analysis::{ analysis::{
forward_interprocedural_fixpoint::Context, forward_interprocedural_fixpoint::Context,
string_abstraction::{ string_abstraction::{context::symbol_calls::tests::Setup, tests::*},
context::symbol_calls::tests::Setup,
tests::mock_project_with_intraprocedural_control_flow, tests::Setup as ProjectSetup,
},
}, },
intermediate_representation::{Bitvector, Blk, ByteSize, ExternSymbol, Jmp, Tid, Variable}, bitvec, def,
intermediate_representation::*,
variable,
}; };
#[test] #[test]
...@@ -28,29 +27,28 @@ fn test_update_def() { ...@@ -28,29 +27,28 @@ fn test_update_def() {
let mut setup: Setup<CharacterInclusionDomain> = Setup::new(&pi_results); let mut setup: Setup<CharacterInclusionDomain> = Setup::new(&pi_results);
setup.context.block_first_def_set = HashSet::new(); setup.context.block_first_def_set = HashSet::new();
let project_setup = ProjectSetup::new(); let assign_def = def!["assign_def: r1:4 = 0x7000:4"];
let assign_def = project_setup.string_input_constant("assign_def", "r1", 0x7000); let load_def = load_var_content_from_temp_var("load_def", "r5", "r2");
let load_def = project_setup.load_var_content_from_temp_var("load_def", "r5", "r2"); let store_def = store_var_content_at_temp_var("store_def", "r0", "r5");
let store_def = project_setup.store_var_content_at_temp_var("store_def", "r0", "r5");
let new_state = setup let new_state = setup
.context .context
.update_def(&setup.state_before_call, &assign_def) .update_def(&setup.state_before_call, &assign_def)
.unwrap(); .unwrap();
let absolute_target = DataDomain::from(Bitvector::from_i32(0x7000)); let absolute_target = DataDomain::from(bitvec!("0x7000:4"));
assert_eq!( assert_eq!(
absolute_target, absolute_target,
*new_state *new_state
.get_variable_to_pointer_map() .get_variable_to_pointer_map()
.get(&Variable::mock("r1", 4)) .get(&variable!("r1:4"))
.unwrap() .unwrap()
); );
let stack_id = AbstractIdentifier::new( let stack_id = AbstractIdentifier::new(
Tid::new("func"), Tid::new("func"),
AbstractLocation::from_var(&Variable::mock("sp", 4)).unwrap(), AbstractLocation::from_var(&variable!("sp:4")).unwrap(),
); );
let loaded_pointer = DataDomain::from_target(stack_id.clone(), IntervalDomain::mock_i32(4, 4)); let loaded_pointer = DataDomain::from_target(stack_id.clone(), IntervalDomain::mock_i32(4, 4));
...@@ -64,7 +62,7 @@ fn test_update_def() { ...@@ -64,7 +62,7 @@ fn test_update_def() {
); );
let r2_reg = Variable { let r2_reg = Variable {
name: String::from("r2"), name: "r2".into(),
size: ByteSize::new(4), size: ByteSize::new(4),
is_temp: true, is_temp: true,
}; };
...@@ -79,7 +77,7 @@ fn test_update_def() { ...@@ -79,7 +77,7 @@ fn test_update_def() {
setup setup
.state_before_call .state_before_call
.add_new_variable_to_pointer_entry(Variable::mock("r3", 4), loaded_pointer.clone()); .add_new_variable_to_pointer_entry(variable!("r3:4"), loaded_pointer.clone());
let new_state = setup let new_state = setup
.context .context
...@@ -90,14 +88,14 @@ fn test_update_def() { ...@@ -90,14 +88,14 @@ fn test_update_def() {
loaded_pointer, loaded_pointer,
*new_state *new_state
.get_variable_to_pointer_map() .get_variable_to_pointer_map()
.get(&Variable::mock("r5", 4)) .get(&variable!("r5:4"))
.unwrap() .unwrap()
); );
let store_target = DataDomain::from_target(stack_id, IntervalDomain::mock_i32(12, 12)); let store_target = DataDomain::from_target(stack_id, IntervalDomain::mock_i32(12, 12));
let r0_reg = Variable { let r0_reg = Variable {
name: String::from("r0"), name: "r0".into(),
size: ByteSize::new(4), size: ByteSize::new(4),
is_temp: true, is_temp: true,
}; };
...@@ -108,7 +106,7 @@ fn test_update_def() { ...@@ -108,7 +106,7 @@ fn test_update_def() {
setup setup
.pi_state_before_symbol_call .pi_state_before_symbol_call
.set_register(&Variable::mock("r5", 4), absolute_target.clone()); .set_register(&variable!("r5:4"), absolute_target.clone());
setup setup
.state_before_call .state_before_call
...@@ -165,9 +163,9 @@ fn test_update_return() { ...@@ -165,9 +163,9 @@ fn test_update_return() {
let mut setup: Setup<CharacterInclusionDomain> = Setup::new(&pi_results); let mut setup: Setup<CharacterInclusionDomain> = Setup::new(&pi_results);
let pointer = DataDomain::from(Bitvector::from_i32(0x6000)); let pointer = DataDomain::from(bitvec!("0x6000:4"));
let callee_saved_reg = Variable::mock("r11", 4); let callee_saved_reg = variable!("r11:4");
let non_callee_saved_reg = Variable::mock("r0", 4); let non_callee_saved_reg = variable!("r0:4");
setup setup
.state_before_call .state_before_call
......
...@@ -171,6 +171,7 @@ impl<'a> Context<'a> { ...@@ -171,6 +171,7 @@ impl<'a> Context<'a> {
pub mod tests { pub mod tests {
use super::*; use super::*;
use crate::analysis::pointer_inference::Data; use crate::analysis::pointer_inference::Data;
use crate::{bitvec, intermediate_representation::parsing};
use std::collections::{HashMap, HashSet}; use std::collections::{HashMap, HashSet};
#[test] #[test]
...@@ -183,9 +184,8 @@ pub mod tests { ...@@ -183,9 +184,8 @@ pub mod tests {
let malloc_call_id = AbstractIdentifier::mock("malloc_call", "RAX", 8); let malloc_call_id = AbstractIdentifier::mock("malloc_call", "RAX", 8);
let main_stack_id = AbstractIdentifier::mock("main", "RSP", 8); let main_stack_id = AbstractIdentifier::mock("main", "RSP", 8);
let param_value = Data::from_target(malloc_call_id.clone(), Bitvector::from_i64(2).into()); let param_value = Data::from_target(malloc_call_id.clone(), bitvec!("2:8").into());
let param_value_2 = let param_value_2 = Data::from_target(main_stack_id.clone(), bitvec!("-10:8").into());
Data::from_target(main_stack_id.clone(), Bitvector::from_i64(-10).into());
let param_replacement_map = HashMap::from([ let param_replacement_map = HashMap::from([
(callsite_id, param_value.clone()), (callsite_id, param_value.clone()),
(callsite_id_2, param_value_2.clone()), (callsite_id_2, param_value_2.clone()),
...@@ -196,7 +196,7 @@ pub mod tests { ...@@ -196,7 +196,7 @@ pub mod tests {
context.callee_to_callsites_map = callee_to_callsites_map; context.callee_to_callsites_map = callee_to_callsites_map;
context context
.malloc_tid_to_object_size_map .malloc_tid_to_object_size_map
.insert(Tid::new("malloc_call"), Data::from(Bitvector::from_i64(42))); .insert(Tid::new("malloc_call"), Data::from(bitvec!("42:8")));
context.call_to_caller_fn_map = HashMap::from([ context.call_to_caller_fn_map = HashMap::from([
(Tid::new("malloc_call"), Tid::new("main")), (Tid::new("malloc_call"), Tid::new("main")),
(Tid::new("callsite_id"), Tid::new("main")), (Tid::new("callsite_id"), Tid::new("main")),
......
...@@ -166,7 +166,7 @@ impl<'a> Context<'a> { ...@@ -166,7 +166,7 @@ impl<'a> Context<'a> {
}; };
let mut cwe_warning = let mut cwe_warning =
CweWarning::new("CWE119", super::CWE_MODULE.version, description); CweWarning::new("CWE119", super::CWE_MODULE.version, description);
cwe_warning.tids = vec![format!("{}", call_tid)]; cwe_warning.tids = vec![format!("{call_tid}")];
cwe_warning.addresses = vec![call_tid.address.to_string()]; cwe_warning.addresses = vec![call_tid.address.to_string()];
cwe_warning.other = vec![warnings]; cwe_warning.other = vec![warnings];
self.log_collector.send(cwe_warning.into()).unwrap(); self.log_collector.send(cwe_warning.into()).unwrap();
......
...@@ -218,6 +218,7 @@ fn add_param_replacements_for_call( ...@@ -218,6 +218,7 @@ fn add_param_replacements_for_call(
#[cfg(test)] #[cfg(test)]
pub mod tests { pub mod tests {
use super::*; use super::*;
use crate::bitvec;
#[test] #[test]
fn test_substitute_param_values_context_sensitive() { fn test_substitute_param_values_context_sensitive() {
...@@ -228,9 +229,8 @@ pub mod tests { ...@@ -228,9 +229,8 @@ pub mod tests {
let recursive_param_id = AbstractIdentifier::mock("main", "RSI", 8); let recursive_param_id = AbstractIdentifier::mock("main", "RSI", 8);
let recursive_callsite_id = AbstractIdentifier::mock("recursive_callsite_id", "RSI", 8); let recursive_callsite_id = AbstractIdentifier::mock("recursive_callsite_id", "RSI", 8);
let param_value = let param_value = Data::from_target(recursive_param_id.clone(), bitvec!("1:8").into());
Data::from_target(recursive_param_id.clone(), Bitvector::from_i64(1).into()); let recursive_param_value = Data::from(bitvec!("41:8"));
let recursive_param_value = Data::from(Bitvector::from_i64(41));
let param_replacement_map = HashMap::from([ let param_replacement_map = HashMap::from([
(callsite_id, param_value.clone()), (callsite_id, param_value.clone()),
(recursive_callsite_id.clone(), recursive_param_value), (recursive_callsite_id.clone(), recursive_param_value),
...@@ -254,7 +254,7 @@ pub mod tests { ...@@ -254,7 +254,7 @@ pub mod tests {
context.call_to_caller_fn_map = call_to_caller_map; context.call_to_caller_fn_map = call_to_caller_map;
// non-recursive substitution // non-recursive substitution
let result = context.substitute_param_values_context_sensitive( let result = context.substitute_param_values_context_sensitive(
&Data::from_target(param_id.clone(), Bitvector::from_i64(5).into()), &Data::from_target(param_id.clone(), bitvec!("5:8").into()),
&Tid::new("callsite_id"), &Tid::new("callsite_id"),
&Tid::new("func"), &Tid::new("func"),
); );
...@@ -264,12 +264,12 @@ pub mod tests { ...@@ -264,12 +264,12 @@ pub mod tests {
); );
// recursive substitution // recursive substitution
let result = context.recursively_substitute_param_values_context_sensitive( let result = context.recursively_substitute_param_values_context_sensitive(
&Data::from_target(param_id, Bitvector::from_i64(5).into()), &Data::from_target(param_id, bitvec!("5:8").into()),
&Tid::new("func"), &Tid::new("func"),
&[Tid::new("callsite_id"), Tid::new("recursive_callsite_id")], &[Tid::new("callsite_id"), Tid::new("recursive_callsite_id")],
); );
println!("{:#}", result.to_json_compact()); println!("{:#}", result.to_json_compact());
assert_eq!(result, Bitvector::from_i64(47).into()); assert_eq!(result, bitvec!("47:8").into());
} }
#[test] #[test]
...@@ -281,9 +281,8 @@ pub mod tests { ...@@ -281,9 +281,8 @@ pub mod tests {
let recursive_param_id = AbstractIdentifier::mock("main", "RSI", 8); let recursive_param_id = AbstractIdentifier::mock("main", "RSI", 8);
let recursive_callsite_id = AbstractIdentifier::mock("recursive_callsite_id", "RSI", 8); let recursive_callsite_id = AbstractIdentifier::mock("recursive_callsite_id", "RSI", 8);
let param_value = let param_value = Data::from_target(recursive_param_id.clone(), bitvec!("1:8").into());
Data::from_target(recursive_param_id.clone(), Bitvector::from_i64(1).into()); let recursive_param_value = Data::from(bitvec!("39:8"));
let recursive_param_value = Data::from(Bitvector::from_i64(39));
let param_replacement_map = HashMap::from([ let param_replacement_map = HashMap::from([
(callsite_id, param_value.clone()), (callsite_id, param_value.clone()),
(recursive_callsite_id.clone(), recursive_param_value), (recursive_callsite_id.clone(), recursive_param_value),
...@@ -304,8 +303,8 @@ pub mod tests { ...@@ -304,8 +303,8 @@ pub mod tests {
// recursive substitution // recursive substitution
let result = context.recursively_substitute_param_values(&Data::from_target( let result = context.recursively_substitute_param_values(&Data::from_target(
param_id, param_id,
Bitvector::from_i64(5).into(), bitvec!("5:8").into(),
)); ));
assert_eq!(result, Bitvector::from_i64(45).into()); assert_eq!(result, bitvec!("45:8").into());
} }
} }
use super::*; use super::*;
use crate::{bitvec, variable};
use std::collections::BTreeSet; use std::collections::BTreeSet;
impl<'a> Context<'a> { impl<'a> Context<'a> {
...@@ -28,9 +29,8 @@ fn test_compute_size_value_of_malloc_like_call() { ...@@ -28,9 +29,8 @@ fn test_compute_size_value_of_malloc_like_call() {
use crate::analysis::pointer_inference::State as PiState; use crate::analysis::pointer_inference::State as PiState;
let project = Project::mock_x64(); let project = Project::mock_x64();
let mut pi_results = PointerInference::mock(&project); let mut pi_results = PointerInference::mock(&project);
let mut malloc_state = let mut malloc_state = PiState::new(&variable!("RSP:8"), Tid::new("func"), BTreeSet::new());
PiState::new(&Variable::mock("RSP", 8), Tid::new("func"), BTreeSet::new()); malloc_state.set_register(&variable!("RDI:8"), bitvec!("3:8").into());
malloc_state.set_register(&Variable::mock("RDI", 8), Bitvector::from_i64(3).into());
*pi_results.get_mut_states_at_tids() = HashMap::from([(Tid::new("malloc_call"), malloc_state)]); *pi_results.get_mut_states_at_tids() = HashMap::from([(Tid::new("malloc_call"), malloc_state)]);
let malloc_symbol = ExternSymbol::mock_x64("malloc"); let malloc_symbol = ExternSymbol::mock_x64("malloc");
...@@ -41,7 +41,7 @@ fn test_compute_size_value_of_malloc_like_call() { ...@@ -41,7 +41,7 @@ fn test_compute_size_value_of_malloc_like_call() {
&pi_results &pi_results
) )
.unwrap(), .unwrap(),
Bitvector::from_i64(3).into() bitvec!("3:8").into()
); );
assert!(compute_size_value_of_malloc_like_call( assert!(compute_size_value_of_malloc_like_call(
&Tid::new("other"), &Tid::new("other"),
......
...@@ -73,11 +73,7 @@ impl State { ...@@ -73,11 +73,7 @@ impl State {
if let Ok((lower_offset, upper_offset)) = offset.try_to_offset_interval() { if let Ok((lower_offset, upper_offset)) = offset.try_to_offset_interval() {
if let Ok(lower_bound) = self.object_lower_bounds.get(id).unwrap().try_to_offset() { if let Ok(lower_bound) = self.object_lower_bounds.get(id).unwrap().try_to_offset() {
if lower_bound > lower_offset { if lower_bound > lower_offset {
out_of_bounds_access_warnings.push(format!("For the object ID {} access to the offset {} may be smaller than the lower object bound of {}.", out_of_bounds_access_warnings.push(format!("For the object ID {id} access to the offset {lower_offset} may be smaller than the lower object bound of {lower_bound}."));
id,
lower_offset,
lower_bound,
));
if let ( if let (
Some(BoundsMetadata { Some(BoundsMetadata {
source: Some(source), source: Some(source),
...@@ -93,7 +89,7 @@ impl State { ...@@ -93,7 +89,7 @@ impl State {
context, context,
); );
out_of_bounds_access_warnings out_of_bounds_access_warnings
.push(format!("Relevant callgraph TIDs: [{}]", call_sequence_tids)); .push(format!("Relevant callgraph TIDs: [{call_sequence_tids}]"));
} else { } else {
out_of_bounds_access_warnings.push(format!( out_of_bounds_access_warnings.push(format!(
"Relevant callgraph TIDs: [{}]", "Relevant callgraph TIDs: [{}]",
...@@ -128,7 +124,7 @@ impl State { ...@@ -128,7 +124,7 @@ impl State {
context, context,
); );
out_of_bounds_access_warnings out_of_bounds_access_warnings
.push(format!("Relevant callgraph TIDs: [{}]", call_sequence_tids)); .push(format!("Relevant callgraph TIDs: [{call_sequence_tids}]"));
} else { } else {
out_of_bounds_access_warnings.push(format!( out_of_bounds_access_warnings.push(format!(
"Relevant callgraph TIDs: [{}]", "Relevant callgraph TIDs: [{}]",
...@@ -204,13 +200,13 @@ impl State { ...@@ -204,13 +200,13 @@ impl State {
let lower_bounds: Vec<_> = self let lower_bounds: Vec<_> = self
.object_lower_bounds .object_lower_bounds
.iter() .iter()
.map(|(id, bound)| Value::String(format!("{}: {}", id, bound))) .map(|(id, bound)| Value::String(format!("{id}: {bound}")))
.collect(); .collect();
state_map.insert("lower_bounds".to_string(), Value::Array(lower_bounds)); state_map.insert("lower_bounds".to_string(), Value::Array(lower_bounds));
let upper_bounds: Vec<_> = self let upper_bounds: Vec<_> = self
.object_upper_bounds .object_upper_bounds
.iter() .iter()
.map(|(id, bound)| Value::String(format!("{}: {}", id, bound))) .map(|(id, bound)| Value::String(format!("{id}: {bound}")))
.collect(); .collect();
state_map.insert("upper_bounds".to_string(), Value::Array(upper_bounds)); state_map.insert("upper_bounds".to_string(), Value::Array(upper_bounds));
...@@ -265,8 +261,8 @@ fn collect_tids_for_cwe_warning( ...@@ -265,8 +261,8 @@ fn collect_tids_for_cwe_warning(
} }
// Build a string out of the TID list // Build a string out of the TID list
tids.iter() tids.iter()
.map(|tid| format!("{}", tid)) .map(|tid| format!("{tid}"))
.reduce(|accum, elem| format!("{}, {}", accum, elem)) .reduce(|accum, elem| format!("{accum}, {elem}"))
.unwrap() .unwrap()
} }
......
...@@ -169,7 +169,7 @@ fn generate_cwe_warning( ...@@ -169,7 +169,7 @@ fn generate_cwe_warning(
_ => panic!("Invalid String Location."), _ => panic!("Invalid String Location."),
}; };
CweWarning::new(CWE_MODULE.name, CWE_MODULE.version, description) CweWarning::new(CWE_MODULE.name, CWE_MODULE.version, description)
.tids(vec![format!("{}", callsite)]) .tids(vec![format!("{callsite}")])
.addresses(vec![callsite.address.clone()]) .addresses(vec![callsite.address.clone()])
.symbols(vec![called_symbol.name.clone()]) .symbols(vec![called_symbol.name.clone()])
} }
...@@ -179,7 +179,7 @@ pub mod tests { ...@@ -179,7 +179,7 @@ pub mod tests {
use std::collections::HashSet; use std::collections::HashSet;
use crate::analysis::pointer_inference::PointerInference as PointerInferenceComputation; use crate::analysis::pointer_inference::PointerInference as PointerInferenceComputation;
use crate::intermediate_representation::*; use crate::{defs, intermediate_representation::*};
use super::*; use super::*;
...@@ -189,21 +189,10 @@ pub mod tests { ...@@ -189,21 +189,10 @@ pub mod tests {
let mut block1 = Blk::mock_with_tid("block1"); let mut block1 = Blk::mock_with_tid("block1");
let block2 = Blk::mock_with_tid("block2"); let block2 = Blk::mock_with_tid("block2");
let def1 = Def::assign( let mut defs = defs!["def2: RDI:8 = RBP:8 + 8:8", "def3: RSI:8 = 0x3002:8"];
"def2",
Variable::mock("RDI", 8 as u64),
Expression::var("RBP", 8).plus_const(8),
);
let def2 = Def::assign(
"def3",
Variable::mock("RSI", 8 as u64),
Expression::Const(Bitvector::from_str_radix(16, "3002").unwrap()),
);
let jump = Jmp::call("call_string", "sprintf", Some("block2")); let jump = Jmp::call("call_string", "sprintf", Some("block2"));
block1.term.defs.push(def1); block1.term.defs.append(&mut defs);
block1.term.defs.push(def2);
block1.term.jmps.push(jump); block1.term.jmps.push(jump);
sub.term.blocks.push(block1); sub.term.blocks.push(block1);
sub.term.blocks.push(block2); sub.term.blocks.push(block2);
......
...@@ -98,7 +98,7 @@ fn generate_cwe_warning(callsite: &Tid, called_symbol: &ExternSymbol) -> CweWarn ...@@ -98,7 +98,7 @@ fn generate_cwe_warning(callsite: &Tid, called_symbol: &ExternSymbol) -> CweWarn
"(Integer Overflow or Wraparound) Potential overflow due to multiplication before call to {} at {}", "(Integer Overflow or Wraparound) Potential overflow due to multiplication before call to {} at {}",
called_symbol.name, callsite.address called_symbol.name, callsite.address
)) ))
.tids(vec![format!("{}", callsite)]) .tids(vec![format!("{callsite}")])
.addresses(vec![callsite.address.clone()]) .addresses(vec![callsite.address.clone()])
.symbols(vec![called_symbol.name.clone()]) .symbols(vec![called_symbol.name.clone()])
} }
......
...@@ -63,7 +63,7 @@ pub fn check_cwe( ...@@ -63,7 +63,7 @@ pub fn check_cwe(
(vec![info_log], Vec::new()) (vec![info_log], Vec::new())
} }
Err(err) => { Err(err) => {
let err_log = LogMessage::new_error(format!("Error while parsing binary: {}", err)) let err_log = LogMessage::new_error(format!("Error while parsing binary: {err}"))
.source(CWE_MODULE.name); .source(CWE_MODULE.name);
(vec![err_log], Vec::new()) (vec![err_log], Vec::new())
} }
......
...@@ -99,7 +99,7 @@ fn generate_cwe_warning(sub: &Term<Sub>, callsite: &Tid) -> CweWarning { ...@@ -99,7 +99,7 @@ fn generate_cwe_warning(sub: &Term<Sub>, callsite: &Tid) -> CweWarning {
"(The program utilizes chroot without dropping privileges and/or changing the directory) at {} ({})", "(The program utilizes chroot without dropping privileges and/or changing the directory) at {} ({})",
callsite.address, sub.term.name callsite.address, sub.term.name
)) ))
.tids(vec![format!("{}", callsite)]) .tids(vec![format!("{callsite}")])
.addresses(vec![callsite.address.clone()]) .addresses(vec![callsite.address.clone()])
.symbols(vec![sub.term.name.clone()]) .symbols(vec![sub.term.name.clone()])
} }
......
...@@ -48,9 +48,7 @@ fn generate_cwe_warning(secure_initializer_func: &str, rand_func: &str) -> CweWa ...@@ -48,9 +48,7 @@ fn generate_cwe_warning(secure_initializer_func: &str, rand_func: &str) -> CweWa
CWE_MODULE.name, CWE_MODULE.name,
CWE_MODULE.version, CWE_MODULE.version,
format!( format!(
"(Insufficient Entropy in PRNG) program uses {} without calling {} before", "(Insufficient Entropy in PRNG) program uses {rand_func} without calling {secure_initializer_func} before"),
rand_func, secure_initializer_func
),
) )
} }
......
...@@ -61,7 +61,7 @@ fn generate_cwe_warning( ...@@ -61,7 +61,7 @@ fn generate_cwe_warning(
"(Time-of-check Time-of-use Race Condition) '{}' is reachable from '{}' at {} ({}). This could lead to a TOCTOU.", "(Time-of-check Time-of-use Race Condition) '{}' is reachable from '{}' at {} ({}). This could lead to a TOCTOU.",
sink, source, sink_callsite.address, sub_name sink, source, sink_callsite.address, sub_name
)) ))
.tids(vec![format!("{}", source_callsite), format!("{}", sink_callsite)]) .tids(vec![format!("{source_callsite}"), format!("{sink_callsite}")])
.addresses(vec![source_callsite.address, sink_callsite.address]) .addresses(vec![source_callsite.address, sink_callsite.address])
.symbols(vec![source.into(), sink.into()]) .symbols(vec![source.into(), sink.into()])
} }
......
...@@ -117,7 +117,7 @@ impl<'a> Context<'a> { ...@@ -117,7 +117,7 @@ impl<'a> Context<'a> {
name: "CWE416".to_string(), name: "CWE416".to_string(),
version: CWE_MODULE.version.to_string(), version: CWE_MODULE.version.to_string(),
addresses: vec![call_tid.address.clone()], addresses: vec![call_tid.address.clone()],
tids: vec![format!("{}", call_tid)], tids: vec![format!("{call_tid}")],
symbols: Vec::new(), symbols: Vec::new(),
other: vec![warnings], other: vec![warnings],
description: format!( description: format!(
...@@ -151,7 +151,7 @@ impl<'a> Context<'a> { ...@@ -151,7 +151,7 @@ impl<'a> Context<'a> {
name: "CWE415".to_string(), name: "CWE415".to_string(),
version: CWE_MODULE.version.to_string(), version: CWE_MODULE.version.to_string(),
addresses: vec![call_tid.address.clone()], addresses: vec![call_tid.address.clone()],
tids: vec![format!("{}", call_tid)], tids: vec![format!("{call_tid}")],
symbols: Vec::new(), symbols: Vec::new(),
other: vec![warning_causes], other: vec![warning_causes],
description: format!( description: format!(
......
...@@ -63,8 +63,7 @@ impl State { ...@@ -63,8 +63,7 @@ impl State {
for id in address.get_relative_values().keys() { for id in address.get_relative_values().keys() {
if let Some(ObjectState::Dangling(free_id)) = self.dangling_objects.get(id) { if let Some(ObjectState::Dangling(free_id)) = self.dangling_objects.get(id) {
free_ids_of_dangling_pointers.push(format!( free_ids_of_dangling_pointers.push(format!(
"Accessed ID {} may have been already freed at {}", "Accessed ID {id} may have been already freed at {free_id}"
id, free_id
)); ));
self.dangling_objects self.dangling_objects
...@@ -101,8 +100,7 @@ impl State { ...@@ -101,8 +100,7 @@ impl State {
.insert(id.clone(), ObjectState::Dangling(call_tid.clone())) .insert(id.clone(), ObjectState::Dangling(call_tid.clone()))
{ {
warnings.push(format!( warnings.push(format!(
"Object {} may have been freed before at {}.", "Object {id} may have been freed before at {old_free_id}."
id, old_free_id
)); ));
} }
} }
...@@ -169,7 +167,7 @@ impl AbstractDomain for State { ...@@ -169,7 +167,7 @@ impl AbstractDomain for State {
#[cfg(test)] #[cfg(test)]
pub mod tests { pub mod tests {
use super::*; use super::*;
use crate::intermediate_representation::Variable; use crate::{bitvec, intermediate_representation::parsing, variable};
use std::collections::BTreeSet; use std::collections::BTreeSet;
#[test] #[test]
...@@ -223,9 +221,9 @@ pub mod tests { ...@@ -223,9 +221,9 @@ pub mod tests {
let mut state = State::new(Tid::new("current_fn")); let mut state = State::new(Tid::new("current_fn"));
let param = Data::from_target( let param = Data::from_target(
AbstractIdentifier::mock("obj_id", "RAX", 8), AbstractIdentifier::mock("obj_id", "RAX", 8),
Bitvector::from_i64(0).into(), bitvec!("0:8").into(),
); );
let pi_state = PiState::new(&Variable::mock("RSP", 8), Tid::new("call"), BTreeSet::new()); let pi_state = PiState::new(&variable!("RSP:8"), Tid::new("call"), BTreeSet::new());
// Check that the parameter is correctly marked as freed in the state. // Check that the parameter is correctly marked as freed in the state.
assert!(state assert!(state
.handle_param_of_free_call(&Tid::new("free_call"), &param, &pi_state) .handle_param_of_free_call(&Tid::new("free_call"), &param, &pi_state)
...@@ -251,12 +249,12 @@ pub mod tests { ...@@ -251,12 +249,12 @@ pub mod tests {
AbstractIdentifier::mock("callee_obj_tid", "RAX", 8), AbstractIdentifier::mock("callee_obj_tid", "RAX", 8),
ObjectState::Dangling(Tid::new("free_tid")), ObjectState::Dangling(Tid::new("free_tid")),
); );
let pi_state = PiState::new(&Variable::mock("RSP", 8), Tid::new("call"), BTreeSet::new()); let pi_state = PiState::new(&variable!("RSP:8"), Tid::new("call"), BTreeSet::new());
let id_replacement_map = BTreeMap::from([( let id_replacement_map = BTreeMap::from([(
AbstractIdentifier::mock("callee_obj_tid", "RAX", 8), AbstractIdentifier::mock("callee_obj_tid", "RAX", 8),
Data::from_target( Data::from_target(
AbstractIdentifier::mock("caller_tid", "RBX", 8), AbstractIdentifier::mock("caller_tid", "RBX", 8),
Bitvector::from_i64(42).into(), bitvec!("42:8").into(),
), ),
)]); )]);
// Check that the callee object ID is correctly translated to a caller object ID // Check that the callee object ID is correctly translated to a caller object ID
......
...@@ -156,7 +156,7 @@ impl<'a> Context<'a> { ...@@ -156,7 +156,7 @@ impl<'a> Context<'a> {
format!("(NULL Pointer Dereference) There is no check if the return value is NULL at {} ({}).", format!("(NULL Pointer Dereference) There is no check if the return value is NULL at {} ({}).",
taint_source.tid.address, taint_source_name)) taint_source.tid.address, taint_source_name))
.addresses(vec![taint_source.tid.address.clone(), taint_access_location.address.clone()]) .addresses(vec![taint_source.tid.address.clone(), taint_access_location.address.clone()])
.tids(vec![format!("{}", taint_source.tid), format!("{}", taint_access_location)]) .tids(vec![format!("{}", taint_source.tid), format!("{taint_access_location}")])
.symbols(vec![taint_source_name]); .symbols(vec![taint_source_name]);
let _ = self.cwe_collector.send(cwe_warning); let _ = self.cwe_collector.send(cwe_warning);
} }
...@@ -412,6 +412,7 @@ impl<'a> crate::analysis::forward_interprocedural_fixpoint::Context<'a> for Cont ...@@ -412,6 +412,7 @@ impl<'a> crate::analysis::forward_interprocedural_fixpoint::Context<'a> for Cont
#[cfg(test)] #[cfg(test)]
mod tests { mod tests {
use super::*; use super::*;
use crate::{def, expr, variable};
impl<'a> Context<'a> { impl<'a> Context<'a> {
pub fn mock( pub fn mock(
...@@ -451,10 +452,7 @@ mod tests { ...@@ -451,10 +452,7 @@ mod tests {
false false
); );
state.set_register_taint( state.set_register_taint(&variable!("RDI:8"), Taint::Tainted(ByteSize::new(8)));
&Variable::mock("RDI", ByteSize::new(8)),
Taint::Tainted(ByteSize::new(8)),
);
assert_eq!( assert_eq!(
context.check_parameters_for_taint( context.check_parameters_for_taint(
&state, &state,
...@@ -476,10 +474,7 @@ mod tests { ...@@ -476,10 +474,7 @@ mod tests {
.handle_generic_call(&state, &Tid::new("call_tid")) .handle_generic_call(&state, &Tid::new("call_tid"))
.is_some()); .is_some());
state.set_register_taint( state.set_register_taint(&variable!("RDX:8"), Taint::Tainted(ByteSize::new(8)));
&Variable::mock("RDX", 8u64),
Taint::Tainted(ByteSize::new(8)),
);
assert!(context assert!(context
.handle_generic_call(&state, &Tid::new("call_tid")) .handle_generic_call(&state, &Tid::new("call_tid"))
.is_none()); .is_none());
...@@ -493,48 +488,21 @@ mod tests { ...@@ -493,48 +488,21 @@ mod tests {
let (mut state, pi_state) = State::mock_with_pi_state(); let (mut state, pi_state) = State::mock_with_pi_state();
state.set_pointer_inference_state(Some(pi_state)); state.set_pointer_inference_state(Some(pi_state));
let assign_def = Term { let assign_def = def!["def: RCX:8 = RAX:8"];
tid: Tid::new("def"),
term: Def::Assign {
var: Variable::mock("RCX", 8u64),
value: Expression::Var(Variable::mock("RAX", 8u64)),
},
};
let result = context.update_def(&state, &assign_def).unwrap(); let result = context.update_def(&state, &assign_def).unwrap();
assert!(result assert!(result.eval(&expr!("RCX:8")).is_tainted());
.eval(&Expression::Var(Variable::mock("RCX", 8u64))) assert!(result.eval(&expr!("RSP:8")).is_top());
.is_tainted());
assert!(result let load_def = def!["def: RCX:8 := Load from RSP:8"];
.eval(&Expression::Var(Variable::mock("RSP", 8u64)))
.is_top());
let load_def = Term {
tid: Tid::new("def"),
term: Def::Load {
var: Variable::mock("RCX", 8u64),
address: Expression::Var(Variable::mock("RSP", 8u64)),
},
};
let result = context.update_def(&state, &load_def).unwrap(); let result = context.update_def(&state, &load_def).unwrap();
assert!(result assert!(result.eval(&expr!("RCX:8")).is_tainted());
.eval(&Expression::Var(Variable::mock("RCX", 8u64))) assert!(result.eval(&expr!("RSP:8")).is_top());
.is_tainted());
assert!(result let store_def = def!["def: Store at RSP:8 := RCX:8"];
.eval(&Expression::Var(Variable::mock("RSP", 8u64)))
.is_top());
let store_def = Term {
tid: Tid::new("def"),
term: Def::Store {
value: Expression::Var(Variable::mock("RCX", 8u64)),
address: Expression::Var(Variable::mock("RSP", 8u64)),
},
};
let result = context.update_def(&state, &store_def).unwrap(); let result = context.update_def(&state, &store_def).unwrap();
let result = context.update_def(&result, &load_def).unwrap(); let result = context.update_def(&result, &load_def).unwrap();
assert!(result assert!(result.eval(&expr!("RCX:8")).is_top());
.eval(&Expression::Var(Variable::mock("RCX", 8u64)))
.is_top());
} }
#[test] #[test]
...@@ -548,7 +516,7 @@ mod tests { ...@@ -548,7 +516,7 @@ mod tests {
tid: Tid::new("jmp"), tid: Tid::new("jmp"),
term: Jmp::CBranch { term: Jmp::CBranch {
target: Tid::new("target"), target: Tid::new("target"),
condition: Expression::Var(Variable::mock("RAX", 8u64)), condition: expr!("RAX:8"),
}, },
}; };
assert!(context assert!(context
...@@ -558,7 +526,7 @@ mod tests { ...@@ -558,7 +526,7 @@ mod tests {
tid: Tid::new("jmp"), tid: Tid::new("jmp"),
term: Jmp::CBranch { term: Jmp::CBranch {
target: Tid::new("target"), target: Tid::new("target"),
condition: Expression::Var(Variable::mock("RBX", 8u64)), condition: expr!("RBX:8"),
}, },
}; };
assert!(context assert!(context
......
...@@ -349,7 +349,7 @@ impl State { ...@@ -349,7 +349,7 @@ impl State {
let register: Vec<(String, Value)> = self let register: Vec<(String, Value)> = self
.register_taint .register_taint
.iter() .iter()
.map(|(var, data)| (var.name.clone(), json!(format!("{}", data)))) .map(|(var, data)| (var.name.clone(), json!(format!("{data}"))))
.collect(); .collect();
let mut memory = Vec::new(); let mut memory = Vec::new();
for (tid, mem_region) in self.memory_taint.iter() { for (tid, mem_region) in self.memory_taint.iter() {
...@@ -357,7 +357,7 @@ impl State { ...@@ -357,7 +357,7 @@ impl State {
for (offset, elem) in mem_region.iter() { for (offset, elem) in mem_region.iter() {
elements.push((offset.to_string(), json!(elem.to_string()))); elements.push((offset.to_string(), json!(elem.to_string())));
} }
memory.push((format!("{}", tid), Value::Object(Map::from_iter(elements)))); memory.push((format!("{tid}"), Value::Object(Map::from_iter(elements))));
} }
let state_map = vec![ let state_map = vec![
( (
...@@ -374,8 +374,8 @@ impl State { ...@@ -374,8 +374,8 @@ impl State {
#[cfg(test)] #[cfg(test)]
mod tests { mod tests {
use super::*; use super::*;
use crate::abstract_domain::*;
use crate::analysis::pointer_inference::ValueDomain; use crate::analysis::pointer_inference::ValueDomain;
use crate::{abstract_domain::*, expr, variable};
use std::collections::BTreeSet; use std::collections::BTreeSet;
impl State { impl State {
...@@ -389,16 +389,16 @@ mod tests { ...@@ -389,16 +389,16 @@ mod tests {
pub fn mock_with_pi_state() -> (State, PointerInferenceState) { pub fn mock_with_pi_state() -> (State, PointerInferenceState) {
let arg1 = Arg::Register { let arg1 = Arg::Register {
expr: Expression::Var(register("RAX")), expr: expr!("RAX:8"),
data_type: None, data_type: None,
}; };
let arg2 = Arg::Stack { let arg2 = Arg::Stack {
address: Expression::Var(register("RSP")), address: expr!("RSP:8"),
size: ByteSize::new(8), size: ByteSize::new(8),
data_type: None, data_type: None,
}; };
let pi_state = let pi_state =
PointerInferenceState::new(&register("RSP"), Tid::new("func"), BTreeSet::new()); PointerInferenceState::new(&variable!("RSP:8"), Tid::new("func"), BTreeSet::new());
let symbol = ExternSymbol { let symbol = ExternSymbol {
tid: Tid::new("extern_symbol".to_string()), tid: Tid::new("extern_symbol".to_string()),
addresses: vec![], addresses: vec![],
...@@ -414,14 +414,6 @@ mod tests { ...@@ -414,14 +414,6 @@ mod tests {
} }
} }
fn register(name: &str) -> Variable {
Variable {
name: name.into(),
size: ByteSize::new(8),
is_temp: false,
}
}
fn bv(value: i64) -> ValueDomain { fn bv(value: i64) -> ValueDomain {
ValueDomain::from(Bitvector::from_i64(value)) ValueDomain::from(Bitvector::from_i64(value))
} }
...@@ -429,7 +421,7 @@ mod tests { ...@@ -429,7 +421,7 @@ mod tests {
fn new_id(name: &str) -> AbstractIdentifier { fn new_id(name: &str) -> AbstractIdentifier {
AbstractIdentifier::new( AbstractIdentifier::new(
Tid::new("time0"), Tid::new("time0"),
AbstractLocation::Register(Variable::mock(name, ByteSize::new(8))), AbstractLocation::Register(variable!(format!("{}:8", name))),
) )
} }
...@@ -444,7 +436,7 @@ mod tests { ...@@ -444,7 +436,7 @@ mod tests {
let top = Taint::Top(ByteSize::new(8)); let top = Taint::Top(ByteSize::new(8));
let mut state = State::mock(); let mut state = State::mock();
state.set_register_taint(&register("RAX"), taint.clone()); state.set_register_taint(&variable!("RAX:8"), taint.clone());
let mut other_state = State::mock(); let mut other_state = State::mock();
let address = new_pointer("mem", 10); let address = new_pointer("mem", 10);
...@@ -452,10 +444,10 @@ mod tests { ...@@ -452,10 +444,10 @@ mod tests {
let merged_state = state.merge(&other_state); let merged_state = state.merge(&other_state);
assert_eq!( assert_eq!(
merged_state.register_taint.get(&register("RAX")), merged_state.register_taint.get(&variable!("RAX:8")),
Some(&taint) Some(&taint)
); );
assert_eq!(merged_state.register_taint.get(&register("RBX")), None); assert_eq!(merged_state.register_taint.get(&variable!("RBX:8")), None);
assert_eq!( assert_eq!(
merged_state.load_taint_from_memory(&address, ByteSize::new(8)), merged_state.load_taint_from_memory(&address, ByteSize::new(8)),
taint.clone() taint.clone()
...@@ -471,9 +463,9 @@ mod tests { ...@@ -471,9 +463,9 @@ mod tests {
fn new_state() { fn new_state() {
let (state, pi_state) = State::mock_with_pi_state(); let (state, pi_state) = State::mock_with_pi_state();
let taint = Taint::Tainted(ByteSize::new(8)); let taint = Taint::Tainted(ByteSize::new(8));
assert_eq!(state.register_taint.get(&register("RAX")), Some(&taint)); assert_eq!(state.register_taint.get(&variable!("RAX:8")), Some(&taint));
assert_eq!(state.register_taint.get(&register("RSP")), None); assert_eq!(state.register_taint.get(&variable!("RSP:8")), None);
let address = Expression::Var(register("RSP")); let address = Expression::Var(variable!("RSP:8"));
assert_eq!( assert_eq!(
state.load_taint_from_memory(&pi_state.eval(&address), ByteSize::new(8)), state.load_taint_from_memory(&pi_state.eval(&address), ByteSize::new(8)),
taint taint
...@@ -484,12 +476,12 @@ mod tests { ...@@ -484,12 +476,12 @@ mod tests {
fn eval_expression() { fn eval_expression() {
let (state, _pi_state) = State::mock_with_pi_state(); let (state, _pi_state) = State::mock_with_pi_state();
let expr = Expression::Var(register("RAX")).plus(Expression::Var(register("RBX"))); let expr = expr!("RAX:8 + RBX:8");
assert!(state.eval(&expr).is_tainted()); assert!(state.eval(&expr).is_tainted());
let expr = Expression::UnOp { let expr = Expression::UnOp {
op: UnOpType::Int2Comp, op: UnOpType::Int2Comp,
arg: Box::new(Expression::Var(register("RSP"))), arg: Box::new(Expression::Var(variable!("RSP:8"))),
}; };
assert!(state.eval(&expr).is_top()); assert!(state.eval(&expr).is_top());
} }
......
...@@ -23,8 +23,8 @@ impl Display for Taint { ...@@ -23,8 +23,8 @@ impl Display for Taint {
/// Print the value of a `Taint` object. /// Print the value of a `Taint` object.
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self { match self {
Self::Tainted(size) => write!(f, "Tainted:{}", size), Self::Tainted(size) => write!(f, "Tainted:{size}"),
Self::Top(size) => write!(f, "Top:{}", size), Self::Top(size) => write!(f, "Top:{size}"),
} }
} }
} }
......
...@@ -92,7 +92,7 @@ fn generate_cwe_warning(sub: &Term<Sub>, jmp: &Term<Jmp>, permission_const: u64) ...@@ -92,7 +92,7 @@ fn generate_cwe_warning(sub: &Term<Sub>, jmp: &Term<Jmp>, permission_const: u64)
.addresses(vec![jmp.tid.address.clone()]) .addresses(vec![jmp.tid.address.clone()])
.other(vec![vec![ .other(vec![vec![
"umask_arg".to_string(), "umask_arg".to_string(),
format!("{:#o}", permission_const), format!("{permission_const:#o}"),
]]) ]])
} }
...@@ -122,8 +122,7 @@ pub fn check_cwe( ...@@ -122,8 +122,7 @@ pub fn check_cwe(
} }
Err(err) => { Err(err) => {
let log = LogMessage::new_info(format!( let log = LogMessage::new_info(format!(
"Could not determine umask argument: {}", "Could not determine umask argument: {err}"
err
)) ))
.location(jmp.tid.clone()) .location(jmp.tid.clone())
.source(CWE_MODULE.name); .source(CWE_MODULE.name);
......
...@@ -66,8 +66,7 @@ pub fn generate_cwe_warnings<'a>( ...@@ -66,8 +66,7 @@ pub fn generate_cwe_warnings<'a>(
for (sub_name, jmp_tid, target_name) in dangerous_calls.iter() { for (sub_name, jmp_tid, target_name) in dangerous_calls.iter() {
let address: &String = &jmp_tid.address; let address: &String = &jmp_tid.address;
let description: String = format!( let description: String = format!(
"(Use of Potentially Dangerous Function) {} ({}) -> {}", "(Use of Potentially Dangerous Function) {sub_name} ({address}) -> {target_name}"
sub_name, address, target_name
); );
let cwe_warning = CweWarning::new( let cwe_warning = CweWarning::new(
String::from(CWE_MODULE.name), String::from(CWE_MODULE.name),
...@@ -75,7 +74,7 @@ pub fn generate_cwe_warnings<'a>( ...@@ -75,7 +74,7 @@ pub fn generate_cwe_warnings<'a>(
description, description,
) )
.addresses(vec![address.clone()]) .addresses(vec![address.clone()])
.tids(vec![format!("{}", jmp_tid)]) .tids(vec![format!("{jmp_tid}")])
.symbols(vec![String::from(*sub_name)]) .symbols(vec![String::from(*sub_name)])
.other(vec![vec![ .other(vec![vec![
String::from("dangerous_function"), String::from("dangerous_function"),
......
...@@ -247,7 +247,7 @@ pub fn generate_cwe_warning(sub_name: &str, jmp_tid: &Tid, symbol_name: &str) -> ...@@ -247,7 +247,7 @@ pub fn generate_cwe_warning(sub_name: &str, jmp_tid: &Tid, symbol_name: &str) ->
description, description,
) )
.addresses(vec![jmp_tid.address.clone()]) .addresses(vec![jmp_tid.address.clone()])
.tids(vec![format!("{}", jmp_tid)]) .tids(vec![format!("{jmp_tid}")])
.symbols(vec![String::from(sub_name)]) .symbols(vec![String::from(sub_name)])
.other(vec![vec![ .other(vec![vec![
String::from("OS Command Injection"), String::from("OS Command Injection"),
......
...@@ -50,16 +50,14 @@ pub fn generate_cwe_warning(calls: &[(&str, &Tid, &str)]) -> Vec<CweWarning> { ...@@ -50,16 +50,14 @@ pub fn generate_cwe_warning(calls: &[(&str, &Tid, &str)]) -> Vec<CweWarning> {
for (sub_name, jmp_tid, _) in calls.iter() { for (sub_name, jmp_tid, _) in calls.iter() {
let address: &String = &jmp_tid.address; let address: &String = &jmp_tid.address;
let description = format!( let description = format!(
"(Exposed IOCTL with Insufficient Access Control) Program uses ioctl at {} ({}). Be sure to double check the program and the corresponding driver.", "(Exposed IOCTL with Insufficient Access Control) Program uses ioctl at {sub_name} ({address}). Be sure to double check the program and the corresponding driver.");
sub_name, address
);
let cwe_warning = CweWarning::new( let cwe_warning = CweWarning::new(
String::from(CWE_MODULE.name), String::from(CWE_MODULE.name),
String::from(CWE_MODULE.version), String::from(CWE_MODULE.version),
description, description,
) )
.addresses(vec![address.clone()]) .addresses(vec![address.clone()])
.tids(vec![format!("{}", jmp_tid)]) .tids(vec![format!("{jmp_tid}")])
.symbols(vec![String::from(*sub_name)]); .symbols(vec![String::from(*sub_name)]);
cwe_warnings.push(cwe_warning); cwe_warnings.push(cwe_warning);
......
...@@ -120,7 +120,7 @@ fn generate_cwe_warning(allocation: &Tid, is_stack_allocation: bool) -> CweWarni ...@@ -120,7 +120,7 @@ fn generate_cwe_warning(allocation: &Tid, is_stack_allocation: bool) -> CweWarni
allocation.address allocation.address
), ),
) )
.tids(vec![format!("{}", allocation)]) .tids(vec![format!("{allocation}")])
.addresses(vec![allocation.address.clone()]) .addresses(vec![allocation.address.clone()])
.symbols(vec![]) .symbols(vec![])
} }
......
...@@ -91,9 +91,9 @@ impl Term<Def> { ...@@ -91,9 +91,9 @@ impl Term<Def> {
impl fmt::Display for Def { impl fmt::Display for Def {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self { match self {
Def::Load { var, address } => write!(f, "{} := Load from {}", var, address), Def::Load { var, address } => write!(f, "{var} := Load from {address}"),
Def::Store { address, value } => write!(f, "Store at {} := {}", address, value), Def::Store { address, value } => write!(f, "Store at {address} := {value}"),
Def::Assign { var, value } => write!(f, "{} = {}", var, value), Def::Assign { var, value } => write!(f, "{var} = {value}"),
} }
} }
} }
......
...@@ -213,24 +213,24 @@ impl Expression { ...@@ -213,24 +213,24 @@ impl Expression {
impl fmt::Display for Expression { impl fmt::Display for Expression {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self { match self {
Expression::Var(var) => write!(f, "{}", var), Expression::Var(var) => write!(f, "{var}"),
Expression::Const(c) => { Expression::Const(c) => {
write!(f, "0x{:016x}:i{}", c, c.bytesize().as_bit_length()) write!(f, "0x{:016x}:{}", c, c.bytesize())
} }
Expression::BinOp { op, lhs, rhs } => match op { Expression::BinOp { op, lhs, rhs } => match op {
BinOpType::IntMult BinOpType::IntMult
| BinOpType::IntDiv | BinOpType::IntDiv
| BinOpType::IntRem | BinOpType::IntRem
| BinOpType::FloatMult | BinOpType::FloatMult
| BinOpType::FloatDiv => write!(f, "{} {} {}", lhs, op, rhs), | BinOpType::FloatDiv => write!(f, "{lhs} {op} {rhs}"),
_ => write!(f, "({} {} {})", lhs, op, rhs), _ => write!(f, "({lhs} {op} {rhs})"),
}, },
Expression::UnOp { op, arg } => write!(f, "{}({})", op, arg), Expression::UnOp { op, arg } => write!(f, "{op}({arg})"),
Expression::Cast { op, size: _, arg } => write!(f, "{}({})", op, arg), Expression::Cast { op, size: _, arg } => write!(f, "{op}({arg})"),
Expression::Unknown { Expression::Unknown {
description, description,
size: _, size: _,
} => write!(f, "{}", description), } => write!(f, "{description}"),
Expression::Subpiece { Expression::Subpiece {
low_byte, low_byte,
size, size,
...@@ -263,7 +263,7 @@ impl fmt::Display for BinOpType { ...@@ -263,7 +263,7 @@ impl fmt::Display for BinOpType {
BinOpType::IntRem => write!(f, "%"), BinOpType::IntRem => write!(f, "%"),
BinOpType::BoolAnd => write!(f, "&&"), BinOpType::BoolAnd => write!(f, "&&"),
BinOpType::BoolOr => write!(f, "||"), BinOpType::BoolOr => write!(f, "||"),
_ => write!(f, "{:?}", self), _ => write!(f, "{self:?}"),
} }
} }
} }
...@@ -272,14 +272,15 @@ impl fmt::Display for UnOpType { ...@@ -272,14 +272,15 @@ impl fmt::Display for UnOpType {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self { match self {
UnOpType::BoolNegate => write!(f, "¬"), UnOpType::BoolNegate => write!(f, "¬"),
_ => write!(f, "{:?}", self), UnOpType::IntNegate => write!(f, "-"),
_ => write!(f, "{self:?}"),
} }
} }
} }
impl fmt::Display for CastOpType { impl fmt::Display for CastOpType {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "{:?}", self) write!(f, "{self:?}")
} }
} }
#[cfg(test)] #[cfg(test)]
......
...@@ -232,7 +232,7 @@ fn display() { ...@@ -232,7 +232,7 @@ fn display() {
.subpiece(ByteSize(0), ByteSize(20)); .subpiece(ByteSize(0), ByteSize(20));
assert_eq!( assert_eq!(
"(FloatCeil(IntSExt(IntNegate((0x2:i32 + RAX:64 * RBP:64)))))[0-19]", "(FloatCeil(IntSExt(-((0x2:4 + RAX:8 * RBP:8)))))[0-19]",
format!("{}", expr) format!("{}", expr)
); );
} }
...@@ -64,9 +64,9 @@ pub enum Jmp { ...@@ -64,9 +64,9 @@ pub enum Jmp {
impl fmt::Display for Jmp { impl fmt::Display for Jmp {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self { match self {
Jmp::Branch(tid) => write!(f, "Jump to {}", tid), Jmp::Branch(tid) => write!(f, "Jump to {tid}"),
Jmp::BranchInd(expr) => write!(f, "Jump to {}", expr), Jmp::BranchInd(expr) => write!(f, "Jump to {expr}"),
Jmp::CBranch { target, condition } => write!(f, "If {} jump to {}", condition, target), Jmp::CBranch { target, condition } => write!(f, "If {condition} jump to {target}"),
Jmp::Call { target, return_ } => write!( Jmp::Call { target, return_ } => write!(
f, f,
"call {} ret {}", "call {} ret {}",
...@@ -79,7 +79,7 @@ impl fmt::Display for Jmp { ...@@ -79,7 +79,7 @@ impl fmt::Display for Jmp {
target, target,
return_.as_ref().unwrap_or(&Tid::new("?")) return_.as_ref().unwrap_or(&Tid::new("?"))
), ),
Jmp::Return(expr) => write!(f, "ret {}", expr), Jmp::Return(expr) => write!(f, "ret {expr}"),
Jmp::CallOther { Jmp::CallOther {
description, description,
return_, return_,
......
use crate::intermediate_representation::*;
#[test]
fn test_var() {
assert_eq!(
variable!("RAX:8"),
Variable {
name: "RAX".to_string(),
size: ByteSize(8),
is_temp: false
}
);
}
#[test]
#[should_panic]
fn var_empty_panics() {
variable!("");
}
#[test]
#[should_panic]
fn var_no_colon_panics() {
variable!("RAX8");
}
#[test]
#[should_panic]
fn var_no_size_panics() {
variable!("RAX:");
}
#[test]
fn test_bitvec() {
assert_eq!(bitvec!("0x42:1"), Bitvector::from_u8(0x42));
assert_eq!(bitvec!("0xFF:2"), Bitvector::from_u16(0xFF));
assert_eq!(bitvec!("0xAAFF:1"), Bitvector::from_u8(0xFF));
assert_eq!(bitvec!("0x-01:1"), Bitvector::from_i8(-1));
assert_eq!(bitvec!("123:4"), Bitvector::from_u32(123));
assert_eq!(bitvec!("-42:8"), Bitvector::from_i64(-42));
}
#[test]
fn test_expr_var() {
assert_eq!(
expr!("RAX:8"),
Expression::Var(Variable {
name: "RAX".into(),
size: ByteSize(8),
is_temp: false
})
);
}
#[test]
fn test_expr_const() {
assert_eq!(
expr!("0x42:8"),
Expression::Const(Bitvector::from_u64(0x42))
);
assert_eq!(
expr!("0xFFFF:1"),
Expression::Const(Bitvector::from_u8(255))
);
assert_eq!(expr!("42:4"), Expression::Const(Bitvector::from_u32(42)));
}
#[test]
fn test_expr_plus() {
assert_eq!(
expr!("RAX:8 + 0x42:8"),
Expression::BinOp {
op: BinOpType::IntAdd,
lhs: Box::new(Expression::Var(Variable {
name: "RAX".into(),
size: ByteSize(8),
is_temp: false
})),
rhs: Box::new(Expression::Const(Bitvector::from_u64(0x42)))
}
);
}
#[test]
fn test_expr_minus() {
assert_eq!(
expr!("RAX:8 - 0x42:8"),
Expression::BinOp {
op: BinOpType::IntSub,
lhs: Box::new(Expression::Var(Variable {
name: "RAX".into(),
size: ByteSize(8),
is_temp: false
})),
rhs: Box::new(Expression::Const(Bitvector::from_u64(0x42)))
}
);
}
#[test]
fn test_expr_int_negate() {
assert_eq!(
expr!("-(RAX:8)"),
Expression::UnOp {
op: UnOpType::IntNegate,
arg: Box::new(Expression::Var(Variable {
name: "RAX".into(),
size: ByteSize(8),
is_temp: false
}))
}
);
}
#[test]
fn test_expr_bool_negate() {
assert_eq!(
expr!("¬(RAX:8)"),
Expression::UnOp {
op: UnOpType::BoolNegate,
arg: Box::new(Expression::Var(Variable {
name: "RAX".into(),
size: ByteSize(8),
is_temp: false
}))
}
);
}
#[test]
fn test_def_tid() {
let defs = defs![
"RDI:8 = RAX:8 + RBP:8",
"A: RAX:8 = 0x42:1",
"RDX:8 = RAX:8 + RBP:8"
];
assert_eq!(
defs.into_iter()
.map(|x| x.tid.to_string())
.collect::<Vec<String>>(),
["tid_0", "A", "tid_2"]
)
}
#[test]
fn test_defs_assign() {
assert_eq!(
defs!["tid_0: RAX:8 = 0x42:1", "tid_1: RDI:8 = RAX:8 + RBP:8"],
vec![
Term {
tid: Tid::new("tid_0"),
term: Def::Assign {
var: Variable {
name: "RAX".into(),
size: ByteSize(8),
is_temp: false
},
value: Expression::Const(Bitvector::from_i8(0x42))
}
},
Term {
tid: Tid::new("tid_1"),
term: Def::Assign {
var: Variable {
name: "RDI".into(),
size: ByteSize(8),
is_temp: false
},
value: Expression::BinOp {
op: BinOpType::IntAdd,
lhs: Box::new(Expression::Var(Variable {
name: "RAX".into(),
size: ByteSize(8),
is_temp: false
})),
rhs: Box::new(Expression::Var(Variable {
name: "RBP".into(),
size: ByteSize(8),
is_temp: false
}))
}
}
}
]
);
}
#[test]
fn test_defs_store() {
assert_eq!(
defs!["tid: Store at RSP:8 - 0x8:1 := 0x42:1"],
vec![Term {
tid: Tid::new("tid"),
term: Def::Store {
address: Expression::BinOp {
op: BinOpType::IntSub,
lhs: Box::new(Expression::Var(Variable {
name: "RSP".into(),
size: ByteSize(8),
is_temp: false
})),
rhs: Box::new(Expression::Const(Bitvector::from_u8(0x8)))
},
value: Expression::Const(Bitvector::from_u8(0x42))
}
}]
)
}
#[test]
fn test_defs_load() {
assert_eq!(
defs!["tid_a: RAX:8 := Load from 0xFF00:4 + 0x08:4"],
vec![Term {
tid: Tid::new("tid_a"),
term: Def::Load {
var: Variable {
name: "RAX".into(),
size: ByteSize(8),
is_temp: false
},
address: Expression::BinOp {
op: BinOpType::IntAdd,
lhs: Box::new(Expression::Const(Bitvector::from_u32(0xFF00))),
rhs: Box::new(Expression::Const(Bitvector::from_u32(0x08)))
}
}
}]
)
}
#[test]
fn test_defs_composition() {
assert_eq!(
defs![
"tid_a: Store at RSP:8 + -(0x8:1) := RAX:8",
"tid_b: RSP:8 = RSP:8 + ¬(0x8:1)",
"tid_c: RDI:8 := Load from RSP:8"
],
vec![
Term {
tid: Tid::new("tid_a"),
term: Def::Store {
address: Expression::BinOp {
op: BinOpType::IntAdd,
lhs: Box::new(Expression::Var(Variable {
name: "RSP".into(),
size: ByteSize(8),
is_temp: false
})),
rhs: Box::new(Expression::UnOp {
op: UnOpType::IntNegate,
arg: Box::new(Expression::Const(Bitvector::from_u8(0x08)))
})
},
value: Expression::Var(Variable {
name: "RAX".into(),
size: ByteSize(8),
is_temp: false
})
}
},
Term {
tid: Tid::new("tid_b"),
term: Def::Assign {
var: Variable {
name: "RSP".into(),
size: ByteSize(8),
is_temp: false
},
value: Expression::BinOp {
op: BinOpType::IntAdd,
lhs: Box::new(Expression::Var(Variable {
name: "RSP".into(),
size: ByteSize(8),
is_temp: false
})),
rhs: Box::new(Expression::UnOp {
op: UnOpType::BoolNegate,
arg: Box::new(Expression::Const(Bitvector::from_u8(0x08)))
})
}
}
},
Term {
tid: Tid::new("tid_c"),
term: Def::Load {
var: Variable {
name: "RDI".into(),
size: ByteSize(8),
is_temp: false
},
address: Expression::Var(Variable {
name: "RSP".into(),
size: ByteSize(8),
is_temp: false
})
}
}
]
)
}
...@@ -32,6 +32,11 @@ mod project; ...@@ -32,6 +32,11 @@ mod project;
pub use project::*; pub use project::*;
mod runtime_memory_image; mod runtime_memory_image;
pub use runtime_memory_image::*; pub use runtime_memory_image::*;
#[cfg(test)]
#[macro_use]
mod macros;
#[cfg(test)]
pub use macros::*;
/// An unsigned number of bytes. /// An unsigned number of bytes.
/// ///
......
...@@ -37,7 +37,7 @@ impl Tid { ...@@ -37,7 +37,7 @@ impl Tid {
/// the returned block ID is the one that would be executed first if a jump to the given address happened. /// the returned block ID is the one that would be executed first if a jump to the given address happened.
pub fn blk_id_at_address(address: &str) -> Tid { pub fn blk_id_at_address(address: &str) -> Tid {
Tid { Tid {
id: format!("blk_{}", address), id: format!("blk_{address}"),
address: address.to_string(), address: address.to_string(),
} }
} }
......
...@@ -22,7 +22,7 @@ pub struct Variable { ...@@ -22,7 +22,7 @@ pub struct Variable {
impl Display for Variable { impl Display for Variable {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(f, "{}:{}", self.name, self.size.as_bit_length())?; write!(f, "{}:{}", self.name, self.size)?;
if self.is_temp { if self.is_temp {
write!(f, "(temp)")?; write!(f, "(temp)")?;
} }
......
...@@ -42,7 +42,7 @@ impl From<Variable> for IrExpression { ...@@ -42,7 +42,7 @@ impl From<Variable> for IrExpression {
match (&pcode_var.name, &pcode_var.value) { match (&pcode_var.name, &pcode_var.value) {
(Some(_name), None) => IrExpression::Var(pcode_var.into()), (Some(_name), None) => IrExpression::Var(pcode_var.into()),
(None, Some(_hex_value)) => IrExpression::Const(pcode_var.parse_const_to_bitvector()), (None, Some(_hex_value)) => IrExpression::Const(pcode_var.parse_const_to_bitvector()),
_ => panic!("Conversion failed:\n{:?}", pcode_var), _ => panic!("Conversion failed:\n{pcode_var:?}"),
} }
} }
} }
......
...@@ -312,7 +312,7 @@ fn piecing_or_zero_extending() { ...@@ -312,7 +312,7 @@ fn piecing_or_zero_extending() {
replace_subregister_in_block(&mut block, &register_map); replace_subregister_in_block(&mut block, &register_map);
assert!(check_defs_of_block( assert!(check_defs_of_block(
&block, &block,
vec!["zext_eax_to_rax: RAX:64 = IntZExt(0x0:i32)"] vec!["zext_eax_to_rax: RAX:8 = IntZExt(0x0:4)"]
)); ));
// Test whether zero extension to base register is still recognized // Test whether zero extension to base register is still recognized
...@@ -328,7 +328,7 @@ fn piecing_or_zero_extending() { ...@@ -328,7 +328,7 @@ fn piecing_or_zero_extending() {
replace_subregister_in_block(&mut block, &register_map); replace_subregister_in_block(&mut block, &register_map);
assert!(check_defs_of_block( assert!(check_defs_of_block(
&block, &block,
vec!["zext_ah_to_rax: RAX:64 = IntZExt(0x0:i8)"] vec!["zext_ah_to_rax: RAX:8 = IntZExt(0x0:1)"]
)); ));
// Test when the next register is a zero extension to a different register. // Test when the next register is a zero extension to a different register.
...@@ -344,8 +344,8 @@ fn piecing_or_zero_extending() { ...@@ -344,8 +344,8 @@ fn piecing_or_zero_extending() {
assert!(check_defs_of_block( assert!(check_defs_of_block(
&block, &block,
vec![ vec![
"eax_assign: RAX:64 = ((RAX:64)[4-7] Piece 0x0:i32)", "eax_assign: RAX:8 = ((RAX:8)[4-7] Piece 0x0:4)",
"zext_eax_to_rcx: RCX:64 = IntZExt((RAX:64)[0-3])" "zext_eax_to_rcx: RCX:8 = IntZExt((RAX:8)[0-3])"
] ]
)); ));
...@@ -362,8 +362,8 @@ fn piecing_or_zero_extending() { ...@@ -362,8 +362,8 @@ fn piecing_or_zero_extending() {
assert!(check_defs_of_block( assert!(check_defs_of_block(
&block, &block,
vec![ vec![
"ah_assign: RAX:64 = (((RAX:64)[2-7] Piece 0x0:i8) Piece (RAX:64)[0-0])", "ah_assign: RAX:8 = (((RAX:8)[2-7] Piece 0x0:1) Piece (RAX:8)[0-0])",
"zext_ah_to_eax: RAX:64 = ((RAX:64)[4-7] Piece IntZExt((RAX:64)[1-1]))", "zext_ah_to_eax: RAX:8 = ((RAX:8)[4-7] Piece IntZExt((RAX:8)[1-1]))",
] ]
)); ));
...@@ -380,8 +380,8 @@ fn piecing_or_zero_extending() { ...@@ -380,8 +380,8 @@ fn piecing_or_zero_extending() {
assert!(check_defs_of_block( assert!(check_defs_of_block(
&block, &block,
vec![ vec![
"load_to_eax: loaded_value:32(temp) := Load from 0x0:i64", "load_to_eax: loaded_value:4(temp) := Load from 0x0:8",
"zext_eax_to_rax: RAX:64 = IntZExt(loaded_value:32(temp))", "zext_eax_to_rax: RAX:8 = IntZExt(loaded_value:4(temp))",
] ]
)); ));
...@@ -398,9 +398,9 @@ fn piecing_or_zero_extending() { ...@@ -398,9 +398,9 @@ fn piecing_or_zero_extending() {
assert!(check_defs_of_block( assert!(check_defs_of_block(
&block, &block,
vec![ vec![
"load_to_eax: loaded_value:32(temp) := Load from 0x0:i64", "load_to_eax: loaded_value:4(temp) := Load from 0x0:8",
"load_to_eax_cast_to_base: RAX:64 = ((RAX:64)[4-7] Piece loaded_value:32(temp))", "load_to_eax_cast_to_base: RAX:8 = ((RAX:8)[4-7] Piece loaded_value:4(temp))",
"zext_eax_to_rcx: RCX:64 = IntZExt((RAX:64)[0-3])" "zext_eax_to_rcx: RCX:8 = IntZExt((RAX:8)[0-3])"
] ]
)); ));
} }
...@@ -293,7 +293,7 @@ impl Blk { ...@@ -293,7 +293,7 @@ impl Blk {
_ => panic!(), _ => panic!(),
}; };
if input.address.is_some() { if input.address.is_some() {
let temp_register_name = format!("$load_temp{}", index); let temp_register_name = format!("$load_temp{index}");
let load_def = input.to_load_def(temp_register_name, generic_pointer_size); let load_def = input.to_load_def(temp_register_name, generic_pointer_size);
*input = load_def.lhs.clone().unwrap(); *input = load_def.lhs.clone().unwrap();
refactored_defs.push(Term { refactored_defs.push(Term {
......
...@@ -792,28 +792,28 @@ fn from_project_to_ir_project() { ...@@ -792,28 +792,28 @@ fn from_project_to_ir_project() {
// Checks if the other definitions and the jump were correctly casted. // Checks if the other definitions and the jump were correctly casted.
assert_eq!( assert_eq!(
format!("{}", ir_block.defs[0].term), format!("{}", ir_block.defs[0].term),
"loaded_value:32(temp) := Load from (RDI:64)[0-3]".to_string() "loaded_value:4(temp) := Load from (RDI:8)[0-3]".to_string()
); );
assert_eq!( assert_eq!(
format!("{}", ir_block.defs[1].term), format!("{}", ir_block.defs[1].term),
"RDI:64 = ((RDI:64)[4-7] Piece loaded_value:32(temp))".to_string() "RDI:8 = ((RDI:8)[4-7] Piece loaded_value:4(temp))".to_string()
); );
assert_eq!( assert_eq!(
format!("{}", ir_block.defs[2].term), format!("{}", ir_block.defs[2].term),
"RAX:64 = (((RAX:64)[2-7] Piece ((RAX:64)[1-1] ^ (RAX:64)[1-1])) Piece (RAX:64)[0-0])" "RAX:8 = (((RAX:8)[2-7] Piece ((RAX:8)[1-1] ^ (RAX:8)[1-1])) Piece (RAX:8)[0-0])"
.to_string() .to_string()
); );
assert_eq!( assert_eq!(
format!("{}", ir_block.defs[3].term), format!("{}", ir_block.defs[3].term),
"RAX:64 = IntZExt((RDI:64)[0-3])".to_string() "RAX:8 = IntZExt((RDI:8)[0-3])".to_string()
); );
assert_eq!( assert_eq!(
format!("{}", ir_block.defs[4].term), format!("{}", ir_block.defs[4].term),
"RAX:64 = ((RAX:64)[4-7] Piece (0x0:i16 Piece (RAX:64)[0-1]))".to_string() "RAX:8 = ((RAX:8)[4-7] Piece (0x0:2 Piece (RAX:8)[0-1]))".to_string()
); );
assert_eq!( assert_eq!(
format!("{}", ir_block.defs[5].term), format!("{}", ir_block.defs[5].term),
"RAX:64 = ((RAX:64)[2-7] Piece ((RDI:64)[0-3])[1-2])".to_string() "RAX:8 = ((RAX:8)[2-7] Piece ((RDI:8)[0-3])[1-2])".to_string()
); );
assert_eq!(ir_block.jmps[0].term, expected_jmp); assert_eq!(ir_block.jmps[0].term, expected_jmp);
} }
...@@ -31,7 +31,7 @@ pub fn get_project_from_ghidra( ...@@ -31,7 +31,7 @@ pub fn get_project_from_ghidra(
.as_millis() .as_millis()
); );
// Create a unique name for the pipe // Create a unique name for the pipe
let fifo_path = tmp_folder.join(format!("pcode_{}.pipe", timestamp_suffix)); let fifo_path = tmp_folder.join(format!("pcode_{timestamp_suffix}.pipe"));
let ghidra_command = generate_ghidra_call_command( let ghidra_command = generate_ghidra_call_command(
file_path, file_path,
&fifo_path, &fifo_path,
...@@ -93,7 +93,7 @@ fn execute_ghidra( ...@@ -93,7 +93,7 @@ fn execute_ghidra(
let output = match ghidra_command.output() { let output = match ghidra_command.output() {
Ok(output) => output, Ok(output) => output,
Err(err) => { Err(err) => {
eprintln!("Ghidra could not be executed: {}", err); eprintln!("Ghidra could not be executed: {err}");
std::process::exit(101); std::process::exit(101);
} }
}; };
...@@ -107,7 +107,7 @@ fn execute_ghidra( ...@@ -107,7 +107,7 @@ fn execute_ghidra(
eprintln!("{}", String::from_utf8(output.stdout).unwrap()); eprintln!("{}", String::from_utf8(output.stdout).unwrap());
eprintln!("{}", String::from_utf8(output.stderr).unwrap()); eprintln!("{}", String::from_utf8(output.stderr).unwrap());
if let Some(code) = output.status.code() { if let Some(code) = output.status.code() {
eprintln!("Ghidra plugin failed with exit code {}", code); eprintln!("Ghidra plugin failed with exit code {code}");
} }
eprintln!("Execution of Ghidra plugin failed."); eprintln!("Execution of Ghidra plugin failed.");
} else { } else {
...@@ -150,7 +150,7 @@ fn generate_ghidra_call_command( ...@@ -150,7 +150,7 @@ fn generate_ghidra_call_command(
let mut ghidra_command = Command::new(headless_path); let mut ghidra_command = Command::new(headless_path);
ghidra_command ghidra_command
.arg(&tmp_folder) // The folder where temporary files should be stored .arg(&tmp_folder) // The folder where temporary files should be stored
.arg(format!("PcodeExtractor_{}_{}", filename, timestamp_suffix)) // The name of the temporary Ghidra Project. .arg(format!("PcodeExtractor_{filename}_{timestamp_suffix}")) // The name of the temporary Ghidra Project.
.arg("-import") // Import a file into the Ghidra project .arg("-import") // Import a file into the Ghidra project
.arg(file_path) // File import path .arg(file_path) // File import path
.arg("-postScript") // Execute a script after standard analysis by Ghidra finished .arg("-postScript") // Execute a script after standard analysis by Ghidra finished
......
...@@ -155,9 +155,9 @@ impl std::fmt::Display for LogMessage { ...@@ -155,9 +155,9 @@ impl std::fmt::Display for LogMessage {
LogLevel::Info => write!(formatter, "INFO: ")?, LogLevel::Info => write!(formatter, "INFO: ")?,
}; };
match (&self.source, &self.location) { match (&self.source, &self.location) {
(Some(source), Some(location)) => write!(formatter, "{} @ {}: ", source, location)?, (Some(source), Some(location)) => write!(formatter, "{source} @ {location}: ")?,
(Some(source), None) => write!(formatter, "{}: ", source)?, (Some(source), None) => write!(formatter, "{source}: ")?,
(None, Some(location)) => write!(formatter, "{}: ", location)?, (None, Some(location)) => write!(formatter, "{location}: ")?,
(None, None) => (), (None, None) => (),
}; };
write!(formatter, "{}", self.text) write!(formatter, "{}", self.text)
...@@ -177,23 +177,22 @@ pub fn print_all_messages( ...@@ -177,23 +177,22 @@ pub fn print_all_messages(
emit_json: bool, emit_json: bool,
) { ) {
for log in logs { for log in logs {
println!("{}", log); println!("{log}");
} }
let output: String = if emit_json { let output: String = if emit_json {
serde_json::to_string_pretty(&cwes).unwrap() serde_json::to_string_pretty(&cwes).unwrap()
} else { } else {
cwes.iter() cwes.iter()
.map(|cwe| format!("{}", cwe)) .map(|cwe| format!("{cwe}"))
.collect::<Vec<String>>() .collect::<Vec<String>>()
.join("\n") .join("\n")
+ "\n" + "\n"
}; };
if let Some(file_path) = out_path { if let Some(file_path) = out_path {
std::fs::write(file_path, output).unwrap_or_else(|error| { std::fs::write(file_path, output)
panic!("Writing to output path {} failed: {}", file_path, error) .unwrap_or_else(|error| panic!("Writing to output path {file_path} failed: {error}"));
});
} else { } else {
print!("{}", output); print!("{output}",);
} }
} }
...@@ -215,7 +214,7 @@ pub fn add_debug_log_statistics(all_logs: &mut Vec<LogMessage>) { ...@@ -215,7 +214,7 @@ pub fn add_debug_log_statistics(all_logs: &mut Vec<LogMessage>) {
} }
for (analysis, count) in analysis_debug_log_count { for (analysis, count) in analysis_debug_log_count {
all_logs.push(LogMessage { all_logs.push(LogMessage {
text: format!("Logged {} debug log messages.", count), text: format!("Logged {count} debug log messages."),
level: LogLevel::Info, level: LogLevel::Info,
location: None, location: None,
source: Some(analysis), source: Some(analysis),
...@@ -223,10 +222,7 @@ pub fn add_debug_log_statistics(all_logs: &mut Vec<LogMessage>) { ...@@ -223,10 +222,7 @@ pub fn add_debug_log_statistics(all_logs: &mut Vec<LogMessage>) {
} }
if general_debug_log_count > 0 { if general_debug_log_count > 0 {
all_logs.push(LogMessage { all_logs.push(LogMessage {
text: format!( text: format!("Logged {general_debug_log_count} general debug log messages."),
"Logged {} general debug log messages.",
general_debug_log_count
),
level: LogLevel::Info, level: LogLevel::Info,
location: None, location: None,
source: None, source: None,
......
...@@ -70,8 +70,7 @@ impl CweTestCase { ...@@ -70,8 +70,7 @@ impl CweTestCase {
} else { } else {
println!("{} \t {}", filepath, "[FAILED]".red()); println!("{} \t {}", filepath, "[FAILED]".red());
Err(format!( Err(format!(
"Expected occurrences: {}. Found: {}", "Expected occurrences: {num_expected_occurences}. Found: {num_cwes}"
num_expected_occurences, num_cwes
)) ))
} }
} else { } else {
...@@ -79,7 +78,7 @@ impl CweTestCase { ...@@ -79,7 +78,7 @@ impl CweTestCase {
match output.status.code() { match output.status.code() {
Some(_code) => Err(String::from_utf8(output.stdout).unwrap() Some(_code) => Err(String::from_utf8(output.stdout).unwrap()
+ &String::from_utf8(output.stderr).unwrap()), + &String::from_utf8(output.stderr).unwrap()),
None => Err(format!("Execution failed for file {}", filepath)), None => Err(format!("Execution failed for file {filepath}")),
} }
} }
} }
...@@ -160,8 +159,8 @@ pub fn all_test_cases(cwe: &'static str, check_name: &'static str) -> Vec<CweTes ...@@ -160,8 +159,8 @@ pub fn all_test_cases(cwe: &'static str, check_name: &'static str) -> Vec<CweTes
/// The `error_log` tuples are of the form `(check_filename, error_message)`. /// The `error_log` tuples are of the form `(check_filename, error_message)`.
pub fn print_errors(error_log: Vec<(String, String)>) { pub fn print_errors(error_log: Vec<(String, String)>) {
for (filepath, error) in error_log { for (filepath, error) in error_log {
println!("{}", format!("+++ Error for {} +++", filepath).red()); println!("{}", format!("+++ Error for {filepath} +++").red());
println!("{}", error); println!("{error}");
} }
} }
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment