Don't crash when nullptr paired with len = 0

This commit is contained in:
topjohnwu 2022-09-15 16:56:22 -07:00
parent c6646efe68
commit af99c1b843
3 changed files with 30 additions and 10 deletions

View File

@ -7,10 +7,11 @@ use crate::{bfmt_cstr, errno, xopen};
mod unsafe_impl { mod unsafe_impl {
use std::ffi::CStr; use std::ffi::CStr;
use std::slice;
use libc::c_char; use libc::c_char;
use crate::slice_from_ptr_mut;
#[no_mangle] #[no_mangle]
pub unsafe extern "C" fn read_link(path: *const c_char, buf: *mut u8, bufsz: usize) -> isize { pub unsafe extern "C" fn read_link(path: *const c_char, buf: *mut u8, bufsz: usize) -> isize {
let r = libc::readlink(path, buf.cast(), bufsz - 1); let r = libc::readlink(path, buf.cast(), bufsz - 1);
@ -22,7 +23,7 @@ mod unsafe_impl {
#[no_mangle] #[no_mangle]
unsafe extern "C" fn canonical_path(path: *const c_char, buf: *mut u8, bufsz: usize) -> isize { unsafe extern "C" fn canonical_path(path: *const c_char, buf: *mut u8, bufsz: usize) -> isize {
super::canonical_path(CStr::from_ptr(path), slice::from_raw_parts_mut(buf, bufsz)) super::canonical_path(CStr::from_ptr(path), slice_from_ptr_mut(buf, bufsz))
} }
} }

View File

@ -1,7 +1,7 @@
use std::cmp::min; use std::cmp::min;
use std::ffi::CStr; use std::ffi::CStr;
use std::fmt;
use std::fmt::Arguments; use std::fmt::Arguments;
use std::{fmt, slice};
struct BufFmtWriter<'a> { struct BufFmtWriter<'a> {
buf: &'a mut [u8], buf: &'a mut [u8],
@ -118,3 +118,23 @@ pub fn errno() -> &'static mut i32 {
pub fn error_str() -> &'static str { pub fn error_str() -> &'static str {
unsafe { ptr_to_str(libc::strerror(*errno())) } unsafe { ptr_to_str(libc::strerror(*errno())) }
} }
// When len is 0, don't care whether buf is null or not
#[inline]
pub unsafe fn slice_from_ptr<'a, T>(buf: *const T, len: usize) -> &'a [T] {
if len == 0 {
&[]
} else {
slice::from_raw_parts(buf, len)
}
}
// When len is 0, don't care whether buf is null or not
#[inline]
pub unsafe fn slice_from_ptr_mut<'a, T>(buf: *mut T, len: usize) -> &'a mut [T] {
if len == 0 {
&mut []
} else {
slice::from_raw_parts_mut(buf, len)
}
}

View File

@ -12,36 +12,35 @@ use crate::{canonical_path, cstr, errno, error, mkdirs, perror, ptr_to_str, read
mod unsafe_impl { mod unsafe_impl {
use std::ffi::CStr; use std::ffi::CStr;
use std::os::unix::io::RawFd; use std::os::unix::io::RawFd;
use std::slice;
use cfg_if::cfg_if; use cfg_if::cfg_if;
use libc::{c_char, nfds_t, off_t, pollfd}; use libc::{c_char, nfds_t, off_t, pollfd};
use crate::{perror, ptr_to_str}; use crate::{perror, ptr_to_str, slice_from_ptr, slice_from_ptr_mut};
#[no_mangle] #[no_mangle]
unsafe extern "C" fn xwrite(fd: RawFd, buf: *const u8, bufsz: usize) -> isize { unsafe extern "C" fn xwrite(fd: RawFd, buf: *const u8, bufsz: usize) -> isize {
super::xwrite(fd, slice::from_raw_parts(buf, bufsz)) super::xwrite(fd, slice_from_ptr(buf, bufsz))
} }
#[no_mangle] #[no_mangle]
unsafe extern "C" fn xread(fd: RawFd, buf: *mut u8, bufsz: usize) -> isize { unsafe extern "C" fn xread(fd: RawFd, buf: *mut u8, bufsz: usize) -> isize {
super::xread(fd, slice::from_raw_parts_mut(buf, bufsz)) super::xread(fd, slice_from_ptr_mut(buf, bufsz))
} }
#[no_mangle] #[no_mangle]
unsafe extern "C" fn xxread(fd: RawFd, buf: *mut u8, bufsz: usize) -> isize { unsafe extern "C" fn xxread(fd: RawFd, buf: *mut u8, bufsz: usize) -> isize {
super::xxread(fd, slice::from_raw_parts_mut(buf, bufsz)) super::xxread(fd, slice_from_ptr_mut(buf, bufsz))
} }
#[no_mangle] #[no_mangle]
unsafe extern "C" fn xcanonical_path(path: *const c_char, buf: *mut u8, bufsz: usize) -> isize { unsafe extern "C" fn xcanonical_path(path: *const c_char, buf: *mut u8, bufsz: usize) -> isize {
super::xcanonical_path(CStr::from_ptr(path), slice::from_raw_parts_mut(buf, bufsz)) super::xcanonical_path(CStr::from_ptr(path), slice_from_ptr_mut(buf, bufsz))
} }
#[no_mangle] #[no_mangle]
unsafe extern "C" fn xreadlink(path: *const c_char, buf: *mut u8, bufsz: usize) -> isize { unsafe extern "C" fn xreadlink(path: *const c_char, buf: *mut u8, bufsz: usize) -> isize {
super::xreadlink(CStr::from_ptr(path), slice::from_raw_parts_mut(buf, bufsz)) super::xreadlink(CStr::from_ptr(path), slice_from_ptr_mut(buf, bufsz))
} }
#[no_mangle] #[no_mangle]