1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140
|
//@ normalize-stderr: "\d+ bytes" -> "$$BYTES bytes"
//@ dont-require-annotations: NOTE
#![feature(core_intrinsics)]
use std::intrinsics::{ptr_offset_from, ptr_offset_from_unsigned};
use std::ptr;
#[repr(C)]
struct Struct {
data: u8,
field: u8,
}
pub const DIFFERENT_ALLOC: usize = {
let uninit = std::mem::MaybeUninit::<Struct>::uninit();
let base_ptr: *const Struct = &uninit as *const _ as *const Struct;
let uninit2 = std::mem::MaybeUninit::<Struct>::uninit();
let field_ptr: *const Struct = &uninit2 as *const _ as *const Struct;
let offset = unsafe { ptr_offset_from(field_ptr, base_ptr) }; //~ERROR evaluation of constant value failed
//~| NOTE not both derived from the same allocation
offset as usize
};
pub const NOT_PTR: usize = {
unsafe { (42 as *const u8).offset_from(&5u8) as usize } //~ ERROR evaluation of constant value failed
};
pub const NOT_MULTIPLE_OF_SIZE: isize = {
let data = [5u8, 6, 7];
let base_ptr = data.as_ptr();
let field_ptr = &data[1] as *const u8 as *const u16;
unsafe { ptr_offset_from(field_ptr, base_ptr as *const u16) } //~ERROR evaluation of constant value failed
//~| NOTE 1_isize cannot be divided by 2_isize without remainder
};
pub const DIFFERENT_INT: isize = { // offset_from with two different integers: like DIFFERENT_ALLOC
let ptr1 = 8 as *const u8;
let ptr2 = 16 as *const u8;
unsafe { ptr_offset_from(ptr2, ptr1) } //~ERROR evaluation of constant value failed
//~| NOTE not both derived from the same allocation
};
const OUT_OF_BOUNDS_1: isize = {
let start_ptr = &4 as *const _ as *const u8;
let length = 10;
let end_ptr = (start_ptr).wrapping_add(length);
// First ptr is out of bounds
unsafe { ptr_offset_from(end_ptr, start_ptr) } //~ERROR evaluation of constant value failed
//~| NOTE the memory range between them is not in-bounds of an allocation
};
const OUT_OF_BOUNDS_2: isize = {
let start_ptr = &4 as *const _ as *const u8;
let length = 10;
let end_ptr = (start_ptr).wrapping_add(length);
// Second ptr is out of bounds
unsafe { ptr_offset_from(start_ptr, end_ptr) } //~ERROR evaluation of constant value failed
//~| NOTE the memory range between them is not in-bounds of an allocation
};
pub const DIFFERENT_ALLOC_UNSIGNED: usize = {
let uninit = std::mem::MaybeUninit::<Struct>::uninit();
let base_ptr: *const Struct = &uninit as *const _ as *const Struct;
let uninit2 = std::mem::MaybeUninit::<Struct>::uninit();
let field_ptr: *const Struct = &uninit2 as *const _ as *const Struct;
unsafe { ptr_offset_from_unsigned(field_ptr, base_ptr) } //~ERROR evaluation of constant value failed
//~| NOTE not both derived from the same allocation
};
pub const TOO_FAR_APART1: isize = {
let ptr1 = &0u8 as *const u8;
let ptr2 = ptr1.wrapping_add(isize::MAX as usize + 42);
unsafe { ptr_offset_from(ptr2, ptr1) } //~ERROR evaluation of constant value failed
//~| NOTE too far ahead
};
pub const TOO_FAR_APART2: isize = {
let ptr1 = &0u8 as *const u8;
let ptr2 = ptr1.wrapping_add(isize::MAX as usize + 42);
unsafe { ptr_offset_from(ptr1, ptr2) } //~ERROR evaluation of constant value failed
//~| NOTE too far before
};
pub const TOO_FAR_APART3: isize = {
let ptr1 = &0u8 as *const u8;
let ptr2 = ptr1.wrapping_offset(isize::MIN);
// The result of this would be `isize::MIN`, which *does* fit in an `isize`, but its
// absolute value does not. (Also anyway there cannot be an allocation of that size.)
unsafe { ptr_offset_from(ptr1, ptr2) } //~ERROR evaluation of constant value failed
//~| NOTE too far before
};
const WRONG_ORDER_UNSIGNED: usize = {
let a = ['a', 'b', 'c'];
let p = a.as_ptr();
unsafe { ptr_offset_from_unsigned(p, p.add(2) ) } //~ERROR evaluation of constant value failed
//~| NOTE first pointer has smaller offset than second: 0 < 8
};
pub const TOO_FAR_APART_UNSIGNED: usize = {
let ptr1 = &0u8 as *const u8;
let ptr2 = ptr1.wrapping_add(isize::MAX as usize + 42);
// This would fit into a `usize` but we still don't allow it.
unsafe { ptr_offset_from_unsigned(ptr2, ptr1) } //~ERROR evaluation of constant value failed
//~| NOTE too far ahead
};
// These do NOT complain that pointers are too far apart; they pass that check (to then fail the
// next one).
pub const OFFSET_VERY_FAR1: isize = {
let ptr1 = ptr::null::<u8>();
let ptr2 = ptr1.wrapping_offset(isize::MAX);
unsafe { ptr2.offset_from(ptr1) }
//~^ ERROR evaluation of constant value failed
};
pub const OFFSET_VERY_FAR2: isize = {
let ptr1 = ptr::null::<u8>();
let ptr2 = ptr1.wrapping_offset(isize::MAX);
unsafe { ptr1.offset_from(ptr2.wrapping_offset(1)) }
//~^ ERROR evaluation of constant value failed
};
// If the pointers are the same, OOB/null/UAF is fine.
pub const OFFSET_FROM_NULL_SAME: isize = {
let ptr = 0 as *const u8;
unsafe { ptr_offset_from(ptr, ptr) }
};
const OUT_OF_BOUNDS_SAME: isize = {
let start_ptr = &4 as *const _ as *const u8;
let length = 10;
let end_ptr = (start_ptr).wrapping_add(length);
unsafe { ptr_offset_from(end_ptr, end_ptr) }
};
const UAF_SAME: isize = {
let uaf_ptr = {
let x = 0;
&x as *const i32
};
unsafe { ptr_offset_from(uaf_ptr, uaf_ptr) }
};
fn main() {}
|