warning: dereferencing a null pointer
--> src/generated/vulkan_bundle.rs:62648:14
|
62648 | &(*(::std::ptr::null::<VkPhysicalDeviceRayQueryFeaturesKHR>())).rayQuery as *const _
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ this code causes undefined behavior when executed
assert_eq!(
unsafe {
&(*(::std::ptr::null::<VkPhysicalDeviceRayQueryFeaturesKHR>())).rayQuery as *const _
as usize
},
16usize,
concat!(
"Offset of field: ",
stringify!(VkPhysicalDeviceRayQueryFeaturesKHR),
"::",
stringify!(rayQuery)
)
);
Test results:
test generated::vulkan_bundle::bindgen_test_layout_VkPhysicalDeviceTimelineSemaphoreFeatures ... ok
test generated::vulkan_bundle::bindgen_test_layout_VkPhysicalDeviceVulkan12Features ... ok
test generated::vulkan_bundle::bindgen_test_layout_VkPhysicalDeviceWorkgroupMemoryExplicitLayoutFeaturesKHR ... ok
test result: ok. 560 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.74s
I got hundreds of warnings, in the tests generated by bindgen 0.59.1, that never appeared before, I recently updated to rust 1.55. The warning seems to make sense to me, a null pointer is created and then a member is accessed through it. The strange thing is that it runs normally. What could be happening?
What it acutally does is &(TypedNull.field) as *FieldPtr as usize, so it doesn't really dereference the pointer, it just calculates the offset to field in a roundabout way (if null was a proper *TypedNull, what would be the adress of it's field).
Not sure if this is a good way of getting the offset or not, but I don't think it actually executes anything undefined, it just looks at it rather closely ...
Creating an invalid pointer is not UB, only dereferencing it is. And yes, this code looks dangerously close to UB, but it doesn't actually dereference the bad pointer.
Note, however, that the expr in addr_of!(expr) is still subject to all the usual rules. In particular, addr_of!(*ptr::null()) is Undefined Behavior because it dereferences a null pointer.
So more is needed to fix bindgen's mess here. I think you could do
let x = MaybeUninit::uninit();
unsafe { addr_of!((*x.as_ptr()).field) } as usize - x.as_ptr() as usize
MaybeUninit is certainly the mechanism used by the offset_of! macro, which there's been talk of upstreaming. Don't know if it would be worth pulling in for the generated code.