Skip to content

Commit 345d60f

Browse files
authored
read/aranges: handle address range overflow (gimli-rs#732)
1 parent 450cb69 commit 345d60f

File tree

2 files changed

+45
-13
lines changed

2 files changed

+45
-13
lines changed

src/read/aranges.rs

Lines changed: 44 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -289,7 +289,7 @@ impl<R: Reader> fallible_iterator::FallibleIterator for ArangeEntryIter<R> {
289289
#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord)]
290290
pub struct ArangeEntry {
291291
segment: Option<u64>,
292-
address: u64,
292+
range: Range,
293293
length: u64,
294294
}
295295

@@ -313,10 +313,13 @@ impl ArangeEntry {
313313
} else {
314314
0
315315
};
316-
let address = input.read_address(address_size)?;
316+
let begin = input.read_address(address_size)?;
317317
let length = input.read_address(address_size)?;
318+
// Calculate end now so that we can handle overflow.
319+
// TODO: handle 32-bit address overflow as well.
320+
let end = begin.checked_add(length).ok_or(Error::AddressOverflow)?;
318321

319-
match (segment, address, length) {
322+
match (segment, begin, length) {
320323
// This is meant to be a null terminator, but in practice it can occur
321324
// before the end, possibly due to a linker omitting a function and
322325
// leaving an unrelocated entry.
@@ -327,7 +330,7 @@ impl ArangeEntry {
327330
} else {
328331
None
329332
},
330-
address,
333+
range: Range { begin, end },
331334
length,
332335
})),
333336
}
@@ -342,7 +345,7 @@ impl ArangeEntry {
342345
/// Return the beginning address of this arange.
343346
#[inline]
344347
pub fn address(&self) -> u64 {
345-
self.address
348+
self.range.begin
346349
}
347350

348351
/// Return the length of this arange.
@@ -354,10 +357,7 @@ impl ArangeEntry {
354357
/// Return the range.
355358
#[inline]
356359
pub fn range(&self) -> Range {
357-
Range {
358-
begin: self.address,
359-
end: self.address.wrapping_add(self.length),
360-
}
360+
self.range
361361
}
362362
}
363363

@@ -576,7 +576,10 @@ mod tests {
576576
entry,
577577
Some(ArangeEntry {
578578
segment: None,
579-
address: 0x0403_0201,
579+
range: Range {
580+
begin: 0x0403_0201,
581+
end: 0x0403_0201 + 0x0807_0605,
582+
},
580583
length: 0x0807_0605,
581584
})
582585
);
@@ -609,7 +612,10 @@ mod tests {
609612
entry,
610613
Some(ArangeEntry {
611614
segment: Some(0x1817_1615_1413_1211),
612-
address: 0x0403_0201,
615+
range: Range {
616+
begin: 0x0403_0201,
617+
end: 0x0403_0201 + 0x0807_0605,
618+
},
613619
length: 0x0807_0605,
614620
})
615621
);
@@ -642,9 +648,35 @@ mod tests {
642648
entry,
643649
Some(ArangeEntry {
644650
segment: None,
645-
address: 0x0403_0201,
651+
range: Range {
652+
begin: 0x0403_0201,
653+
end: 0x0403_0201 + 0x0807_0605,
654+
},
646655
length: 0x0807_0605,
647656
})
648657
);
649658
}
659+
660+
#[test]
661+
fn test_parse_entry_overflow() {
662+
let encoding = Encoding {
663+
format: Format::Dwarf32,
664+
version: 2,
665+
address_size: 8,
666+
};
667+
let segment_size = 0;
668+
#[rustfmt::skip]
669+
let buf = [
670+
// Address.
671+
0x01, 0x02, 0x03, 0x04, 0x00, 0x00, 0x00, 0x80,
672+
// Length.
673+
0x05, 0x06, 0x07, 0x08, 0x00, 0x00, 0x00, 0x80,
674+
// Next tuple.
675+
0x09
676+
];
677+
let rest = &mut EndianSlice::new(&buf, LittleEndian);
678+
let entry = ArangeEntry::parse(rest, encoding, segment_size);
679+
assert_eq!(*rest, EndianSlice::new(&buf[buf.len() - 1..], LittleEndian));
680+
assert_eq!(entry, Err(Error::AddressOverflow));
681+
}
650682
}

src/read/rnglists.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -624,7 +624,7 @@ impl RawRange {
624624
}
625625

626626
/// An address range from the `.debug_ranges`, `.debug_rnglists`, or `.debug_aranges` sections.
627-
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
627+
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
628628
pub struct Range {
629629
/// The beginning address of the range.
630630
pub begin: u64,

0 commit comments

Comments
 (0)