Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 8 additions & 1 deletion src/buffer.rs
Original file line number Diff line number Diff line change
Expand Up @@ -173,6 +173,8 @@ impl<'a, T> private::Sealed<T> for &'a mut [MaybeUninit<T>] {

#[inline]
unsafe fn assume_init(self, len: usize) -> Self::Output {
// The syscall may report more than the buffer holds, as in an xattr size query.
let len = len.min(self.len());
let (init, uninit) = self.split_at_mut(len);

// SAFETY: The user asserts that the slice is now initialized.
Expand All @@ -192,6 +194,8 @@ impl<'a, T, const N: usize> private::Sealed<T> for &'a mut [MaybeUninit<T>; N] {

#[inline]
unsafe fn assume_init(self, len: usize) -> Self::Output {
// The syscall may report more than the buffer holds, as in an xattr size query.
let len = len.min(self.len());
let (init, uninit) = self.split_at_mut(len);

// SAFETY: The user asserts that the slice is now initialized.
Expand All @@ -212,6 +216,8 @@ impl<'a, T> private::Sealed<T> for &'a mut Vec<MaybeUninit<T>> {

#[inline]
unsafe fn assume_init(self, len: usize) -> Self::Output {
// The syscall may report more than the buffer holds, as in an xattr size query.
let len = len.min(self.len());
let (init, uninit) = self.split_at_mut(len);

// SAFETY: The user asserts that the slice is now initialized.
Expand Down Expand Up @@ -316,7 +322,8 @@ mod private {
///
/// # Safety
///
/// At least `len` elements of the buffer must now be initialized.
/// At least `len` elements of the buffer, or the whole buffer if `len` is
/// larger, must now be initialized.
#[must_use]
unsafe fn assume_init(self, len: usize) -> Self::Output;
}
Expand Down
21 changes: 21 additions & 0 deletions tests/fs/xattr.rs
Original file line number Diff line number Diff line change
Expand Up @@ -131,6 +131,27 @@ fn xattr_basic() {
);
}

#[test]
fn xattr_size_query_uninit() {
use rustix::fs::XattrFlags;
use std::mem::MaybeUninit;

let tmp = tempfile::tempdir().unwrap();
let path = tmp.path().join("file");
std::fs::write(&path, b"").unwrap();
rustix::fs::setxattr(&path, "user.test", b"hello", XattrFlags::empty()).unwrap();

let empty: &mut [MaybeUninit<u8>] = &mut [];
let (init, uninit) = rustix::fs::getxattr(&path, "user.test", empty).unwrap();
assert!(init.is_empty());
assert!(uninit.is_empty());

let empty: &mut [MaybeUninit<u8>] = &mut [];
let (init, uninit) = rustix::fs::listxattr(&path, empty).unwrap();
assert!(init.is_empty());
assert!(uninit.is_empty());
}

/// To check the correctness of the tested implementations of *listxattr(), their output can be
/// compared to an external implementation, in this case listxattr() from the libc crate.
fn libc_listxattr(path: &str) -> usize {
Expand Down
Loading