|  | // Copyright 2022 The Chromium Authors | 
|  | // Use of this source code is governed by a BSD-style license that can be | 
|  | // found in the LICENSE file. | 
|  |  | 
|  | #include "net/base/sockaddr_util_posix.h" | 
|  |  | 
|  | #include <string.h> | 
|  |  | 
|  | #include <sys/socket.h> | 
|  | #include <sys/un.h> | 
|  |  | 
|  | #include "net/base/sockaddr_storage.h" | 
|  | #include "testing/gmock/include/gmock/gmock-matchers.h" | 
|  | #include "testing/gtest/include/gtest/gtest.h" | 
|  |  | 
|  | namespace net { | 
|  |  | 
|  | namespace { | 
|  |  | 
|  | size_t MaxPathLength(SockaddrStorage* storage) { | 
|  | // |storage.addr_len| is initialized to the largest possible platform- | 
|  | // dependent value. Subtracting the size of the initial fields in | 
|  | // sockaddr_un gives us the longest permissible path value including space | 
|  | // for an extra NUL character at the front or back. | 
|  | return storage->addr_len - offsetof(struct sockaddr_un, sun_path) - 1; | 
|  | } | 
|  |  | 
|  | }  // namespace | 
|  |  | 
|  | TEST(FillUnixAddressTest, SimpleAddress) { | 
|  | SockaddrStorage storage; | 
|  | std::string path = "/tmp/socket/path"; | 
|  |  | 
|  | EXPECT_TRUE( | 
|  | FillUnixAddress(path, /*use_abstract_namespace=*/false, &storage)); | 
|  |  | 
|  | // |storage.addr_len| indicates the full size of the data in sockaddr_un. | 
|  | // The size is increased by one byte to include the string NUL terminator. | 
|  | EXPECT_EQ(path.size() + 1U + offsetof(struct sockaddr_un, sun_path), | 
|  | (unsigned int)storage.addr_len); | 
|  |  | 
|  | struct sockaddr_un* socket_addr = | 
|  | reinterpret_cast<struct sockaddr_un*>(storage.addr); | 
|  | EXPECT_EQ(socket_addr->sun_family, AF_UNIX); | 
|  |  | 
|  | // Implicit conversion to std::string for comparison is fine since the path | 
|  | // is always NUL terminated. | 
|  | EXPECT_EQ(socket_addr->sun_path, path); | 
|  | } | 
|  |  | 
|  | TEST(FillUnixAddressTest, PathEmpty) { | 
|  | SockaddrStorage storage; | 
|  | std::string path = ""; | 
|  | EXPECT_FALSE( | 
|  | FillUnixAddress(path, /*use_abstract_namespace=*/false, &storage)); | 
|  | } | 
|  |  | 
|  | TEST(FillUnixAddressTest, AddressMaxLength) { | 
|  | SockaddrStorage storage; | 
|  | size_t path_max = MaxPathLength(&storage); | 
|  | std::string path(path_max, '0'); | 
|  |  | 
|  | EXPECT_TRUE( | 
|  | FillUnixAddress(path, /*use_abstract_namespace=*/false, &storage)); | 
|  |  | 
|  | struct sockaddr_un* socket_addr = | 
|  | reinterpret_cast<struct sockaddr_un*>(storage.addr); | 
|  | EXPECT_EQ(socket_addr->sun_family, AF_UNIX); | 
|  | EXPECT_EQ(socket_addr->sun_path, path); | 
|  | } | 
|  |  | 
|  | TEST(FillUnixAddressTest, AddressTooLong) { | 
|  | SockaddrStorage storage; | 
|  | size_t path_max = MaxPathLength(&storage); | 
|  | std::string path(path_max + 1, '0'); | 
|  |  | 
|  | EXPECT_FALSE( | 
|  | FillUnixAddress(path, /*use_abstract_namespace=*/false, &storage)); | 
|  | } | 
|  |  | 
|  | TEST(FillUnixAddressTest, AbstractLinuxAddress) { | 
|  | SockaddrStorage storage; | 
|  | size_t path_max = MaxPathLength(&storage); | 
|  | std::string path(path_max, '0'); | 
|  |  | 
|  | #if BUILDFLAG(IS_ANDROID) || BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_CHROMEOS) | 
|  | EXPECT_TRUE(FillUnixAddress(path, /*use_abstract_namespace=*/true, &storage)); | 
|  |  | 
|  | EXPECT_EQ(path.size() + 1U + offsetof(struct sockaddr_un, sun_path), | 
|  | (unsigned int)storage.addr_len); | 
|  |  | 
|  | struct sockaddr_un* socket_addr = | 
|  | reinterpret_cast<struct sockaddr_un*>(storage.addr); | 
|  | EXPECT_EQ(socket_addr->sun_family, AF_UNIX); | 
|  |  | 
|  | // The path buffer is preceded by a NUL character for abstract Linux | 
|  | // addresses. | 
|  | EXPECT_EQ(socket_addr->sun_path[0], '\0'); | 
|  |  | 
|  | // The path string may not be NUL terminated, so do a buffer copy when | 
|  | // converting to std::string. | 
|  | std::string unix_path(reinterpret_cast<char*>(socket_addr->sun_path + 1), | 
|  | path.size()); | 
|  | EXPECT_EQ(unix_path, path); | 
|  | #else | 
|  | // Other platforms don't support the abstract Linux namespace. | 
|  | EXPECT_FALSE( | 
|  | FillUnixAddress(path, /*use_abstract_namespace=*/true, &storage)); | 
|  | #endif | 
|  | } | 
|  |  | 
|  | }  // namespace net |