diff --git a/Cargo.lock b/Cargo.lock index 589e0516690..c8b125779b4 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1496,6 +1496,7 @@ dependencies = [ "rand_distr", "rustc-hash", "serde_json", + "sptr", "uuid", ] @@ -1660,6 +1661,7 @@ version = "1.0.0" dependencies = [ "allocator-api2", "naughty-strings", + "sptr", "tagged-pointer", ] @@ -4954,6 +4956,12 @@ version = "0.9.8" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6980e8d7511241f8acf4aebddbb1ff938df5eebe98691418c4468d0b72a96a67" +[[package]] +name = "sptr" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3b9b39299b249ad65f3b7e96443bad61c02ca5cd3589f46cb6d610a0fd6c0d6a" + [[package]] name = "stable_deref_trait" version = "1.2.0" diff --git a/profiling/Cargo.toml b/profiling/Cargo.toml index 59b94e06e6c..6a6a87d622f 100644 --- a/profiling/Cargo.toml +++ b/profiling/Cargo.toml @@ -34,6 +34,7 @@ serde_json = {version = "1.0"} rand = { version = "0.8.5" } rand_distr = { version = "0.4.3" } rustc-hash = "1.1.0" +sptr = "0.3" uuid = { version = "1.0", features = ["v4"] } [dev-dependencies] diff --git a/profiling/src/profiling/stack_walking.rs b/profiling/src/profiling/stack_walking.rs index 3695d9a6c07..fc4d57fa214 100644 --- a/profiling/src/profiling/stack_walking.rs +++ b/profiling/src/profiling/stack_walking.rs @@ -92,9 +92,13 @@ unsafe fn extract_file_and_line(execute_data: &zend_execute_data) -> (Option usize conv. let cached = unsafe { self.cache_slots.get_unchecked_mut(slot as usize) }; - let ptr = *cached as *mut ThinHeader; + let ptr = sptr::from_exposed_addr_mut(*cached); match NonNull::new(ptr) { Some(non_null) => { // SAFETY: the string set is only reset between requests, @@ -139,7 +143,7 @@ mod detail { let string = f()?; let thin_str = self.string_set.insert(&string); let non_null = thin_str.header_ptr(); - *cached = non_null.as_ptr() as usize; + *cached = non_null.as_ptr().expose_addr(); Some(string) } } diff --git a/thin-str/Cargo.toml b/thin-str/Cargo.toml index c0b57f151ba..a0df08e2c66 100644 --- a/thin-str/Cargo.toml +++ b/thin-str/Cargo.toml @@ -22,3 +22,4 @@ tagged-pointer = { version = "0.2", default-features = false } [dev-dependencies] naughty-strings = "0.2" +sptr = { version = "0.3", default-features = false } diff --git a/thin-str/src/thin_string.rs b/thin-str/src/thin_string.rs index e0424781808..1dd2ba4d97b 100644 --- a/thin-str/src/thin_string.rs +++ b/thin-str/src/thin_string.rs @@ -265,6 +265,10 @@ mod ext { #[cfg(test)] mod tests { + // See: https://doc.rust-lang.org/nightly/std/ptr/index.html#strict-provenance + #![allow(unstable_name_collisions, unused_imports)] + use sptr::Strict; + use super::*; use allocator_api2::alloc::Global; @@ -327,15 +331,19 @@ This is a tribute. fn test_round_tripping_to_usize() { let datadog = "See inside any stack, any app, at any scale, anywhere."; let string = ThinString::from(datadog); - - let bits = { + let ptr = { let thin_str = string.as_thin_str(); - let non_null = thin_str.header_ptr(); - non_null.as_ptr() as usize + thin_str.header_ptr().as_ptr() }; + let bits = ptr.addr(); + let restored = { - let non_null = unsafe { ptr::NonNull::new_unchecked(bits as *mut ThinHeader) }; + // with_addr allows us to restore the provenance of the pointer, + // and we can do this because we have the original to restore it. + // The actually PHP profiler will not have such things available, + // and should use `expose_addr` and similar. + let non_null = unsafe { ptr::NonNull::new_unchecked(ptr.with_addr(bits)) }; unsafe { ThinStr::from_header(non_null) } };