]> granicus.if.org Git - strace/commitdiff
Fix decoding of preadv syscall in case of short read
authorDmitry V. Levin <ldv@altlinux.org>
Wed, 30 Mar 2016 18:04:00 +0000 (18:04 +0000)
committerDmitry V. Levin <ldv@altlinux.org>
Wed, 30 Mar 2016 18:04:00 +0000 (18:04 +0000)
* io.c (SYS_FUNC(preadv)): Call tprint_iov_upto instead
of tprint_iov and specify syscall return value as a data size limit.
* NEWS: Mention it.
* tests/preadv.c (main): Add a test case for preadv short read.

NEWS
io.c
tests/preadv.c

diff --git a/NEWS b/NEWS
index 24365b05904a4e854c851bc587c8a5a8aae606f0..c5a4d2e0558c1bff770e1ae557496c45431909e9 100644 (file)
--- a/NEWS
+++ b/NEWS
@@ -20,6 +20,7 @@ Noteworthy changes in release ?.?? (????-??-??)
   * Fixed decoding of mlock2 syscall on sparc.
   * Fixed decoding of syscalls unknown to the kernel on s390/s390x.
     (addresses Debian bug #485979 and Fedora bug #1298294).
+  * Fixed decoding of preadv syscall in case of short read.
   * Fixed decoding and dumping of readv syscall in case of short read.
   * Fixed dumping of recvmsg and recvmmsg syscalls in case of short read.
   * Fixed decoding of mincore syscall's last argument.
diff --git a/io.c b/io.c
index cda5f92c2589838d8806d5e299e0966b1d414f1a..d8444f3988f5cc38c064eaac10afd76caa4cca00 100644 (file)
--- a/io.c
+++ b/io.c
@@ -221,7 +221,8 @@ SYS_FUNC(preadv)
                printfd(tcp, tcp->u_arg[0]);
                tprints(", ");
        } else {
-               tprint_iov(tcp, tcp->u_arg[2], tcp->u_arg[1], 1);
+               tprint_iov_upto(tcp, tcp->u_arg[2], tcp->u_arg[1], 1,
+                               tcp->u_rval);
                tprintf(", %lu, ", tcp->u_arg[2]);
                print_lld_from_low_high_val(tcp, 3);
        }
index 53d7ed6777da91596a8d655f2e265e9088d7a738..0fabed254e5497bffe5110f059f0839feb3b6f56 100644 (file)
@@ -92,6 +92,61 @@ main(void)
                perror_msg_and_fail("preadv");
        printf("preadv(0, [], 0, -3) = -1 EINVAL (%m)\n");
 
+       static const char tmp[] = "preadv-tmpfile";
+       int fd = open(tmp, O_RDWR | O_CREAT | O_TRUNC, 0600);
+       if (fd < 0)
+               perror_msg_and_fail("open");
+       if (unlink(tmp))
+               perror_msg_and_fail("unlink");
+
+       static const char w[] = "0123456789abcde";
+       if (write(fd, w, LENGTH_OF(w)) != LENGTH_OF(w))
+               perror_msg_and_fail("write");
+
+       static const char r0_c[] = "01234567";
+       static const char r1_c[] = "89abcde";
+
+       const unsigned int r_len = (LENGTH_OF(w) + 1) / 2;
+       void *r0 = tail_alloc(r_len);
+       const struct iovec r0_iov_[] = {
+               {
+                       .iov_base = r0,
+                       .iov_len = r_len
+               }
+       };
+       const struct iovec *r_iov = tail_memdup(r0_iov_, sizeof(r0_iov_));
+
+       long rc;
+
+       rc = preadv(fd, r_iov, ARRAY_SIZE(r0_iov_), 0);
+       if (rc != (int) r_len)
+               perror_msg_and_fail("preadv: expected %u, returned %ld",
+                                   r_len, rc);
+       printf("preadv(%d, [{\"%s\", %u}], %u, 0) = %u\n",
+              fd, r0_c, r_len, ARRAY_SIZE(r0_iov_), r_len);
+
+       void *r1 = tail_alloc(r_len);
+       void *r2 = tail_alloc(LENGTH_OF(w));
+       const struct iovec r1_iov_[] = {
+               {
+                       .iov_base = r1,
+                       .iov_len = r_len
+               },
+               {
+                       .iov_base = r2,
+                       .iov_len = LENGTH_OF(w)
+               }
+       };
+       r_iov = tail_memdup(r1_iov_, sizeof(r1_iov_));
+
+       rc = preadv(fd, r_iov, ARRAY_SIZE(r1_iov_), r_len);
+       if (rc != (int) LENGTH_OF(w) - r_len)
+               perror_msg_and_fail("preadv: expected %d, returned %ld",
+                                   (int) LENGTH_OF(w) - r_len, rc);
+       printf("preadv(%d, [{\"%s\", %u}, {\"\", %u}], %u, %u) = %u\n",
+              fd, r1_c, r_len, LENGTH_OF(w), ARRAY_SIZE(r1_iov_),
+               r_len, LENGTH_OF(w) - r_len);
+
        puts("+++ exited with 0 +++");
        return 0;
 }