Call Vec::set_len() after checking for Vulkan errors (#684)

The entire reason for calling `unsafe` `set_len()` after the Vulkan
driver function call is to ensure the `Vec` never gives safe access to
uninitialized values (as allocted via `Vec::with_capacity()`).  This
contract is broken within the implementation of these functions by
temporarily setting a nonzero length when the Vulkan driver may not have
initialized the underlying data at all, and communicated this by
returning an error code.

Simply check the error code first, before jumping to a now-infallible
codepath that calls `.set_len()` and always returns `Ok()`.
This commit is contained in:
Marijn Suijten 2022-11-22 23:27:33 +01:00
parent 47ec56c30e
commit d176eef678
4 changed files with 25 additions and 19 deletions

View file

@ -1502,14 +1502,15 @@ impl Device {
create_info: &vk::DescriptorSetAllocateInfo,
) -> VkResult<Vec<vk::DescriptorSet>> {
let mut desc_set = Vec::with_capacity(create_info.descriptor_set_count as usize);
let err_code = (self.device_fn_1_0.allocate_descriptor_sets)(
(self.device_fn_1_0.allocate_descriptor_sets)(
self.handle(),
create_info,
desc_set.as_mut_ptr(),
);
)
.result()?;
desc_set.set_len(create_info.descriptor_set_count as usize);
err_code.result_with_success(desc_set)
Ok(desc_set)
}
/// <https://www.khronos.org/registry/vulkan/specs/1.3-extensions/man/html/vkCreateDescriptorSetLayout.html>
@ -2490,13 +2491,14 @@ impl Device {
create_info: &vk::CommandBufferAllocateInfo,
) -> VkResult<Vec<vk::CommandBuffer>> {
let mut buffers = Vec::with_capacity(create_info.command_buffer_count as usize);
let err_code = (self.device_fn_1_0.allocate_command_buffers)(
(self.device_fn_1_0.allocate_command_buffers)(
self.handle(),
create_info,
buffers.as_mut_ptr(),
);
)
.result()?;
buffers.set_len(create_info.command_buffer_count as usize);
err_code.result_with_success(buffers)
Ok(buffers)
}
/// <https://www.khronos.org/registry/vulkan/specs/1.3-extensions/man/html/vkCreateCommandPool.html>

View file

@ -28,15 +28,16 @@ impl DisplaySwapchain {
allocation_callbacks: Option<&vk::AllocationCallbacks>,
) -> VkResult<Vec<vk::SwapchainKHR>> {
let mut swapchains = Vec::with_capacity(create_infos.len());
let err_code = (self.fp.create_shared_swapchains_khr)(
(self.fp.create_shared_swapchains_khr)(
self.handle,
create_infos.len() as u32,
create_infos.as_ptr(),
allocation_callbacks.as_raw_ptr(),
swapchains.as_mut_ptr(),
);
)
.result()?;
swapchains.set_len(create_infos.len());
err_code.result_with_success(swapchains)
Ok(swapchains)
}
#[inline]

View file

@ -90,16 +90,17 @@ impl RayTracingPipeline {
data_size: usize,
) -> VkResult<Vec<u8>> {
let mut data = Vec::<u8>::with_capacity(data_size);
let err_code = (self.fp.get_ray_tracing_shader_group_handles_khr)(
(self.fp.get_ray_tracing_shader_group_handles_khr)(
self.handle,
pipeline,
first_group,
group_count,
data_size,
data.as_mut_ptr() as *mut std::ffi::c_void,
);
data.as_mut_ptr().cast(),
)
.result()?;
data.set_len(data_size);
err_code.result_with_success(data)
Ok(data)
}
/// <https://www.khronos.org/registry/vulkan/specs/1.3-extensions/man/html/vkGetRayTracingCaptureReplayShaderGroupHandlesKHR.html>
@ -111,8 +112,8 @@ impl RayTracingPipeline {
group_count: u32,
data_size: usize,
) -> VkResult<Vec<u8>> {
let mut data: Vec<u8> = Vec::with_capacity(data_size);
let err_code = (self
let mut data = Vec::<u8>::with_capacity(data_size);
(self
.fp
.get_ray_tracing_capture_replay_shader_group_handles_khr)(
self.handle,
@ -120,10 +121,11 @@ impl RayTracingPipeline {
first_group,
group_count,
data_size,
data.as_mut_ptr() as *mut _,
);
data.as_mut_ptr().cast(),
)
.result()?;
data.set_len(data_size);
err_code.result_with_success(data)
Ok(data)
}
/// <https://www.khronos.org/registry/vulkan/specs/1.3-extensions/man/html/vkCmdTraceRaysIndirectKHR.html>

View file

@ -49,8 +49,9 @@ where
let err_code = f(&mut count, data.as_mut_ptr());
if err_code != vk::Result::INCOMPLETE {
err_code.result()?;
data.set_len(count.try_into().expect("`N` failed to convert to `usize`"));
break err_code.result_with_success(data);
break Ok(data);
}
}
}