@@ -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 ) ]
632632pub 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( ) ) ;
0 commit comments