Skip to content

Commit c4054ea

Browse files
committed
implement insta testing
1 parent ba38ca8 commit c4054ea

File tree

893 files changed

+2553447
-273
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

893 files changed

+2553447
-273
lines changed

Cargo.toml

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ num_enum = "0.7.3"
1515
num-traits = "0.2.19"
1616
zstd = "0.13.3"
1717
rstest = "0.25.0"
18+
insta = "1.43.1"
1819

1920
[features]
2021
default = []
@@ -26,3 +27,7 @@ path = "src/tools/tools.rs"
2627

2728
[dev-dependencies]
2829
insta = { version = "1.43.1", features = ["yaml"] }
30+
31+
[profile.dev.package]
32+
insta.opt-level = 3
33+
similar.opt-level = 3

build.rs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
pub fn main() {
2+
// recompile so new til/idb files are included to tests
3+
println!("cargo::rerun-if-changed=resources/idbs");
4+
println!("cargo::rerun-if-changed=resources/tils");
5+
}

src/addr_info.rs

Lines changed: 9 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,3 @@
1-
use std::borrow::Cow;
2-
31
use crate::bytes_info::BytesInfo;
42
use crate::id0::entry_iter::EntryTagContinuousSubkeys;
53
use crate::id0::flag::nalt::x::NALT_DREF_FROM;
@@ -12,7 +10,7 @@ use crate::id0::{
1210
use crate::id1::{ByteDataType, ByteInfo, ByteType, ID1Section};
1311
use crate::id2::ID2Section;
1412
use crate::til::Type;
15-
use crate::{Address, IDAKind};
13+
use crate::{Address, IDAKind, IDBStr, IDBString};
1614

1715
use anyhow::{anyhow, Result};
1816

@@ -76,32 +74,32 @@ impl<'a, K: IDAKind> AddressInfo<'a, K> {
7674
// the function `get_cmt` search for the next non-tail entry in id1,
7775
// maybe that's for compatibility reasons, but maybe the `has_comment`
7876
// flag should be ignored in tail id1 entries
79-
pub fn comment(&self) -> Option<&'a [u8]> {
77+
pub fn comment(&self) -> Option<IDBStr<'a>> {
8078
self.id0.comment_at(self.netnode())
8179
}
8280

83-
pub fn comment_repeatable(&self) -> Option<&'a [u8]> {
81+
pub fn comment_repeatable(&self) -> Option<IDBStr<'a>> {
8482
if !self.byte_info.has_comment() {
8583
return None;
8684
}
8785
self.id0.comment_repeatable_at(self.netnode())
8886
}
8987

90-
pub fn comment_pre(&self) -> Option<impl Iterator<Item = &[u8]>> {
88+
pub fn comment_pre(&self) -> Option<impl Iterator<Item = IDBStr<'a>>> {
9189
if !self.byte_info.has_comment_ext() {
9290
return None;
9391
}
9492
Some(self.id0.comment_pre_at(self.netnode()))
9593
}
9694

97-
pub fn comment_post(&self) -> Option<impl Iterator<Item = &[u8]>> {
95+
pub fn comment_post(&self) -> Option<impl Iterator<Item = IDBStr<'a>>> {
9896
if !self.byte_info.has_comment_ext() {
9997
return None;
10098
}
10199
Some(self.id0.comment_post_at(self.netnode()))
102100
}
103101

104-
pub fn label(&self) -> Result<Option<Cow<'a, [u8]>>> {
102+
pub fn label(&self) -> Result<Option<IDBString>> {
105103
if !self.byte_info.has_name() {
106104
if !self.byte_info.has_dummy_name() {
107105
return Ok(None);
@@ -121,15 +119,15 @@ impl<'a, K: IDAKind> AddressInfo<'a, K> {
121119
anyhow!("Label is not a valid CStr or ID0 Ref")
122120
})?;
123121
match value {
124-
ID0CStr::CStr(label) => Ok(Some(Cow::Borrowed(label))),
122+
ID0CStr::CStr(label) => Ok(Some(label.to_idb_string())),
125123
ID0CStr::Ref(label_ref) => {
126124
let entries = self.id0.address_info_value(label_ref)?;
127-
let label = entries
125+
let label: Vec<u8> = entries
128126
.iter()
129127
.flat_map(|x| &x.value[..])
130128
.copied()
131129
.collect();
132-
Ok(Some(Cow::Owned(label)))
130+
Ok(Some(IDBString::new(label)))
133131
}
134132
}
135133
}

src/id0.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
use std::collections::HashMap;
22
use std::num::NonZeroU32;
33

4-
use crate::ida_reader::IdbRead;
54
use crate::IDAKind;
5+
use crate::{ida_reader::IdbRead, IDBStr};
66

77
use anyhow::{anyhow, ensure};
88

@@ -110,7 +110,7 @@ pub(crate) fn parse_maybe_cstr(data: &[u8]) -> Option<&[u8]> {
110110
}
111111

112112
pub(crate) enum ID0CStr<'a, K: IDAKind> {
113-
CStr(&'a [u8]),
113+
CStr(IDBStr<'a>),
114114
Ref(K::Usize),
115115
}
116116

@@ -123,7 +123,7 @@ impl<'a, K: IDAKind> ID0CStr<'a, K> {
123123
[b'\x00', rest @ ..] => {
124124
K::usize_try_from_be_bytes(rest).map(ID0CStr::Ref)
125125
}
126-
_ => parse_maybe_cstr(data).map(ID0CStr::CStr),
126+
_ => parse_maybe_cstr(data).map(IDBStr::new).map(ID0CStr::CStr),
127127
}
128128
}
129129
}

src/id0/db.rs

Lines changed: 25 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ use num_traits::{AsPrimitive, CheckedAdd, PrimInt, ToBytes};
88
use crate::addr_info::SubtypeId;
99
use crate::id0::flag::nsup::NSUP_LLABEL;
1010
use crate::ida_reader::{IdbBufRead, IdbReadKind};
11-
use crate::{til, Address};
11+
use crate::{til, Address, IDBStr};
1212
use crate::{IDAVariants, SectionReader, IDA32, IDA64};
1313

1414
use super::entry_iter::{
@@ -503,7 +503,7 @@ impl<K: IDAKind> ID0Section<K> {
503503
// TODO there is also a "P" entry in patches, it seems to only contains
504504
// the value 0x01 for each equivalent "A" entry
505505

506-
pub fn segment_name(&self, idx: SegmentNameIdx<K>) -> Result<&[u8]> {
506+
pub fn segment_name(&self, idx: SegmentNameIdx<K>) -> Result<IDBStr<'_>> {
507507
let seg_idx = self.segment_strings_idx()?;
508508
// TODO I think this is dependent on the version, and not on availability
509509
if let Some(seg_idx) = seg_idx {
@@ -523,7 +523,7 @@ impl<K: IDAKind> ID0Section<K> {
523523
pub(crate) fn name_by_index(
524524
&self,
525525
idx: SegmentNameIdx<K>,
526-
) -> Result<&[u8]> {
526+
) -> Result<IDBStr<'_>> {
527527
// if there is no names, AKA `$ segstrings`, search for the key directly
528528
let name_idx = self
529529
.netnode_tag_idx(
@@ -532,6 +532,7 @@ impl<K: IDAKind> ID0Section<K> {
532532
)
533533
.ok_or_else(|| anyhow!("Not found name for segment {}", idx.0))?;
534534
parse_maybe_cstr(&self.entries[name_idx].value)
535+
.map(IDBStr::new)
535536
.ok_or_else(|| anyhow!("Invalid segment name {}", idx.0))
536537
}
537538

@@ -585,8 +586,8 @@ impl<K: IDAKind> ID0Section<K> {
585586
)
586587
}
587588

588-
pub fn input_file(&self, idx: RootNodeIdx<K>) -> Option<&[u8]> {
589-
self.netnode_value(idx.into())
589+
pub fn input_file(&self, idx: RootNodeIdx<K>) -> Option<IDBStr<'_>> {
590+
self.netnode_value(idx.into()).map(IDBStr::new)
590591
}
591592

592593
// TODO identify the data
@@ -1139,17 +1140,20 @@ impl<K: IDAKind> ID0Section<K> {
11391140
Ok(None)
11401141
}
11411142

1142-
pub(crate) fn comment_at(&self, netnode: NetnodeIdx<K>) -> Option<&[u8]> {
1143+
pub(crate) fn comment_at(
1144+
&self,
1145+
netnode: NetnodeIdx<K>,
1146+
) -> Option<IDBStr<'_>> {
11431147
let comment = self.sup_value(netnode, 0u8.into(), ARRAY_SUP_TAG)?;
1144-
Some(parse_maybe_cstr(comment).unwrap_or(comment))
1148+
Some(IDBStr::new(parse_maybe_cstr(comment).unwrap_or(comment)))
11451149
}
11461150

11471151
pub(crate) fn comment_repeatable_at(
11481152
&self,
11491153
netnode: NetnodeIdx<K>,
1150-
) -> Option<&[u8]> {
1154+
) -> Option<IDBStr<'_>> {
11511155
let comment = self.sup_value(netnode, 1u8.into(), ARRAY_SUP_TAG)?;
1152-
Some(parse_maybe_cstr(comment).unwrap_or(comment))
1156+
Some(IDBStr::new(parse_maybe_cstr(comment).unwrap_or(comment)))
11531157
}
11541158

11551159
// TODO: comments have a strange hole in id0
@@ -1162,7 +1166,7 @@ impl<K: IDAKind> ID0Section<K> {
11621166
pub(crate) fn comment_pre_at(
11631167
&self,
11641168
netnode: NetnodeIdx<K>,
1165-
) -> impl Iterator<Item = &[u8]> {
1169+
) -> impl Iterator<Item = IDBStr<'_>> {
11661170
crate::id0::entry_iter::EntryTagContinuousSubkeys::new(
11671171
self,
11681172
netnode,
@@ -1172,13 +1176,17 @@ impl<K: IDAKind> ID0Section<K> {
11721176
// 1000..2000
11731177
// max number of lines, NOTE this check is not done by IDA
11741178
.take(1000)
1175-
.map(|entry| parse_maybe_cstr(&entry.value).unwrap_or(&entry.value[..]))
1179+
.map(|entry| {
1180+
IDBStr::new(
1181+
parse_maybe_cstr(&entry.value).unwrap_or(&entry.value[..]),
1182+
)
1183+
})
11761184
}
11771185

11781186
pub(crate) fn comment_post_at(
11791187
&self,
11801188
netnode: NetnodeIdx<K>,
1181-
) -> impl Iterator<Item = &[u8]> {
1189+
) -> impl Iterator<Item = IDBStr<'_>> {
11821190
crate::id0::entry_iter::EntryTagContinuousSubkeys::new(
11831191
self,
11841192
netnode,
@@ -1188,7 +1196,11 @@ impl<K: IDAKind> ID0Section<K> {
11881196
// 2000..3000
11891197
// max number of lines, NOTE this check is not done by IDA
11901198
.take(1000)
1191-
.map(|entry| parse_maybe_cstr(&entry.value).unwrap_or(&entry.value[..]))
1199+
.map(|entry| {
1200+
IDBStr::new(
1201+
parse_maybe_cstr(&entry.value).unwrap_or(&entry.value[..]),
1202+
)
1203+
})
11921204
}
11931205

11941206
pub fn struct_at(&self, idx: SubtypeId<K>) -> Result<&[u8]> {

src/id0/dirtree.rs

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,11 +2,12 @@ use std::collections::HashMap;
22

33
use anyhow::{anyhow, ensure, Result};
44
use num_traits::WrappingAdd;
5+
use serde::Serialize;
56

67
use crate::ida_reader::{IdbBufRead, IdbReadKind};
78
use crate::{IDAKind, IDAUsize};
89

9-
#[derive(Clone, Debug)]
10+
#[derive(Clone, Debug, Serialize)]
1011
pub struct DirTreeRoot<T> {
1112
pub entries: Vec<DirTreeEntry<T>>,
1213
}
@@ -31,7 +32,7 @@ impl<T> DirTreeRoot<T> {
3132
}
3233
}
3334

34-
#[derive(Clone, Debug)]
35+
#[derive(Clone, Debug, Serialize)]
3536
pub enum DirTreeEntry<T> {
3637
Leaf(T),
3738
Directory {

src/id0/file_region.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,13 @@
11
use anyhow::{anyhow, Result};
22
use num_traits::CheckedAdd;
3+
use serde::Serialize;
34

45
use crate::ida_reader::IdbReadKind;
56
use crate::IDAKind;
67

78
use super::{entry_iter::NetnodeSupRangeIter, NetnodeIdx};
89

9-
#[derive(Clone, Debug)]
10+
#[derive(Clone, Debug, Serialize)]
1011
pub struct FileRegions<K: IDAKind> {
1112
pub start: K::Usize,
1213
pub end: K::Usize,

src/id0/function.rs

Lines changed: 19 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -2,31 +2,32 @@ use std::ops::Range;
22

33
use crate::id0::parse_maybe_cstr;
44
use crate::ida_reader::{IdbBufRead, IdbRead, IdbReadKind};
5-
use crate::{flags_to_struct, til, Address, IDAKind};
5+
use crate::{flags_to_struct, til, Address, IDAKind, IDBStr};
66

77
use super::flag::func::*;
88
use super::flag::netnode::nn_res::ARRAY_SUP_TAG;
99
use super::{flag, ID0Section, NetnodeIdx};
1010

1111
use anyhow::{anyhow, ensure, Result};
1212
use num_traits::WrappingSub;
13+
use serde::Serialize;
1314

14-
#[derive(Clone, Debug)]
15+
#[derive(Clone, Debug, Serialize)]
1516
pub enum Comments<'a> {
16-
Comment(&'a [u8]),
17-
RepeatableComment(&'a [u8]),
18-
PreComment(&'a [u8]),
19-
PostComment(&'a [u8]),
17+
Comment(IDBStr<'a>),
18+
RepeatableComment(IDBStr<'a>),
19+
PreComment(IDBStr<'a>),
20+
PostComment(IDBStr<'a>),
2021
}
2122

2223
impl<'a> Comments<'a> {
2324
/// The message on the comment, NOTE that IDA don't have a default character encoding
24-
pub fn message(&self) -> &'a [u8] {
25+
pub fn message(&self) -> IDBStr<'a> {
2526
match self {
2627
Comments::Comment(x)
2728
| Comments::RepeatableComment(x)
2829
| Comments::PreComment(x)
29-
| Comments::PostComment(x) => x,
30+
| Comments::PostComment(x) => *x,
3031
}
3132
}
3233
}
@@ -63,28 +64,28 @@ pub(crate) fn fchunks<K: IDAKind>(
6364
.map(move |value| IDBFunction::read(&value.value[..]))
6465
}
6566

66-
#[derive(Clone, Debug)]
67+
#[derive(Clone, Debug, Serialize)]
6768
pub struct IDBFunction<K: IDAKind> {
6869
pub address: Range<Address<K>>,
6970
pub flags: IDBFunctionFlag,
7071
pub extra: IDBFunctionType<K>,
7172
}
7273

73-
#[derive(Clone, Debug)]
74+
#[derive(Clone, Debug, Serialize)]
7475
pub enum IDBFunctionType<K: IDAKind> {
7576
Tail(IDBFunctionTail<K>),
7677
NonTail(IDBFunctionNonTail<K>),
7778
}
7879

79-
#[derive(Clone, Debug)]
80+
#[derive(Clone, Debug, Serialize)]
8081
pub struct IDBFunctionTail<K: IDAKind> {
8182
/// function owner of the function start
8283
pub owner: K::Usize,
8384
pub _unknown4: u16,
8485
pub _unknown5: Option<u32>,
8586
}
8687

87-
#[derive(Clone, Debug)]
88+
#[derive(Clone, Debug, Serialize)]
8889
pub struct IDBFunctionNonTail<K: IDAKind> {
8990
pub frame: K::Usize,
9091
/// Local variables area
@@ -102,7 +103,7 @@ pub struct IDBFunctionNonTail<K: IDAKind> {
102103
pub fpd: K::Usize,
103104
}
104105

105-
#[derive(Clone, Debug)]
106+
#[derive(Clone, Debug, Serialize)]
106107
pub enum FunctionsAndComments<'a, K: IDAKind> {
107108
// It's just the name "$ funcs"
108109
Name,
@@ -140,7 +141,7 @@ impl<'a, K: IDAKind> FunctionsAndComments<'a, K> {
140141
parse_maybe_cstr(value)
141142
.map(|value| Self::Comment {
142143
address,
143-
comment: Comments::Comment(value),
144+
comment: Comments::Comment(IDBStr::new(value)),
144145
})
145146
.ok_or_else(|| anyhow!("Invalid Comment string"))
146147
}
@@ -152,7 +153,9 @@ impl<'a, K: IDAKind> FunctionsAndComments<'a, K> {
152153
parse_maybe_cstr(value)
153154
.map(|value| Self::Comment {
154155
address,
155-
comment: Comments::RepeatableComment(value),
156+
comment: Comments::RepeatableComment(IDBStr::new(
157+
value,
158+
)),
156159
})
157160
.ok_or_else(|| anyhow!("Invalid Repetable Comment string"))
158161
}
@@ -350,7 +353,7 @@ impl<'a, K: IDAKind> EntryPointRaw<'a, K> {
350353
}
351354
}
352355

353-
#[derive(Clone, Debug)]
356+
#[derive(Clone, Debug, Serialize)]
354357
pub struct EntryPoint<K: IDAKind> {
355358
pub name: String,
356359
pub address: K::Usize,

0 commit comments

Comments
 (0)