]> granicus.if.org Git - strace/commitdiff
Fix printing of negative offsets in preadv and pwritev syscalls
authorDmitry V. Levin <ldv@altlinux.org>
Wed, 30 Mar 2016 03:54:21 +0000 (03:54 +0000)
committerDmitry V. Levin <ldv@altlinux.org>
Wed, 30 Mar 2016 03:54:21 +0000 (03:54 +0000)
* io.c (print_llu_from_low_high_val): Rename to
print_lld_from_low_high_val, all callers changed.
Print value as a signed integer.
* tests/preadv.c: New file.
* tests/preadv.test: New test.
* tests/pwritev.c: New file.
* tests/pwritev.test: New test.
* tests/.gitignore: Add preadv and pwritev.
* tests/Makefile.am (check_PROGRAMS): Likewise.
(preadv_CPPFLAGS, pwritev_CPPFLAGS): New variables.
(DECODER_TESTS): Add preadv.test and pwritev.test.

io.c
tests/.gitignore
tests/Makefile.am
tests/preadv.c [new file with mode: 0644]
tests/preadv.test [new file with mode: 0755]
tests/pwritev.c [new file with mode: 0644]
tests/pwritev.test [new file with mode: 0755]

diff --git a/io.c b/io.c
index aac93eaecfa55bb6c50aa7075dc18321eb552256..cda5f92c2589838d8806d5e299e0966b1d414f1a 100644 (file)
--- a/io.c
+++ b/io.c
@@ -186,7 +186,7 @@ SYS_FUNC(pwrite)
 }
 
 static void
-print_llu_from_low_high_val(struct tcb *tcp, int arg)
+print_lld_from_low_high_val(struct tcb *tcp, int arg)
 {
 #if SIZEOF_LONG == SIZEOF_LONG_LONG
 # if SUPPORTED_PERSONALITIES > 1
@@ -196,20 +196,20 @@ print_llu_from_low_high_val(struct tcb *tcp, int arg)
        if (current_wordsize == sizeof(long))
 #  endif
 # endif
-               tprintf("%lu", (unsigned long) tcp->u_arg[arg]);
+               tprintf("%ld", tcp->u_arg[arg]);
 # if SUPPORTED_PERSONALITIES > 1
        else
-               tprintf("%lu",
+               tprintf("%ld",
                        ((unsigned long) tcp->u_arg[arg + 1] << current_wordsize * 8)
                        | (unsigned long) tcp->u_arg[arg]);
 # endif
 #else
 # ifdef X32
        if (current_personality == 0)
-               tprintf("%llu", (unsigned long long) tcp->ext_arg[arg]);
+               tprintf("%lld", tcp->ext_arg[arg]);
        else
 # endif
-       tprintf("%llu",
+       tprintf("%lld",
                ((unsigned long long) (unsigned long) tcp->u_arg[arg + 1] << sizeof(long) * 8)
                | (unsigned long long) (unsigned long) tcp->u_arg[arg]);
 #endif
@@ -223,7 +223,7 @@ SYS_FUNC(preadv)
        } else {
                tprint_iov(tcp, tcp->u_arg[2], tcp->u_arg[1], 1);
                tprintf(", %lu, ", tcp->u_arg[2]);
-               print_llu_from_low_high_val(tcp, 3);
+               print_lld_from_low_high_val(tcp, 3);
        }
        return 0;
 }
@@ -234,7 +234,7 @@ SYS_FUNC(pwritev)
        tprints(", ");
        tprint_iov(tcp, tcp->u_arg[2], tcp->u_arg[1], 1);
        tprintf(", %lu, ", tcp->u_arg[2]);
-       print_llu_from_low_high_val(tcp, 3);
+       print_lld_from_low_high_val(tcp, 3);
 
        return RVAL_DECODED;
 }
index d5bbe5884493ba39049549cbb0b755b11498c62a..1e1da4827d9a8363b8c145b8daf59fb4ac4a5a6b 100644 (file)
@@ -89,7 +89,9 @@ personality
 pipe
 poll
 ppoll
+preadv
 pselect6
+pwritev
 readdir
 readlink
 readlinkat
index 883249378c2660a7d919f9852f06070f615b43e7..7e4038c7e7247e6077232bc633e8eca4e8599c30 100644 (file)
@@ -138,7 +138,9 @@ check_PROGRAMS = \
        pipe \
        poll \
        ppoll \
+       preadv \
        pselect6 \
+       pwritev \
        readdir \
        readlink \
        readlinkat \
@@ -222,11 +224,14 @@ mmap64_CPPFLAGS = $(AM_CPPFLAGS) -D_FILE_OFFSET_BITS=64
 mq_LDADD = -lrt $(LDADD)
 newfstatat_CPPFLAGS = $(AM_CPPFLAGS) -D_FILE_OFFSET_BITS=64
 pc_LDADD = $(dl_LIBS) $(LDADD)
+preadv_CPPFLAGS = $(AM_CPPFLAGS) -D_FILE_OFFSET_BITS=64
+pwritev_CPPFLAGS = $(AM_CPPFLAGS) -D_FILE_OFFSET_BITS=64
 stat64_CPPFLAGS = $(AM_CPPFLAGS) -D_FILE_OFFSET_BITS=64
 statfs_CPPFLAGS = $(AM_CPPFLAGS) -D_FILE_OFFSET_BITS=64
 times_LDADD = -lrt $(LDADD)
 truncate64_CPPFLAGS = $(AM_CPPFLAGS) -D_FILE_OFFSET_BITS=64
 uio_CPPFLAGS = $(AM_CPPFLAGS) -D_FILE_OFFSET_BITS=64
+
 stack_fcall_SOURCES = stack-fcall.c \
        stack-fcall-0.c stack-fcall-1.c stack-fcall-2.c stack-fcall-3.c
 
@@ -309,7 +314,9 @@ DECODER_TESTS = \
        pipe.test \
        poll.test \
        ppoll.test \
+       preadv.test \
        pselect6.test \
+       pwritev.test \
        readdir.test \
        readlink.test \
        readlinkat.test \
diff --git a/tests/preadv.c b/tests/preadv.c
new file mode 100644 (file)
index 0000000..53d7ed6
--- /dev/null
@@ -0,0 +1,103 @@
+/*
+ * Copyright (c) 2014-2016 Dmitry V. Levin <ldv@altlinux.org>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. The name of the author may not be used to endorse or promote products
+ *    derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "tests.h"
+
+#ifdef HAVE_PREADV
+
+# include <fcntl.h>
+# include <stdio.h>
+# include <sys/uio.h>
+# include <unistd.h>
+
+# define LEN 8
+
+static void
+print_iov(const struct iovec *iov)
+{
+       unsigned int i;
+       unsigned char *buf = iov->iov_base;
+
+       fputs("{\"", stdout);
+       for (i = 0; i < iov->iov_len; ++i)
+               printf("\\%d", (int) buf[i]);
+       printf("\", %u}", (unsigned) iov->iov_len);
+}
+
+static void
+print_iovec(const struct iovec *iov, unsigned int cnt)
+{
+       unsigned int i;
+       putchar('[');
+       for (i = 0; i < cnt; ++i) {
+               if (i)
+                       fputs(", ", stdout);
+               print_iov(&iov[i]);
+       }
+       putchar(']');
+}
+
+int
+main(void)
+{
+       const off_t offset = 0xdefaceddeadbeefLL;
+       char *buf = tail_alloc(LEN);
+       struct iovec *iov = tail_alloc(sizeof(*iov));
+       iov->iov_base = buf;
+       iov->iov_len = LEN;
+
+       (void) close(0);
+       if (open("/dev/zero", O_RDONLY))
+               perror_msg_and_fail("open");
+
+       if (preadv(0, iov, 1, offset) != LEN)
+               perror_msg_and_fail("preadv");
+       printf("preadv(0, ");
+       print_iovec(iov, 1);
+       printf(", 1, %lld) = %u\n", (long long) offset, LEN);
+
+       if (preadv(0, iov, 1, -1) != -1)
+               perror_msg_and_fail("preadv");
+       printf("preadv(0, %p, 1, -1) = -1 EINVAL (%m)\n", iov);
+
+       if (preadv(0, NULL, 1, -2) != -1)
+               perror_msg_and_fail("preadv");
+       printf("preadv(0, NULL, 1, -2) = -1 EINVAL (%m)\n");
+
+       if (preadv(0, NULL, 0, -3) != -1)
+               perror_msg_and_fail("preadv");
+       printf("preadv(0, [], 0, -3) = -1 EINVAL (%m)\n");
+
+       puts("+++ exited with 0 +++");
+       return 0;
+}
+
+#else
+
+SKIP_MAIN_UNDEFINED("HAVE_PREADV")
+
+#endif
diff --git a/tests/preadv.test b/tests/preadv.test
new file mode 100755 (executable)
index 0000000..d1abdb7
--- /dev/null
@@ -0,0 +1,6 @@
+#!/bin/sh
+
+# Check preadv syscall decoding.
+
+. "${srcdir=.}/init.sh"
+run_strace_match_diff -a21
diff --git a/tests/pwritev.c b/tests/pwritev.c
new file mode 100644 (file)
index 0000000..99b3018
--- /dev/null
@@ -0,0 +1,149 @@
+/*
+ * Copyright (c) 2014-2016 Dmitry V. Levin <ldv@altlinux.org>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. The name of the author may not be used to endorse or promote products
+ *    derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "tests.h"
+
+#ifdef HAVE_PWRITEV
+
+# include <fcntl.h>
+# include <stdio.h>
+# include <sys/uio.h>
+# include <unistd.h>
+
+# define LEN 8
+# define LIM (LEN - 1)
+
+static void
+print_iov(const struct iovec *iov)
+{
+       unsigned int i;
+       unsigned char *buf = iov->iov_base;
+
+       fputs("{\"", stdout);
+       for (i = 0; i < iov->iov_len; ++i) {
+               if (i < LIM)
+                       printf("\\%d", (int) buf[i]);
+       }
+       printf("\"%s, %u}",
+              i > LIM ? "..." : "", (unsigned) iov->iov_len);
+}
+
+static void
+print_iovec(const struct iovec *iov, unsigned int cnt, unsigned int size)
+{
+       if (!size) {
+               printf("%p", iov);
+               return;
+       }
+       unsigned int i;
+       putchar('[');
+       for (i = 0; i < cnt; ++i) {
+               if (i)
+                       fputs(", ", stdout);
+               if (i == LIM) {
+                       fputs("...", stdout);
+                       break;
+               }
+               if (i == size) {
+                       printf("%p", &iov[i]);
+                       break;
+               }
+               print_iov(&iov[i]);
+       }
+       putchar(']');
+}
+
+int
+main(void)
+{
+       (void) close(0);
+       if (open("/dev/null", O_WRONLY))
+               perror_msg_and_fail("open");
+
+       char *buf = tail_alloc(LEN);
+       unsigned i;
+       for (i = 0; i < LEN; ++i)
+               buf[i] = i;
+
+       struct iovec *iov = tail_alloc(sizeof(*iov) * LEN);
+       for (i = 0; i < LEN; ++i) {
+               buf[i] = i;
+               iov[i].iov_base = &buf[i];
+               iov[i].iov_len = LEN - i;
+       }
+       tail_alloc(1);
+
+       const off_t offset = 0xdefaceddeadbeefLL;
+       int written = 0;
+       for (i = 0; i < LEN; ++i) {
+               written += iov[i].iov_len;
+               if (pwritev(0, iov, i + 1, offset + i) != written)
+                       perror_msg_and_fail("pwritev");
+               fputs("pwritev(0, ", stdout);
+               print_iovec(iov, i + 1, LEN);
+               printf(", %u, %lld) = %d\n",
+                      i + 1, (long long) offset + i, written);
+       }
+
+       for (i = 0; i <= LEN; ++i) {
+               unsigned int n = LEN + 1 - i;
+               if (pwritev(0, iov + i, n, offset + LEN + i) != -1)
+                       perror_msg_and_fail("pwritev");
+               fputs("pwritev(0, ", stdout);
+               print_iovec(iov + i, n, LEN - i);
+               printf(", %u, %lld) = -1 EFAULT (%m)\n",
+                      n, (long long) offset + LEN + i);
+       }
+
+       iov->iov_base = iov + LEN * 2;
+       if (pwritev(0, iov, 1, -1) != -1)
+               perror_msg_and_fail("pwritev");
+       printf("pwritev(0, [{%p, %d}], 1, -1) = -1 EINVAL (%m)\n",
+              iov->iov_base, LEN);
+
+       iov += LEN;
+       if (pwritev(0, iov, 42, -2) != -1)
+               perror_msg_and_fail("pwritev");
+       printf("pwritev(0, %p, 42, -2) = -1 EINVAL (%m)\n", iov);
+
+       if (pwritev(0, NULL, 1, -3) != -1)
+               perror_msg_and_fail("pwritev");
+       printf("pwritev(0, NULL, 1, -3) = -1 EINVAL (%m)\n");
+
+       if (pwritev(0, NULL, 0, -4) != -1)
+               perror_msg_and_fail("pwritev");
+       printf("pwritev(0, [], 0, -4) = -1 EINVAL (%m)\n");
+
+       puts("+++ exited with 0 +++");
+       return 0;
+}
+
+#else
+
+SKIP_MAIN_UNDEFINED("HAVE_PWRITEV")
+
+#endif
diff --git a/tests/pwritev.test b/tests/pwritev.test
new file mode 100755 (executable)
index 0000000..0aed683
--- /dev/null
@@ -0,0 +1,6 @@
+#!/bin/sh
+
+# Check pwritev syscall decoding.
+
+. "${srcdir=.}/init.sh"
+run_strace_match_diff -a22 -s7