[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