@@ -10,27 +10,37 @@ impl BoxedUint {
10
10
/// Returns a zero and a truthy `Choice` if `shift >= self.bits_precision()`,
11
11
/// or the result and a falsy `Choice` otherwise.
12
12
pub fn shl ( & self , shift : u32 ) -> ( Self , Choice ) {
13
+ let mut result = self . clone ( ) ;
14
+ let overflow = result. overflowing_shl_assign ( shift) ;
15
+ ( result, overflow)
16
+ }
17
+
18
+ /// Computes `self <<= shift`.
19
+ ///
20
+ /// Returns a zero and a truthy `Choice` if `shift >= self.bits_precision()`,
21
+ /// or a falsy `Choice` otherwise.
22
+ fn overflowing_shl_assign ( & mut self , shift : u32 ) -> Choice {
13
23
// `floor(log2(bits_precision - 1))` is the number of bits in the representation of `shift`
14
24
// (which lies in range `0 <= shift < bits_precision`).
15
25
let shift_bits = u32:: BITS - ( self . bits_precision ( ) - 1 ) . leading_zeros ( ) ;
16
26
let overflow = !shift. ct_lt ( & self . bits_precision ( ) ) ;
17
27
let shift = shift % self . bits_precision ( ) ;
18
- let mut result = self . clone ( ) ;
19
28
let mut temp = self . clone ( ) ;
20
29
21
30
for i in 0 ..shift_bits {
22
31
let bit = Choice :: from ( ( ( shift >> i) & 1 ) as u8 ) ;
23
32
temp. set_zero ( ) ;
24
33
// Will not overflow by construction
25
- result
26
- . shl_vartime_into ( & mut temp, 1 << i)
34
+ self . shl_vartime_into ( & mut temp, 1 << i)
27
35
. expect ( "shift within range" ) ;
28
- result . conditional_assign ( & temp, bit) ;
36
+ self . conditional_assign ( & temp, bit) ;
29
37
}
30
38
31
- result. conditional_set_zero ( overflow) ;
39
+ #[ cfg( feature = "zeroize" ) ]
40
+ zeroize:: Zeroize :: zeroize ( & mut temp) ;
32
41
33
- ( result, overflow)
42
+ self . conditional_set_zero ( overflow) ;
43
+ overflow
34
44
}
35
45
36
46
/// Computes `self << shift` and writes the result into `dest`.
@@ -124,8 +134,8 @@ impl Shl<u32> for &BoxedUint {
124
134
125
135
impl ShlAssign < u32 > for BoxedUint {
126
136
fn shl_assign ( & mut self , shift : u32 ) {
127
- // TODO(tarcieri): in-place implementation that avoids clone
128
- * self = self . clone ( ) . shl ( shift)
137
+ let overflow = self . overflowing_shl_assign ( shift ) ;
138
+ assert ! ( ! bool :: from ( overflow ) , "attempt to shift left with overflow" ) ;
129
139
}
130
140
}
131
141
0 commit comments