[libc-commits] [libc] [libc][stdlib] Implement setenv() with environment management infrastructure (PR #163018)
Jeff Bailey via libc-commits
libc-commits at lists.llvm.org
Sat Oct 11 14:15:12 PDT 2025
================
@@ -0,0 +1,165 @@
+//===-- Implementation of internal environment utilities ------------------===//
+//
+// 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
+//
+//===----------------------------------------------------------------------===//
+
+#include "environ_internal.h"
+#include "config/app.h"
+#include "src/__support/CPP/string_view.h"
+#include "src/__support/macros/config.h"
+#include "src/string/memcpy.h"
+
+// We use extern "C" declarations for malloc/free/realloc instead of including
+// src/stdlib/malloc.h, src/stdlib/free.h, and src/stdlib/realloc.h. This allows
+// the implementation to work with different allocator implementations,
+// particularly in integration tests which provide a simple bump allocator. The
+// extern "C" linkage ensures we use whatever allocator is linked with the test
+// or application.
+extern "C" void *malloc(size_t);
+extern "C" void free(void *);
+extern "C" void *realloc(void *, size_t);
+
+namespace LIBC_NAMESPACE_DECL {
+namespace internal {
+
+// Minimum initial capacity for the environment array when first allocated.
+// This avoids frequent reallocations for small environments.
+constexpr size_t MIN_ENVIRON_CAPACITY = 32;
+
+// Growth factor for environment array capacity when expanding.
+// When capacity is exceeded, new_capacity = old_capacity *
+// ENVIRON_GROWTH_FACTOR.
+constexpr size_t ENVIRON_GROWTH_FACTOR = 2;
+
+// Global state for environment management
+Mutex environ_mutex(false, false, false, false);
+char **environ_storage = nullptr;
+EnvStringOwnership *environ_ownership = nullptr;
+size_t environ_capacity = 0;
+size_t environ_size = 0;
+bool environ_is_ours = false;
+
+char **get_environ_array() {
+ if (environ_is_ours)
+ return environ_storage;
+ return reinterpret_cast<char **>(LIBC_NAMESPACE::app.env_ptr);
+}
+
+void init_environ() {
+ // Count entries in the startup environ
+ char **env_ptr = reinterpret_cast<char **>(LIBC_NAMESPACE::app.env_ptr);
+ if (!env_ptr)
+ return;
+
+ size_t count = 0;
+ for (char **env = env_ptr; *env != nullptr; env++)
+ count++;
+
+ environ_size = count;
+}
+
+int find_env_var(cpp::string_view name) {
+ char **env_array = get_environ_array();
+ if (!env_array)
+ return -1;
+
+ for (size_t i = 0; i < environ_size; i++) {
+ cpp::string_view current(env_array[i]);
+ if (!current.starts_with(name))
+ continue;
+
+ // Check that name is followed by '='
+ if (current.size() > name.size() && current[name.size()] == '=')
+ return static_cast<int>(i);
+ }
+
+ return -1;
+}
+
+bool ensure_capacity(size_t needed) {
+ // IMPORTANT: This function assumes environ_mutex is already held by the
+ // caller. Do not add locking here as it would cause deadlock.
----------------
kaladron wrote:
I'm happy to give it a try! I'm heading to bed now, but will take a look in the morning (likewise with the windows and Mac bot failures).
I tried running with ASan / UBSan but couldn't figure those out with the bump allocator.
https://github.com/llvm/llvm-project/pull/163018
More information about the libc-commits
mailing list