]> git.ipfire.org Git - thirdparty/valgrind.git/commitdiff
Bug 397354 utimensat should ignore tv_sec if tv_nsec is UTIME_NOW/OMIT.
authorMark Wielaard <mark@klomp.org>
Mon, 3 Sep 2018 09:54:38 +0000 (11:54 +0200)
committerMark Wielaard <mark@klomp.org>
Mon, 3 Sep 2018 09:54:38 +0000 (11:54 +0200)
When code uses utimensat with UTIME_NOW or UTIME_OMIT valgrind memcheck
would generate a warning. But as the utimensat manpage says:

  If the tv_nsec field of one of the timespec structures has the  special
  value  UTIME_NOW,  then  the corresponding file timestamp is set to the
  current time.  If the tv_nsec field of one of the  timespec  structures
  has the special value UTIME_OMIT, then the corresponding file timestamp
  is left unchanged.  In both of these cases, the  value  of  the  corre‐
  sponding tv_sec field is ignored.

So ignore the timespec tv_sec when tv_nsec is set to UTIME_NOW or
UTIME_OMIT.

NEWS
coregrind/m_syswrap/syswrap-linux.c
include/vki/vki-linux.h

diff --git a/NEWS b/NEWS
index 982e3ec82946b4de6550236a2e286bfb60b12eb1..c79d775092dc7cd77a92420ff89e0f83f33c69f6 100644 (file)
--- a/NEWS
+++ b/NEWS
@@ -143,6 +143,7 @@ where XXXXXX is the bug number as listed below.
 396475  valgrind OS-X build: config.h not found (out-of-tree macOS builds)
 396887  arch_prctl should return EINVAL on unknown option
 397012  glibc ld.so uses arch_prctl on i386
+397354  utimensat should ignore timespec tv_sec if tv_nsec is UTIME_NOW/OMIT
 397424  glibc 2.27 and gdb_server tests
 
 n-i-bz  Fix missing workq_ops operations (macOS)
index 2c96fedf0c065512c416ddc428218ed92bc42cd0..90d4a8586ff12afc5db9a8554fa1cfe44e11b137 100644 (file)
@@ -5303,8 +5303,25 @@ PRE(sys_utimensat)
                  int, dfd, char *, filename, struct timespec *, utimes, int, flags);
    if (ARG2 != 0)
       PRE_MEM_RASCIIZ( "utimensat(filename)", ARG2 );
-   if (ARG3 != 0)
-      PRE_MEM_READ( "utimensat(tvp)", ARG3, 2 * sizeof(struct vki_timespec) );
+   if (ARG3 != 0) {
+      /* If timespec.tv_nsec has the special value UTIME_NOW or UTIME_OMIT
+         then the tv_sec field is ignored.  */
+      struct vki_timespec *times = (struct vki_timespec *)(Addr)ARG3;
+      PRE_MEM_READ( "utimensat(times[0].tv_nsec)",
+                    (Addr)&times[0].tv_nsec, sizeof(times[0].tv_nsec));
+      PRE_MEM_READ( "utimensat(times[1].tv_nsec)",
+                    (Addr)&times[1].tv_nsec, sizeof(times[1].tv_nsec));
+      if (ML_(safe_to_deref)(times, 2 * sizeof(struct vki_timespec))) {
+         if (times[0].tv_nsec != VKI_UTIME_NOW
+             && times[0].tv_nsec != VKI_UTIME_OMIT)
+            PRE_MEM_READ( "utimensat(times[0].tv_sec)",
+                          (Addr)&times[0].tv_sec, sizeof(times[0].tv_sec));
+         if (times[1].tv_nsec != VKI_UTIME_NOW
+             && times[1].tv_nsec != VKI_UTIME_OMIT)
+            PRE_MEM_READ( "utimensat(times[1].tv_sec)",
+                          (Addr)&times[1].tv_sec, sizeof(times[1].tv_sec));
+      }
+   }
 }
 
 PRE(sys_newfstatat)
index 815f658e1202539c2c514ab3ef5051b996022ba9..b4c60854a36c378542db939503dde41eed480af1 100644 (file)
@@ -285,6 +285,10 @@ struct vki_timespec {
        long            tv_nsec;        /* nanoseconds */
 };
 
+/* Special values for vki_timespec.tv_nsec when used with utimensat.  */
+#define VKI_UTIME_NOW  ((1l << 30) - 1l)
+#define VKI_UTIME_OMIT ((1l << 30) - 2l)
+
 struct vki_timeval {
        vki_time_t      tv_sec;         /* seconds */
        vki_suseconds_t tv_usec;        /* microseconds */