Join GitHub today
GitHub is home to over 31 million developers working together to host and review code, manage projects, and build software together.
Sign upIterators over slices of ZST behave strange #42789
Comments
This comment has been minimized.
This comment has been minimized.
|
To clarify, the way the test fails is that the slice iterator returns |
This comment has been minimized.
This comment has been minimized.
By "dangling element" you mean In particular, LLVM does not try to know about all allocas in address space, it only cares about the ones it knows about, so |
This comment has been minimized.
This comment has been minimized.
IMHO that would be fine, if the
|
RalfJung
referenced this issue
Jun 21, 2017
Open
Clarify which inputs are permitted for the offset intrinsic (and the MIR binop) #38
This comment has been minimized.
This comment has been minimized.
|
We could treat any cast to a raw pointer to a zst as a constant producing an integer. Should be trivial to do as a Mir pass and has clear semantics imo. |
This comment has been minimized.
This comment has been minimized.
|
This can't be done on polymorphic code though, can it? |
This comment has been minimized.
This comment has been minimized.
|
@arielb1 Could you show where LLVM talks about treating ~0 specially? |
Mark-Simulacrum
added
T-compiler
T-lang
labels
Jun 23, 2017
Mark-Simulacrum
added
the
C-bug
label
Jul 28, 2017
This comment has been minimized.
This comment has been minimized.
|
I was going to fix this for the slice iterator in #46223, but I have yet to pick it up again (feel free to do that anyone). |
This comment has been minimized.
This comment has been minimized.
|
Thanks to @rkruppe for pointing out that this is actually a soundness issue. The following module should never panic: mod unique_token {
use std::sync::atomic::{AtomicBool, Ordering};
// With a private field so it can only be constructed inside this module
pub struct Token(());
// Stores whether we have already created a token
static GUARD : AtomicBool = AtomicBool::new(false);
impl Token {
pub fn new() -> Option<Token> {
if GUARD.compare_and_swap(false, true, Ordering::AcqRel) == false {
Some(Token(()))
} else {
None
}
}
pub fn take_two(a: &Token, b: &Token) {
// There's only ever one token so these have to be the same
assert_eq!(a as *const _, b as *const _,
"How can there be two tokes?!?");
}
}
}and yet here is how we can make it panic: use unique_token::Token;
fn main() {
let t = Token::new().expect("Couldn't even get a single token");
// make sure we can't get a second
assert!(Token::new().is_none());
let s = &[t];
let t1 = &s[0];
let t2 = s.iter().next().expect("Slice can't be empty");
Token::take_two(t1, t2);
} |
This comment has been minimized.
This comment has been minimized.
|
You can also get elements of slices through slice patterns, which don't squash ZST pointers to 0x1. You have a good argument for having slice iterators use the "real" address of the ZST instead of squashing it. cc @rust-lang/libs - what's the obstacle to not squashing pointers in iterators? |
arielb1
added
T-libs
I-unsound 💥
labels
Jul 7, 2018
This comment has been minimized.
This comment has been minimized.
|
Not sure whether we should tag this as I-unsound |
This comment has been minimized.
This comment has been minimized.
|
The iterators also play fast-and-loose with the alignment rules. For example, |
RalfJung
referenced this issue
Jul 10, 2018
Merged
slices: fix ZST slice iterators making up pointers; debug_assert alignment in from_raw_parts #52206
This comment has been minimized.
This comment has been minimized.
|
I have a proposed fix at #52206. |
RalfJung commentedJun 21, 2017
•
edited
The following test passes for slices over non-ZST, but fails for ZST:
Playpen
While pointers to ZSTs don't really matter as they will never be dereferenced, I think providing consistent addresses for the same element would still make sense.
Yet,
x2turns out to be0x55e742ee85dc, no idea where that address is coming from. The LLVM IR contains someundef, but I am not sure if that always indicates a problem.Generally, the iterator's treatment of ZST's seems a little fishy. Below
rust/src/libcore/slice/mod.rs
Line 777 in 4450779
getmethods defer to.offsetto compute the address of an element of the slice.offsetis only well-defined for in-bounds accesses, yet it is used here on a dangling pointer-to-ZST, with some non-0 offset.