{"record":{"id":"c756e06213270262","repo":"can1357/oh-my-pi","slug":"path-contains-nul","errorCode":null,"errorMessage":"path contains NUL","messagePattern":"path contains NUL","errorType":"error_code","errorClass":"io::Error","httpStatus":null,"severity":"error","filePath":"crates/pi-walker/src/lib.rs","lineNumber":3567,"sourceCode":"\t\t\t\t\t},\n\t\t\t\t\tErr(err) if is_skippable_entry_error(&err) => continue,\n\t\t\t\t\tErr(err) => return Err(err.into()),\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tlet raw_entry =\n\t\t\t\tRawDirEntry { name: Cow::Owned(entry.file_name()), file_type, mtime, size };\n\n\t\t\tif emit(raw_entry).map_err(ReadDirError::Walk)? == ReadDirControl::Stop {\n\t\t\t\treturn Ok(ReadDirControl::Stop);\n\t\t\t}\n\t\t}\n\t\tOk(ReadDirControl::Continue)\n\t}\n\n\tfn open_dir(path: &Path) -> io::Result<FdGuard> {\n\t\tlet path = CString::new(path.as_os_str().as_bytes())\n\t\t\t.map_err(|_| io::Error::new(io::ErrorKind::InvalidInput, \"path contains NUL\"))?;\n\t\t// SAFETY: `path` is a NUL-terminated C string; flags open the directory for\n\t\t// metadata traversal only and do not transfer ownership of the string.\n\t\tlet fd =\n\t\t\tunsafe { libc::open(path.as_ptr(), libc::O_RDONLY | libc::O_DIRECTORY | libc::O_CLOEXEC) };\n\t\tif fd < 0 {\n\t\t\tErr(io::Error::last_os_error())\n\t\t} else {\n\t\t\tOk(FdGuard(fd))\n\t\t}\n\t}\n\n\tfn parse_record(record: &[u8], detail: WalkDetail) -> io::Result<Option<RawDirEntry<'_>>> {\n\t\tlet mut cursor = size_of::<u32>();\n\t\tlet name_ref_start = cursor;\n\t\tlet name_ref = read_value::<libc::attrreference_t>(record, &mut cursor)?;\n\t\tlet obj_type = read_value::<u32>(record, &mut cursor)?;\n\t\tlet (mtime, data_length) = if detail == WalkDetail::Full {\n\t\t\tlet modified = read_value::<libc::timespec>(record, &mut cursor)?;","sourceCodeStart":3549,"sourceCodeEnd":3585,"githubUrl":"https://github.com/can1357/oh-my-pi/blob/969062200754ea02cfac922e5ebb8c608c079e15/crates/pi-walker/src/lib.rs#L3549-L3585","documentation":"pi-walker's directory-descriptor helper converts a Path's bytes to a CString before calling libc::open, and conversion fails if the path embeds a NUL byte (0x00). Rust Paths can contain interior NULs; libc APIs are NUL-terminated C strings, so such a path can never be opened. The walker maps the failure to io::ErrorKind::InvalidInput with this message.","triggerScenarios":"Calling open_dir with a Path whose OS bytes contain an interior 0x00 byte; typically reached via walk/read_dir APIs when the filesystem tree (or a crafted path input) contains NUL in a component.","commonSituations":"Paths sourced from binary data, corrupted filesystem entries, or user/network input that was not sanitized; rare on normal trees since most filesystems forbid NUL in names.","solutions":["Sanitize or reject paths containing interior NUL bytes before passing them to the walker.","Find the source of the malformed path (decoded buffer, binary format, database) and fix the producer.","Catch io::ErrorKind::InvalidInput with this message and surface a user-facing validation error instead of walking."],"exampleFix":"// before\nwalker.walk(untrustedPath);\n// after\nif (untrustedPath.as_os_str().as_bytes().contains(&0)) {\n  return Err(\"path contains NUL byte\");\n}\nwalker.walk(untrustedPath);","handlingStrategy":"validation","validationCode":"if (path.as_os_str().as_bytes().contains(&0)) {\n  return Err(io::Error::new(io::ErrorKind::InvalidInput, \"rejecting path with NUL\"));\n}","typeGuard":null,"tryCatchPattern":"match walker.walk(path) {\n  Err(e) if e.kind() == io::ErrorKind::InvalidInput => eprintln!(\"invalid path: {e}\"),\n  Err(e) => return Err(e),\n  Ok(()) => {},\n}","preventionTips":["Validate paths from untrusted/binary sources before walking.","Never build Paths from raw byte buffers without a NUL check.","Log and skip invalid paths instead of aborting the whole walk."],"tags":["filesystem","invalid-input","nul-byte","linux"],"backgroundTag":"nul-byte-in-path","analyzedSha":"969062200754ea02cfac922e5ebb8c608c079e15","analyzedAt":"2026-08-31T10:29:35.737Z","schemaVersion":2},"datasetVersion":"2026-08-31T14:17:45.589Z"}