8
8
// option. This file may not be copied, modified, or distributed
9
9
// except according to those terms.
10
10
11
- use std:: num:: { One , Zero , CheckedAdd } ;
11
+ use std:: num:: One ;
12
12
use std:: vec:: bytes:: { MutableByteVector , copy_memory} ;
13
13
14
14
@@ -36,18 +36,6 @@ pub fn write_u32_be(dst: &mut[u8], input: u32) {
36
36
}
37
37
}
38
38
39
- /// Write a u32 into a vector, which must be 4 bytes long. The value is written in little-endian
40
- /// format.
41
- pub fn write_u32_le ( dst : & mut [ u8 ] , input : u32 ) {
42
- use std:: cast:: transmute;
43
- use std:: unstable:: intrinsics:: to_le32;
44
- assert ! ( dst. len( ) == 4 ) ;
45
- unsafe {
46
- let x: * mut i32 = transmute ( dst. unsafe_mut_ref ( 0 ) ) ;
47
- * x = to_le32 ( input as i32 ) ;
48
- }
49
- }
50
-
51
39
/// Read a vector of bytes into a vector of u64s. The values are read in big-endian format.
52
40
pub fn read_u64v_be ( dst : & mut [ u64 ] , input : & [ u8 ] ) {
53
41
use std:: cast:: transmute;
@@ -80,90 +68,51 @@ pub fn read_u32v_be(dst: &mut[u32], input: &[u8]) {
80
68
}
81
69
}
82
70
83
- /// Read a vector of bytes into a vector of u32s. The values are read in little-endian format.
84
- pub fn read_u32v_le ( dst : & mut [ u32 ] , input : & [ u8 ] ) {
85
- use std:: cast:: transmute;
86
- use std:: unstable:: intrinsics:: to_le32;
87
- assert ! ( dst. len( ) * 4 == input. len( ) ) ;
88
- unsafe {
89
- let mut x: * mut i32 = transmute ( dst. unsafe_mut_ref ( 0 ) ) ;
90
- let mut y: * i32 = transmute ( input. unsafe_ref ( 0 ) ) ;
91
- do dst. len ( ) . times ( ) {
92
- * x = to_le32 ( * y) ;
93
- x = x. offset ( 1 ) ;
94
- y = y. offset ( 1 ) ;
95
- }
96
- }
97
- }
98
-
99
71
100
- trait ToBits {
101
- /// Convert the value in bytes to the number of bits, a tuple where the 1st item is the
102
- /// high-order value and the 2nd item is the low order value.
103
- fn to_bits ( self ) -> ( Self , Self ) ;
72
+ /// Returns true if adding the two parameters will result in integer overflow
73
+ pub fn will_add_overflow < T : Int + Unsigned > ( x : T , y : T ) -> bool {
74
+ // This doesn't handle negative values! Don't copy this code elsewhere without considering if
75
+ // negative values are important to you!
76
+ let max: T = Bounded :: max_value ( ) ;
77
+ return x > max - y;
104
78
}
105
79
106
- impl ToBits for u64 {
107
- fn to_bits ( self ) -> ( u64 , u64 ) {
108
- return ( self >> 61 , self << 3 ) ;
80
+ /// Shifts the second parameter and then adds it to the first. fails!() if there would be unsigned
81
+ /// integer overflow.
82
+ pub fn shift_add_check_overflow < T : Int + Unsigned + Clone > ( x : T , mut y : T , shift : T ) -> T {
83
+ if y. leading_zeros ( ) < shift {
84
+ fail ! ( "Could not add values - integer overflow." ) ;
109
85
}
110
- }
86
+ y = y << shift ;
111
87
112
- /// Adds the specified number of bytes to the bit count. fail!() if this would cause numeric
113
- /// overflow.
114
- pub fn add_bytes_to_bits < T : Int + CheckedAdd + ToBits > ( bits : T , bytes : T ) -> T {
115
- let ( new_high_bits, new_low_bits) = bytes. to_bits ( ) ;
116
-
117
- if new_high_bits > Zero :: zero ( ) {
118
- fail ! ( "Numeric overflow occured." )
88
+ if will_add_overflow ( x. clone ( ) , y. clone ( ) ) {
89
+ fail ! ( "Could not add values - integer overflow." ) ;
119
90
}
120
91
121
- match bits. checked_add ( & new_low_bits) {
122
- Some ( x) => return x,
123
- None => fail ! ( "Numeric overflow occured." )
124
- }
92
+ return x + y;
125
93
}
126
94
127
- /// Adds the specified number of bytes to the bit count, which is a tuple where the first element is
128
- /// the high order value. fail!() if this would cause numeric overflow.
129
- pub fn add_bytes_to_bits_tuple
130
- < T : Int + Unsigned + CheckedAdd + ToBits >
131
- ( bits : ( T , T ) , bytes : T ) -> ( T , T ) {
132
- let ( new_high_bits, new_low_bits) = bytes. to_bits ( ) ;
133
- let ( hi, low) = bits;
134
-
135
- // Add the low order value - if there is no overflow, then add the high order values
136
- // If the addition of the low order values causes overflow, add one to the high order values
137
- // before adding them.
138
- match low. checked_add ( & new_low_bits) {
139
- Some ( x) => {
140
- if new_high_bits == Zero :: zero ( ) {
141
- // This is the fast path - every other alternative will rarely occur in practice
142
- // considering how large an input would need to be for those paths to be used.
143
- return ( hi, x) ;
144
- } else {
145
- match hi. checked_add ( & new_high_bits) {
146
- Some ( y) => return ( y, x) ,
147
- None => fail ! ( "Numeric overflow occured." )
148
- }
149
- }
150
- } ,
151
- None => {
95
+ /// Shifts the second parameter and then adds it to the first, which is a tuple where the first
96
+ /// element is the high order value. fails!() if there would be unsigned integer overflow.
97
+ pub fn shift_add_check_overflow_tuple
98
+ < T : Int + Unsigned + Clone >
99
+ ( x : ( T , T ) , mut y : T , shift : T ) -> ( T , T ) {
100
+ if y. leading_zeros ( ) < shift {
101
+ fail ! ( "Could not add values - integer overflow." ) ;
102
+ }
103
+ y = y << shift;
104
+
105
+ match x {
106
+ ( hi, low) => {
152
107
let one: T = One :: one ( ) ;
153
- let z = match new_high_bits. checked_add ( & one) {
154
- Some ( w) => w,
155
- None => fail ! ( "Numeric overflow occured." )
156
- } ;
157
- match hi. checked_add ( & z) {
158
- // This re-executes the addition that was already performed earlier when overflow
159
- // occured, this time allowing the overflow to happen. Technically, this could be
160
- // avoided by using the checked add intrinsic directly, but that involves using
161
- // unsafe code and is not really worthwhile considering how infrequently code will
162
- // run in practice. This is the reason that this function requires that the type T
163
- // be Unsigned - overflow is not defined for Signed types. This function could be
164
- // implemented for signed types as well if that were needed.
165
- Some ( y) => return ( y, low + new_low_bits) ,
166
- None => fail ! ( "Numeric overflow occured." )
108
+ if will_add_overflow ( low. clone ( ) , y. clone ( ) ) {
109
+ if will_add_overflow ( hi. clone ( ) , one. clone ( ) ) {
110
+ fail ! ( "Could not add values - integer overflow." ) ;
111
+ } else {
112
+ return ( hi + one, low + y) ;
113
+ }
114
+ } else {
115
+ return ( hi, low + y) ;
167
116
}
168
117
}
169
118
}
@@ -351,7 +300,6 @@ mod test {
351
300
use std:: rand:: RngUtil ;
352
301
use std:: vec;
353
302
354
- use cryptoutil:: { add_bytes_to_bits, add_bytes_to_bits_tuple} ;
355
303
use digest:: Digest ;
356
304
357
305
/// Feed 1,000,000 'a's into the digest with varying input sizes and check that the result is
@@ -376,50 +324,4 @@ mod test {
376
324
377
325
assert ! ( expected == result_str) ;
378
326
}
379
-
380
- // A normal addition - no overflow occurs
381
- #[ test]
382
- fn test_add_bytes_to_bits_ok ( ) {
383
- assert ! ( add_bytes_to_bits:: <u64 >( 100 , 10 ) == 180 ) ;
384
- }
385
-
386
- // A simple failure case - adding 1 to the max value
387
- #[ test]
388
- #[ should_fail]
389
- fn test_add_bytes_to_bits_overflow ( ) {
390
- add_bytes_to_bits :: < u64 > ( Bounded :: max_value ( ) , 1 ) ;
391
- }
392
-
393
- // A normal addition - no overflow occurs (fast path)
394
- #[ test]
395
- fn test_add_bytes_to_bits_tuple_ok ( ) {
396
- assert ! ( add_bytes_to_bits_tuple:: <u64 >( ( 5 , 100 ) , 10 ) == ( 5 , 180 ) ) ;
397
- }
398
-
399
- // The low order value overflows into the high order value
400
- #[ test]
401
- fn test_add_bytes_to_bits_tuple_ok2 ( ) {
402
- assert ! ( add_bytes_to_bits_tuple:: <u64 >( ( 5 , Bounded :: max_value( ) ) , 1 ) == ( 6 , 7 ) ) ;
403
- }
404
-
405
- // The value to add is too large to be converted into bits without overflowing its type
406
- #[ test]
407
- fn test_add_bytes_to_bits_tuple_ok3 ( ) {
408
- assert ! ( add_bytes_to_bits_tuple:: <u64 >( ( 5 , 0 ) , 0x4000000000000001 ) == ( 7 , 8 ) ) ;
409
- }
410
-
411
- // A simple failure case - adding 1 to the max value
412
- #[ test]
413
- #[ should_fail]
414
- fn test_add_bytes_to_bits_tuple_overflow ( ) {
415
- add_bytes_to_bits_tuple :: < u64 > ( ( Bounded :: max_value ( ) , Bounded :: max_value ( ) ) , 1 ) ;
416
- }
417
-
418
- // The value to add is too large to convert to bytes without overflowing its type, but the high
419
- // order value from this conversion overflows when added to the existing high order value
420
- #[ test]
421
- #[ should_fail]
422
- fn test_add_bytes_to_bits_tuple_overflow2 ( ) {
423
- add_bytes_to_bits_tuple :: < u64 > ( ( Bounded :: max_value :: < u64 > ( ) - 1 , 0 ) , 0x8000000000000000 ) ;
424
- }
425
327
}
0 commit comments