From 52549346d2b9132485b6ebe8b0004f0c67683bdc Mon Sep 17 00:00:00 2001 From: Amber Sprenkels Date: Thu, 9 Mar 2023 20:44:13 +0800 Subject: [PATCH] Revert "Replace black_box with std::hint::black_box" This reverts commit 4978f4235b37cae2eb9f125cc5095772b3adc561. --- README.md | 2 +- src/lib.rs | 29 ++++++++++++++++++++++++++++- 2 files changed, 29 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 928bcb7..0753be3 100644 --- a/README.md +++ b/README.md @@ -43,7 +43,7 @@ Documentation is available [here][docs]. ## Minimum Supported Rust Version -Rust **1.66** or higher. +Rust **1.41** or higher. Minimum supported Rust version can be changed in the future, but it will be done with a minor version bump. diff --git a/src/lib.rs b/src/lib.rs index 1aa0acf..63cf19f 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -206,12 +206,39 @@ impl Not for Choice { } } +/// This function is a best-effort attempt to prevent the compiler from knowing +/// anything about the value of the returned `u8`, other than its type. +/// +/// Because we want to support stable Rust, we don't have access to inline +/// assembly or test::black_box, so we use the fact that volatile values will +/// never be elided to register values. +/// +/// Note: Rust's notion of "volatile" is subject to change over time. While this +/// code may break in a non-destructive way in the future, “constant-time” code +/// is a continually moving target, and this is better than doing nothing. +#[inline(never)] +fn black_box(input: u8) -> u8 { + debug_assert!((input == 0u8) | (input == 1u8)); + + unsafe { + // Optimization barrier + // + // Unsafe is ok, because: + // - &input is not NULL; + // - size of input is not zero; + // - u8 is neither Sync, nor Send; + // - u8 is Copy, so input is always live; + // - u8 type is always properly aligned. + core::ptr::read_volatile(&input as *const u8) + } +} + impl From for Choice { #[inline] fn from(input: u8) -> Choice { // Our goal is to prevent the compiler from inferring that the value held inside the // resulting `Choice` struct is really an `i1` instead of an `i8`. - Choice(core::hint::black_box(input)) + Choice(black_box(input)) } }