Skip to content

Commit 450cb69

Browse files
authored
read/line: check for overflow when advancing the address (gimli-rs#731)
Addresses in line sequences should only increase. The `addr2line` crate relies on this for its binary search.
1 parent 9257192 commit 450cb69

File tree

2 files changed

+99
-43
lines changed

2 files changed

+99
-43
lines changed

src/read/line.rs

Lines changed: 96 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -240,7 +240,7 @@ where
240240
Err(err) => return Err(err),
241241
Ok(None) => return Ok(None),
242242
Ok(Some(instruction)) => {
243-
if self.row.execute(instruction, &mut self.program) {
243+
if self.row.execute(instruction, &mut self.program)? {
244244
if self.row.tombstone {
245245
// Perform any reset that was required for the tombstone row.
246246
// Normally this is done when `next_row` is called again, but for
@@ -631,7 +631,7 @@ pub type LineNumberRow = LineRow;
631631
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
632632
pub struct LineRow {
633633
tombstone: bool,
634-
address: Wrapping<u64>,
634+
address: u64,
635635
op_index: Wrapping<u64>,
636636
file: u64,
637637
line: Wrapping<u64>,
@@ -652,7 +652,7 @@ impl LineRow {
652652
// "At the beginning of each sequence within a line number program, the
653653
// state of the registers is:" -- Section 6.2.2
654654
tombstone: false,
655-
address: Wrapping(0),
655+
address: 0,
656656
op_index: Wrapping(0),
657657
file: 1,
658658
line: Wrapping(1),
@@ -676,7 +676,7 @@ impl LineRow {
676676
/// generated by the compiler."
677677
#[inline]
678678
pub fn address(&self) -> u64 {
679-
self.address.0
679+
self.address
680680
}
681681

682682
/// > An unsigned integer representing the index of an operation within a VLIW
@@ -800,21 +800,21 @@ impl LineRow {
800800
&mut self,
801801
instruction: LineInstruction<R>,
802802
program: &mut Program,
803-
) -> bool
803+
) -> Result<bool>
804804
where
805805
Program: LineProgram<R>,
806806
R: Reader,
807807
{
808-
match instruction {
808+
Ok(match instruction {
809809
LineInstruction::Special(opcode) => {
810-
self.exec_special_opcode(opcode, program.header());
810+
self.exec_special_opcode(opcode, program.header())?;
811811
true
812812
}
813813

814814
LineInstruction::Copy => true,
815815

816816
LineInstruction::AdvancePc(operation_advance) => {
817-
self.apply_operation_advance(operation_advance, program.header());
817+
self.apply_operation_advance(operation_advance, program.header())?;
818818
false
819819
}
820820

@@ -846,13 +846,18 @@ impl LineRow {
846846
LineInstruction::ConstAddPc => {
847847
let adjusted = self.adjust_opcode(255, program.header());
848848
let operation_advance = adjusted / program.header().line_encoding.line_range;
849-
self.apply_operation_advance(u64::from(operation_advance), program.header());
849+
self.apply_operation_advance(u64::from(operation_advance), program.header())?;
850850
false
851851
}
852852

853853
LineInstruction::FixedAddPc(operand) => {
854-
self.address += Wrapping(u64::from(operand));
855-
self.op_index.0 = 0;
854+
if !self.tombstone {
855+
self.address = self
856+
.address
857+
.checked_add(u64::from(operand))
858+
.ok_or(Error::AddressOverflow)?;
859+
self.op_index.0 = 0;
860+
}
856861
false
857862
}
858863

@@ -879,8 +884,13 @@ impl LineRow {
879884
LineInstruction::SetAddress(address) => {
880885
let tombstone_address = !0 >> (64 - program.header().encoding.address_size * 8);
881886
self.tombstone = address == tombstone_address;
882-
self.address.0 = address;
883-
self.op_index.0 = 0;
887+
if !self.tombstone {
888+
if address < self.address {
889+
return Err(Error::InvalidAddressRange);
890+
}
891+
self.address = address;
892+
self.op_index.0 = 0;
893+
}
884894
false
885895
}
886896

@@ -899,7 +909,7 @@ impl LineRow {
899909
| LineInstruction::UnknownStandard1(_, _)
900910
| LineInstruction::UnknownStandardN(_, _)
901911
| LineInstruction::UnknownExtended(_, _) => false,
902-
}
912+
})
903913
}
904914

905915
/// Perform any reset that was required after copying the previous row.
@@ -940,7 +950,11 @@ impl LineRow {
940950
&mut self,
941951
operation_advance: u64,
942952
header: &LineProgramHeader<R>,
943-
) {
953+
) -> Result<()> {
954+
if self.tombstone {
955+
return Ok(());
956+
}
957+
944958
let operation_advance = Wrapping(operation_advance);
945959

946960
let minimum_instruction_length = u64::from(header.line_encoding.minimum_instruction_length);
@@ -950,15 +964,20 @@ impl LineRow {
950964
u64::from(header.line_encoding.maximum_operations_per_instruction);
951965
let maximum_operations_per_instruction = Wrapping(maximum_operations_per_instruction);
952966

953-
if maximum_operations_per_instruction.0 == 1 {
954-
self.address += minimum_instruction_length * operation_advance;
967+
let address_advance = if maximum_operations_per_instruction.0 == 1 {
955968
self.op_index.0 = 0;
969+
minimum_instruction_length * operation_advance
956970
} else {
957971
let op_index_with_advance = self.op_index + operation_advance;
958-
self.address += minimum_instruction_length
959-
* (op_index_with_advance / maximum_operations_per_instruction);
960972
self.op_index = op_index_with_advance % maximum_operations_per_instruction;
961-
}
973+
minimum_instruction_length
974+
* (op_index_with_advance / maximum_operations_per_instruction)
975+
};
976+
self.address = self
977+
.address
978+
.checked_add(address_advance.0)
979+
.ok_or(Error::AddressOverflow)?;
980+
Ok(())
962981
}
963982

964983
#[inline]
@@ -967,7 +986,11 @@ impl LineRow {
967986
}
968987

969988
/// Section 6.2.5.1
970-
fn exec_special_opcode<R: Reader>(&mut self, opcode: u8, header: &LineProgramHeader<R>) {
989+
fn exec_special_opcode<R: Reader>(
990+
&mut self,
991+
opcode: u8,
992+
header: &LineProgramHeader<R>,
993+
) -> Result<()> {
971994
let adjusted_opcode = self.adjust_opcode(opcode, header);
972995

973996
let line_range = header.line_encoding.line_range;
@@ -979,7 +1002,8 @@ impl LineRow {
9791002
self.apply_line_advance(line_base + i64::from(line_advance));
9801003

9811004
// Step 2
982-
self.apply_operation_advance(u64::from(operation_advance), header);
1005+
self.apply_operation_advance(u64::from(operation_advance), header)?;
1006+
Ok(())
9831007
}
9841008
}
9851009

@@ -2480,7 +2504,7 @@ mod tests {
24802504
let mut program = IncompleteLineProgram { header };
24812505
let is_new_row = registers.execute(opcode, &mut program);
24822506

2483-
assert_eq!(is_new_row, expect_new_row);
2507+
assert_eq!(is_new_row, Ok(expect_new_row));
24842508
assert_eq!(registers, expected_registers);
24852509
}
24862510

@@ -2533,7 +2557,7 @@ mod tests {
25332557
let opcode = LineInstruction::Special(52);
25342558

25352559
let mut expected_registers = initial_registers;
2536-
expected_registers.address.0 += 3;
2560+
expected_registers.address += 3;
25372561

25382562
assert_exec_opcode(header, initial_registers, opcode, expected_registers, true);
25392563
}
@@ -2547,7 +2571,7 @@ mod tests {
25472571
let opcode = LineInstruction::Special(55);
25482572

25492573
let mut expected_registers = initial_registers;
2550-
expected_registers.address.0 += 3;
2574+
expected_registers.address += 3;
25512575
expected_registers.line.0 += 3;
25522576

25532577
assert_exec_opcode(header, initial_registers, opcode, expected_registers, true);
@@ -2563,7 +2587,7 @@ mod tests {
25632587
let opcode = LineInstruction::Special(49);
25642588

25652589
let mut expected_registers = initial_registers;
2566-
expected_registers.address.0 += 3;
2590+
expected_registers.address += 3;
25672591
expected_registers.line.0 -= 3;
25682592

25692593
assert_exec_opcode(header, initial_registers, opcode, expected_registers, true);
@@ -2592,7 +2616,7 @@ mod tests {
25922616
let header = make_test_header(EndianSlice::new(&[], LittleEndian));
25932617

25942618
let mut initial_registers = LineRow::new(&header);
2595-
initial_registers.address.0 = 1337;
2619+
initial_registers.address = 1337;
25962620
initial_registers.line.0 = 42;
25972621

25982622
let opcode = LineInstruction::Copy;
@@ -2609,23 +2633,20 @@ mod tests {
26092633
let opcode = LineInstruction::AdvancePc(42);
26102634

26112635
let mut expected_registers = initial_registers;
2612-
expected_registers.address.0 += 42;
2636+
expected_registers.address += 42;
26132637

26142638
assert_exec_opcode(header, initial_registers, opcode, expected_registers, false);
26152639
}
26162640

26172641
#[test]
26182642
fn test_exec_advance_pc_overflow() {
26192643
let header = make_test_header(EndianSlice::new(&[], LittleEndian));
2644+
let mut registers = LineRow::new(&header);
2645+
registers.address = u64::MAX;
26202646
let opcode = LineInstruction::AdvancePc(42);
2621-
2622-
let mut initial_registers = LineRow::new(&header);
2623-
initial_registers.address.0 = u64::MAX;
2624-
2625-
let mut expected_registers = initial_registers;
2626-
expected_registers.address.0 = 41;
2627-
2628-
assert_exec_opcode(header, initial_registers, opcode, expected_registers, false);
2647+
let mut program = IncompleteLineProgram { header };
2648+
let result = registers.execute(opcode, &mut program);
2649+
assert_eq!(result, Err(Error::AddressOverflow));
26292650
}
26302651

26312652
#[test]
@@ -2758,11 +2779,22 @@ mod tests {
27582779
let opcode = LineInstruction::ConstAddPc;
27592780

27602781
let mut expected_registers = initial_registers;
2761-
expected_registers.address.0 += 20;
2782+
expected_registers.address += 20;
27622783

27632784
assert_exec_opcode(header, initial_registers, opcode, expected_registers, false);
27642785
}
27652786

2787+
#[test]
2788+
fn test_exec_const_add_pc_overflow() {
2789+
let header = make_test_header(EndianSlice::new(&[], LittleEndian));
2790+
let mut registers = LineRow::new(&header);
2791+
registers.address = u64::MAX;
2792+
let opcode = LineInstruction::ConstAddPc;
2793+
let mut program = IncompleteLineProgram { header };
2794+
let result = registers.execute(opcode, &mut program);
2795+
assert_eq!(result, Err(Error::AddressOverflow));
2796+
}
2797+
27662798
#[test]
27672799
fn test_exec_fixed_add_pc() {
27682800
let header = make_test_header(EndianSlice::new(&[], LittleEndian));
@@ -2773,12 +2805,24 @@ mod tests {
27732805
let opcode = LineInstruction::FixedAddPc(10);
27742806

27752807
let mut expected_registers = initial_registers;
2776-
expected_registers.address.0 += 10;
2808+
expected_registers.address += 10;
27772809
expected_registers.op_index.0 = 0;
27782810

27792811
assert_exec_opcode(header, initial_registers, opcode, expected_registers, false);
27802812
}
27812813

2814+
#[test]
2815+
fn test_exec_fixed_add_pc_overflow() {
2816+
let header = make_test_header(EndianSlice::new(&[], LittleEndian));
2817+
let mut registers = LineRow::new(&header);
2818+
registers.address = u64::MAX;
2819+
registers.op_index.0 = 1;
2820+
let opcode = LineInstruction::FixedAddPc(10);
2821+
let mut program = IncompleteLineProgram { header };
2822+
let result = registers.execute(opcode, &mut program);
2823+
assert_eq!(result, Err(Error::AddressOverflow));
2824+
}
2825+
27822826
#[test]
27832827
fn test_exec_set_prologue_end() {
27842828
let header = make_test_header(EndianSlice::new(&[], LittleEndian));
@@ -2855,7 +2899,7 @@ mod tests {
28552899
let opcode = LineInstruction::SetAddress(3030);
28562900

28572901
let mut expected_registers = initial_registers;
2858-
expected_registers.address.0 = 3030;
2902+
expected_registers.address = 3030;
28592903

28602904
assert_exec_opcode(header, initial_registers, opcode, expected_registers, false);
28612905
}
@@ -2868,11 +2912,22 @@ mod tests {
28682912

28692913
let mut expected_registers = initial_registers;
28702914
expected_registers.tombstone = true;
2871-
expected_registers.address.0 = !0;
28722915

28732916
assert_exec_opcode(header, initial_registers, opcode, expected_registers, false);
28742917
}
28752918

2919+
#[test]
2920+
fn test_exec_set_address_backwards() {
2921+
let header = make_test_header(EndianSlice::new(&[], LittleEndian));
2922+
let mut registers = LineRow::new(&header);
2923+
registers.address = 1;
2924+
let opcode = LineInstruction::SetAddress(0);
2925+
2926+
let mut program = IncompleteLineProgram { header };
2927+
let result = registers.execute(opcode, &mut program);
2928+
assert_eq!(result, Err(Error::InvalidAddressRange));
2929+
}
2930+
28762931
#[test]
28772932
fn test_exec_define_file() {
28782933
let mut program = make_test_program(EndianSlice::new(&[], LittleEndian));
@@ -2888,7 +2943,7 @@ mod tests {
28882943
};
28892944

28902945
let opcode = LineInstruction::DefineFile(file);
2891-
let is_new_row = row.execute(opcode, &mut program);
2946+
let is_new_row = row.execute(opcode, &mut program).unwrap();
28922947

28932948
assert!(!is_new_row);
28942949
assert_eq!(Some(&file), program.header().file_names.last());

src/write/line.rs

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1126,13 +1126,14 @@ mod convert {
11261126
Some(val) => address = Some(val),
11271127
None => return Err(ConvertError::InvalidAddress),
11281128
}
1129-
from_row.execute(read::LineInstruction::SetAddress(0), &mut from_program);
1129+
from_row
1130+
.execute(read::LineInstruction::SetAddress(0), &mut from_program)?;
11301131
}
11311132
read::LineInstruction::DefineFile(_) => {
11321133
return Err(ConvertError::UnsupportedLineInstruction);
11331134
}
11341135
_ => {
1135-
if from_row.execute(instruction, &mut from_program) {
1136+
if from_row.execute(instruction, &mut from_program)? {
11361137
if !program.in_sequence() {
11371138
program.begin_sequence(address);
11381139
address = None;

0 commit comments

Comments
 (0)