zowens / crc32c

Fast CRC-32-Castagnoli implementation in Rust

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

UB in build script

nissaofthesea opened this issue · comments

commented

the build script creates uninitialized integers in a few places:

let mut table: [[u32; 256]; 8] = unsafe { mem::MaybeUninit::uninit().assume_init() };

crc32c/build.rs

Lines 43 to 49 in 47c2999

pub struct Matrix([u32; 32]);
impl Matrix {
/// Allocates space for a new matrix.
fn new() -> Self {
unsafe { mem::MaybeUninit::uninit().assume_init() }
}

crc32c/build.rs

Line 135 in 47c2999

let mut zeroes: [[u32; 256]; 4] = unsafe { mem::MaybeUninit::uninit().assume_init() };

afaik, this is undefined behavior (excerpt from MaybeUninit type docs)

Moreover, uninitialized memory is special in that it does not have a fixed value (“fixed” meaning “it won’t change without being written to”). Reading the same uninitialized byte multiple times can give different results. This makes it undefined behavior to have uninitialized data in a variable even if that variable has an integer type, which otherwise can hold any fixed bit pattern:

use std::mem::{self, MaybeUninit};

let x: i32 = unsafe { mem::uninitialized() }; // undefined behavior! ⚠️
// The equivalent code with `MaybeUninit<i32>`:
let x: i32 = unsafe { MaybeUninit::uninit().assume_init() }; // undefined behavior! ⚠️

i haven't looked at the code in too much detail but this may be an issue if there's references to this data before it's been initialized for reals.

commented

did a quick look, found some places where there are references to said uninit integers.
(these are because the Index and IndexMut traits take references)

table[0][n as usize] = crc;

result[i] = self * self[i];

crc32c/build.rs

Line 141 in 47c2999

zeroes[i as usize][n] = op * ((n << shift) as u32);

commented

as mentioned here: #33
fixed here: #39