[libc-commits] [libc] [libc] Fix inet_aton (PR #198791)

Pavel Labath via libc-commits libc-commits at lists.llvm.org
Thu May 21 07:01:09 PDT 2026


================
@@ -0,0 +1,65 @@
+//===----------------------------------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+///
+/// \file
+/// This file implements helper functions for parsing network addresses.
+///
+//===----------------------------------------------------------------------===//
+
+#include "src/__support/net/address.h"
+#include "src/__support/common.h"
+#include "src/__support/ctype_utils.h"
+#include "src/__support/endian_internal.h"
+#include "src/__support/str_to_integer.h"
+
+namespace LIBC_NAMESPACE_DECL {
+namespace internal {
+
+cpp::optional<in_addr_t> inet_addr(const char *cp) {
+  constexpr int IPV4_MAX_DOT_NUM = 3;
+  in_addr_t parts[IPV4_MAX_DOT_NUM + 1] = {0};
+  int dot_num = 0;
+
+  for (; dot_num <= IPV4_MAX_DOT_NUM; ++dot_num) {
+    // strtointeger skips leading whitespace signs (1.+2.-3. 4), but we don't
+    // want that, so we explicitly check that the first character is a digit.
+    if (!isdigit(*cp))
+      return cpp::nullopt;
+
+    auto result = strtointeger<in_addr_t>(cp, 0);
+    parts[dot_num] = result;
+
+    if (result.has_error() || result.parsed_len == 0)
+      return cpp::nullopt;
+    cp += result.parsed_len;
+    if (*cp == '\0' || isspace(*cp))
+      break;
+    if (*cp != '.')
+      return cpp::nullopt;
+    ++cp;
+  }
+
+  if (dot_num > IPV4_MAX_DOT_NUM)
+    return cpp::nullopt;
+
+  // converts the Internet host address cp from the IPv4 numbers-and-dots
+  // notation (a[.b[.c[.d]]]) into binary form (in network byte order)
+  in_addr_t result = 0;
+  for (int i = 0; i <= dot_num; ++i) {
+    in_addr_t max_part = i == dot_num ? (0xffffffffu >> (8 * dot_num)) : 0xffu;
+    if (parts[i] > max_part)
+      return cpp::nullopt;
+    int shift = i == dot_num ? 0 : 8 * (IPV4_MAX_DOT_NUM - i);
+    result |= parts[i] << shift;
+  }
+
+  return LIBC_NAMESPACE::Endian::to_big_endian(result);
----------------
labath wrote:

That makes sense, and my only problem with that is figuring out how to call this function then, as it sort of really is the *internal* implementation of *inet_addr*. Looking around, I think that has been the problem for many other functions. Like I'm pretty sure that's how the functions in __support/wchar ended up in the internal namespace -- though maybe they're not the best example to follow as they also which file-local static functions, which [is not supposed to happen](https://libc.llvm.org/dev/code_style.html#inline-functions-and-variables-defined-in-header-files). Math functions solve this by creating their own (sub)namespace, so the new version of the patch does the same.

LMK is that's okay.

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


More information about the libc-commits mailing list