blob: 8d80de9a7ceba5f4cb6bd7f405b9d7af0774698c [file] [edit]
//===----------------------------------------------------------------------===//
//
// 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 the clearenv function.
///
//===----------------------------------------------------------------------===//
#include "src/stdlib/clearenv.h"
#include "src/stdlib/getenv.h"
#include "src/stdlib/putenv.h"
#include "src/stdlib/setenv.h"
#include "src/stdlib/unsetenv.h"
#include "src/unistd/environ.h"
#include "test/IntegrationTest/test.h"
TEST_MAIN([[maybe_unused]] int argc, [[maybe_unused]] char **argv,
[[maybe_unused]] char **envp) {
// Test: Clear environment and verify getenv and environ are null
{
ASSERT_EQ(LIBC_NAMESPACE::setenv("PRE_CLEAR_VAR", "hello", 1), 0);
ASSERT_NE(LIBC_NAMESPACE::getenv("PRE_CLEAR_VAR"), nullptr);
ASSERT_EQ(LIBC_NAMESPACE::clearenv(), 0);
ASSERT_EQ(LIBC_NAMESPACE::getenv("PRE_CLEAR_VAR"), nullptr);
ASSERT_EQ(LIBC_NAMESPACE::environ, nullptr);
}
// Test: Adding variables after clearenv using setenv
{
ASSERT_EQ(LIBC_NAMESPACE::clearenv(), 0);
ASSERT_EQ(LIBC_NAMESPACE::environ, nullptr);
ASSERT_EQ(LIBC_NAMESPACE::setenv("POST_CLEAR_VAR", "world", 1), 0);
ASSERT_NE(LIBC_NAMESPACE::environ, nullptr);
ASSERT_NE(LIBC_NAMESPACE::getenv("POST_CLEAR_VAR"), nullptr);
ASSERT_STREQ(LIBC_NAMESPACE::getenv("POST_CLEAR_VAR"), "world");
ASSERT_STREQ(LIBC_NAMESPACE::environ[0], "POST_CLEAR_VAR=world");
ASSERT_EQ(LIBC_NAMESPACE::environ[1], nullptr);
}
// Test: Adding variables after clearenv using putenv
{
ASSERT_EQ(LIBC_NAMESPACE::clearenv(), 0);
ASSERT_EQ(LIBC_NAMESPACE::environ, nullptr);
static char put_buf[] = "PUT_AFTER_CLEAR=test";
ASSERT_EQ(LIBC_NAMESPACE::putenv(put_buf), 0);
ASSERT_NE(LIBC_NAMESPACE::environ, nullptr);
ASSERT_NE(LIBC_NAMESPACE::getenv("PUT_AFTER_CLEAR"), nullptr);
ASSERT_STREQ(LIBC_NAMESPACE::getenv("PUT_AFTER_CLEAR"), "test");
ASSERT_STREQ(LIBC_NAMESPACE::environ[0], "PUT_AFTER_CLEAR=test");
ASSERT_EQ(LIBC_NAMESPACE::environ[1], nullptr);
}
// Test: Calling clearenv multiple times is idempotent
{
ASSERT_EQ(LIBC_NAMESPACE::clearenv(), 0);
ASSERT_EQ(LIBC_NAMESPACE::environ, nullptr);
ASSERT_EQ(LIBC_NAMESPACE::clearenv(), 0);
ASSERT_EQ(LIBC_NAMESPACE::environ, nullptr);
}
// Test: Unsetenv after clearenv succeeds
{
ASSERT_EQ(LIBC_NAMESPACE::clearenv(), 0);
ASSERT_EQ(LIBC_NAMESPACE::unsetenv("NONEXISTENT"), 0);
ASSERT_EQ(LIBC_NAMESPACE::environ, nullptr);
}
// Test: Multiple setenv allocations followed by clear
{
ASSERT_EQ(LIBC_NAMESPACE::setenv("MULTI_1", "v1", 1), 0);
ASSERT_EQ(LIBC_NAMESPACE::setenv("MULTI_2", "v2", 1), 0);
ASSERT_EQ(LIBC_NAMESPACE::setenv("MULTI_3", "v3", 1), 0);
ASSERT_STREQ(LIBC_NAMESPACE::getenv("MULTI_1"), "v1");
ASSERT_STREQ(LIBC_NAMESPACE::getenv("MULTI_2"), "v2");
ASSERT_STREQ(LIBC_NAMESPACE::getenv("MULTI_3"), "v3");
ASSERT_EQ(LIBC_NAMESPACE::clearenv(), 0);
ASSERT_EQ(LIBC_NAMESPACE::environ, nullptr);
ASSERT_EQ(LIBC_NAMESPACE::getenv("MULTI_1"), nullptr);
ASSERT_EQ(LIBC_NAMESPACE::getenv("MULTI_2"), nullptr);
ASSERT_EQ(LIBC_NAMESPACE::getenv("MULTI_3"), nullptr);
}
// Test: Pointers obtained from getenv remain valid after clearenv
{
ASSERT_EQ(LIBC_NAMESPACE::setenv("RETAINED_VAR", "retained_val", 1), 0);
char *val = LIBC_NAMESPACE::getenv("RETAINED_VAR");
ASSERT_NE(val, nullptr);
ASSERT_STREQ(val, "retained_val");
ASSERT_EQ(LIBC_NAMESPACE::clearenv(), 0);
ASSERT_EQ(LIBC_NAMESPACE::getenv("RETAINED_VAR"), nullptr);
ASSERT_EQ(LIBC_NAMESPACE::environ, nullptr);
// The buffer itself was not erased/deallocated, so existing pointers
// remain readable without use-after-free.
ASSERT_STREQ(val, "retained_val");
}
return 0;
}