Skip to content

Commit

Permalink
test multiple initial counter values for hash_many
Browse files Browse the repository at this point in the history
I'm adding the i32::MAX test case here because I personally screwed it
up while I was working on
BLAKE3-team#271. The correct
implementation of the carry bit is the ANDNOT of old high bit (1) and
the new high bit (0). Using XOR instead of ANDNOT gives the correct
answer in the overflow case, but it also reports an incorrect "extra"
overflow when the high bit goes from 0 to 1.
  • Loading branch information
oconnor663 committed Nov 23, 2022
1 parent bd6ce26 commit b7d0901
Showing 1 changed file with 98 additions and 90 deletions.
188 changes: 98 additions & 90 deletions blake3_c_rust_bindings/src/test.rs
Expand Up @@ -207,99 +207,107 @@ type HashManyFn = unsafe extern "C" fn(

// A shared helper function for platform-specific tests.
pub fn test_hash_many_fn(hash_many_fn: HashManyFn) {
// 31 (16 + 8 + 4 + 2 + 1) inputs
const NUM_INPUTS: usize = 31;
let mut input_buf = [0; CHUNK_LEN * NUM_INPUTS];
crate::test::paint_test_input(&mut input_buf);
// A counter just prior to u32::MAX.
let counter = (1u64 << 32) - 1;

// First hash chunks.
let mut chunks = ArrayVec::<&[u8; CHUNK_LEN], NUM_INPUTS>::new();
for i in 0..NUM_INPUTS {
chunks.push(array_ref!(input_buf, i * CHUNK_LEN, CHUNK_LEN));
}
let mut portable_chunks_out = [0; NUM_INPUTS * OUT_LEN];
unsafe {
crate::ffi::blake3_hash_many_portable(
chunks.as_ptr() as _,
chunks.len(),
CHUNK_LEN / BLOCK_LEN,
TEST_KEY_WORDS.as_ptr(),
counter,
true,
KEYED_HASH,
CHUNK_START,
CHUNK_END,
portable_chunks_out.as_mut_ptr(),
);
}
// Test a few different initial counter values.
// - 0: The base case.
// - u32::MAX: The low word of the counter overflows for all inputs except the first.
// - i32::MAX: *No* overflow. But carry bugs in tricky SIMD code can screw this up, if you XOR
// when you're supposed to ANDNOT...
let initial_counters = [0, u32::MAX as u64, i32::MAX as u64];
for counter in initial_counters {
dbg!(counter);

// 31 (16 + 8 + 4 + 2 + 1) inputs
const NUM_INPUTS: usize = 31;
let mut input_buf = [0; CHUNK_LEN * NUM_INPUTS];
crate::test::paint_test_input(&mut input_buf);

// First hash chunks.
let mut chunks = ArrayVec::<&[u8; CHUNK_LEN], NUM_INPUTS>::new();
for i in 0..NUM_INPUTS {
chunks.push(array_ref!(input_buf, i * CHUNK_LEN, CHUNK_LEN));
}
let mut portable_chunks_out = [0; NUM_INPUTS * OUT_LEN];
unsafe {
crate::ffi::blake3_hash_many_portable(
chunks.as_ptr() as _,
chunks.len(),
CHUNK_LEN / BLOCK_LEN,
TEST_KEY_WORDS.as_ptr(),
counter,
true,
KEYED_HASH,
CHUNK_START,
CHUNK_END,
portable_chunks_out.as_mut_ptr(),
);
}

let mut test_chunks_out = [0; NUM_INPUTS * OUT_LEN];
unsafe {
hash_many_fn(
chunks.as_ptr() as _,
chunks.len(),
CHUNK_LEN / BLOCK_LEN,
TEST_KEY_WORDS.as_ptr(),
counter,
true,
KEYED_HASH,
CHUNK_START,
CHUNK_END,
test_chunks_out.as_mut_ptr(),
);
}
for n in 0..NUM_INPUTS {
dbg!(n);
assert_eq!(
&portable_chunks_out[n * OUT_LEN..][..OUT_LEN],
&test_chunks_out[n * OUT_LEN..][..OUT_LEN]
);
}
let mut test_chunks_out = [0; NUM_INPUTS * OUT_LEN];
unsafe {
hash_many_fn(
chunks.as_ptr() as _,
chunks.len(),
CHUNK_LEN / BLOCK_LEN,
TEST_KEY_WORDS.as_ptr(),
counter,
true,
KEYED_HASH,
CHUNK_START,
CHUNK_END,
test_chunks_out.as_mut_ptr(),
);
}
for n in 0..NUM_INPUTS {
dbg!(n);
assert_eq!(
&portable_chunks_out[n * OUT_LEN..][..OUT_LEN],
&test_chunks_out[n * OUT_LEN..][..OUT_LEN]
);
}

// Then hash parents.
let mut parents = ArrayVec::<&[u8; 2 * OUT_LEN], NUM_INPUTS>::new();
for i in 0..NUM_INPUTS {
parents.push(array_ref!(input_buf, i * 2 * OUT_LEN, 2 * OUT_LEN));
}
let mut portable_parents_out = [0; NUM_INPUTS * OUT_LEN];
unsafe {
crate::ffi::blake3_hash_many_portable(
parents.as_ptr() as _,
parents.len(),
1,
TEST_KEY_WORDS.as_ptr(),
counter,
false,
KEYED_HASH | PARENT,
0,
0,
portable_parents_out.as_mut_ptr(),
);
}
// Then hash parents.
let mut parents = ArrayVec::<&[u8; 2 * OUT_LEN], NUM_INPUTS>::new();
for i in 0..NUM_INPUTS {
parents.push(array_ref!(input_buf, i * 2 * OUT_LEN, 2 * OUT_LEN));
}
let mut portable_parents_out = [0; NUM_INPUTS * OUT_LEN];
unsafe {
crate::ffi::blake3_hash_many_portable(
parents.as_ptr() as _,
parents.len(),
1,
TEST_KEY_WORDS.as_ptr(),
counter,
false,
KEYED_HASH | PARENT,
0,
0,
portable_parents_out.as_mut_ptr(),
);
}

let mut test_parents_out = [0; NUM_INPUTS * OUT_LEN];
unsafe {
hash_many_fn(
parents.as_ptr() as _,
parents.len(),
1,
TEST_KEY_WORDS.as_ptr(),
counter,
false,
KEYED_HASH | PARENT,
0,
0,
test_parents_out.as_mut_ptr(),
);
}
for n in 0..NUM_INPUTS {
dbg!(n);
assert_eq!(
&portable_parents_out[n * OUT_LEN..][..OUT_LEN],
&test_parents_out[n * OUT_LEN..][..OUT_LEN]
);
let mut test_parents_out = [0; NUM_INPUTS * OUT_LEN];
unsafe {
hash_many_fn(
parents.as_ptr() as _,
parents.len(),
1,
TEST_KEY_WORDS.as_ptr(),
counter,
false,
KEYED_HASH | PARENT,
0,
0,
test_parents_out.as_mut_ptr(),
);
}
for n in 0..NUM_INPUTS {
dbg!(n);
assert_eq!(
&portable_parents_out[n * OUT_LEN..][..OUT_LEN],
&test_parents_out[n * OUT_LEN..][..OUT_LEN]
);
}
}
}

Expand Down

0 comments on commit b7d0901

Please sign in to comment.