libc+tests: Check for manual modifications of environ
All checks were successful
continuous-integration/drone/push Build is passing

Closes #31.
This commit is contained in:
apio 2023-07-12 16:25:06 +02:00
parent 5f698b4774
commit 2951d6d112
Signed by: apio
GPG Key ID: B8A7D06E42258954
3 changed files with 108 additions and 0 deletions

View File

@ -94,12 +94,30 @@ static void _update_env()
environ = g_dynamic_env.data();
}
// Check if a user has modified environ, in which case we should reset env_is_dynamic and free our buffers.
static void _check_dynamic_env()
{
if (!env_is_dynamic) return;
env_is_dynamic = environ == g_dynamic_env.data();
if (!env_is_dynamic)
{
for (auto element : g_dynamic_env)
{
if (element) free(element);
}
}
}
extern "C"
{
char** environ = nullptr;
int clearenv()
{
_check_dynamic_env();
if (env_is_dynamic)
{
for (auto element : g_dynamic_env)
@ -127,6 +145,8 @@ extern "C"
auto index = _findenv(key, nullptr);
if (index < 0) return 0;
_check_dynamic_env();
if (!env_is_dynamic)
{
if (_move_env() < 0) return -1;
@ -149,6 +169,8 @@ extern "C"
auto index = _findenv(key, nullptr);
if (index >= 0 && !overwrite) return 0;
_check_dynamic_env();
if (!env_is_dynamic)
{
if (_move_env() < 0) return -1;

View File

@ -21,6 +21,7 @@ luna_test(libluna/TestHashTable.cpp TestHashTable)
luna_test(libluna/TestCPath.cpp TestCPath)
luna_test(libc/TestScanf.cpp TestScanf)
luna_test(libc/TestString.cpp TestString)
luna_test(libc/TestEnv.cpp TestEnv)
luna_app(run-tests.cpp run-tests)
endif()

85
tests/libc/TestEnv.cpp Normal file
View File

@ -0,0 +1,85 @@
#include <stdlib.h>
#include <string.h>
#include <test.h>
extern char** environ;
TestResult test_setenv_then_getenv()
{
clearenv();
validate(setenv("sample", "value", 1) == 0);
char* value = getenv("sample");
validate(value);
validate(!strcmp(value, "value"));
test_success;
}
TestResult test_setenv_dont_overwrite()
{
clearenv();
validate(setenv("sample", "value", 1) == 0);
char* value = getenv("sample");
validate(value);
validate(!strcmp(value, "value"));
validate(setenv("sample", "other_value", 0) == 0);
value = getenv("sample");
validate(value);
validate(!strcmp(value, "value"));
test_success;
}
TestResult test_unsetenv()
{
clearenv();
validate(setenv("sample", "value", 1) == 0);
char* value = getenv("sample");
validate(value);
validate(!strcmp(value, "value"));
validate(unsetenv("sample") == 0);
value = getenv("sample");
validate(!value);
test_success;
}
TestResult test_setenv_before_and_after_manual_environ_modification()
{
clearenv();
validate(setenv("sample", "value", 1) == 0);
char* list[] = { "hello=world", NULL };
environ = list;
validate(setenv("other", "value", 1) == 0);
char* value = getenv("hello");
validate(value);
validate(!strcmp(value, "world"));
test_success;
}
Result<void> test_main()
{
test_prelude;
run_test(test_setenv_then_getenv);
run_test(test_setenv_dont_overwrite);
run_test(test_unsetenv);
run_test(test_setenv_before_and_after_manual_environ_modification);
return {};
}