[libc-commits] [libc] [libc][stdlib] Add putenv (PR #208339)
Jeff Bailey via libc-commits
libc-commits at lists.llvm.org
Tue Jul 28 06:45:35 PDT 2026
https://github.com/kaladron updated https://github.com/llvm/llvm-project/pull/208339
>From d2f88315923429c5d14327f5b77251f7085731ee Mon Sep 17 00:00:00 2001
From: Jeff Bailey <jbailey at raspberryginger.com>
Date: Mon, 8 Jun 2026 20:39:26 +0100
Subject: [PATCH 1/3] [libc][stdlib] Add putenv
Added the POSIX putenv() function and its internal support.
Implemented EnvironmentManager::put() to insert caller-provided
"name=value" strings directly into the environment array, managing
ownership correctly (caller retains ownership).
If no '=' is present, it removes the variable (glibc/musl extension).
Added validation to reject empty variable names (e.g. "=value" or ""),
returning -1 and setting errno to EINVAL (defense-in-depth).
Registered for x86_64, aarch64, and riscv. Integration tests cover
basic operations, ownership semantics, validation, and edge cases.
Assisted-by: Automated tooling, human reviewed.
---
libc/config/linux/aarch64/entrypoints.txt | 1 +
libc/config/linux/riscv/entrypoints.txt | 1 +
libc/config/linux/x86_64/entrypoints.txt | 1 +
libc/include/stdlib.yaml | 6 +
libc/src/stdlib/CMakeLists.txt | 7 ++
libc/src/stdlib/environ_internal.cpp | 36 ++++++
libc/src/stdlib/environ_internal.h | 6 +
libc/src/stdlib/linux/CMakeLists.txt | 15 +++
libc/src/stdlib/linux/putenv.cpp | 48 ++++++++
libc/src/stdlib/putenv.h | 25 ++++
.../integration/src/stdlib/CMakeLists.txt | 14 +++
.../integration/src/stdlib/putenv_test.cpp | 116 ++++++++++++++++++
12 files changed, 276 insertions(+)
create mode 100644 libc/src/stdlib/linux/putenv.cpp
create mode 100644 libc/src/stdlib/putenv.h
create mode 100644 libc/test/integration/src/stdlib/putenv_test.cpp
diff --git a/libc/config/linux/aarch64/entrypoints.txt b/libc/config/linux/aarch64/entrypoints.txt
index 81ff70d0086c6..89322ea29b6cb 100644
--- a/libc/config/linux/aarch64/entrypoints.txt
+++ b/libc/config/linux/aarch64/entrypoints.txt
@@ -1202,6 +1202,7 @@ if(LLVM_LIBC_FULL_BUILD)
libc.src.stdlib.atexit
libc.src.stdlib.exit
libc.src.stdlib.getenv
+ libc.src.stdlib.putenv
libc.src.stdlib.setenv
libc.src.stdlib.unsetenv
libc.src.stdlib.quick_exit
diff --git a/libc/config/linux/riscv/entrypoints.txt b/libc/config/linux/riscv/entrypoints.txt
index eb3f9a77b889b..3eb1317377d2c 100644
--- a/libc/config/linux/riscv/entrypoints.txt
+++ b/libc/config/linux/riscv/entrypoints.txt
@@ -1388,6 +1388,7 @@ if(LLVM_LIBC_FULL_BUILD)
libc.src.stdlib.atexit
libc.src.stdlib.exit
libc.src.stdlib.getenv
+ libc.src.stdlib.putenv
libc.src.stdlib.setenv
libc.src.stdlib.unsetenv
libc.src.stdlib.mbstowcs
diff --git a/libc/config/linux/x86_64/entrypoints.txt b/libc/config/linux/x86_64/entrypoints.txt
index d7e4408357658..97f3caadee390 100644
--- a/libc/config/linux/x86_64/entrypoints.txt
+++ b/libc/config/linux/x86_64/entrypoints.txt
@@ -1397,6 +1397,7 @@ if(LLVM_LIBC_FULL_BUILD)
libc.src.stdlib.atexit
libc.src.stdlib.exit
libc.src.stdlib.getenv
+ libc.src.stdlib.putenv
libc.src.stdlib.setenv
libc.src.stdlib.unsetenv
libc.src.stdlib.mbstowcs
diff --git a/libc/include/stdlib.yaml b/libc/include/stdlib.yaml
index 0533fe04aecbb..efbd47029199e 100644
--- a/libc/include/stdlib.yaml
+++ b/libc/include/stdlib.yaml
@@ -185,6 +185,12 @@ functions:
- type: void **
- type: size_t
- type: size_t
+ - name: putenv
+ standards:
+ - posix
+ return_type: int
+ arguments:
+ - type: char *
- name: qsort
standards:
- stdc
diff --git a/libc/src/stdlib/CMakeLists.txt b/libc/src/stdlib/CMakeLists.txt
index 8758694d1b272..038a949d143b2 100644
--- a/libc/src/stdlib/CMakeLists.txt
+++ b/libc/src/stdlib/CMakeLists.txt
@@ -695,6 +695,13 @@ add_entrypoint_object(
.${LIBC_TARGET_OS}.setenv
)
+add_entrypoint_object(
+ putenv
+ ALIAS
+ DEPENDS
+ .${LIBC_TARGET_OS}.putenv
+)
+
add_entrypoint_object(
unsetenv
ALIAS
diff --git a/libc/src/stdlib/environ_internal.cpp b/libc/src/stdlib/environ_internal.cpp
index d7ef081e7e2b1..64ff87c3097df 100644
--- a/libc/src/stdlib/environ_internal.cpp
+++ b/libc/src/stdlib/environ_internal.cpp
@@ -265,5 +265,41 @@ int EnvironmentManager::unset(cpp::string_view name) {
return 0;
}
+int EnvironmentManager::put(char *string) {
+ cpp::string_view sv(string);
+ size_t eq_pos = sv.find_first_of('=');
+
+ // No '=' found: treat as unset (glibc/musl convention).
+ if (eq_pos == cpp::string_view::npos)
+ return unset(sv);
+
+ cpp::string_view name = sv.substr(0, eq_pos);
+
+ cpp::optional<size_t> idx = find_var(name);
+
+ size_t needed = idx ? count : count + 1;
+ if (!ensure_capacity(needed))
+ return -1;
+
+ char **env_array = get_array();
+
+ if (idx) {
+ // Replace existing variable. Free old string if we own it.
+ if (ownership[*idx].can_free())
+ delete[] env_array[*idx];
+
+ env_array[*idx] = string;
+ ownership[*idx].allocated_by_us = false; // Caller owns this string.
+ } else {
+ // Add new variable at the end.
+ env_array[count] = string;
+ ownership[count].allocated_by_us = false;
+ count++;
+ env_array[count] = nullptr;
+ }
+
+ return 0;
+}
+
} // namespace internal
} // namespace LIBC_NAMESPACE_DECL
diff --git a/libc/src/stdlib/environ_internal.h b/libc/src/stdlib/environ_internal.h
index f16d841779734..c315f2d8626e0 100644
--- a/libc/src/stdlib/environ_internal.h
+++ b/libc/src/stdlib/environ_internal.h
@@ -130,6 +130,12 @@ class EnvironmentManager {
// errno to ENOMEM).
int set(cpp::string_view name, cpp::string_view value, bool overwrite);
+ // Insert a caller-provided "name=value" string into the environment.
+ // The caller retains ownership of the string; the manager will not
+ // free it. If string contains no '=', the named variable is removed
+ // (glibc/musl convention). Returns 0 on success, -1 on failure.
+ int put(char *string);
+
// Remove a variable by name. Frees the string if we own it, then
// compacts the array. Returns 0 on success (including if the variable
// was not found), -1 on allocation failure during array transition.
diff --git a/libc/src/stdlib/linux/CMakeLists.txt b/libc/src/stdlib/linux/CMakeLists.txt
index 9189c985d9a27..9f2ef97d516cf 100644
--- a/libc/src/stdlib/linux/CMakeLists.txt
+++ b/libc/src/stdlib/linux/CMakeLists.txt
@@ -45,6 +45,21 @@ add_entrypoint_object(
libc.src.stdlib.environ_internal
)
+add_entrypoint_object(
+ putenv
+ SRCS
+ putenv.cpp
+ HDRS
+ ../putenv.h
+ DEPENDS
+ libc.src.__support.CPP.string_view
+ libc.src.__support.common
+ libc.src.__support.libc_errno
+ libc.src.__support.macros.config
+ libc.src.__support.macros.null_check
+ libc.src.stdlib.environ_internal
+)
+
add_entrypoint_object(
unsetenv
SRCS
diff --git a/libc/src/stdlib/linux/putenv.cpp b/libc/src/stdlib/linux/putenv.cpp
new file mode 100644
index 0000000000000..e97d9c8b33e7a
--- /dev/null
+++ b/libc/src/stdlib/linux/putenv.cpp
@@ -0,0 +1,48 @@
+//===----------------------------------------------------------------------===//
+//
+// 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
+/// Implementation of the POSIX putenv function.
+///
+//===----------------------------------------------------------------------===//
+
+#include "src/stdlib/putenv.h"
+#include "src/__support/CPP/string_view.h"
+#include "src/__support/common.h"
+#include "src/__support/libc_errno.h"
+#include "src/__support/macros/config.h"
+#include "src/__support/macros/null_check.h"
+#include "src/stdlib/environ_internal.h"
+
+namespace LIBC_NAMESPACE_DECL {
+
+LLVM_LIBC_FUNCTION(int, putenv, (char *string)) {
+ LIBC_CRASH_ON_NULLPTR(string);
+
+ cpp::string_view sv(string);
+ size_t eq_pos = sv.find_first_of('=');
+
+ // Defense in depth: Reject empty variable names.
+ // - eq_pos == 0: e.g. "=value" (empty name)
+ // - eq_pos == cpp::string_view::npos && sv.empty(): e.g. "" (attempting to
+ // unset empty name)
+ if (eq_pos == 0 || (eq_pos == cpp::string_view::npos && sv.empty())) {
+ libc_errno = EINVAL;
+ return -1;
+ }
+
+ int result = internal::EnvironmentManager::get_instance().put(string);
+ if (result != 0) {
+ libc_errno = ENOMEM;
+ return -1;
+ }
+
+ return 0;
+}
+
+} // namespace LIBC_NAMESPACE_DECL
diff --git a/libc/src/stdlib/putenv.h b/libc/src/stdlib/putenv.h
new file mode 100644
index 0000000000000..1c07c5f80a61f
--- /dev/null
+++ b/libc/src/stdlib/putenv.h
@@ -0,0 +1,25 @@
+//===----------------------------------------------------------------------===//
+//
+// 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
+/// Declaration of the POSIX putenv function.
+///
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_LIBC_SRC_STDLIB_PUTENV_H
+#define LLVM_LIBC_SRC_STDLIB_PUTENV_H
+
+#include "src/__support/macros/config.h"
+
+namespace LIBC_NAMESPACE_DECL {
+
+int putenv(char *string);
+
+} // namespace LIBC_NAMESPACE_DECL
+
+#endif // LLVM_LIBC_SRC_STDLIB_PUTENV_H
diff --git a/libc/test/integration/src/stdlib/CMakeLists.txt b/libc/test/integration/src/stdlib/CMakeLists.txt
index 789f9aded9570..169779e9278b4 100644
--- a/libc/test/integration/src/stdlib/CMakeLists.txt
+++ b/libc/test/integration/src/stdlib/CMakeLists.txt
@@ -30,6 +30,20 @@ if(${LIBC_TARGET_OS} STREQUAL "linux")
libc.src.string.strcmp
)
+ add_integration_test(
+ putenv_test
+ SUITE
+ stdlib-integration-tests
+ SRCS
+ putenv_test.cpp
+ DEPENDS
+ libc.src.errno.errno
+ libc.src.stdlib.getenv
+ libc.src.stdlib.putenv
+ libc.src.string.strcmp
+ libc.src.unistd.environ
+ )
+
add_integration_test(
unsetenv_test
SUITE
diff --git a/libc/test/integration/src/stdlib/putenv_test.cpp b/libc/test/integration/src/stdlib/putenv_test.cpp
new file mode 100644
index 0000000000000..ed82ae5e9ccd6
--- /dev/null
+++ b/libc/test/integration/src/stdlib/putenv_test.cpp
@@ -0,0 +1,116 @@
+//===----------------------------------------------------------------------===//
+//
+// 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
+/// Integration tests for putenv.
+///
+//===----------------------------------------------------------------------===//
+
+#include "src/stdlib/getenv.h"
+#include "src/stdlib/putenv.h"
+#include "src/string/strcmp.h"
+#include "src/unistd/environ.h"
+
+#include "test/IntegrationTest/test.h"
+
+#include <errno.h>
+
+static char set_var[] = "PUTENV_TEST=hello";
+static char replace_var[] = "PUTENV_TEST=world";
+static char empty_value[] = "PUTENV_EMPTY=";
+static char special_chars[] = "PUTENV_SPECIAL=!@#$%^&*()";
+
+TEST_MAIN([[maybe_unused]] int argc, [[maybe_unused]] char **argv,
+ [[maybe_unused]] char **envp) {
+ // Test: Basic set
+ {
+ ASSERT_EQ(LIBC_NAMESPACE::putenv(set_var), 0);
+ char *value = LIBC_NAMESPACE::getenv("PUTENV_TEST");
+ ASSERT_TRUE(value != nullptr);
+ ASSERT_EQ(LIBC_NAMESPACE::strcmp(value, "hello"), 0);
+ }
+
+ // Test: Overwrite existing variable
+ {
+ ASSERT_EQ(LIBC_NAMESPACE::putenv(replace_var), 0);
+ char *value = LIBC_NAMESPACE::getenv("PUTENV_TEST");
+ ASSERT_TRUE(value != nullptr);
+ ASSERT_EQ(LIBC_NAMESPACE::strcmp(value, "world"), 0);
+ }
+
+ // Test: The pointer itself is used (not a copy)
+ {
+ // After putenv, getenv should return a pointer into the original string.
+ char *value = LIBC_NAMESPACE::getenv("PUTENV_TEST");
+ ASSERT_TRUE(value == replace_var + 12); // "PUTENV_TEST=" is 12 chars
+ }
+
+ // Test: Empty value
+ {
+ ASSERT_EQ(LIBC_NAMESPACE::putenv(empty_value), 0);
+ char *value = LIBC_NAMESPACE::getenv("PUTENV_EMPTY");
+ ASSERT_TRUE(value != nullptr);
+ ASSERT_EQ(LIBC_NAMESPACE::strcmp(value, ""), 0);
+ }
+
+ // Test: Special characters in value
+ {
+ ASSERT_EQ(LIBC_NAMESPACE::putenv(special_chars), 0);
+ char *value = LIBC_NAMESPACE::getenv("PUTENV_SPECIAL");
+ ASSERT_TRUE(value != nullptr);
+ ASSERT_EQ(LIBC_NAMESPACE::strcmp(value, "!@#$%^&*()"), 0);
+ }
+
+ // Test: No '=' removes the variable (glibc/musl convention)
+ {
+ // First set a variable via putenv
+ static char var_to_remove[] = "REMOVE_ME=present";
+ ASSERT_EQ(LIBC_NAMESPACE::putenv(var_to_remove), 0);
+ ASSERT_TRUE(LIBC_NAMESPACE::getenv("REMOVE_ME") != nullptr);
+
+ // Now call putenv without '=' to remove it
+ static char remove_cmd[] = "REMOVE_ME";
+ ASSERT_EQ(LIBC_NAMESPACE::putenv(remove_cmd), 0);
+ ASSERT_TRUE(LIBC_NAMESPACE::getenv("REMOVE_ME") == nullptr);
+ }
+
+ // Test: environ is updated and contains the exact pointer
+ {
+ bool found = false;
+ for (char **env = LIBC_NAMESPACE::environ; *env != nullptr; ++env) {
+ if (*env == replace_var) {
+ found = true;
+ break;
+ }
+ }
+ ASSERT_TRUE(found);
+ }
+
+ // Test: Invalid inputs (defense-in-depth)
+ {
+ // Empty string (attempt to unset empty name)
+ static char empty_string[] = "";
+ errno = 0;
+ ASSERT_EQ(LIBC_NAMESPACE::putenv(empty_string), -1);
+ ASSERT_ERRNO_EQ(EINVAL);
+
+ // Empty name with value
+ static char empty_name[] = "=value";
+ errno = 0;
+ ASSERT_EQ(LIBC_NAMESPACE::putenv(empty_name), -1);
+ ASSERT_ERRNO_EQ(EINVAL);
+
+ // Just "=" (empty name, empty value)
+ static char just_equals[] = "=";
+ errno = 0;
+ ASSERT_EQ(LIBC_NAMESPACE::putenv(just_equals), -1);
+ ASSERT_ERRNO_EQ(EINVAL);
+ }
+
+ return 0;
+}
>From 7f361ab3d76ca1f3ad0aa8f3c15f0de9e8d38fbd Mon Sep 17 00:00:00 2001
From: Jeff Bailey <jbailey at raspberryginger.com>
Date: Tue, 14 Jul 2026 17:21:34 +0100
Subject: [PATCH 2/3] Address review comments: remove empty name validation
from putenv
---
libc/src/stdlib/linux/CMakeLists.txt | 1 -
libc/src/stdlib/linux/putenv.cpp | 19 +------
.../integration/src/stdlib/putenv_test.cpp | 50 +++++++++++++------
3 files changed, 37 insertions(+), 33 deletions(-)
diff --git a/libc/src/stdlib/linux/CMakeLists.txt b/libc/src/stdlib/linux/CMakeLists.txt
index 9f2ef97d516cf..40b5fd0a5b551 100644
--- a/libc/src/stdlib/linux/CMakeLists.txt
+++ b/libc/src/stdlib/linux/CMakeLists.txt
@@ -52,7 +52,6 @@ add_entrypoint_object(
HDRS
../putenv.h
DEPENDS
- libc.src.__support.CPP.string_view
libc.src.__support.common
libc.src.__support.libc_errno
libc.src.__support.macros.config
diff --git a/libc/src/stdlib/linux/putenv.cpp b/libc/src/stdlib/linux/putenv.cpp
index e97d9c8b33e7a..3a499d6c0d1ba 100644
--- a/libc/src/stdlib/linux/putenv.cpp
+++ b/libc/src/stdlib/linux/putenv.cpp
@@ -12,7 +12,6 @@
//===----------------------------------------------------------------------===//
#include "src/stdlib/putenv.h"
-#include "src/__support/CPP/string_view.h"
#include "src/__support/common.h"
#include "src/__support/libc_errno.h"
#include "src/__support/macros/config.h"
@@ -24,25 +23,11 @@ namespace LIBC_NAMESPACE_DECL {
LLVM_LIBC_FUNCTION(int, putenv, (char *string)) {
LIBC_CRASH_ON_NULLPTR(string);
- cpp::string_view sv(string);
- size_t eq_pos = sv.find_first_of('=');
-
- // Defense in depth: Reject empty variable names.
- // - eq_pos == 0: e.g. "=value" (empty name)
- // - eq_pos == cpp::string_view::npos && sv.empty(): e.g. "" (attempting to
- // unset empty name)
- if (eq_pos == 0 || (eq_pos == cpp::string_view::npos && sv.empty())) {
- libc_errno = EINVAL;
- return -1;
- }
-
int result = internal::EnvironmentManager::get_instance().put(string);
- if (result != 0) {
+ if (result != 0)
libc_errno = ENOMEM;
- return -1;
- }
- return 0;
+ return result;
}
} // namespace LIBC_NAMESPACE_DECL
diff --git a/libc/test/integration/src/stdlib/putenv_test.cpp b/libc/test/integration/src/stdlib/putenv_test.cpp
index ed82ae5e9ccd6..03ce6d89b8642 100644
--- a/libc/test/integration/src/stdlib/putenv_test.cpp
+++ b/libc/test/integration/src/stdlib/putenv_test.cpp
@@ -91,25 +91,45 @@ TEST_MAIN([[maybe_unused]] int argc, [[maybe_unused]] char **argv,
ASSERT_TRUE(found);
}
- // Test: Invalid inputs (defense-in-depth)
+ // Test: Pathological inputs (empty names, empty string) are allowed to match
+ // glibc.
{
- // Empty string (attempt to unset empty name)
- static char empty_string[] = "";
- errno = 0;
- ASSERT_EQ(LIBC_NAMESPACE::putenv(empty_string), -1);
- ASSERT_ERRNO_EQ(EINVAL);
-
- // Empty name with value
+ // Empty name with value (=value) should succeed and be found in environ.
static char empty_name[] = "=value";
- errno = 0;
- ASSERT_EQ(LIBC_NAMESPACE::putenv(empty_name), -1);
- ASSERT_ERRNO_EQ(EINVAL);
+ ASSERT_EQ(LIBC_NAMESPACE::putenv(empty_name), 0);
+ bool found = false;
+ for (char **env = LIBC_NAMESPACE::environ; *env != nullptr; ++env) {
+ if (*env == empty_name) {
+ found = true;
+ break;
+ }
+ }
+ ASSERT_TRUE(found);
- // Just "=" (empty name, empty value)
+ // Just "=" should succeed and be found in environ.
static char just_equals[] = "=";
- errno = 0;
- ASSERT_EQ(LIBC_NAMESPACE::putenv(just_equals), -1);
- ASSERT_ERRNO_EQ(EINVAL);
+ ASSERT_EQ(LIBC_NAMESPACE::putenv(just_equals), 0);
+ found = false;
+ for (char **env = LIBC_NAMESPACE::environ; *env != nullptr; ++env) {
+ if (*env == just_equals) {
+ found = true;
+ break;
+ }
+ }
+ ASSERT_TRUE(found);
+
+ // Empty string unsets the empty name.
+ static char empty_string[] = "";
+ ASSERT_EQ(LIBC_NAMESPACE::putenv(empty_string), 0);
+ // Verify "=value" is no longer in environ (it should have been unset).
+ found = false;
+ for (char **env = LIBC_NAMESPACE::environ; *env != nullptr; ++env) {
+ if (*env == empty_name) {
+ found = true;
+ break;
+ }
+ }
+ ASSERT_FALSE(found);
}
return 0;
>From b6f5a0202b82cbf97aa68c9aed534dd6061d0c39 Mon Sep 17 00:00:00 2001
From: Jeff Bailey <jbailey at raspberryginger.com>
Date: Tue, 28 Jul 2026 14:45:19 +0100
Subject: [PATCH 3/3] Address review comments: update comments to POSIX and
simplify TEST_MAIN
---
libc/src/stdlib/environ_internal.cpp | 2 +-
libc/src/stdlib/environ_internal.h | 2 +-
libc/test/integration/src/stdlib/putenv_test.cpp | 5 ++---
3 files changed, 4 insertions(+), 5 deletions(-)
diff --git a/libc/src/stdlib/environ_internal.cpp b/libc/src/stdlib/environ_internal.cpp
index 64ff87c3097df..da2e5c8185ca0 100644
--- a/libc/src/stdlib/environ_internal.cpp
+++ b/libc/src/stdlib/environ_internal.cpp
@@ -269,7 +269,7 @@ int EnvironmentManager::put(char *string) {
cpp::string_view sv(string);
size_t eq_pos = sv.find_first_of('=');
- // No '=' found: treat as unset (glibc/musl convention).
+ // No '=' found: treat as unset (POSIX behavior).
if (eq_pos == cpp::string_view::npos)
return unset(sv);
diff --git a/libc/src/stdlib/environ_internal.h b/libc/src/stdlib/environ_internal.h
index c315f2d8626e0..aa111b8496aec 100644
--- a/libc/src/stdlib/environ_internal.h
+++ b/libc/src/stdlib/environ_internal.h
@@ -133,7 +133,7 @@ class EnvironmentManager {
// Insert a caller-provided "name=value" string into the environment.
// The caller retains ownership of the string; the manager will not
// free it. If string contains no '=', the named variable is removed
- // (glibc/musl convention). Returns 0 on success, -1 on failure.
+ // (POSIX behavior). Returns 0 on success, -1 on failure.
int put(char *string);
// Remove a variable by name. Frees the string if we own it, then
diff --git a/libc/test/integration/src/stdlib/putenv_test.cpp b/libc/test/integration/src/stdlib/putenv_test.cpp
index 03ce6d89b8642..0781299936726 100644
--- a/libc/test/integration/src/stdlib/putenv_test.cpp
+++ b/libc/test/integration/src/stdlib/putenv_test.cpp
@@ -25,8 +25,7 @@ static char replace_var[] = "PUTENV_TEST=world";
static char empty_value[] = "PUTENV_EMPTY=";
static char special_chars[] = "PUTENV_SPECIAL=!@#$%^&*()";
-TEST_MAIN([[maybe_unused]] int argc, [[maybe_unused]] char **argv,
- [[maybe_unused]] char **envp) {
+TEST_MAIN() {
// Test: Basic set
{
ASSERT_EQ(LIBC_NAMESPACE::putenv(set_var), 0);
@@ -66,7 +65,7 @@ TEST_MAIN([[maybe_unused]] int argc, [[maybe_unused]] char **argv,
ASSERT_EQ(LIBC_NAMESPACE::strcmp(value, "!@#$%^&*()"), 0);
}
- // Test: No '=' removes the variable (glibc/musl convention)
+ // Test: No '=' removes the variable (POSIX behavior)
{
// First set a variable via putenv
static char var_to_remove[] = "REMOVE_ME=present";
More information about the libc-commits
mailing list