diff options
Diffstat (limited to 'lib/msan/tests/msan_test.cc')
-rw-r--r-- | lib/msan/tests/msan_test.cc | 332 |
1 files changed, 219 insertions, 113 deletions
diff --git a/lib/msan/tests/msan_test.cc b/lib/msan/tests/msan_test.cc index 9ec1e28374db..dd81c4d798f6 100644 --- a/lib/msan/tests/msan_test.cc +++ b/lib/msan/tests/msan_test.cc @@ -175,10 +175,16 @@ void ExpectPoisonedWithOrigin(const T& t, unsigned origin) { } #define EXPECT_NOT_POISONED(x) EXPECT_EQ(true, TestForNotPoisoned((x))) +#define EXPECT_NOT_POISONED2(data, size) \ + EXPECT_EQ(true, TestForNotPoisoned((data), (size))) + +bool TestForNotPoisoned(const void *data, size_t size) { + return __msan_test_shadow(data, size) == -1; +} template<typename T> bool TestForNotPoisoned(const T& t) { - return __msan_test_shadow((void*)&t, sizeof(t)) == -1; + return TestForNotPoisoned((void *)&t, sizeof(t)); } static U8 poisoned_array[100]; @@ -879,92 +885,203 @@ TEST(MemorySanitizer, bind_getsockname) { close(sock); } -TEST(MemorySanitizer, accept) { - int listen_socket = socket(AF_INET, SOCK_STREAM, 0); +class SocketAddr { + public: + virtual ~SocketAddr() = default; + virtual struct sockaddr *ptr() = 0; + virtual size_t size() const = 0; + + template <class... Args> + static std::unique_ptr<SocketAddr> Create(int family, Args... args); +}; + +class SocketAddr4 : public SocketAddr { + public: + SocketAddr4() { EXPECT_POISONED(sai_); } + explicit SocketAddr4(uint16_t port) { + memset(&sai_, 0, sizeof(sai_)); + sai_.sin_family = AF_INET; + sai_.sin_port = port; + sai_.sin_addr.s_addr = htonl(INADDR_LOOPBACK); + } + + sockaddr *ptr() override { return reinterpret_cast<sockaddr *>(&sai_); } + + size_t size() const override { return sizeof(sai_); } + + private: + sockaddr_in sai_; +}; + +class SocketAddr6 : public SocketAddr { + public: + SocketAddr6() { EXPECT_POISONED(sai_); } + explicit SocketAddr6(uint16_t port) { + memset(&sai_, 0, sizeof(sai_)); + sai_.sin6_family = AF_INET6; + sai_.sin6_port = port; + sai_.sin6_addr = in6addr_loopback; + } + + sockaddr *ptr() override { return reinterpret_cast<sockaddr *>(&sai_); } + + size_t size() const override { return sizeof(sai_); } + + private: + sockaddr_in6 sai_; +}; + +template <class... Args> +std::unique_ptr<SocketAddr> SocketAddr::Create(int family, Args... args) { + if (family == AF_INET) + return std::unique_ptr<SocketAddr>(new SocketAddr4(args...)); + return std::unique_ptr<SocketAddr>(new SocketAddr6(args...)); +} + +class MemorySanitizerIpTest : public ::testing::TestWithParam<int> { + public: + void SetUp() override { + ASSERT_TRUE(GetParam() == AF_INET || GetParam() == AF_INET6); + } + + template <class... Args> + std::unique_ptr<SocketAddr> CreateSockAddr(Args... args) const { + return SocketAddr::Create(GetParam(), args...); + } + + int CreateSocket(int socket_type) const { + return socket(GetParam(), socket_type, 0); + } +}; + +std::vector<int> GetAvailableIpSocketFamilies() { + std::vector<int> result; + + for (int i : {AF_INET, AF_INET6}) { + int s = socket(i, SOCK_STREAM, 0); + if (s > 0) { + auto sai = SocketAddr::Create(i, 0); + if (bind(s, sai->ptr(), sai->size()) == 0) result.push_back(i); + close(s); + } + } + + return result; +} + +INSTANTIATE_TEST_CASE_P(IpTests, MemorySanitizerIpTest, + ::testing::ValuesIn(GetAvailableIpSocketFamilies())); + +TEST_P(MemorySanitizerIpTest, accept) { + int listen_socket = CreateSocket(SOCK_STREAM); ASSERT_LT(0, listen_socket); - struct sockaddr_in sai; - memset(&sai, 0, sizeof(sai)); - sai.sin_family = AF_INET; - sai.sin_port = 0; - sai.sin_addr.s_addr = htonl(INADDR_LOOPBACK); - int res = bind(listen_socket, (struct sockaddr *)&sai, sizeof(sai)); + auto sai = CreateSockAddr(0); + int res = bind(listen_socket, sai->ptr(), sai->size()); ASSERT_EQ(0, res); res = listen(listen_socket, 1); ASSERT_EQ(0, res); - socklen_t sz = sizeof(sai); - res = getsockname(listen_socket, (struct sockaddr *)&sai, &sz); + socklen_t sz = sai->size(); + res = getsockname(listen_socket, sai->ptr(), &sz); ASSERT_EQ(0, res); - ASSERT_EQ(sizeof(sai), sz); + ASSERT_EQ(sai->size(), sz); - int connect_socket = socket(AF_INET, SOCK_STREAM, 0); + int connect_socket = CreateSocket(SOCK_STREAM); ASSERT_LT(0, connect_socket); res = fcntl(connect_socket, F_SETFL, O_NONBLOCK); ASSERT_EQ(0, res); - res = connect(connect_socket, (struct sockaddr *)&sai, sizeof(sai)); + res = connect(connect_socket, sai->ptr(), sai->size()); // On FreeBSD this connection completes immediately. if (res != 0) { ASSERT_EQ(-1, res); ASSERT_EQ(EINPROGRESS, errno); } - __msan_poison(&sai, sizeof(sai)); - int new_sock = accept(listen_socket, (struct sockaddr *)&sai, &sz); + __msan_poison(sai->ptr(), sai->size()); + int new_sock = accept(listen_socket, sai->ptr(), &sz); ASSERT_LT(0, new_sock); - ASSERT_EQ(sizeof(sai), sz); - EXPECT_NOT_POISONED(sai); + ASSERT_EQ(sai->size(), sz); + EXPECT_NOT_POISONED2(sai->ptr(), sai->size()); - __msan_poison(&sai, sizeof(sai)); - res = getpeername(new_sock, (struct sockaddr *)&sai, &sz); + __msan_poison(sai->ptr(), sai->size()); + res = getpeername(new_sock, sai->ptr(), &sz); ASSERT_EQ(0, res); - ASSERT_EQ(sizeof(sai), sz); - EXPECT_NOT_POISONED(sai); + ASSERT_EQ(sai->size(), sz); + EXPECT_NOT_POISONED2(sai->ptr(), sai->size()); close(new_sock); close(connect_socket); close(listen_socket); } -TEST(MemorySanitizer, getaddrinfo) { - struct addrinfo *ai; - struct addrinfo hints; - memset(&hints, 0, sizeof(hints)); - hints.ai_family = AF_INET; - int res = getaddrinfo("localhost", NULL, &hints, &ai); +TEST_P(MemorySanitizerIpTest, recvmsg) { + int server_socket = CreateSocket(SOCK_DGRAM); + ASSERT_LT(0, server_socket); + + auto sai = CreateSockAddr(0); + int res = bind(server_socket, sai->ptr(), sai->size()); ASSERT_EQ(0, res); - EXPECT_NOT_POISONED(*ai); - ASSERT_EQ(sizeof(sockaddr_in), ai->ai_addrlen); - EXPECT_NOT_POISONED(*(sockaddr_in*)ai->ai_addr); -} -TEST(MemorySanitizer, getnameinfo) { - struct sockaddr_in sai; - memset(&sai, 0, sizeof(sai)); - sai.sin_family = AF_INET; - sai.sin_port = 80; - sai.sin_addr.s_addr = htonl(INADDR_LOOPBACK); - char host[500]; - char serv[500]; - int res = getnameinfo((struct sockaddr *)&sai, sizeof(sai), host, - sizeof(host), serv, sizeof(serv), 0); + socklen_t sz = sai->size(); + res = getsockname(server_socket, sai->ptr(), &sz); ASSERT_EQ(0, res); - EXPECT_NOT_POISONED(host[0]); - EXPECT_POISONED(host[sizeof(host) - 1]); + ASSERT_EQ(sai->size(), sz); - ASSERT_NE(0U, strlen(host)); - EXPECT_NOT_POISONED(serv[0]); - EXPECT_POISONED(serv[sizeof(serv) - 1]); - ASSERT_NE(0U, strlen(serv)); + int client_socket = CreateSocket(SOCK_DGRAM); + ASSERT_LT(0, client_socket); + + auto client_sai = CreateSockAddr(0); + res = bind(client_socket, client_sai->ptr(), client_sai->size()); + ASSERT_EQ(0, res); + + sz = client_sai->size(); + res = getsockname(client_socket, client_sai->ptr(), &sz); + ASSERT_EQ(0, res); + ASSERT_EQ(client_sai->size(), sz); + + const char *s = "message text"; + struct iovec iov; + iov.iov_base = (void *)s; + iov.iov_len = strlen(s) + 1; + struct msghdr msg; + memset(&msg, 0, sizeof(msg)); + msg.msg_name = sai->ptr(); + msg.msg_namelen = sai->size(); + msg.msg_iov = &iov; + msg.msg_iovlen = 1; + res = sendmsg(client_socket, &msg, 0); + ASSERT_LT(0, res); + + char buf[1000]; + struct iovec recv_iov; + recv_iov.iov_base = (void *)&buf; + recv_iov.iov_len = sizeof(buf); + auto recv_sai = CreateSockAddr(); + struct msghdr recv_msg; + memset(&recv_msg, 0, sizeof(recv_msg)); + recv_msg.msg_name = recv_sai->ptr(); + recv_msg.msg_namelen = recv_sai->size(); + recv_msg.msg_iov = &recv_iov; + recv_msg.msg_iovlen = 1; + res = recvmsg(server_socket, &recv_msg, 0); + ASSERT_LT(0, res); + + ASSERT_EQ(recv_sai->size(), recv_msg.msg_namelen); + EXPECT_NOT_POISONED2(recv_sai->ptr(), recv_sai->size()); + EXPECT_STREQ(s, buf); + + close(server_socket); + close(client_socket); } #define EXPECT_HOSTENT_NOT_POISONED(he) \ do { \ EXPECT_NOT_POISONED(*(he)); \ - ASSERT_NE((void *) 0, (he)->h_name); \ - ASSERT_NE((void *) 0, (he)->h_aliases); \ - ASSERT_NE((void *) 0, (he)->h_addr_list); \ + ASSERT_NE((void *)0, (he)->h_name); \ + ASSERT_NE((void *)0, (he)->h_aliases); \ + ASSERT_NE((void *)0, (he)->h_addr_list); \ EXPECT_NOT_POISONED(strlen((he)->h_name)); \ char **p = (he)->h_aliases; \ while (*p) { \ @@ -993,76 +1110,38 @@ TEST(MemorySanitizer, gethostbyname) { EXPECT_HOSTENT_NOT_POISONED(he); } -#endif // MSAN_TEST_DISABLE_GETHOSTBYNAME +#endif // MSAN_TEST_DISABLE_GETHOSTBYNAME -TEST(MemorySanitizer, recvmsg) { - int server_socket = socket(AF_INET, SOCK_DGRAM, 0); - ASSERT_LT(0, server_socket); +TEST(MemorySanitizer, getaddrinfo) { + struct addrinfo *ai; + struct addrinfo hints; + memset(&hints, 0, sizeof(hints)); + hints.ai_family = AF_INET; + int res = getaddrinfo("localhost", NULL, &hints, &ai); + ASSERT_EQ(0, res); + EXPECT_NOT_POISONED(*ai); + ASSERT_EQ(sizeof(sockaddr_in), ai->ai_addrlen); + EXPECT_NOT_POISONED(*(sockaddr_in *)ai->ai_addr); +} +TEST(MemorySanitizer, getnameinfo) { struct sockaddr_in sai; memset(&sai, 0, sizeof(sai)); sai.sin_family = AF_INET; - sai.sin_port = 0; + sai.sin_port = 80; sai.sin_addr.s_addr = htonl(INADDR_LOOPBACK); - int res = bind(server_socket, (struct sockaddr *)&sai, sizeof(sai)); - ASSERT_EQ(0, res); - - socklen_t sz = sizeof(sai); - res = getsockname(server_socket, (struct sockaddr *)&sai, &sz); - ASSERT_EQ(0, res); - ASSERT_EQ(sizeof(sai), sz); - - - int client_socket = socket(AF_INET, SOCK_DGRAM, 0); - ASSERT_LT(0, client_socket); - - struct sockaddr_in client_sai; - memset(&client_sai, 0, sizeof(client_sai)); - client_sai.sin_family = AF_INET; - client_sai.sin_port = 0; - client_sai.sin_addr.s_addr = htonl(INADDR_LOOPBACK); - res = bind(client_socket, (struct sockaddr *)&client_sai, sizeof(client_sai)); - ASSERT_EQ(0, res); - - sz = sizeof(client_sai); - res = getsockname(client_socket, (struct sockaddr *)&client_sai, &sz); + char host[500]; + char serv[500]; + int res = getnameinfo((struct sockaddr *)&sai, sizeof(sai), host, + sizeof(host), serv, sizeof(serv), 0); ASSERT_EQ(0, res); - ASSERT_EQ(sizeof(client_sai), sz); - - const char *s = "message text"; - struct iovec iov; - iov.iov_base = (void *)s; - iov.iov_len = strlen(s) + 1; - struct msghdr msg; - memset(&msg, 0, sizeof(msg)); - msg.msg_name = &sai; - msg.msg_namelen = sizeof(sai); - msg.msg_iov = &iov; - msg.msg_iovlen = 1; - res = sendmsg(client_socket, &msg, 0); - ASSERT_LT(0, res); - - - char buf[1000]; - struct iovec recv_iov; - recv_iov.iov_base = (void *)&buf; - recv_iov.iov_len = sizeof(buf); - struct sockaddr_in recv_sai; - struct msghdr recv_msg; - memset(&recv_msg, 0, sizeof(recv_msg)); - recv_msg.msg_name = &recv_sai; - recv_msg.msg_namelen = sizeof(recv_sai); - recv_msg.msg_iov = &recv_iov; - recv_msg.msg_iovlen = 1; - res = recvmsg(server_socket, &recv_msg, 0); - ASSERT_LT(0, res); - - ASSERT_EQ(sizeof(recv_sai), recv_msg.msg_namelen); - EXPECT_NOT_POISONED(*(struct sockaddr_in *)recv_msg.msg_name); - EXPECT_STREQ(s, buf); + EXPECT_NOT_POISONED(host[0]); + EXPECT_POISONED(host[sizeof(host) - 1]); - close(server_socket); - close(client_socket); + ASSERT_NE(0U, strlen(host)); + EXPECT_NOT_POISONED(serv[0]); + EXPECT_POISONED(serv[sizeof(serv) - 1]); + ASSERT_NE(0U, strlen(serv)); } TEST(MemorySanitizer, gethostbyname2) { @@ -3502,6 +3581,21 @@ TEST(MemorySanitizer, getgroups) { EXPECT_NOT_POISONED(gids[i]); } +TEST(MemorySanitizer, getgroups_zero) { + gid_t group; + int n = getgroups(0, &group); + ASSERT_GE(n, 0); +} + +TEST(MemorySanitizer, getgroups_negative) { + gid_t group; + int n = getgroups(-1, 0); + ASSERT_EQ(-1, n); + + n = getgroups(-1, 0); + ASSERT_EQ(-1, n); +} + TEST(MemorySanitizer, wordexp) { wordexp_t w; int res = wordexp("a b c", &w, 0); @@ -3602,6 +3696,18 @@ TEST(MemorySanitizer, ICmpVectorRelational) { EXPECT_POISONED(_mm_cmpgt_epi16(poisoned(_mm_set1_epi16(6), _mm_set1_epi16(0xF)), poisoned(_mm_set1_epi16(7), _mm_set1_epi16(0)))); } + +TEST(MemorySanitizer, stmxcsr_ldmxcsr) { + U4 x = _mm_getcsr(); + EXPECT_NOT_POISONED(x); + + _mm_setcsr(x); + + __msan_poison(&x, sizeof(x)); + U4 origin = __LINE__; + __msan_set_origin(&x, sizeof(x), origin); + EXPECT_UMR_O(_mm_setcsr(x), origin); +} #endif // Volatile bitfield store is implemented as load-mask-store |