wasi-libc/libc-bottom-half/sources/__environ.c
Dan Gohman bdfbb54520
Call populate_environ only if we actually need environment variables. (#109)
* Link `populate_environ` only if we actually need environment variables.

This avoids linking in the environment variable initialization code,
and the __wasi_environ_sizes_get and __wasi_environ_get imports, in
programs that don't use environment variables.

This also removes the "___environ" (three underscores) alias symbol,
which is only in musl for backwards compatibility.

* Switch to //-style comments.

* If malloc fails, don't leave `__environ` pointing to an uninitialized buffer.

* Fix a memory leak if one malloc succeeds and the other fails.

* Use calloc to handle multiplication overflow.

This also handles the NULL terminator.

* Don't initialize __environ until everything has succeeded.

* Avoid leaking in case __wasi_environ_get fails.

* Handle overflow in the add too.

* Add #include <stdlib.h> for malloc etc.

* If the environment is empty, don't allocate any memory.
2019-10-22 06:02:44 -07:00

58 lines
1.8 KiB
C

#include <unistd.h>
#include <stdlib.h>
#include <wasi/core.h>
#include <wasi/libc.h>
#include <wasi/libc-internal.h>
char **__environ = NULL;
extern __typeof(__environ) _environ __attribute__((weak, alias("__environ")));
extern __typeof(__environ) environ __attribute__((weak, alias("__environ")));
// This function is referenced by a weak symbol in crt1.c, and we define
// it here in the same source file as __environ, so that this function is
// linked in iff environment variable support is used.
__wasi_errno_t __wasilibc_populate_environ(void) {
__wasi_errno_t err;
// 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;
err = __wasi_environ_sizes_get(&environ_count, &environ_buf_size);
if (err != __WASI_ESUCCESS) {
return err;
}
if (environ_count == 0) {
return __WASI_ESUCCESS;
}
// 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) {
return __WASI_ENOMEM;
}
// Allocate memory for storing the environment chars.
char *environ_buf = malloc(environ_buf_size);
if (environ_buf == NULL) {
return __WASI_ENOMEM;
}
// 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 *));
if (environ_ptrs == NULL) {
free(environ_buf);
return __WASI_ENOMEM;
}
// Fill the environment chars, and the __environ array with pointers into those chars.
err = __wasi_environ_get(environ_ptrs, environ_buf);
if (err == __WASI_ESUCCESS) {
__environ = environ_ptrs;
} else {
free(environ_buf);
free(environ_ptrs);
}
return err;
}