fix: Require non-null pointer in StorePath

Fixes https://github.com/nixops4/nixops4/issues/65,
possible undefined behavior.

This doesn't make the code nice wrt *const/*mut distinction, but
since we're not mutating it, this should be fine.

(cherry picked from commit 75d448aad923a5f835f0562400e223df43103ea4)
This commit is contained in:
Robert Hensing 2024-12-16 14:11:17 +01:00
parent 28deb20a2b
commit 6193575d1e
2 changed files with 21 additions and 6 deletions

View file

@ -403,6 +403,11 @@ impl EvalState {
let mut paths = Vec::with_capacity(n as usize);
for i in 0..n {
let path = raw::realised_string_get_store_path(rs, i);
let path = NonNull::new(path as *mut raw::StorePath).ok_or_else(|| {
anyhow::format_err!(
"nix_realised_string_get_store_path returned a null pointer"
)
})?;
paths.push(StorePath::new_raw_clone(path));
}
paths

View file

@ -1,3 +1,5 @@
use std::ptr::NonNull;
use anyhow::Result;
use nix_c_raw as raw;
use nix_util::{
@ -6,38 +8,46 @@ use nix_util::{
};
pub struct StorePath {
raw: *mut raw::StorePath,
raw: NonNull<raw::StorePath>,
}
impl StorePath {
/// This is a low level function that you shouldn't have to call unless you are developing the Nix bindings.
///
/// Construct a new `StorePath` by first cloning the C store path.
/// This does not take ownership of the C store path, so it should be a borrowed value, or you should free it.
pub fn new_raw_clone(raw: *const raw::StorePath) -> Self {
Self::new_raw(unsafe { raw::store_path_clone(raw as *mut raw::StorePath) })
pub fn new_raw_clone(raw: NonNull<raw::StorePath>) -> Self {
Self::new_raw(
NonNull::new(unsafe { raw::store_path_clone(raw.as_ptr()) })
.or_else(|| panic!("nix_store_path_clone returned a null pointer"))
.unwrap(),
)
}
/// This is a low level function that you shouldn't have to call unless you are developing the Nix bindings.
///
/// Takes ownership of a C `nix_store_path`. It will be freed when the `StorePath` is dropped.
pub fn new_raw(raw: *mut raw::StorePath) -> Self {
pub fn new_raw(raw: NonNull<raw::StorePath>) -> Self {
StorePath { raw }
}
pub fn name(&self) -> Result<String> {
unsafe {
let mut r = result_string_init!();
raw::store_path_name(
self.raw,
self.as_ptr(),
Some(callback_get_result_string),
callback_get_result_string_data(&mut r),
);
r
}
}
pub fn as_ptr(&self) -> *mut nix_c_raw::StorePath {
self.raw.as_ptr()
}
}
impl Drop for StorePath {
fn drop(&mut self) {
unsafe {
raw::store_path_free(self.raw);
raw::store_path_free(self.as_ptr());
}
}
}