libc+tests: Check for manual modifications of environ
All checks were successful
continuous-integration/drone/push Build is passing
All checks were successful
continuous-integration/drone/push Build is passing
Closes #31.
This commit is contained in:
parent
5f698b4774
commit
2951d6d112
@ -94,12 +94,30 @@ static void _update_env()
|
|||||||
environ = g_dynamic_env.data();
|
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"
|
extern "C"
|
||||||
{
|
{
|
||||||
char** environ = nullptr;
|
char** environ = nullptr;
|
||||||
|
|
||||||
int clearenv()
|
int clearenv()
|
||||||
{
|
{
|
||||||
|
_check_dynamic_env();
|
||||||
|
|
||||||
if (env_is_dynamic)
|
if (env_is_dynamic)
|
||||||
{
|
{
|
||||||
for (auto element : g_dynamic_env)
|
for (auto element : g_dynamic_env)
|
||||||
@ -127,6 +145,8 @@ extern "C"
|
|||||||
auto index = _findenv(key, nullptr);
|
auto index = _findenv(key, nullptr);
|
||||||
if (index < 0) return 0;
|
if (index < 0) return 0;
|
||||||
|
|
||||||
|
_check_dynamic_env();
|
||||||
|
|
||||||
if (!env_is_dynamic)
|
if (!env_is_dynamic)
|
||||||
{
|
{
|
||||||
if (_move_env() < 0) return -1;
|
if (_move_env() < 0) return -1;
|
||||||
@ -149,6 +169,8 @@ extern "C"
|
|||||||
auto index = _findenv(key, nullptr);
|
auto index = _findenv(key, nullptr);
|
||||||
if (index >= 0 && !overwrite) return 0;
|
if (index >= 0 && !overwrite) return 0;
|
||||||
|
|
||||||
|
_check_dynamic_env();
|
||||||
|
|
||||||
if (!env_is_dynamic)
|
if (!env_is_dynamic)
|
||||||
{
|
{
|
||||||
if (_move_env() < 0) return -1;
|
if (_move_env() < 0) return -1;
|
||||||
|
@ -21,6 +21,7 @@ luna_test(libluna/TestHashTable.cpp TestHashTable)
|
|||||||
luna_test(libluna/TestCPath.cpp TestCPath)
|
luna_test(libluna/TestCPath.cpp TestCPath)
|
||||||
luna_test(libc/TestScanf.cpp TestScanf)
|
luna_test(libc/TestScanf.cpp TestScanf)
|
||||||
luna_test(libc/TestString.cpp TestString)
|
luna_test(libc/TestString.cpp TestString)
|
||||||
|
luna_test(libc/TestEnv.cpp TestEnv)
|
||||||
|
|
||||||
luna_app(run-tests.cpp run-tests)
|
luna_app(run-tests.cpp run-tests)
|
||||||
endif()
|
endif()
|
||||||
|
85
tests/libc/TestEnv.cpp
Normal file
85
tests/libc/TestEnv.cpp
Normal 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 {};
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user