// Copyright 2022 The Chromium Authors. All rights reserved. // 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 #include #include #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(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(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(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(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