-
Notifications
You must be signed in to change notification settings - Fork 13.1k
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
fix some uses of pointer intrinsics with invalid pointers #53804
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 | ||||||
---|---|---|---|---|---|---|---|---|
|
@@ -742,7 +742,9 @@ impl<K, V> RawTable<K, V> { | |||||||
) -> Result<RawTable<K, V>, CollectionAllocErr> { | ||||||||
unsafe { | ||||||||
let ret = RawTable::new_uninitialized_internal(capacity, fallibility)?; | ||||||||
ptr::write_bytes(ret.hashes.ptr(), 0, capacity); | ||||||||
if capacity > 0 { | ||||||||
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. Instead of adding this workaround, I would prefer if here: rust/src/libstd/collections/hash/table.rs Line 35 in 9f9f2c0
we would 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. /// Note: when the pointer is initialized to EMPTY `.ptr()` will return
/// null and the tag functions shouldn't be used.
The table states this, but there are no 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 am afraid of touching The pointer here was previously NULL, so I don't think it came from 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. If capacity == 0, then rust/src/libstd/collections/hash/table.rs Line 688 in 9f9f2c0
) hashes with this value:
hashes: TaggedHashUintPtr::new(EMPTY as *mut HashUint), which basically calls ( rust/src/libstd/collections/hash/table.rs Line 45 in 9f9f2c0
Unique::new_unchecked(EMPTY as *mut HashUint)
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.
Well, the tag functions cannot assert anything reasonable because the last bit can be either 0 or 1. I think this also uses values as sentinel values in ways it should not. But that really needs someone to actually dig in the code. I can open an issue about that if you want, right now I only have time to do the most obvious thing.
As the comment you quoted says, If 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.
Yeah, this is already an improvement. 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. Done, I opened #53853. Anything left to do in this PR? |
||||||||
ptr::write_bytes(ret.hashes.ptr(), 0, capacity); | ||||||||
} | ||||||||
Ok(ret) | ||||||||
} | ||||||||
} | ||||||||
|
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.
Would it be possible for
ptr::read
to contain adebug_assert_eq!(ptr.align_offset(align_of::<T>()), 0)
?If that assert fails, it would currently be UB, so we might as well just panic in debug builds to at least catch these inside of
std
on CI. Maybe someday users will benefit from these without having to use miri to detect these issues.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.
My plan was to open an E-easy issue (once #53783 lands) to decorate all these functions with a
debug_assert!
testing non-NULL and being aligned.I would however use
ptr as usize % mem::align_of<T>() == 0
, because your test will always fail on miri. Remember,align_offset
can spuriously "fail" (returnusize::max
).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.
That's a good idea.
I didn't know this :/ whyyyy
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.
Because we cannot implement it completely in miri/CTFE -- allocations do not actually have "real" base addresses there.
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.
Ah, that makes sense. This is getting off topic, but couldn't miri track the alignment requested for an allocation and use that in
align_offset
?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.
It could, and it could give a better return value in that case.
But
align_offset
is also used e.g. on a largeu8
allocation to find a subslice that is 256bit-aligned for use with SSE. There is no way for miri to provide an alignment stronger than what the allocation promises.So maybe it could be made good enough for your test, not sure... the
%
works today though.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.
It is a bit worrying that we might prefer slower run-time code because it works on miri to fast run-time code. Does the
%
lower to the same LLVM-IR thanalign_offset
, at least after runningopt
?An alternative is to use conditional compilation, and use
%
formiri
andalign_offset
for run-time rust.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.
I don't see how
%
could be any slower than the intrinsic. If anything,align_offset
is doing the harder job (computing which offset to add, not just testing it for 0) so I'd expect it to be slower.Currently, LLVM optimizes the to the same code to the extend that they get deduplicated.^^