From 02780057f0dad0c607f5e1d91ccab80e22cf15e4 Mon Sep 17 00:00:00 2001 From: Martin Welgemoed <git@mwelgemoed.nl> Date: Thu, 7 Dec 2023 15:39:38 +0000 Subject: [PATCH] Fixed utimes segfault when given nullptr --- src/header/sys_time/mod.rs | 31 ++++++++++++++++++++----------- src/platform/redox/libredox.rs | 24 +++++++++++++++++++----- 2 files changed, 39 insertions(+), 16 deletions(-) diff --git a/src/header/sys_time/mod.rs b/src/header/sys_time/mod.rs index edb2fc92d..de7d34b6f 100644 --- a/src/header/sys_time/mod.rs +++ b/src/header/sys_time/mod.rs @@ -5,6 +5,7 @@ use crate::{ header::time::timespec, platform::{types::*, Pal, PalSignal, Sys}, }; +use core::ptr::null; pub const ITIMER_REAL: c_int = 0; pub const ITIMER_VIRTUAL: c_int = 1; @@ -57,15 +58,23 @@ pub extern "C" fn gettimeofday(tp: *mut timeval, tzp: *mut timezone) -> c_int { #[no_mangle] pub unsafe extern "C" fn utimes(path: *const c_char, times: *const timeval) -> c_int { let path = CStr::from_ptr(path); - let times_spec = [ - timespec { - tv_sec: (*times.offset(0)).tv_sec, - tv_nsec: ((*times.offset(0)).tv_usec as c_long) * 1000, - }, - timespec { - tv_sec: (*times.offset(1)).tv_sec, - tv_nsec: ((*times.offset(1)).tv_usec as c_long) * 1000, - }, - ]; - Sys::utimens(path, times_spec.as_ptr()) + // Nullptr is valid here, it means "use current time" + let times_spec = if times.is_null() { + null() + } else { + { + [ + timespec { + tv_sec: (*times.offset(0)).tv_sec, + tv_nsec: ((*times.offset(0)).tv_usec as c_long) * 1000, + }, + timespec { + tv_sec: (*times.offset(1)).tv_sec, + tv_nsec: ((*times.offset(1)).tv_usec as c_long) * 1000, + }, + ] + } + .as_ptr() + }; + Sys::utimens(path, times_spec) } diff --git a/src/platform/redox/libredox.rs b/src/platform/redox/libredox.rs index df67379f3..09686e588 100644 --- a/src/platform/redox/libredox.rs +++ b/src/platform/redox/libredox.rs @@ -3,7 +3,7 @@ use core::{slice, str}; use syscall::{Error, Result, WaitFlags, EMFILE}; use crate::{ - header::{signal::sigaction, time::timespec}, + header::{signal::sigaction, sys_stat::UTIME_NOW, time::timespec}, platform::types::*, }; @@ -77,10 +77,24 @@ pub unsafe fn fstatvfs( Ok(()) } pub unsafe fn futimens(fd: usize, times: *const timespec) -> syscall::Result<()> { - let times = times - .cast::<[timespec; 2]>() - .read() - .map(|ts| syscall::TimeSpec::from(&ts)); + let times = if times.is_null() { + // null means set to current time using special UTIME_NOW value (tv_sec is ignored in that case) + [ + syscall::TimeSpec { + tv_sec: 0, + tv_nsec: UTIME_NOW as c_int, + }, + syscall::TimeSpec { + tv_sec: 0, + tv_nsec: UTIME_NOW as c_int, + }, + ] + } else { + times + .cast::<[timespec; 2]>() + .read() + .map(|ts| syscall::TimeSpec::from(&ts)) + }; syscall::futimens(fd as usize, ×)?; Ok(()) } -- GitLab