[libc-commits] [libc] [libc][stdlib] Add unsetenv (PR #202422)
Pavel Labath via libc-commits
libc-commits at lists.llvm.org
Fri Jun 26 05:23:08 PDT 2026
================
@@ -221,5 +230,40 @@ int EnvironmentManager::set(cpp::string_view name, cpp::string_view value,
return 0;
}
+int EnvironmentManager::unset(cpp::string_view name) {
+ cpp::optional<size_t> idx = find_var(name);
+ if (!idx)
+ return 0; // Variable not found; POSIX defines this as success.
+
+ // Transition to managed storage so we can modify the array and track
+ // ownership correctly.
+ if (!ensure_capacity(count))
+ return -1;
+
+ char **env_array = get_array();
+
+ // Loop to remove all instances of the variable (e.g. duplicates from execve).
+ while (idx) {
+ size_t i = *idx;
+ if (ownership[i].can_free())
+ delete[] env_array[i];
+
+ // Compact: shift remaining entries left to fill the gap.
+ // Shifting elements preserves the order of environment variables, which is
+ // desirable to maintain consistency with getenv resolution order and
+ // typical environ iteration behavior.
+ for (size_t j = i; j < count - 1; j++) {
+ env_array[j] = env_array[j + 1];
+ ownership[j] = ownership[j + 1];
+ }
+ count--;
+ env_array[count] = nullptr;
+
+ idx = find_var(name);
----------------
labath wrote:
In the worst case this could end up with a quadratic behavior (an environment consisting of `n` entries setting the same environment variable.
It might need some code restructuring, but it should be relatively easy to include a variable name check in the shifting loop, to ensure we only have to make a single pass through the environment.
https://github.com/llvm/llvm-project/pull/202422
More information about the libc-commits
mailing list