Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
54 changes: 54 additions & 0 deletions libc-bottom-half/sources/__wasilibc_initialize_environ.c
Original file line number Diff line number Diff line change
@@ -1,7 +1,11 @@
#include <unistd.h>
#include <stdlib.h>
#include <sysexits.h>
#ifdef __wasilibc_use_wasip2
#include <wasi/wasip2.h>
#else
#include <wasi/api.h>
#endif
#include <wasi/libc.h>
#include <wasi/libc-environ.h>

Expand All @@ -26,6 +30,55 @@ static char *empty_environ[1] = { NULL };

// See the comments in libc-environ.h.
void __wasilibc_initialize_environ(void) {
#ifdef __wasilibc_use_wasip2
// Get the environment
wasip2_list_tuple2_string_string_t wasi_environment;
environment_get_environment(&wasi_environment);

size_t environ_count = wasi_environment.len;
if (environ_count == 0) {
__wasilibc_environ = empty_environ;
return;
}

// Add 1 for the NULL pointer to mark the end, and check for overflow.
size_t num_ptrs = environ_count + 1;
if (num_ptrs == 0) {
goto software;
}

// Allocate memory for the array of pointers. This uses `calloc` both to
// handle overflow and to initialize the NULL pointer at the end.
char **environ_ptrs = calloc(num_ptrs, sizeof(char *));

// Copy the environment variables
for (size_t i = 0; i < environ_count; i++) {
wasip2_tuple2_string_string_t pair = wasi_environment.ptr[i];
// 1 extra character for the null terminator, 1 for the '=' character
environ_ptrs[i] = malloc(pair.f0.len + pair.f1.len + 2);
if (!environ_ptrs[i]) {
for (size_t j = 0; j < i; j++)
free(environ_ptrs[j]);
free(environ_ptrs);
goto software;
}
memcpy(environ_ptrs[i], pair.f0.ptr, pair.f0.len);
environ_ptrs[i][pair.f0.len] = '=';
memcpy(environ_ptrs[i] + pair.f0.len + 1, pair.f1.ptr, pair.f1.len);
environ_ptrs[i][pair.f0.len + pair.f1.len + 1] = '\0';
}

// Free the WASI environment list
wasip2_list_tuple2_string_string_free(&wasi_environment);

// Initialize the environment from the created array
__wasilibc_environ = environ_ptrs;
return;
software:
wasip2_list_tuple2_string_string_free(&wasi_environment);
_Exit(EX_SOFTWARE);

#else
// Get the sizes of the arrays we'll have to create to copy in the environment.
size_t environ_count;
size_t environ_buf_size;
Expand Down Expand Up @@ -74,6 +127,7 @@ void __wasilibc_initialize_environ(void) {
_Exit(EX_OSERR);
software:
_Exit(EX_SOFTWARE);
#endif
}

// See the comments in libc-environ.h.
Expand Down
4 changes: 3 additions & 1 deletion test/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -210,8 +210,10 @@ wasm_to_c = $(patsubst $(OBJPAT),$(SRCDIR)/%.c,$1)
$(RUNDIR)/%/success: $(OBJPAT)
@mkdir -p $(@D)
@DIR="$(abspath $(@D))" \
ENV="$(shell scripts/add-flags.py ENV $(call wasm_to_c,$<))" \
WASM="$(abspath $<)" \
ENGINE="$(ENGINE) $(shell scripts/add-flags.py RUN $(call wasm_to_c,$<))" \
ENGINE="$(ENGINE)" \
RUN="$(shell scripts/add-flags.py RUN $(call wasm_to_c,$<))" \
ARGS="$(shell scripts/add-flags.py ARGS $(call wasm_to_c,$<))" \
scripts/run-test.sh

Expand Down
2 changes: 2 additions & 0 deletions test/scripts/browser-test/harness.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,8 @@ const SKIP_TESTS = [
"libc-test/functional/pthread_tsd",
// Skip test that uses command-line arguments
"misc/argv_two_args",
// Skip test that uses environment variables
"misc/external_env",
// XFAIL: @bjorn3/browser_wasi_shim doesn't support symlinks for now
"misc/fts",
];
Expand Down
4 changes: 2 additions & 2 deletions test/scripts/run-test.sh
Original file line number Diff line number Diff line change
Expand Up @@ -6,15 +6,15 @@
# - a `fs` directory which the test may have used for file IO
# - an `output.log` file containing the output of the test
#
# Usage: DIR=... WASM=... ENGINE=... ARGS="..." ./run-test.sh
# Usage: ENV="..." DIR=... WASM=... ENGINE=... RUN="..." ARGS="..." ./run-test.sh

ENGINE="${ENGINE:-wasmtime}"
[ -n "$WASM" ] || (echo "missing WASM variable" && exit 1)
[ -n "$DIR" ] || (echo "missing DIR variable" && exit 1)

cd $DIR
mkdir -p fs
echo "$ENGINE $WASM $ARGS" > cmd.sh
echo "$ENV $ENGINE $RUN $WASM $ARGS" > cmd.sh
chmod +x cmd.sh
./cmd.sh &> output.log
[ $? -eq 0 ] || echo "Test failed" >> output.log
20 changes: 20 additions & 0 deletions test/src/misc/external_env.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
//! add-flags.py(CFLAGS): -I.
//! add-flags.py(RUN): --wasi=inherit-env=y
//! add-flags.py(ENV): VAR1=foo VAR2=bar
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include "test.h"

#define TEST(c, ...) \
( (c) || (t_error(#c " failed: " __VA_ARGS__),0) )

int main(int argc, char **argv)
{
char* s = getenv("VAR1");
TEST(strcmp(s, "foo")==0);
s = getenv("VAR2");
TEST(strcmp(s, "bar")==0);

return t_status;
}