@@ -206,12 +206,39 @@ impl Not for Choice {
206206 }
207207}
208208
209+ /// This function is a best-effort attempt to prevent the compiler from knowing
210+ /// anything about the value of the returned `u8`, other than its type.
211+ ///
212+ /// Because we want to support stable Rust, we don't have access to inline
213+ /// assembly or test::black_box, so we use the fact that volatile values will
214+ /// never be elided to register values.
215+ ///
216+ /// Note: Rust's notion of "volatile" is subject to change over time. While this
217+ /// code may break in a non-destructive way in the future, “constant-time” code
218+ /// is a continually moving target, and this is better than doing nothing.
219+ #[ inline( never) ]
220+ fn black_box ( input : u8 ) -> u8 {
221+ debug_assert ! ( ( input == 0u8 ) | ( input == 1u8 ) ) ;
222+
223+ unsafe {
224+ // Optimization barrier
225+ //
226+ // Unsafe is ok, because:
227+ // - &input is not NULL;
228+ // - size of input is not zero;
229+ // - u8 is neither Sync, nor Send;
230+ // - u8 is Copy, so input is always live;
231+ // - u8 type is always properly aligned.
232+ core:: ptr:: read_volatile ( & input as * const u8 )
233+ }
234+ }
235+
209236impl From < u8 > for Choice {
210237 #[ inline]
211238 fn from ( input : u8 ) -> Choice {
212239 // Our goal is to prevent the compiler from inferring that the value held inside the
213240 // resulting `Choice` struct is really an `i1` instead of an `i8`.
214- Choice ( core :: hint :: black_box ( input) )
241+ Choice ( black_box ( input) )
215242 }
216243}
217244
0 commit comments