Skip to content

Commit e0c952f

Browse files
bors[bot]CAD97
andauthored
Merge #81
81: Improve ptr-union's behavior under strict provenance r=CAD97 a=CAD97 Co-authored-by: CAD97 <[email protected]>
2 parents f9821ca + 5180809 commit e0c952f

File tree

4 files changed

+48
-6
lines changed

4 files changed

+48
-6
lines changed

Cargo.lock

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

crates/ptr-union/Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
[package]
22
name = "ptr-union"
3-
version = "2.2.1"
3+
version = "2.2.2"
44
edition = "2018"
55

66
authors = ["Christopher Durham (cad97) <[email protected]>"]

crates/ptr-union/README.md

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,16 @@ by storing the tag in the alignment bits.
33

44
## Changelist
55

6+
### 2.2.2
7+
#### Fixed
8+
9+
- Crate now works under a [strict provenance] model. (In short, it doesn't use inttoptr.)
10+
- Crate is now tested with many more strictness Miri flags. Notably,
11+
- `-Zmiri-check-number-validity` and
12+
- `-Zmiri-tag-raw-pointers`
13+
14+
[strict provenance]: https://github.com/rust-lang/rust/issues/95228
15+
616
### 2.2.0
717
#### Added
818

crates/ptr-union/src/lib.rs

Lines changed: 36 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -38,29 +38,61 @@ const TAG_N: usize = 0b1101;
3838
const TAG_O: usize = 0b1110;
3939
const TAG_P: usize = 0b1111;
4040

41+
// See rust-lang/rust#95228 for why these are necessary.
42+
fn ptr_addr<T>(this: *mut T) -> usize {
43+
// FIXME(strict_provenance_magic): I am magic and should be a compiler intrinsic.
44+
this as usize
45+
}
46+
47+
fn ptr_with_addr<T>(this: *mut T, addr: usize) -> *mut T {
48+
// FIXME(strict_provenance_magic): I am magic and should be a compiler intrinsic.
49+
//
50+
// In the mean-time, this operation is defined to be "as if" it was
51+
// a wrapping_offset, so we can emulate it as such. This should properly
52+
// restore pointer provenance even under today's compiler.
53+
let this_addr = ptr_addr(this) as isize;
54+
let dest_addr = addr as isize;
55+
let offset = dest_addr.wrapping_sub(this_addr);
56+
57+
// This is the canonical desugarring of this operation
58+
this.cast::<u8>().wrapping_offset(offset).cast::<T>()
59+
}
60+
61+
fn ptr_map_addr<T>(this: *mut T, f: impl FnOnce(usize) -> usize) -> *mut T {
62+
ptr_with_addr(this, f(ptr_addr(this)))
63+
}
64+
65+
fn ptr_tag<T>(this: *mut T, tag: usize) -> *mut T {
66+
ptr_map_addr(this, |addr| addr | tag)
67+
}
68+
69+
fn ptr_mask<T>(this: *mut T, mask: usize) -> *mut T {
70+
ptr_map_addr(this, |addr| addr & mask)
71+
}
72+
4173
#[inline(always)]
4274
fn check_tag(ptr: ErasedPtr, mask: usize, tag: usize) -> bool {
4375
debug_assert_eq!(tag & mask, tag);
44-
(ptr.as_ptr() as usize & mask) == tag
76+
ptr_addr(ptr_mask(ptr.as_ptr(), mask)) == tag
4577
}
4678

4779
#[inline(always)]
4880
fn set_tag(ptr: ErasedPtr, mask: usize, tag: usize) -> ErasedPtr {
4981
debug_assert_eq!(tag & mask, tag);
5082
debug_assert!(check_tag(ptr, mask, 0));
51-
unsafe { ErasedPtr::new_unchecked((ptr.as_ptr() as usize | tag) as *mut _) }
83+
unsafe { ErasedPtr::new_unchecked(ptr_tag(ptr.as_ptr(), tag)) }
5284
}
5385

5486
#[inline(always)]
5587
fn unset_tag(ptr: ErasedPtr, mask: usize, tag: usize) -> ErasedPtr {
5688
debug_assert_eq!(tag & mask, tag);
5789
debug_assert!(check_tag(ptr, mask, tag));
58-
unsafe { ErasedPtr::new_unchecked((ptr.as_ptr() as usize & !mask) as *mut _) }
90+
unsafe { ErasedPtr::new_unchecked(ptr_mask(ptr.as_ptr(), !mask)) }
5991
}
6092

6193
#[inline(always)]
6294
fn unset_any_tag(ptr: ErasedPtr, mask: usize) -> ErasedPtr {
63-
unsafe { ErasedPtr::new_unchecked((ptr.as_ptr() as usize & !mask) as *mut _) }
95+
unsafe { ErasedPtr::new_unchecked(ptr_mask(ptr.as_ptr(), !mask)) }
6496
}
6597

6698
#[cfg(has_never)]

0 commit comments

Comments
 (0)