Skip to content

Commit 0c012db

Browse files
committed
add func_cmt to tests
1 parent 14ca426 commit 0c012db

File tree

111 files changed

+84094
-94
lines changed

Some content is hidden

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

111 files changed

+84094
-94
lines changed

resources/idc-diff/gen-idb-rs.sh

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,5 +6,5 @@ sh -c "find ../idbs/ -name '*.i64'; find ../idbs/ -name '*.idb'" | while read li
66
do
77
file=$(echo $line | cut -d '/' -f 3-)
88
mkdir -p "idb-rs/$(dirname ${file})"
9-
cargo run --all-features --manifest-path ${HOME}/src/idb-rs/Cargo.toml --release --bin idb-tools -- --input ${line} produce-idc > "idb-rs/${file}.idc" "$@"
9+
cargo run --all-features --manifest-path ${HOME}/src/idb-rs/Cargo.toml --release --bin idb-tools -- --input ${line} produce-idc "$@" > "idb-rs/${file}.idc"
1010
done

src/addr_info.rs

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -157,8 +157,7 @@ impl<'a, K: IDAKind> AddressInfo<'a, K> {
157157
// usually this string ends with \x00, but maybe there is no garanty for that.
158158
// TODO what if there is more fields that can fit a id0 entry
159159
let field_names = if let Some(fields_entry) = iter.next() {
160-
let value = parse_maybe_cstr(&fields_entry.value)
161-
.ok_or_else(|| anyhow!("Incomplete Fields for TIL Type"))?;
160+
let value = parse_maybe_cstr(&fields_entry.value);
162161
crate::ida_reader::split_strings_from_array(value)
163162
.ok_or_else(|| anyhow!("Invalid Fields for TIL Type"))?
164163
} else {

src/id0.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -102,11 +102,11 @@ pub(crate) fn key_from_netnode_tag_hash<K: IDAKind>(
102102
}
103103

104104
// parse a string that maybe is finalized with \x00
105-
pub(crate) fn parse_maybe_cstr(data: &[u8]) -> Option<&[u8]> {
105+
pub(crate) fn parse_maybe_cstr(data: &[u8]) -> &[u8] {
106106
// find the end of the string
107107
let end_pos = data.iter().position(|b| *b == 0).unwrap_or(data.len());
108108
// Return the slice up to the first null byte
109-
Some(&data[..end_pos])
109+
&data[..end_pos]
110110
}
111111

112112
pub(crate) enum ID0CStr<'a, K: IDAKind> {
@@ -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(IDBStr::new).map(ID0CStr::CStr),
126+
_ => Some(ID0CStr::CStr(IDBStr::new(parse_maybe_cstr(data)))),
127127
}
128128
}
129129
}

src/id0/btree.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -57,7 +57,7 @@ impl ID0Header {
5757
// mixing the offset 13 with 0x13.
5858
let version = match magic {
5959
IDBMagic::IDA0 => {
60-
let version = ID0Version::read(&mut &buf[0xd..0x27])
60+
let version = ID0Version::read(&buf[0xd..0x27])
6161
.ok_or_else(|| anyhow!("Unknown B-tree version"))?;
6262
if version != ID0Version::V15 {
6363
return Err(anyhow!(
@@ -67,7 +67,7 @@ impl ID0Header {
6767
version
6868
}
6969
IDBMagic::IDA1 | IDBMagic::IDA2 => {
70-
let version = ID0Version::read(&mut &buf[0x13..0x2d])
70+
let version = ID0Version::read(&buf[0x13..0x2d])
7171
.ok_or_else(|| anyhow!("Unknown B-tree version"))?;
7272
if version == ID0Version::V15 {
7373
return Err(anyhow!(

src/id0/db.rs

Lines changed: 35 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ use std::borrow::Cow;
22
use std::ffi::CStr;
33
use std::ops::Range;
44

5-
use anyhow::Result;
5+
use anyhow::{Context, Result};
66
use num_traits::{AsPrimitive, CheckedAdd, PrimInt, ToBytes};
77

88
use crate::addr_info::SubtypeId;
@@ -369,7 +369,7 @@ impl<K: IDAKind> ID0Section<K> {
369369
alt: K::Usize,
370370
tag: u8,
371371
) -> Result<Option<NetnodeIdx<K>>> {
372-
self.netnode_tag_alt_idx(idx, alt.into(), tag)
372+
self.netnode_tag_alt_idx(idx, alt, tag)
373373
.map(|idx| {
374374
K::usize_try_from_le_bytes(&self.entries[idx].value[..])
375375
.map(NetnodeIdx::from_raw)
@@ -532,25 +532,22 @@ impl<K: IDAKind> ID0Section<K> {
532532
Ok(None)
533533
} else {
534534
// if there is no names, AKA `$ segstrings`, search for the key directly
535-
self.name_by_index(idx)
535+
Ok(self.name_by_index(idx))
536536
}
537537
}
538538

539539
pub(crate) fn name_by_index(
540540
&self,
541541
idx: SegmentNameIdx<K>,
542-
) -> Result<Option<IDBStr<'_>>> {
542+
) -> Option<IDBStr<'_>> {
543543
// if there is no names, AKA `$ segstrings`, search for the key directly
544-
let Some(name_idx) = self.netnode_tag_idx(
544+
self.netnode_tag_idx(
545545
NetnodeIdx(K::Usize::from(0xFFu8).swap_bytes() | idx.0),
546546
NAME_TAG,
547-
) else {
548-
return Ok(None);
549-
};
550-
parse_maybe_cstr(&self.entries[name_idx].value)
551-
.map(IDBStr::new)
552-
.map(Option::Some)
553-
.ok_or_else(|| anyhow!("Invalid segment name {}", idx.0))
547+
)
548+
.map(|name_idx| {
549+
IDBStr::new(parse_maybe_cstr(&self.entries[name_idx].value))
550+
})
554551
}
555552

556553
/// read the `$ loader name` entries of the database
@@ -1017,31 +1014,40 @@ impl<K: IDAKind> ID0Section<K> {
10171014
let Some(cmt) = self.sup_value(idx.into(), addr.into_raw(), tag) else {
10181015
return Ok(None);
10191016
};
1020-
// NOTE this is a u32
1017+
1018+
// NOTE the value is stored as 8 bytes in the 64bits version, but it
1019+
// only checks the first 4 bytes
10211020
if !cmt.starts_with(&0x01020304u32.to_le_bytes()) {
1022-
return Ok(Some(IDBString(cmt.to_vec())));
1021+
return Ok(Some(IDBString(parse_maybe_cstr(cmt).to_vec())));
10231022
}
10241023

10251024
let netnode = netdelta.ea2node(addr);
1026-
let Some(cmt) = self.sup_value(idx.into(), netnode.into_raw(), tag)
1025+
let Some(cmt2) = self.sup_value(idx.into(), netnode.into_raw(), tag)
10271026
else {
10281027
return Ok(None);
10291028
};
1030-
// TODO is this u64 or usize?
1031-
// NOTE this is a u64
1029+
// NOTE this is a usize and not u32, the full value is actually 8 bytes
1030+
let mut cursor = cmt2;
1031+
let header = IdbReadKind::<K>::read_usize(&mut cursor)
1032+
.context("Missing function cmt 4321 header")?;
10321033
ensure!(
1033-
cmt.starts_with(&0x01020304u64.to_le_bytes()),
1034+
header == K::Usize::from(0x01020304u32),
10341035
"Invalid cmt type 4321"
10351036
);
1036-
let Some(num) = cmt.get(8..16).and_then(K::usize_try_from_le_bytes)
1037-
else {
1038-
return Err(anyhow!("Invalid cmt type 4321 value"));
1039-
};
1040-
1037+
let idx = IdbReadKind::<K>::read_usize(&mut cursor)
1038+
.context("Missing function cmt 4321 netnode_idx")?;
10411039
// TODO ignore if it is repeatable not not?
10421040
Ok(Some(IDBString(
1043-
self.blob(NetnodeIdx::from_raw(num), 0u8.into(), b'S')
1044-
.collect(),
1041+
crate::id0::entry_iter::EntryTagContinuousSubkeys::new(
1042+
self,
1043+
NetnodeIdx::from_raw(idx),
1044+
ARRAY_SUP_TAG,
1045+
0u8.into(),
1046+
)
1047+
.flat_map(|entry| {
1048+
parse_maybe_cstr(&entry.value).iter().chain(b"\n").copied()
1049+
})
1050+
.collect(),
10451051
)))
10461052
}
10471053

@@ -1202,15 +1208,15 @@ impl<K: IDAKind> ID0Section<K> {
12021208
netnode: NetnodeIdx<K>,
12031209
) -> Option<IDBStr<'_>> {
12041210
let comment = self.sup_value(netnode, 0u8.into(), ARRAY_SUP_TAG)?;
1205-
Some(IDBStr::new(parse_maybe_cstr(comment).unwrap_or(comment)))
1211+
Some(IDBStr::new(parse_maybe_cstr(comment)))
12061212
}
12071213

12081214
pub(crate) fn comment_repeatable_at(
12091215
&self,
12101216
netnode: NetnodeIdx<K>,
12111217
) -> Option<IDBStr<'_>> {
12121218
let comment = self.sup_value(netnode, 1u8.into(), ARRAY_SUP_TAG)?;
1213-
Some(IDBStr::new(parse_maybe_cstr(comment).unwrap_or(comment)))
1219+
Some(IDBStr::new(parse_maybe_cstr(comment)))
12141220
}
12151221

12161222
// TODO: comments have a strange hole in id0
@@ -1233,11 +1239,7 @@ impl<K: IDAKind> ID0Section<K> {
12331239
// 1000..2000
12341240
// max number of lines, NOTE this check is not done by IDA
12351241
.take(1000)
1236-
.map(|entry| {
1237-
IDBStr::new(
1238-
parse_maybe_cstr(&entry.value).unwrap_or(&entry.value[..]),
1239-
)
1240-
})
1242+
.map(|entry| IDBStr::new(parse_maybe_cstr(&entry.value)))
12411243
}
12421244

12431245
pub(crate) fn comment_post_at(
@@ -1253,11 +1255,7 @@ impl<K: IDAKind> ID0Section<K> {
12531255
// 2000..3000
12541256
// max number of lines, NOTE this check is not done by IDA
12551257
.take(1000)
1256-
.map(|entry| {
1257-
IDBStr::new(
1258-
parse_maybe_cstr(&entry.value).unwrap_or(&entry.value[..]),
1259-
)
1260-
})
1258+
.map(|entry| IDBStr::new(parse_maybe_cstr(&entry.value)))
12611259
}
12621260

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

src/id0/entry_iter.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -109,7 +109,7 @@ impl<'a, K: IDAKind> Iterator for EntryTagContinuousFlat<'a, K> {
109109
// NOTE the recursive is called to force check if the entry have values
110110
// although having an empty entry is nonsensical, it's valid on a DB
111111
// level
112-
return self.next();
112+
self.next()
113113
}
114114
}
115115

src/id0/function.rs

Lines changed: 11 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -248,7 +248,7 @@ impl<'a, K: IDAKind> EntryPointRaw<'a, K> {
248248
return Err(anyhow!("invalid Funcs subkey"));
249249
};
250250
if *key_type == b'N' {
251-
ensure!(parse_maybe_cstr(value) == Some(&b"$ entry points"[..]));
251+
ensure!(parse_maybe_cstr(value) == &b"$ entry points"[..]);
252252
return Ok(Self::Name);
253253
}
254254
let Some(sub_key) = K::usize_try_from_be_bytes(sub_key) else {
@@ -270,22 +270,16 @@ impl<'a, K: IDAKind> EntryPointRaw<'a, K> {
270270
ordinal,
271271
})
272272
.map_err(|_| anyhow!("Invalid Ordinal value")),
273-
b'F' => parse_maybe_cstr(value)
274-
.and_then(|symbol| {
275-
Some(Self::ForwardedSymbol {
276-
key: sub_key,
277-
symbol: std::str::from_utf8(symbol).ok()?,
278-
})
279-
})
280-
.ok_or_else(|| anyhow!("Invalid Forwarded symbol name")),
281-
flag::netnode::nn_res::ARRAY_SUP_TAG => parse_maybe_cstr(value)
282-
.and_then(|name| {
283-
Some(Self::FunctionName {
284-
key: sub_key,
285-
name: std::str::from_utf8(name).ok()?,
286-
})
287-
})
288-
.ok_or_else(|| anyhow!("Invalid Function name")),
273+
b'F' => Ok(Self::ForwardedSymbol {
274+
key: sub_key,
275+
symbol: std::str::from_utf8(parse_maybe_cstr(value))
276+
.map_err(|_| anyhow!("Invalid Forwarded symbol name"))?,
277+
}),
278+
flag::netnode::nn_res::ARRAY_SUP_TAG => Ok(Self::FunctionName {
279+
key: sub_key,
280+
name: std::str::from_utf8(parse_maybe_cstr(value))
281+
.map_err(|_| anyhow!("Invalid Function name"))?,
282+
}),
289283
// TODO find the meaning of "$ funcs" b'V' entry
290284
_ => Ok(Self::Unknown { key, value }),
291285
}

src/id0/root_info.rs

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -281,8 +281,7 @@ impl<K: IDAKind> RootInfo<K> {
281281
let mut processor = [0; 8];
282282
input.read_exact(&mut processor)?;
283283
// remove any \x00 that marks the end of the str
284-
let cpu_str_part = parse_maybe_cstr(&processor[..])
285-
.ok_or_else(|| anyhow!("Invalid RootInfo CStr cpu name"))?;
284+
let cpu_str_part = parse_maybe_cstr(&processor[..]);
286285
let processor = processor[0..cpu_str_part.len()].to_vec();
287286

288287
let genflags = Inffl::new(input.read_u16()?)?;
@@ -476,8 +475,7 @@ impl<K: IDAKind> RootInfo<K> {
476475
let mut processor = vec![0; cpu_len];
477476
input.read_exact(&mut processor)?;
478477
// remove any \x00 that marks the end of the str
479-
let cpu_str_part = parse_maybe_cstr(&processor[..])
480-
.ok_or_else(|| anyhow!("Invalid RootInfo CStr cpu name"))?;
478+
let cpu_str_part = parse_maybe_cstr(&processor[..]);
481479
processor.truncate(cpu_str_part.len());
482480

483481
// NOTE in this version parse_* functions are used

src/id0/root_info/migration.rs

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -44,14 +44,12 @@ impl<K: IDAKind> RootInfo<K> {
4444

4545
let mut processor = data.cpu_name.to_vec();
4646
// remove any \x00 that marks the end of the str
47-
let cpu_str_part = parse_maybe_cstr(&processor[..])
48-
.ok_or_else(|| anyhow!("Invalid RootInfo CStr cpu name"))?;
47+
let cpu_str_part = parse_maybe_cstr(&processor[..]);
4948
processor.truncate(cpu_str_part.len());
5049

5150
let mut strlit_name_prefix = data.strlit_name_prefix.to_vec();
5251
// remove any \x00 that marks the end of the str
53-
let strlit_name_prefix_part = parse_maybe_cstr(&processor[..])
54-
.ok_or_else(|| anyhow!("Invalid RootInfo CStr cpu name"))?;
52+
let strlit_name_prefix_part = parse_maybe_cstr(&processor[..]);
5553
strlit_name_prefix.truncate(strlit_name_prefix_part.len());
5654

5755
let is_cc_guessed = data.cc_id_raw & 0x80 != 0;

src/lib.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1157,7 +1157,7 @@ where
11571157
read_section::<F, _, _>(
11581158
input,
11591159
section_header.compress,
1160-
section_header.len.into(),
1160+
section_header.len,
11611161
magic,
11621162
)
11631163
}

0 commit comments

Comments
 (0)