-
Notifications
You must be signed in to change notification settings - Fork 13.5k
add const_leak
and reject interning non-leaked const_allocate
ptrs
#143595
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: master
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change | ||||
---|---|---|---|---|---|---|
|
@@ -311,6 +311,24 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> { | |||||
interp_ok(new_ptr) | ||||||
} | ||||||
|
||||||
pub fn leak_const_heap_ptr( | ||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Also needs the name adjusted to non-leak terminology |
||||||
&mut self, | ||||||
ptr: Pointer<Option<CtfeProvenance>>, | ||||||
) -> InterpResult<'tcx> | ||||||
where | ||||||
M: Machine<'tcx, Provenance = CtfeProvenance, AllocExtra = (), Bytes = Box<[u8]>>, | ||||||
{ | ||||||
let (alloc_id, _, _) = self.ptr_get_alloc_id(ptr, 0)?; | ||||||
let Some((_kind, mut alloc)) = self.memory.alloc_map.remove(&alloc_id) else { | ||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Should check the |
||||||
return Err(err_ub!(PointerUseAfterFree(alloc_id, CheckInAllocMsg::MemoryAccess))) | ||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Also test this code path (both by trying it on a dangling pointer and by trying it on an already interned allocation) |
||||||
.into(); | ||||||
}; | ||||||
alloc.mutability = Mutability::Not; | ||||||
let alloc = self.tcx.mk_const_alloc(alloc); | ||||||
self.tcx.set_alloc_id_memory(alloc_id, alloc); | ||||||
interp_ok(()) | ||||||
Comment on lines
+326
to
+329
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This risks breaking key invariants like "tcx-managed allocations do not have any dangling pointers". So as nice as this is I think it won't work. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I'm pretty sure both There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Yes that's what I mean. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. It's a bit easier in this situation than during interning, because we don't need to intern nested allocations, so you could just iterate over the relocation table and check if all of the relocations in it are already interned There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I don't think we want that, as already mentioned it would make it impossible to use this on cyclic structures. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I'm thinking of only marking it as immutable here and leaving it for the interning to actually make it into global. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Please also add a test for a cyclic globalification |
||||||
} | ||||||
|
||||||
#[instrument(skip(self), level = "debug")] | ||||||
pub fn deallocate_ptr( | ||||||
&mut self, | ||||||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,8 +1,16 @@ | ||
error: encountered `const_allocate` pointer in final value that was not made global | ||
--> $DIR/alloc_intrinsic_untyped.rs:8:1 | ||
| | ||
LL | const BAR: *mut i32 = unsafe { intrinsics::const_allocate(4, 4) as *mut i32 }; | ||
| ^^^^^^^^^^^^^^^^^^^ | ||
| | ||
= note: use `const_make_global` to make allocated pointers immutable before returning | ||
|
||
error: encountered mutable pointer in final value of constant | ||
--> $DIR/alloc_intrinsic_untyped.rs:8:1 | ||
| | ||
LL | const BAR: *mut i32 = unsafe { intrinsics::const_allocate(4, 4) as *mut i32 }; | ||
| ^^^^^^^^^^^^^^^^^^^ | ||
|
||
error: aborting due to 1 previous error | ||
error: aborting due to 2 previous errors | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,14 @@ | ||
#![feature(core_intrinsics)] | ||
#![feature(const_heap)] | ||
use std::intrinsics; | ||
|
||
const A: &u8 = unsafe { | ||
let ptr = intrinsics::const_allocate(1, 1); | ||
*ptr = 1; | ||
let ptr: *const u8 = intrinsics::const_make_global(ptr, 1, 1); | ||
*(ptr as *mut u8) = 2; | ||
//~^ error: writing to ALLOC0 which is read-only | ||
&*ptr | ||
}; | ||
|
||
fn main() {} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,9 @@ | ||
error[E0080]: writing to ALLOC0 which is read-only | ||
--> $DIR/ptr_made_global_mutated.rs:9:5 | ||
| | ||
LL | *(ptr as *mut u8) = 2; | ||
| ^^^^^^^^^^^^^^^^^^^^^ evaluation of `A` failed here | ||
|
||
error: aborting due to 1 previous error | ||
|
||
For more information about this error, try `rustc --explain E0080`. |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,19 @@ | ||
#![feature(core_intrinsics)] | ||
#![feature(const_heap)] | ||
use std::intrinsics; | ||
|
||
const FOO: &i32 = foo(); | ||
//~^ error: encountered `const_allocate` pointer in final value that was not made global | ||
const FOO_RAW: *const i32 = foo(); | ||
//~^ error: encountered `const_allocate` pointer in final value that was not made global | ||
|
||
const fn foo() -> &'static i32 { | ||
let t = unsafe { | ||
let i = intrinsics::const_allocate(4, 4) as *mut i32; | ||
*i = 20; | ||
i | ||
}; | ||
unsafe { &*t } | ||
} | ||
|
||
fn main() {} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,18 @@ | ||
error: encountered `const_allocate` pointer in final value that was not made global | ||
--> $DIR/ptr_not_made_global.rs:5:1 | ||
| | ||
LL | const FOO: &i32 = foo(); | ||
| ^^^^^^^^^^^^^^^ | ||
| | ||
= note: use `const_make_global` to make allocated pointers immutable before returning | ||
|
||
error: encountered `const_allocate` pointer in final value that was not made global | ||
--> $DIR/ptr_not_made_global.rs:7:1 | ||
| | ||
LL | const FOO_RAW: *const i32 = foo(); | ||
| ^^^^^^^^^^^^^^^^^^^^^^^^^ | ||
| | ||
= note: use `const_make_global` to make allocated pointers immutable before returning | ||
|
||
error: aborting due to 2 previous errors | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
actually I think we don't need this check at all,
leak_const_heap_ptr
will just fail with its error path because the allocation is not in the current alloc_map