Skip to content

Commit 986d7bb

Browse files
authored
Change push_next() to unsafe fn extend() and add push() alternative (ash-rs#909)
`push_next()` is totally `unsafe` because of dereferencing a chain of `p_next` pointers to find the end of the chain to insert, which was obfuscated by a large `unsafe` block for the `BaseOutStructure` pointer cast in commit c8c8f69 ("`next` can contain a pointer chain and we need to correct insert it."). While this function should definitely be marked unsafe, wrapping builders in `unsafe {}` en masse in user code isn't all too desirable, especially when this soundness issue only exists to optionally walk a `p_next` chain while most users are likely inserting bare structs without pointer chains most of the time. `push()` is introduced for this reason, remaining safe to call without any unintended raw pointer dereferences. `push_next()` has been renamed to `extend()` to more closely align with standard naming, and force existing users to notice this change and hopefully analyze their uses to decide which are safe/correct to switch over to safe `push()`.
1 parent 7dcf57b commit 986d7bb

File tree

5 files changed

+4743
-925
lines changed

5 files changed

+4743
-925
lines changed

Changelog.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
99

1010
### Added
1111

12+
- Added `push()` method to all root structs to insert a single extension-struct in the pointer chain. (#909)
1213
- Update Vulkan-Headers to 1.3.296 (#910)
1314
- Added `VK_KHR_get_display_properties2` instance extension (#932)
1415
- Added `VK_EXT_metal_objects` device extension (#942)
@@ -24,6 +25,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
2425
- `get_pipeline_executable_properties()`;
2526
- `get_pipeline_executable_statistics()`.
2627
The expected length of this array can be queried with the respective `*_len()` variant of these functions.
28+
- `push_next()` has been renamed to `extend()` and marked as `unsafe`. Users are encouraged to call `push()` for singular structs instead. (#909)
2729

2830
## [0.38.0] - 2024-04-01
2931

README.md

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -91,19 +91,19 @@ let device: Device = instance
9191

9292
### Pointer chains
9393

94-
Use `base.push_next(ext)` to insert `ext` at the front of the pointer chain attached to `base`.
94+
Use `base.push(ext)` to insert `ext` at the front of the pointer chain attached to `base`. If `ext` already contains a valid pointer chain of its own, `unsafe`ly call `extend()` instead.
9595

9696
```rust
9797
let mut variable_pointers = vk::PhysicalDeviceVariablePointerFeatures::default();
9898
let mut corner = vk::PhysicalDeviceCornerSampledImageFeaturesNV::default();
9999

100100
let mut device_create_info = vk::DeviceCreateInfo::default()
101-
.push_next(&mut corner)
102-
.push_next(&mut variable_pointers);
101+
.push(&mut corner)
102+
.push(&mut variable_pointers);
103103
```
104104

105-
The generic argument of `.push_next()` only allows valid structs to extend a given struct (known as [`structextends` in the Vulkan registry](https://registry.khronos.org/vulkan/specs/1.3/styleguide.html#extensions-interactions), mapped to `Extends*` traits).
106-
Only structs that are listed one or more times in any `structextends` will implement a `.push_next()`.
105+
The generic argument of `.push()` only allows valid structs to extend a given struct (known as [`structextends` in the Vulkan registry](https://registry.khronos.org/vulkan/specs/1.3/styleguide.html#extensions-interactions), mapped to `Extends*` traits).
106+
Only structs that are listed one or more times in any `structextends` will implement a `.push()`.
107107

108108
### Flags and constants as associated constants
109109

ash/src/lib.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -205,8 +205,8 @@ mod tests {
205205
<*mut _>::cast(&mut corner),
206206
];
207207
let mut device_create_info = vk::DeviceCreateInfo::default()
208-
.push_next(&mut corner)
209-
.push_next(&mut variable_pointers);
208+
.push(&mut corner)
209+
.push(&mut variable_pointers);
210210
let chain2: Vec<*mut vk::BaseOutStructure<'_>> = unsafe {
211211
vk::ptr_chain_iter(&mut device_create_info)
212212
.skip(1)

0 commit comments

Comments
 (0)