Skip to content

Commit 7bb282b

Browse files
committed
check for overflow (at compile time) in *_refs! (closes #26)
1 parent 6a0d584 commit 7bb282b

File tree

1 file changed

+40
-6
lines changed

1 file changed

+40
-6
lines changed

src/lib.rs

+40-6
Original file line numberDiff line numberDiff line change
@@ -105,14 +105,31 @@ macro_rules! array_ref {
105105
macro_rules! array_refs {
106106
( $arr:expr, $( $pre:expr ),* ; .. ; $( $post:expr ),* ) => {{
107107
{
108+
/// A hokey struct to avoid theoretical overflow, which is only used
109+
/// at compile time, so efficiency of the overflow checks are not of
110+
/// concern.
111+
struct SaturatingUsize(usize);
112+
impl SaturatingUsize {
113+
// It is only used at compile time, so gets incorrectly
114+
// triggered as "dead code".
115+
#[allow(dead_code)]
116+
const fn add(self, rhs: usize) -> Self {
117+
if let Some(v) = self.0.checked_add(rhs) {
118+
SaturatingUsize(v)
119+
} else {
120+
SaturatingUsize(usize::MAX)
121+
}
122+
}
123+
}
124+
108125
use core::slice;
109126
#[inline]
110127
#[allow(unused_assignments)]
111128
#[allow(clippy::eval_order_dependence)]
112129
unsafe fn as_arrays<T>(a: &[T]) -> ( $( &[T; $pre], )* &[T], $( &[T; $post], )*) {
113-
let min_len = $( $pre + )* $( $post + )* 0;
114-
let var_len = a.len() - min_len;
115-
assert!(a.len() >= min_len);
130+
const MIN_LEN: usize = SaturatingUsize(0) $( .add($pre) )* $( .add($post) )* .0;
131+
let var_len = a.len() - MIN_LEN;
132+
assert!(a.len() >= MIN_LEN);
116133
let mut p = a.as_ptr();
117134
( $( {
118135
let aref = & *(p as *const [T; $pre]);
@@ -202,14 +219,31 @@ macro_rules! array_refs {
202219
macro_rules! mut_array_refs {
203220
( $arr:expr, $( $pre:expr ),* ; .. ; $( $post:expr ),* ) => {{
204221
{
222+
/// A hokey struct to avoid theoretical overflow, which is only used
223+
/// at compile time, so efficiency of the overflow checks are not of
224+
/// concern.
225+
struct SaturatingUsize(usize);
226+
impl SaturatingUsize {
227+
// It is only used at compile time, so gets incorrectly
228+
// triggered as "dead code".
229+
#[allow(dead_code)]
230+
const fn add(self, rhs: usize) -> Self {
231+
if let Some(v) = self.0.checked_add(rhs) {
232+
SaturatingUsize(v)
233+
} else {
234+
SaturatingUsize(usize::MAX)
235+
}
236+
}
237+
}
238+
205239
use core::slice;
206240
#[inline]
207241
#[allow(unused_assignments)]
208242
#[allow(clippy::eval_order_dependence)]
209243
unsafe fn as_arrays<T>(a: &mut [T]) -> ( $( &mut [T; $pre], )* &mut [T], $( &mut [T; $post], )*) {
210-
let min_len = $( $pre + )* $( $post + )* 0;
211-
let var_len = a.len() - min_len;
212-
assert!(a.len() >= min_len);
244+
const MIN_LEN: usize = SaturatingUsize(0) $( .add($pre) )* $( .add($post) )* .0;
245+
let var_len = a.len() - MIN_LEN;
246+
assert!(a.len() >= MIN_LEN);
213247
let mut p = a.as_mut_ptr();
214248
( $( {
215249
let aref = &mut *(p as *mut [T; $pre]);

0 commit comments

Comments
 (0)