can1357/oh-my-pi · error · io::Error

entry name contains NUL

Error message

entry name contains NUL

What it means

stat_entry converts a directory-entry name (raw bytes from getdents) into a CString for statx; an interior NUL makes conversion impossible, so it returns InvalidInput with this message. Entry names should never contain NUL on a healthy filesystem, so this guards against corrupt directory data or memory-safety hazards from passing the name to libc.

Source

Thrown at crates/pi-walker/src/lib.rs:3839

			.map_err(|_| io::Error::new(io::ErrorKind::InvalidInput, "path contains NUL"))?;
		// SAFETY: `path` is a NUL-terminated C string; flags request a directory
		// descriptor used only with getdents/statx and do not retain the pointer.
		let fd =
			unsafe { libc::open(path.as_ptr(), libc::O_RDONLY | libc::O_DIRECTORY | libc::O_CLOEXEC) };
		if fd < 0 {
			Err(io::Error::last_os_error())
		} else {
			Ok(FdGuard(fd))
		}
	}

	fn stat_entry(
		dirfd: libc::c_int,
		name: &[u8],
		detail: WalkDetail,
	) -> io::Result<Option<EntryStat>> {
		let name = CString::new(name)
			.map_err(|_| io::Error::new(io::ErrorKind::InvalidInput, "entry name contains NUL"))?;
		match statx_entry(dirfd, &name, detail) {
			Ok(value) => Ok(value),
			Err(err) if matches!(err.raw_os_error(), Some(libc::ENOSYS | libc::EINVAL)) => {
				fstatat_entry(dirfd, &name, detail)
			},
			Err(err) => Err(err),
		}
	}

	fn statx_entry(
		dirfd: libc::c_int,
		name: &CString,
		detail: WalkDetail,
	) -> io::Result<Option<EntryStat>> {
		// SAFETY: `Statx` is a plain-old-data buffer whose all-zero value is a
		// valid initialization before the kernel fills it.
		let mut statx = unsafe { zeroed::<Statx>() };
		let mask = if detail == WalkDetail::Full {

View on GitHub (pinned to 9690622007)

Solutions

  1. Investigate the filesystem or mount producing entries with NUL in names (corruption, FUSE bug).
  2. Skip or report such entries: catch InvalidInput and continue the walk instead of failing the whole traversal.
  3. If fuzz-testing, treat this as expected validation behavior and assert on it rather than fixing the walker.
Defensive patterns

Strategy: try-catch

Try / catch

// walker callback
Err(e) if e.kind() == io::ErrorKind::InvalidInput => {
  // entry name corrupt; skip entry, continue walk
  ReadDirControl::Continue
}

Prevention

When it happens

Trigger: A directory stream yields an entry whose raw name bytes include 0x00, then the walker attempts statx/fstatat metadata lookup on that entry.

Common situations: Traversing a corrupted or synthetic filesystem, fuzzing the walker, or reading directory data from a misbehaving FUSE/overlay mount.

Related errors


AI-assisted analysis of can1357/oh-my-pi@9690622007 (2026-08-31). Data as JSON: /api/errors/2b8bb19554e10603. Report an issue: GitHub.