[libc-commits] [libc] [libc] Implement IPv6 (AF_INET6) support in inet_pton (PR #226550)

Pavel Labath via libc-commits libc-commits at lists.llvm.org
Tue Sep 29 05:17:21 PDT 2026


================
@@ -90,6 +92,154 @@ TEST_F(LlvmLibcInetPtonTest, StrictPosixLeadingZeros) {
   ASSERT_ERRNO_SUCCESS();
 }
 
+static bool check_ipv6(const struct in6_addr &addr, uint16_t a, uint16_t b,
+                       uint16_t c, uint16_t d, uint16_t e, uint16_t f,
+                       uint16_t g, uint16_t h) {
+  uint16_t words[8] = {a, b, c, d, e, f, g, h};
+  struct in6_addr expected;
+  for (size_t i = 0; i < 8; ++i)
+    expected.s6_addr16[i] = LIBC_NAMESPACE::Endian::to_big_endian(words[i]);
+  return LIBC_NAMESPACE::inline_memcmp(&addr, &expected,
+                                       sizeof(struct in6_addr)) == 0;
+}
+
+TEST_F(LlvmLibcInetPtonTest, ValidIPv6Addresses) {
+  struct in6_addr addr;
+
+  // Unspecified address
+  EXPECT_EQ(1, LIBC_NAMESPACE::inet_pton(AF_INET6, "::", &addr));
+  EXPECT_TRUE(check_ipv6(addr, 0, 0, 0, 0, 0, 0, 0, 0));
+  ASSERT_ERRNO_SUCCESS();
+
+  // Loopback address
+  EXPECT_EQ(1, LIBC_NAMESPACE::inet_pton(AF_INET6, "::1", &addr));
+  EXPECT_TRUE(check_ipv6(addr, 0, 0, 0, 0, 0, 0, 0, 1));
+  ASSERT_ERRNO_SUCCESS();
+
+  // Full 8 groups without compression
+  EXPECT_EQ(1, LIBC_NAMESPACE::inet_pton(
+                   AF_INET6, "2001:0db8:85a3:0000:0000:8a2e:0370:7334", &addr));
+  EXPECT_TRUE(
+      check_ipv6(addr, 0x2001, 0x0db8, 0x85a3, 0, 0, 0x8a2e, 0x0370, 0x7334));
+  ASSERT_ERRNO_SUCCESS();
+
+  // Full 8 groups with varying digit lengths
+  EXPECT_EQ(1, LIBC_NAMESPACE::inet_pton(
+                   AF_INET6, "2001:db8:85a3:0:0:8a2e:370:7334", &addr));
+  EXPECT_TRUE(
+      check_ipv6(addr, 0x2001, 0x0db8, 0x85a3, 0, 0, 0x8a2e, 0x0370, 0x7334));
+  ASSERT_ERRNO_SUCCESS();
+
+  // Compression at beginning
+  EXPECT_EQ(1, LIBC_NAMESPACE::inet_pton(AF_INET6, "::1234", &addr));
+  EXPECT_TRUE(check_ipv6(addr, 0, 0, 0, 0, 0, 0, 0, 0x1234));
+  ASSERT_ERRNO_SUCCESS();
+
+  // Compression at end
+  EXPECT_EQ(1, LIBC_NAMESPACE::inet_pton(AF_INET6, "fe80::", &addr));
+  EXPECT_TRUE(check_ipv6(addr, 0xfe80, 0, 0, 0, 0, 0, 0, 0));
+  ASSERT_ERRNO_SUCCESS();
+
+  // Compression in middle
+  EXPECT_EQ(1, LIBC_NAMESPACE::inet_pton(AF_INET6, "2001:db8::1", &addr));
+  EXPECT_TRUE(check_ipv6(addr, 0x2001, 0x0db8, 0, 0, 0, 0, 0, 1));
+  ASSERT_ERRNO_SUCCESS();
+
+  // Multiple words before and after compression
+  EXPECT_EQ(1, LIBC_NAMESPACE::inet_pton(
+                   AF_INET6, "2001:db8:85a3::8a2e:370:7334", &addr));
+  EXPECT_TRUE(
+      check_ipv6(addr, 0x2001, 0x0db8, 0x85a3, 0, 0, 0x8a2e, 0x0370, 0x7334));
+  ASSERT_ERRNO_SUCCESS();
+
+  // Case insensitivity
+  EXPECT_EQ(1, LIBC_NAMESPACE::inet_pton(AF_INET6, "2001:Db8::AbCd", &addr));
+  EXPECT_TRUE(check_ipv6(addr, 0x2001, 0x0db8, 0, 0, 0, 0, 0, 0xabcd));
+  ASSERT_ERRNO_SUCCESS();
+}
+
+TEST_F(LlvmLibcInetPtonTest, ValidIPv4MappedIPv6Addresses) {
+  struct in6_addr addr;
+
+  // Standard IPv4-mapped address ::ffff:192.168.1.1
+  EXPECT_EQ(1,
+            LIBC_NAMESPACE::inet_pton(AF_INET6, "::ffff:192.168.1.1", &addr));
+  EXPECT_TRUE(check_ipv6(addr, 0, 0, 0, 0, 0, 0xffff, 0xc0a8, 0x0101));
+  ASSERT_ERRNO_SUCCESS();
+
+  // IPv4-compatible address ::192.168.1.1
+  EXPECT_EQ(1, LIBC_NAMESPACE::inet_pton(AF_INET6, "::192.168.1.1", &addr));
+  EXPECT_TRUE(check_ipv6(addr, 0, 0, 0, 0, 0, 0, 0xc0a8, 0x0101));
+  ASSERT_ERRNO_SUCCESS();
+
+  // Mixed prefix with compression: 2001:db8::192.168.1.1
+  EXPECT_EQ(
+      1, LIBC_NAMESPACE::inet_pton(AF_INET6, "2001:db8::192.168.1.1", &addr));
+  EXPECT_TRUE(check_ipv6(addr, 0x2001, 0x0db8, 0, 0, 0, 0, 0xc0a8, 0x0101));
+  ASSERT_ERRNO_SUCCESS();
+
+  // Full 6 words without compression followed by IPv4
+  EXPECT_EQ(
+      1, LIBC_NAMESPACE::inet_pton(AF_INET6, "0:0:0:0:0:0:192.168.1.1", &addr));
+  EXPECT_TRUE(check_ipv6(addr, 0, 0, 0, 0, 0, 0, 0xc0a8, 0x0101));
+  ASSERT_ERRNO_SUCCESS();
+}
+
+TEST_F(LlvmLibcInetPtonTest, InvalidIPv6Formats) {
+  struct in6_addr addr;
+
+  // Empty string
+  EXPECT_EQ(0, LIBC_NAMESPACE::inet_pton(AF_INET6, "", &addr));
+
+  // Colon misuse
+  EXPECT_EQ(0, LIBC_NAMESPACE::inet_pton(AF_INET6, ":", &addr));
+  EXPECT_EQ(0, LIBC_NAMESPACE::inet_pton(AF_INET6, ":::", &addr));
+  EXPECT_EQ(0, LIBC_NAMESPACE::inet_pton(AF_INET6, ":1:2:3:4:5:6:7:8", &addr));
+  EXPECT_EQ(0, LIBC_NAMESPACE::inet_pton(AF_INET6, "1:2:3:4:5:6:7:8:", &addr));
+  EXPECT_EQ(0, LIBC_NAMESPACE::inet_pton(AF_INET6, "1::2:", &addr));
+  EXPECT_EQ(0, LIBC_NAMESPACE::inet_pton(AF_INET6, "1::2::3", &addr));
+
+  // Word count errors
+  EXPECT_EQ(0, LIBC_NAMESPACE::inet_pton(AF_INET6, "1:2:3:4:5:6:7:8:9", &addr));
+  EXPECT_EQ(0, LIBC_NAMESPACE::inet_pton(AF_INET6, "1:2:3:4::5:6:7:8", &addr));
+  EXPECT_EQ(0, LIBC_NAMESPACE::inet_pton(AF_INET6, "1:2:3:4:5:6:7", &addr));
+
+  // Field overflow (> 4 hex digits)
+  EXPECT_EQ(0, LIBC_NAMESPACE::inet_pton(AF_INET6, "12345::1", &addr));
+  EXPECT_EQ(0, LIBC_NAMESPACE::inet_pton(AF_INET6, "00000::1", &addr));
+
+  // Non-hex characters
+  EXPECT_EQ(0, LIBC_NAMESPACE::inet_pton(AF_INET6, "2001:xyz::1", &addr));
+  EXPECT_EQ(0, LIBC_NAMESPACE::inet_pton(AF_INET6, "fe80::1%eth0", &addr));
+
+  // Plain IPv4 without ::
+  EXPECT_EQ(0, LIBC_NAMESPACE::inet_pton(AF_INET6, "192.168.1.1", &addr));
+
+  // Embedded IPv4 errors
+  EXPECT_EQ(0, LIBC_NAMESPACE::inet_pton(AF_INET6, "::ffff:192.168.1", &addr));
+  EXPECT_EQ(0,
+            LIBC_NAMESPACE::inet_pton(AF_INET6, "::ffff:192.168.1.256", &addr));
+  EXPECT_EQ(0,
+            LIBC_NAMESPACE::inet_pton(AF_INET6, "::ffff:192.168.1.1:", &addr));
+  EXPECT_EQ(0,
+            LIBC_NAMESPACE::inet_pton(AF_INET6, "::ffff:192.168.01.1", &addr));
+  EXPECT_EQ(0, LIBC_NAMESPACE::inet_pton(AF_INET6, "1:2:3:4:5:6:7:192.168.1.1",
+                                         &addr));
+  EXPECT_EQ(0, LIBC_NAMESPACE::inet_pton(AF_INET6, "1:2:3:4:5:6::192.168.1.1",
----------------
labath wrote:

Also something like `1::2.3.4.5:6`

https://github.com/llvm/llvm-project/pull/226550


More information about the libc-commits mailing list