From ea8327af0f0c5b771bb08d6c6299b51e5671b335 Mon Sep 17 00:00:00 2001 From: Jianfeng Jiang Date: Tue, 10 Sep 2024 11:21:24 +0000 Subject: [PATCH] Add regression test for sendmsg/recvmsg --- test/apps/network/tcp_err.c | 60 ++++++++++++++++++++++++++- test/apps/network/udp_err.c | 83 ++++++++++++++++++++++++++++++++++++- 2 files changed, 139 insertions(+), 4 deletions(-) diff --git a/test/apps/network/tcp_err.c b/test/apps/network/tcp_err.c index 77785fa0..d506c042 100644 --- a/test/apps/network/tcp_err.c +++ b/test/apps/network/tcp_err.c @@ -364,7 +364,8 @@ FN_TEST(sendmsg_and_recvmsg) msg.msg_iov = iov; msg.msg_iovlen = 2; - // Send one message and recv one message + // TEST CASE 1: Send one message and recv one message + TEST_RES(sendmsg(sk_connected, &msg, 0), _ret == strlen(message) + strlen(message2)); @@ -382,7 +383,7 @@ FN_TEST(sendmsg_and_recvmsg) _ret == strlen(concatenated) && strcmp(buffer, concatenated) == 0); - // Send two message and receive two message + // TEST CASE 2: Send two message and receive two message iov[0].iov_base = message; iov[0].iov_len = strlen(message); @@ -402,5 +403,60 @@ FN_TEST(sendmsg_and_recvmsg) sleep(1); TEST_RES(recvmsg(sk_connected, &msg, 0), _ret == strlen(message) * 2); + + // TEST CASE 3: Send via a partially bad send buffer + + char *good_buffer = "abc"; + char *bad_buffer = (char *)1; + iov[0].iov_base = good_buffer; + iov[0].iov_len = strlen(good_buffer); + iov[1].iov_base = bad_buffer; + iov[1].iov_len = 1; + msg.msg_iov = iov; + msg.msg_iovlen = 2; + TEST_ERRNO(sendmsg(sk_accepted, &msg, 0), EFAULT); + + // TEST CASE 4: Receive via a partially bad receive buffer + + iov[0].iov_base = good_buffer; + iov[0].iov_len = strlen(good_buffer); + msg.msg_iov = iov; + msg.msg_iovlen = 1; + + TEST_RES(sendmsg(sk_accepted, &msg, 0), _ret == strlen(good_buffer)); + + sleep(1); + + char recv_buffer[4096] = { 0 }; + iov[0].iov_base = recv_buffer; + iov[0].iov_len = 1; + TEST_RES(recvmsg(sk_connected, &msg, 0), _ret == 1); + + iov[0].iov_base = recv_buffer; + iov[0].iov_len = 1; + iov[1].iov_base = (char *)1; + iov[1].iov_len = 1; + msg.msg_iovlen = 2; + TEST_ERRNO(recvmsg(sk_connected, &msg, 0), EFAULT); + + iov[0].iov_base = recv_buffer; + iov[0].iov_len = 4096; + msg.msg_iovlen = 1; + TEST_RES(recvmsg(sk_connected, &msg, 0), + _ret == strlen(good_buffer) - 1); + + // TEST CASE 5: Send a large buffer + + int big_buffer_size = 1000000; + char *big_buffer = (char *)calloc(0, big_buffer_size); + iov[0].iov_base = big_buffer; + iov[0].iov_len = big_buffer_size; + msg.msg_iovlen = 2; + + int sndbuf = 0; + socklen_t optlen = sizeof(sndbuf); + TEST_SUCC(getsockopt(sk_accepted, SOL_SOCKET, SO_SNDBUF, &sndbuf, + &optlen)); + TEST_RES(sendmsg(sk_accepted, &msg, 0), _ret <= sndbuf); } END_TEST() diff --git a/test/apps/network/udp_err.c b/test/apps/network/udp_err.c index bf679ec3..cf0597a3 100644 --- a/test/apps/network/udp_err.c +++ b/test/apps/network/udp_err.c @@ -276,7 +276,8 @@ FN_TEST(sendmsg_and_recvmsg) msg.msg_name = (struct sockaddr *)&sk_addr; msg.msg_namelen = addrlen; - // Send one message and receive one message + // TEST CASE 1: Send one message and receive one message + TEST_RES(sendmsg(sk_connected, &msg, 0), _ret == strlen(message)); #define BUFFER_SIZE 50 @@ -287,7 +288,8 @@ FN_TEST(sendmsg_and_recvmsg) TEST_RES(recvmsg(sk_bound, &msg, 0), _ret == strlen(message) && strcmp(message, buffer) == 0); - // Send two messages and receive two messages + // TEST CASE 2: Send two messages and receive two messages + iov[0].iov_base = message; iov[0].iov_len = strlen(message); msg.msg_name = (struct sockaddr *)&sk_addr; @@ -305,3 +307,80 @@ FN_TEST(sendmsg_and_recvmsg) _ret == strlen(message) && strcmp(message, buffer) == 0); } END_TEST() + +void set_nonblocking(int sockfd) +{ + int flags = CHECK(fcntl(sockfd, F_GETFL, 0)); + CHECK(fcntl(sockfd, F_SETFL, flags | O_NONBLOCK)); +} + +FN_SETUP(enter_nonblocking_mode) +{ + set_nonblocking(sk_connected); + set_nonblocking(sk_bound); +} +END_SETUP() + +FN_TEST(sendmsg_and_recvmsg_bad_buffer) +{ + struct sockaddr_in saddr; + socklen_t addrlen = sizeof(saddr); + + sk_addr.sin_port = C_PORT; + + struct msghdr msg = { 0 }; + struct iovec iov[2]; + msg.msg_name = (struct sockaddr *)&sk_addr; + msg.msg_namelen = addrlen; + + // TEST CASE 1: Send via a partially bad send buffer + + char *good_buffer = "abc"; + char *bad_buffer = (char *)1; + iov[0].iov_base = good_buffer; + iov[0].iov_len = strlen(good_buffer); + iov[1].iov_base = bad_buffer; + iov[1].iov_len = 1; + msg.msg_iov = iov; + msg.msg_iovlen = 2; + TEST_ERRNO(sendmsg(sk_connected, &msg, 0), EFAULT); + + // TEST CASE 2: Receive via a partially bad receive buffer + + iov[0].iov_base = good_buffer; + iov[0].iov_len = strlen(good_buffer); + msg.msg_iov = iov; + msg.msg_iovlen = 1; + + TEST_RES(sendmsg(sk_connected, &msg, 0), _ret == strlen(good_buffer)); + TEST_RES(sendmsg(sk_connected, &msg, 0), _ret == strlen(good_buffer)); + TEST_RES(sendmsg(sk_connected, &msg, 0), _ret == strlen(good_buffer)); + TEST_RES(sendmsg(sk_connected, &msg, 0), _ret == strlen(good_buffer)); + + sleep(1); + + char recv_buffer[4096] = { 0 }; + iov[0].iov_base = recv_buffer; + iov[0].iov_len = 1; + TEST_RES(recvmsg(sk_bound, &msg, 0), _ret == 1); + + iov[0].iov_base = recv_buffer; + iov[0].iov_len = 1; + iov[1].iov_base = (char *)1; + iov[1].iov_len = 1; + msg.msg_iovlen = 2; + TEST_ERRNO(recvmsg(sk_bound, &msg, 0), EFAULT); + + iov[0].iov_base = recv_buffer; + iov[0].iov_len = 4096; + msg.msg_iovlen = 1; + TEST_RES(recvmsg(sk_bound, &msg, 0), _ret == strlen(good_buffer)); + + iov[0].iov_base = recv_buffer; + iov[0].iov_len = 4096; + iov[1].iov_base = (char *)1; + iov[1].iov_len = 1; + msg.msg_iovlen = 2; + TEST_RES(recvmsg(sk_bound, &msg, 0), _ret == strlen(good_buffer)); +} +END_TEST()