Skip to content

Commit 8686806

Browse files
committed
Test getrandom_uninit() with initially-uninitialized buffer.
None of the tests are testing `getrandom_uninit()` directly, but instead it is marked as covered because `getrandom()` forwards to it. However, this means we're never testing an uninitialized input to `getrandom_uninit()`. Fix that.
1 parent 10a0ae0 commit 8686806

File tree

4 files changed

+69
-21
lines changed

4 files changed

+69
-21
lines changed

tests/common/mod.rs

Lines changed: 59 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,27 @@
1-
use super::getrandom_impl;
1+
use super::{getrandom_impl, getrandom_uninit_impl};
2+
use core::mem::MaybeUninit;
3+
#[cfg(not(feature = "custom"))]
4+
use getrandom::Error;
25

36
#[cfg(all(target_arch = "wasm32", target_os = "unknown"))]
47
use wasm_bindgen_test::wasm_bindgen_test as test;
58

69
#[cfg(feature = "test-in-browser")]
710
wasm_bindgen_test::wasm_bindgen_test_configure!(run_in_browser);
811

12+
#[cfg(not(feature = "custom"))]
13+
fn wrapped_getrandom(dest: &mut [u8]) -> Result<&mut [u8], Error> {
14+
getrandom_impl(dest).map(|()| dest)
15+
}
16+
17+
// Test that APIs are happy with zero-length requests
918
#[test]
1019
fn test_zero() {
11-
// Test that APIs are happy with zero-length requests
12-
getrandom_impl(&mut [0u8; 0]).unwrap();
20+
getrandom_impl(&mut []).unwrap();
21+
}
22+
#[test]
23+
fn test_zero_uninit() {
24+
getrandom_uninit_impl(&mut []).unwrap();
1325
}
1426

1527
// Return the number of bits in which s1 and s2 differ
@@ -23,52 +35,82 @@ fn num_diff_bits(s1: &[u8], s2: &[u8]) -> usize {
2335
}
2436

2537
// Tests the quality of calling getrandom on two large buffers
26-
#[test]
38+
2739
#[cfg(not(feature = "custom"))]
28-
fn test_diff() {
29-
let mut v1 = [0u8; 1000];
30-
getrandom_impl(&mut v1).unwrap();
40+
fn test_diff_large<T: Copy>(initial: T, f: impl Fn(&mut [T]) -> Result<&mut [u8], Error>) {
41+
let mut v1 = [initial; 1000];
42+
let r1 = f(&mut v1).unwrap();
3143

32-
let mut v2 = [0u8; 1000];
33-
getrandom_impl(&mut v2).unwrap();
44+
let mut v2 = [initial; 1000];
45+
let r2 = f(&mut v2).unwrap();
3446

3547
// Between 3.5 and 4.5 bits per byte should differ. Probability of failure:
3648
// ~ 2^(-94) = 2 * CDF[BinomialDistribution[8000, 0.5], 3500]
37-
let d = num_diff_bits(&v1, &v2);
49+
let d = num_diff_bits(r1, r2);
3850
assert!(d > 3500);
3951
assert!(d < 4500);
4052
}
4153

42-
// Tests the quality of calling getrandom repeatedly on small buffers
54+
#[cfg(not(feature = "custom"))]
4355
#[test]
56+
fn test_large() {
57+
test_diff_large(0u8, wrapped_getrandom);
58+
}
59+
4460
#[cfg(not(feature = "custom"))]
45-
fn test_small() {
61+
#[test]
62+
fn test_large_uninit() {
63+
test_diff_large(MaybeUninit::uninit(), getrandom_uninit_impl);
64+
}
65+
66+
// Tests the quality of calling getrandom repeatedly on small buffers
67+
68+
#[cfg(not(feature = "custom"))]
69+
fn test_diff_small<T: Copy>(initial: T, f: impl Fn(&mut [T]) -> Result<&mut [u8], Error>) {
4670
// For each buffer size, get at least 256 bytes and check that between
4771
// 3 and 5 bits per byte differ. Probability of failure:
4872
// ~ 2^(-91) = 64 * 2 * CDF[BinomialDistribution[8*256, 0.5], 3*256]
4973
for size in 1..=64 {
5074
let mut num_bytes = 0;
5175
let mut diff_bits = 0;
5276
while num_bytes < 256 {
53-
let mut s1 = vec![0u8; size];
54-
getrandom_impl(&mut s1).unwrap();
55-
let mut s2 = vec![0u8; size];
56-
getrandom_impl(&mut s2).unwrap();
77+
let mut s1 = vec![initial; size];
78+
let r1 = f(&mut s1).unwrap();
79+
let mut s2 = vec![initial; size];
80+
let r2 = f(&mut s2).unwrap();
5781

5882
num_bytes += size;
59-
diff_bits += num_diff_bits(&s1, &s2);
83+
diff_bits += num_diff_bits(r1, r2);
6084
}
6185
assert!(diff_bits > 3 * num_bytes);
6286
assert!(diff_bits < 5 * num_bytes);
6387
}
6488
}
6589

90+
#[cfg(not(feature = "custom"))]
91+
#[test]
92+
fn test_small() {
93+
test_diff_small(0u8, wrapped_getrandom);
94+
}
95+
96+
#[cfg(not(feature = "custom"))]
97+
#[test]
98+
fn test_small_unnit() {
99+
test_diff_small(MaybeUninit::uninit(), getrandom_uninit_impl);
100+
}
101+
66102
#[test]
67103
fn test_huge() {
68104
let mut huge = [0u8; 100_000];
69105
getrandom_impl(&mut huge).unwrap();
70106
}
71107

108+
#[test]
109+
fn test_huge_uninit() {
110+
let mut huge = [MaybeUninit::uninit(); 100_000];
111+
getrandom_uninit_impl(&mut huge).unwrap();
112+
}
113+
72114
// On WASM, the thread API always fails/panics
73115
#[cfg(not(target_arch = "wasm32"))]
74116
#[test]

tests/custom.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@ fn super_insecure_rng(buf: &mut [u8]) -> Result<(), Error> {
3434

3535
register_custom_getrandom!(super_insecure_rng);
3636

37-
use getrandom::getrandom as getrandom_impl;
37+
use getrandom::{getrandom as getrandom_impl, getrandom_uninit as getrandom_uninit_impl};
3838
mod common;
3939

4040
#[test]

tests/normal.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,5 +7,5 @@
77
)))]
88

99
// Use the normal getrandom implementation on this architecture.
10-
use getrandom::getrandom as getrandom_impl;
10+
use getrandom::{getrandom as getrandom_impl, getrandom_uninit as getrandom_uninit_impl};
1111
mod common;

tests/rdrand.rs

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33

44
// rdrand.rs expects to be part of the getrandom main crate, so we need these
55
// additional imports to get rdrand.rs to compile.
6+
use core::mem::MaybeUninit;
67
use getrandom::Error;
78
#[macro_use]
89
extern crate cfg_if;
@@ -13,10 +14,15 @@ mod rdrand;
1314
#[path = "../src/util.rs"]
1415
mod util;
1516

16-
// The rdrand implementation has the signature of getrandom_uninit(), but our
17-
// tests expect getrandom_impl() to have the signature of getrandom().
17+
use crate::util::slice_assume_init_mut;
18+
1819
fn getrandom_impl(dest: &mut [u8]) -> Result<(), Error> {
1920
rdrand::getrandom_inner(unsafe { util::slice_as_uninit_mut(dest) })?;
2021
Ok(())
2122
}
23+
fn getrandom_uninit_impl(dest: &mut [MaybeUninit<u8>]) -> Result<&mut [u8], Error> {
24+
rdrand::getrandom_inner(dest)?;
25+
Ok(unsafe { slice_assume_init_mut(dest) })
26+
}
27+
2228
mod common;

0 commit comments

Comments
 (0)