diff options
author | Eugene Syromyatnikov <evgsyr@gmail.com> | 2022-08-10 12:21:35 +0200 |
---|---|---|
committer | Eugene Syromyatnikov <evgsyr@gmail.com> | 2022-08-11 14:34:17 +0200 |
commit | 5bbf28be59b7c04f89399c22d3b5502a75e8e4f1 (patch) | |
tree | 5f4219bef41c28ec1b30345999da04c9493b8a1a | |
parent | 58f134b650133e0e8dff13a27957f2fcc2718f61 (diff) | |
download | strace-5bbf28be59b7c04f89399c22d3b5502a75e8e4f1.tar.gz |
tests: expand so_error test checks
Check decoding with various optlen values.
* tests/so_error.c: Add checks.
-rw-r--r-- | tests/so_error.c | 116 |
1 files changed, 73 insertions, 43 deletions
diff --git a/tests/so_error.c b/tests/so_error.c index 03211ab91..f6bc2875e 100644 --- a/tests/so_error.c +++ b/tests/so_error.c @@ -47,58 +47,88 @@ reserve_ephemeral_port(void) int main(void) { - in_port_t port = reserve_ephemeral_port (); - - /* - * Connect to the reserved port in NONBLOCK mode. - * The port is reserved but not listened. So - * the client doing "connect" gets error asynchronously. - */ - int fd = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); - if (fd < 0) - perror_msg_and_skip("socket AF_UNIX SOCK_STREAM"); - - int flag = fcntl(fd, F_GETFL); - if (flag < 0) - perror_msg_and_skip("fcntl F_GETFL"); - flag |= O_NONBLOCK; - if (fcntl(fd, F_SETFL, flag) < 0) - perror_msg_and_skip("fcntl F_SETFL"); + static const int sizes[] = { + -1, 0, 1, + sizeof(int) - 1, + sizeof(int), + sizeof(int) + 1, + }; - struct sockaddr_in addr = { + TAIL_ALLOC_OBJECT_CONST_PTR(int, sock_errno); + in_port_t port = reserve_ephemeral_port(); + const struct sockaddr_in addr = { .sin_family = AF_INET, .sin_addr.s_addr = htonl(INADDR_LOOPBACK), .sin_port = htons(port), }; - if (connect(fd, (void *) &addr, sizeof(addr)) == 0) - error_msg_and_skip("connect unexpectedly succeeded"); - if (errno != EINPROGRESS) - perror_msg_and_skip("connect failed for unexpected reason"); - struct timeval to = { - .tv_sec = 1, - .tv_usec = 0, - }; - fd_set wfds; - FD_ZERO(&wfds); - FD_SET(fd, &wfds); - if (select(fd + 1, NULL, &wfds, NULL, &to) < 0) - perror_msg_and_skip("select"); + for (size_t i = 0; i < ARRAY_SIZE(sizes); i++) { + /* + * Connect to the reserved port in NONBLOCK mode. + * The port is reserved but not listened. So + * the client doing "connect" gets error asynchronously. + */ + int fd = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); + if (fd < 0) + perror_msg_and_skip("socket AF_UNIX SOCK_STREAM"); + + int flag = fcntl(fd, F_GETFL); + if (flag < 0) + perror_msg_and_skip("fcntl F_GETFL"); + flag |= O_NONBLOCK; + if (fcntl(fd, F_SETFL, flag) < 0) + perror_msg_and_skip("fcntl F_SETFL"); + + if (connect(fd, (void *) &addr, sizeof(addr)) == 0) + error_msg_and_skip("connect unexpectedly succeeded"); + if (errno != EINPROGRESS) + perror_msg_and_skip("connect failed for unexpected reason"); + + struct timeval to = { + .tv_sec = 1, + .tv_usec = 0, + }; + fd_set wfds; + FD_ZERO(&wfds); + FD_SET(fd, &wfds); + if (select(fd + 1, NULL, &wfds, NULL, &to) < 0) + perror_msg_and_skip("select"); + + *sock_errno = 0xbadc0ded; + socklen_t optlen = sizes[i]; + long rc = getsockopt(fd, SOL_SOCKET, SO_ERROR, sock_errno, + &optlen); + const char *errstr = sprintrc(rc); + if (sizes[i] > 0 && rc < 0) + perror_msg_and_skip("getsockopt"); + if (sizes[i] >= (int) sizeof(*sock_errno) + && *sock_errno != ECONNREFUSED) { + errno = *sock_errno; + perror_msg_and_skip("unexpected socket error"); + } + if (sizes[i] >= (int) sizeof(*sock_errno) + && optlen != sizeof(*sock_errno)) { + error_msg_and_skip("unexpected data size for error" + " option: %d", optlen); + } + + printf("getsockopt(%d, SOL_SOCKET, SO_ERROR, ", fd); + if (sizes[i] <= 0) { + printf("%p, [%d]", sock_errno, sizes[i]); + } else if (sizes[i] < (int) sizeof(*sock_errno)) { + print_quoted_hex(sock_errno, sizes[i]); + printf(", [%u]", sizes[i]); + } else if (sizes[i] == sizeof(*sock_errno)) { + printf("[ECONNREFUSED], [%zu]", sizeof(*sock_errno)); + } else { + printf("[ECONNREFUSED], [%u => %zu]", + sizes[i], sizeof(*sock_errno)); + } + printf(") = %s\n", errstr); - int sock_errno; - socklen_t optlen = sizeof(sock_errno); - if (getsockopt(fd, SOL_SOCKET, SO_ERROR, &sock_errno, &optlen) < 0) - perror_msg_and_skip("getsockopt"); - if (sock_errno != ECONNREFUSED) { - errno = sock_errno; - perror_msg_and_skip("unexpected socket error"); + close(fd); } - if (optlen != sizeof(sock_errno)) - error_msg_and_skip("unexpected data size for error option: %d", - optlen); - printf("getsockopt(%d, SOL_SOCKET, SO_ERROR, [ECONNREFUSED], [%u]) = 0\n", - fd, optlen); puts("+++ exited with 0 +++"); return 0; } |