[RFC] final time64 switch-over patch series

Submitted by Rich Felker on Aug. 4, 2019, 6:11 p.m.

Details

Message ID 20190804181148.GN9017@brightrain.aerifal.cx
State New
Series "final time64 switch-over patch series"
Headers show

Commit Message

Rich Felker Aug. 4, 2019, 6:11 p.m.
On Sun, Aug 04, 2019 at 12:33:16AM -0400, Rich Felker wrote:
> On Fri, Aug 02, 2019 at 05:44:33PM -0400, Rich Felker wrote:
> > diff --git a/compat/time32/ppoll_time32.c b/compat/time32/ppoll_time32.c
> > new file mode 100644
> > index 00000000..d1eef134
> > --- /dev/null
> > +++ b/compat/time32/ppoll_time32.c
> > @@ -0,0 +1,10 @@
> > +#include "time32.h"
> > +#define _GNU_SOURCE
> > +#include <time.h>
> > +#include <poll.h>
> > +
> > +int __ppoll_time32(struct pollfd *fds, nfds_t n, const struct timespec32 *ts32, const sigset_t *mask)
> > +{
> > +	return ppoll(fds, n, (&(struct timespec){
> > +		.tv_sec = ts32->tv_sec, .tv_nsec = ts32->tv_nsec}), mask);
> > +}
> > diff --git a/compat/time32/pselect_time32.c b/compat/time32/pselect_time32.c
> > new file mode 100644
> > index 00000000..5b358c73
> > --- /dev/null
> > +++ b/compat/time32/pselect_time32.c
> > @@ -0,0 +1,9 @@
> > +#include "time32.h"
> > +#include <time.h>
> > +#include <sys/select.h>
> > +
> > +int __pselect_time32(int n, fd_set *restrict rfds, fd_set *restrict wfds, fd_set *restrict efds, const struct timespec32 *restrict ts32, const sigset_t *restrict mask)
> > +{
> > +	return pselect(n, rfds, wfds, efds, (&(struct timespec){
> > +		.tv_sec = ts32->tv_sec, .tv_nsec = ts32->tv_nsec}), mask);
> > +}
> > diff --git a/compat/time32/select_time32.c b/compat/time32/select_time32.c
> > new file mode 100644
> > index 00000000..2bd76e33
> > --- /dev/null
> > +++ b/compat/time32/select_time32.c
> > @@ -0,0 +1,10 @@
> > +#include "time32.h"
> > +#include <time.h>
> > +#include <sys/time.h>
> > +#include <sys/select.h>
> > +
> > +int __select_time32(int n, fd_set *restrict rfds, fd_set *restrict wfds, fd_set *restrict efds, struct timeval32 *restrict tv32)
> > +{
> > +	return select(n, rfds, wfds, efds, (&(struct timeval){
> > +		.tv_sec = tv32->tv_sec, .tv_usec = tv32->tv_usec}));
> > +}
> 
> These all fail to check the timeout argument is non-null before
> accessing it; caught in testing against Adelie and Alpine i386.
> 
> There may be other functions with the same problem; need to review
> them all for this.

Lots more. Patch attached. I also found one place (timer[fd]_settime)
where it's beneficial to avoid passing a pointer to "old" (the time64
intermediate buffer) when "old32" (the argument) is null -- this
avoids the real function having to try the time64 syscall since it
doesn't know if the result will fit in 32-bit. There may be other
places like this that would be nice to optimize too.

FWIW the mix of !ts32 ? 0 : ... and ts32 ? ... : 0 idioms is
intentional for legibility; the former is in some sense anti-idiomatic
but avoids separating the trivial case far away from the condition
where it's not immediately visible what it goes with. The latter (more
typical) was done in a few places where it fits in the line structure
better.

Rich

Patch hide | download patch | download mbox

diff --git a/compat/time32/adjtime32.c b/compat/time32/adjtime32.c
index 459be156..b0042c63 100644
--- a/compat/time32/adjtime32.c
+++ b/compat/time32/adjtime32.c
@@ -13,7 +13,9 @@  int __adjtime32(const struct timeval32 *in32, struct timeval32 *out32)
 	if (r) return r;
 	/* We can't range-check the result because success was already
 	 * committed by the above call. */
-	out32->tv_sec = out.tv_sec;
-	out32->tv_usec = out.tv_usec;
+	if (out32) {
+		out32->tv_sec = out.tv_sec;
+		out32->tv_usec = out.tv_usec;
+	}
 	return r;
 }
diff --git a/compat/time32/aio_suspend_time32.c b/compat/time32/aio_suspend_time32.c
index 0c43ddee..ed5119bd 100644
--- a/compat/time32/aio_suspend_time32.c
+++ b/compat/time32/aio_suspend_time32.c
@@ -4,8 +4,8 @@ 
 
 int __aio_suspend_time32(const struct aiocb *const cbs[], int cnt, const struct timespec32 *ts32)
 {
-	return aio_suspend(cbs, cnt, (&(struct timespec){
-		.tv_sec = ts32->tv_sec, .tv_nsec = ts32->tv_nsec}));
+	return aio_suspend(cbs, cnt, ts32 ? (&(struct timespec){
+		.tv_sec = ts32->tv_sec, .tv_nsec = ts32->tv_nsec}) : 0);
 }
 
 weak_alias(aio_suspend, aio_suspend64);
diff --git a/compat/time32/cnd_timedwait_time32.c b/compat/time32/cnd_timedwait_time32.c
index 46e7e289..314251d1 100644
--- a/compat/time32/cnd_timedwait_time32.c
+++ b/compat/time32/cnd_timedwait_time32.c
@@ -4,6 +4,6 @@ 
 
 int __cnd_timedwait_time32(cnd_t *restrict c, mtx_t *restrict m, const struct timespec32 *restrict ts32)
 {
-	return cnd_timedwait(c, m, (&(struct timespec){
-		.tv_sec = ts32->tv_sec, .tv_nsec = ts32->tv_nsec}));
+	return cnd_timedwait(c, m, ts32 ? (&(struct timespec){
+		.tv_sec = ts32->tv_sec, .tv_nsec = ts32->tv_nsec}) : 0);
 }
diff --git a/compat/time32/futimens_time32.c b/compat/time32/futimens_time32.c
index 06fa1947..7856f176 100644
--- a/compat/time32/futimens_time32.c
+++ b/compat/time32/futimens_time32.c
@@ -4,7 +4,7 @@ 
 
 int __futimens_time32(int fd, const struct timespec32 *times32)
 {
-	return futimens(fd, ((struct timespec[2]){
+	return futimens(fd, !times32 ? 0 : ((struct timespec[2]){
 		{.tv_sec = times32[0].tv_sec,.tv_nsec = times32[0].tv_nsec},
 		{.tv_sec = times32[1].tv_sec,.tv_nsec = times32[1].tv_nsec}}));
 }
diff --git a/compat/time32/futimes_time32.c b/compat/time32/futimes_time32.c
index edee9f48..f29533f1 100644
--- a/compat/time32/futimes_time32.c
+++ b/compat/time32/futimes_time32.c
@@ -6,7 +6,7 @@ 
 
 int __futimes_time32(int fd, const struct timeval32 times32[2])
 {
-	return futimes(fd, ((struct timeval[2]){
+	return futimes(fd, !times32 ? 0 : ((struct timeval[2]){
 		{.tv_sec = times32[0].tv_sec,.tv_usec = times32[0].tv_usec},
 		{.tv_sec = times32[1].tv_sec,.tv_usec = times32[1].tv_usec}}));
 }
diff --git a/compat/time32/futimesat_time32.c b/compat/time32/futimesat_time32.c
index 54d1573c..5a1295bd 100644
--- a/compat/time32/futimesat_time32.c
+++ b/compat/time32/futimesat_time32.c
@@ -6,7 +6,7 @@ 
 
 int __futimesat_time32(int dirfd, const char *pathname, const struct timeval32 times32[2])
 {
-	return futimesat(dirfd, pathname, ((struct timeval[2]){
+	return futimesat(dirfd, pathname, !times32 ? 0 : ((struct timeval[2]){
 		{.tv_sec = times32[0].tv_sec,.tv_usec = times32[0].tv_usec},
 		{.tv_sec = times32[1].tv_sec,.tv_usec = times32[1].tv_usec}}));
 }
diff --git a/compat/time32/gettimeofday_time32.c b/compat/time32/gettimeofday_time32.c
index 3a39775c..1f3ce68e 100644
--- a/compat/time32/gettimeofday_time32.c
+++ b/compat/time32/gettimeofday_time32.c
@@ -6,6 +6,7 @@ 
 int __gettimeofday_time32(struct timeval32 *tv32, void *tz)
 {
 	struct timeval tv;
+	if (!tv32) return 0;
 	int r = gettimeofday(&tv, 0);
 	if (r) return r;
 	if (tv.tv_sec < INT32_MIN || tv.tv_sec > INT32_MAX) {
diff --git a/compat/time32/lutimes_time32.c b/compat/time32/lutimes_time32.c
index b418a2eb..7f75cd4a 100644
--- a/compat/time32/lutimes_time32.c
+++ b/compat/time32/lutimes_time32.c
@@ -6,7 +6,7 @@ 
 
 int __lutimes_time32(const char *path, const struct timeval32 times32[2])
 {
-	return lutimes(path, ((struct timeval[2]){
+	return lutimes(path, !times32 ? 0 : ((struct timeval[2]){
 		{.tv_sec = times32[0].tv_sec,.tv_usec = times32[0].tv_usec},
 		{.tv_sec = times32[1].tv_sec,.tv_usec = times32[1].tv_usec}}));
 }
diff --git a/compat/time32/mq_timedreceive_time32.c b/compat/time32/mq_timedreceive_time32.c
index 25abe9da..211cea4b 100644
--- a/compat/time32/mq_timedreceive_time32.c
+++ b/compat/time32/mq_timedreceive_time32.c
@@ -4,6 +4,6 @@ 
 
 ssize_t __mq_timedreceive_time32(mqd_t mqd, char *restrict msg, size_t len, unsigned *restrict prio, const struct timespec32 *restrict ts32)
 {
-	return mq_timedreceive(mqd, msg, len, prio, (&(struct timespec){
-		.tv_sec = ts32->tv_sec, .tv_nsec = ts32->tv_nsec}));
+	return mq_timedreceive(mqd, msg, len, prio, ts32 ? (&(struct timespec){
+		.tv_sec = ts32->tv_sec, .tv_nsec = ts32->tv_nsec}) : 0);
 }
diff --git a/compat/time32/mq_timedsend_time32.c b/compat/time32/mq_timedsend_time32.c
index 2a2fea3d..93b697a7 100644
--- a/compat/time32/mq_timedsend_time32.c
+++ b/compat/time32/mq_timedsend_time32.c
@@ -4,6 +4,6 @@ 
 
 int __mq_timedsend_time32(mqd_t mqd, const char *msg, size_t len, unsigned prio, const struct timespec32 *ts32)
 {
-	return mq_timedsend(mqd, msg, len, prio, (&(struct timespec){
-		.tv_sec = ts32->tv_sec, .tv_nsec = ts32->tv_nsec}));
+	return mq_timedsend(mqd, msg, len, prio, ts32 ? (&(struct timespec){
+		.tv_sec = ts32->tv_sec, .tv_nsec = ts32->tv_nsec}) : 0);
 }
diff --git a/compat/time32/mtx_timedlock_time32.c b/compat/time32/mtx_timedlock_time32.c
index 7f187be8..a01f09b8 100644
--- a/compat/time32/mtx_timedlock_time32.c
+++ b/compat/time32/mtx_timedlock_time32.c
@@ -4,6 +4,6 @@ 
 
 int __mtx_timedlock_time32(mtx_t *restrict m, const struct timespec32 *restrict ts32)
 {
-	return mtx_timedlock(m, (&(struct timespec){
+	return mtx_timedlock(m, !ts32 ? 0 : (&(struct timespec){
 		.tv_sec = ts32->tv_sec, .tv_nsec = ts32->tv_nsec}));
 }
diff --git a/compat/time32/ppoll_time32.c b/compat/time32/ppoll_time32.c
index d1eef134..43b4b0df 100644
--- a/compat/time32/ppoll_time32.c
+++ b/compat/time32/ppoll_time32.c
@@ -5,6 +5,6 @@ 
 
 int __ppoll_time32(struct pollfd *fds, nfds_t n, const struct timespec32 *ts32, const sigset_t *mask)
 {
-	return ppoll(fds, n, (&(struct timespec){
+	return ppoll(fds, n, !ts32 ? 0 : (&(struct timespec){
 		.tv_sec = ts32->tv_sec, .tv_nsec = ts32->tv_nsec}), mask);
 }
diff --git a/compat/time32/pselect_time32.c b/compat/time32/pselect_time32.c
index 5b358c73..ecaa8f86 100644
--- a/compat/time32/pselect_time32.c
+++ b/compat/time32/pselect_time32.c
@@ -4,6 +4,6 @@ 
 
 int __pselect_time32(int n, fd_set *restrict rfds, fd_set *restrict wfds, fd_set *restrict efds, const struct timespec32 *restrict ts32, const sigset_t *restrict mask)
 {
-	return pselect(n, rfds, wfds, efds, (&(struct timespec){
+	return pselect(n, rfds, wfds, efds, !ts32 ? 0 : (&(struct timespec){
 		.tv_sec = ts32->tv_sec, .tv_nsec = ts32->tv_nsec}), mask);
 }
diff --git a/compat/time32/pthread_cond_timedwait_time32.c b/compat/time32/pthread_cond_timedwait_time32.c
index 4f80a362..fba1f2a9 100644
--- a/compat/time32/pthread_cond_timedwait_time32.c
+++ b/compat/time32/pthread_cond_timedwait_time32.c
@@ -4,6 +4,6 @@ 
 
 int __pthread_cond_timedwait_time32(pthread_cond_t *restrict c, pthread_mutex_t *restrict m, const struct timespec32 *restrict ts32)
 {
-	return pthread_cond_timedwait(c, m, (&(struct timespec){
+	return pthread_cond_timedwait(c, m, !ts32 ? 0 : (&(struct timespec){
 		.tv_sec = ts32->tv_sec, .tv_nsec = ts32->tv_nsec}));
 }
diff --git a/compat/time32/pthread_mutex_timedlock_time32.c b/compat/time32/pthread_mutex_timedlock_time32.c
index 400a0120..2d29602c 100644
--- a/compat/time32/pthread_mutex_timedlock_time32.c
+++ b/compat/time32/pthread_mutex_timedlock_time32.c
@@ -4,6 +4,6 @@ 
 
 int __pthread_mutex_timedlock_time32(pthread_mutex_t *restrict m, const struct timespec32 *restrict ts32)
 {
-	return pthread_mutex_timedlock(m, (&(struct timespec){
+	return pthread_mutex_timedlock(m, !ts32 ? 0 : (&(struct timespec){
 		.tv_sec = ts32->tv_sec, .tv_nsec = ts32->tv_nsec}));
 }
diff --git a/compat/time32/pthread_rwlock_timedrdlock_time32.c b/compat/time32/pthread_rwlock_timedrdlock_time32.c
index 20a8d1d0..33df27a4 100644
--- a/compat/time32/pthread_rwlock_timedrdlock_time32.c
+++ b/compat/time32/pthread_rwlock_timedrdlock_time32.c
@@ -4,6 +4,6 @@ 
 
 int __pthread_rwlock_timedrdlock_time32(pthread_rwlock_t *restrict rw, const struct timespec32 *restrict ts32)
 {
-	return pthread_rwlock_timedrdlock(rw, (&(struct timespec){
+	return pthread_rwlock_timedrdlock(rw, !ts32 ? 0 : (&(struct timespec){
 		.tv_sec = ts32->tv_sec, .tv_nsec = ts32->tv_nsec}));
 }
diff --git a/compat/time32/pthread_rwlock_timedwrlock_time32.c b/compat/time32/pthread_rwlock_timedwrlock_time32.c
index d7c100b5..99f24f73 100644
--- a/compat/time32/pthread_rwlock_timedwrlock_time32.c
+++ b/compat/time32/pthread_rwlock_timedwrlock_time32.c
@@ -4,6 +4,6 @@ 
 
 int __pthread_rwlock_timedwrlock_time32(pthread_rwlock_t *restrict rw, const struct timespec32 *restrict ts32)
 {
-	return pthread_rwlock_timedwrlock(rw, (&(struct timespec){
+	return pthread_rwlock_timedwrlock(rw, !ts32 ? 0 : (&(struct timespec){
 		.tv_sec = ts32->tv_sec, .tv_nsec = ts32->tv_nsec}));
 }
diff --git a/compat/time32/pthread_timedjoin_np_time32.c b/compat/time32/pthread_timedjoin_np_time32.c
index 0cd84026..99a26bc6 100644
--- a/compat/time32/pthread_timedjoin_np_time32.c
+++ b/compat/time32/pthread_timedjoin_np_time32.c
@@ -5,6 +5,6 @@ 
 
 int __pthread_timedjoin_np_time32(pthread_t t, void **res, const struct timespec *at32)
 {
-	return pthread_timedjoin_np(t, res, (&(struct timespec){
+	return pthread_timedjoin_np(t, res, !at32 ? 0 : (&(struct timespec){
 		.tv_sec = at32->tv_sec, .tv_nsec = at32->tv_nsec}));
 }
diff --git a/compat/time32/recvmmsg_time32.c b/compat/time32/recvmmsg_time32.c
index 48db6940..acf1cfb8 100644
--- a/compat/time32/recvmmsg_time32.c
+++ b/compat/time32/recvmmsg_time32.c
@@ -5,6 +5,6 @@ 
 
 int __recvmmsg_time32(int fd, struct mmsghdr *msgvec, unsigned int vlen, unsigned int flags, struct timespec32 *ts32)
 {
-	return recvmmsg(fd, msgvec, vlen, flags, (&(struct timespec){
-		.tv_sec = ts32->tv_sec, .tv_nsec = ts32->tv_nsec}));
+	return recvmmsg(fd, msgvec, vlen, flags, ts32 ? (&(struct timespec){
+		.tv_sec = ts32->tv_sec, .tv_nsec = ts32->tv_nsec}) : 0);
 }
diff --git a/compat/time32/select_time32.c b/compat/time32/select_time32.c
index 2bd76e33..2d8df9ac 100644
--- a/compat/time32/select_time32.c
+++ b/compat/time32/select_time32.c
@@ -5,6 +5,6 @@ 
 
 int __select_time32(int n, fd_set *restrict rfds, fd_set *restrict wfds, fd_set *restrict efds, struct timeval32 *restrict tv32)
 {
-	return select(n, rfds, wfds, efds, (&(struct timeval){
+	return select(n, rfds, wfds, efds, !tv32 ? 0 : (&(struct timeval){
 		.tv_sec = tv32->tv_sec, .tv_usec = tv32->tv_usec}));
 }
diff --git a/compat/time32/sem_timedwait_time32.c b/compat/time32/sem_timedwait_time32.c
index a27a41dc..c3469f9b 100644
--- a/compat/time32/sem_timedwait_time32.c
+++ b/compat/time32/sem_timedwait_time32.c
@@ -4,6 +4,6 @@ 
 
 int __sem_timedwait_time32(sem_t *sem, const struct timespec32 *restrict ts32)
 {
-	return sem_timedwait(sem, (&(struct timespec){
+	return sem_timedwait(sem, !ts32 ? 0 : (&(struct timespec){
 		.tv_sec = ts32->tv_sec, .tv_nsec = ts32->tv_nsec}));
 }
diff --git a/compat/time32/semtimedop_time32.c b/compat/time32/semtimedop_time32.c
index cd3c5c4a..34ec5281 100644
--- a/compat/time32/semtimedop_time32.c
+++ b/compat/time32/semtimedop_time32.c
@@ -5,6 +5,6 @@ 
 
 int __semtimedop_time32(int id, struct sembuf *buf, size_t n, const struct timespec32 *ts32)
 {
-	return semtimedop(id, buf, n, (&(struct timespec){
+	return semtimedop(id, buf, n, !ts32 ? 0 : (&(struct timespec){
 		.tv_sec = ts32->tv_sec, .tv_nsec = ts32->tv_nsec}));
 }
diff --git a/compat/time32/settimeofday_time32.c b/compat/time32/settimeofday_time32.c
index 181d23a7..09e625cb 100644
--- a/compat/time32/settimeofday_time32.c
+++ b/compat/time32/settimeofday_time32.c
@@ -4,7 +4,7 @@ 
 
 int __settimeofday_time32(const struct timeval32 *tv32, const void *tz)
 {
-	return settimeofday((&(struct timeval){
+	return settimeofday(!tv32 ? 0 : (&(struct timeval){
 		.tv_sec = tv32->tv_sec,
 		.tv_usec = tv32->tv_usec}), 0);
 }
diff --git a/compat/time32/sigtimedwait_time32.c b/compat/time32/sigtimedwait_time32.c
index f9a525c5..6b3aa39c 100644
--- a/compat/time32/sigtimedwait_time32.c
+++ b/compat/time32/sigtimedwait_time32.c
@@ -4,6 +4,6 @@ 
 
 int __sigtimedwait_time32(const sigset_t *restrict set, siginfo_t *restrict si, const struct timespec32 *restrict ts32)
 {
-	return sigtimedwait(set, si, (&(struct timespec){
+	return sigtimedwait(set, si, !ts32 ? 0 : (&(struct timespec){
 		.tv_sec = ts32->tv_sec, .tv_nsec = ts32->tv_nsec}));
 }
diff --git a/compat/time32/timer_settime32.c b/compat/time32/timer_settime32.c
index 95d597fe..a447e7d4 100644
--- a/compat/time32/timer_settime32.c
+++ b/compat/time32/timer_settime32.c
@@ -8,15 +8,18 @@  int __timer_settime32(timer_t t, int flags, const struct itimerspec32 *restrict
 		.it_interval.tv_sec = val32->it_interval.tv_sec,
 		.it_interval.tv_nsec = val32->it_interval.tv_nsec,
 		.it_value.tv_sec = val32->it_value.tv_sec,
-		.it_value.tv_nsec = val32->it_value.tv_nsec}), &old);
+		.it_value.tv_nsec = val32->it_value.tv_nsec}),
+		old32 ? &old : 0);
 	if (r) return r;
 	/* The above call has already committed to success by changing the
 	 * timer setting, so we can't fail on out-of-range old value.
 	 * Since these are relative times, values large enough to overflow
 	 * don't make sense anyway. */
-	old32->it_interval.tv_sec = old.it_interval.tv_sec;
-	old32->it_interval.tv_nsec = old.it_interval.tv_nsec;
-	old32->it_value.tv_sec = old.it_value.tv_sec;
-	old32->it_value.tv_nsec = old.it_value.tv_nsec;
+	if (old32) {
+		old32->it_interval.tv_sec = old.it_interval.tv_sec;
+		old32->it_interval.tv_nsec = old.it_interval.tv_nsec;
+		old32->it_value.tv_sec = old.it_value.tv_sec;
+		old32->it_value.tv_nsec = old.it_value.tv_nsec;
+	}
 	return 0;
 }
diff --git a/compat/time32/timerfd_settime32.c b/compat/time32/timerfd_settime32.c
index a16e2700..67830d34 100644
--- a/compat/time32/timerfd_settime32.c
+++ b/compat/time32/timerfd_settime32.c
@@ -9,15 +9,18 @@  int __timerfd_settime32(int t, int flags, const struct itimerspec32 *restrict va
 		.it_interval.tv_sec = val32->it_interval.tv_sec,
 		.it_interval.tv_nsec = val32->it_interval.tv_nsec,
 		.it_value.tv_sec = val32->it_value.tv_sec,
-		.it_value.tv_nsec = val32->it_value.tv_nsec}), &old);
+		.it_value.tv_nsec = val32->it_value.tv_nsec}),
+		old32 ? &old : 0);
 	if (r) return r;
 	/* The above call has already committed to success by changing the
 	 * timer setting, so we can't fail on out-of-range old value.
 	 * Since these are relative times, values large enough to overflow
 	 * don't make sense anyway. */
-	old32->it_interval.tv_sec = old.it_interval.tv_sec;
-	old32->it_interval.tv_nsec = old.it_interval.tv_nsec;
-	old32->it_value.tv_sec = old.it_value.tv_sec;
-	old32->it_value.tv_nsec = old.it_value.tv_nsec;
+	if (old32) {
+		old32->it_interval.tv_sec = old.it_interval.tv_sec;
+		old32->it_interval.tv_nsec = old.it_interval.tv_nsec;
+		old32->it_value.tv_sec = old.it_value.tv_sec;
+		old32->it_value.tv_nsec = old.it_value.tv_nsec;
+	}
 	return 0;
 }
diff --git a/compat/time32/utime_time32.c b/compat/time32/utime_time32.c
index 32454ddc..65f11d46 100644
--- a/compat/time32/utime_time32.c
+++ b/compat/time32/utime_time32.c
@@ -9,6 +9,6 @@  struct utimbuf32 {
 
 int __utime_time32(const char *path, const struct utimbuf32 *times32)
 {
-	return utime(path, (&(struct utimbuf){
+	return utime(path, !times32 ? 0 : (&(struct utimbuf){
 		.actime = times32->actime, .modtime = times32->modtime}));
 }
diff --git a/compat/time32/utimensat_time32.c b/compat/time32/utimensat_time32.c
index 3d8e320d..c687b8d1 100644
--- a/compat/time32/utimensat_time32.c
+++ b/compat/time32/utimensat_time32.c
@@ -4,7 +4,7 @@ 
 
 int __utimensat_time32(int fd, const char *path, const struct timespec32 times32[2], int flags)
 {
-	return utimensat(fd, path, ((struct timespec[2]){
+	return utimensat(fd, path, !times32 ? 0 : ((struct timespec[2]){
 		{.tv_sec = times32[0].tv_sec,.tv_nsec = times32[0].tv_nsec},
 		{.tv_sec = times32[1].tv_sec,.tv_nsec = times32[1].tv_nsec}}),
 		flags);
diff --git a/compat/time32/utimes_time32.c b/compat/time32/utimes_time32.c
index 94abb5e7..59248f62 100644
--- a/compat/time32/utimes_time32.c
+++ b/compat/time32/utimes_time32.c
@@ -5,7 +5,7 @@ 
 
 int __utimes_time32(const char *path, const struct timeval32 times32[2])
 {
-	return utimes(path, ((struct timeval[2]){
+	return utimes(path, !times32 ? 0 : ((struct timeval[2]){
 		{.tv_sec = times32[0].tv_sec,.tv_usec = times32[0].tv_usec},
 		{.tv_sec = times32[1].tv_sec,.tv_usec = times32[1].tv_usec}}));
 }
diff --git a/compat/time32/wait3_time32.c b/compat/time32/wait3_time32.c
index f8e63b91..0d07de4e 100644
--- a/compat/time32/wait3_time32.c
+++ b/compat/time32/wait3_time32.c
@@ -25,7 +25,7 @@  struct compat_rusage {
 pid_t __wait3_time32(int *status, int options, struct rusage *usage)
 {
 	struct rusage ru;
-	int r = wait3(status, options, &ru);
-	if (!r) memcpy(usage, &ru, sizeof(struct compat_rusage));
+	int r = wait3(status, options, usage ? &ru : 0);
+	if (!r && usage) memcpy(usage, &ru, sizeof(struct compat_rusage));
 	return r;
 }
diff --git a/compat/time32/wait4_time32.c b/compat/time32/wait4_time32.c
index 7fbf5397..f2b4e90e 100644
--- a/compat/time32/wait4_time32.c
+++ b/compat/time32/wait4_time32.c
@@ -25,7 +25,7 @@  struct compat_rusage {
 pid_t __wait4_time32(pid_t pid, int *status, int options, struct rusage *usage)
 {
 	struct rusage ru;
-	int r = wait4(pid, status, options, &ru);
-	if (!r) memcpy(usage, &ru, sizeof(struct compat_rusage));
+	int r = wait4(pid, status, options, usage ? &ru : 0);
+	if (!r && usage) memcpy(usage, &ru, sizeof(struct compat_rusage));
 	return r;
 }