Fix decoding of preadv syscall in case of short read

* 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.
This commit is contained in:
Дмитрий Левин 2016-03-30 18:04:00 +00:00
parent d461151f23
commit c98ab8805b
3 changed files with 58 additions and 1 deletions

1
NEWS
View File

@ -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.

3
io.c
View File

@ -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);
}

View 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;
}