[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