Skip to content

Instantly share code, notes, and snippets.

@brion brion/Makefile

Created Feb 9, 2020
What would you like to do?
Test case for emscripten stray syscall issue

The library code in lib.c conditionally calls the POSIX read syscall causing an import, but optimization on the final output eliminates that code path.

Result is a stray __syscall3 function which references FS, imported by the wasm but unused in it. Since the FS isn't defined because of using -s NO_FILESYSTEM=1, Closure sees it's undefined and either turns it into a (void 0) (1.39.6) or fails immediately (1.39.7).

#include "lib.h"
size_t read_something(state_t *state) {
const size_t n_bytes = 512;
char buffer[n_bytes];
if (state->fd) {
return read(state->fd, buffer, n_bytes);
} else {
return state->read(buffer, n_bytes, state->user_data);
#include <unistd.h>
typedef size_t (*read_func)(char *buffer, size_t n_bytes, void *user_data);
typedef struct {
int fd;
read_func read;
void *user_data;
} state_t;
extern size_t read_something(state_t *state);
OPTS=-O3 -g1 --closure 1 -s NO_FILESYSTEM=1
test.js : lib.o test.o
emcc $(OPTS) -o test.js lib.o test.o
lib.o : lib.c lib.h
emcc $(OPTS) -c -o lib.o lib.c
test.o : test.c lib.h
emcc $(OPTS) -c -o test.o test.c
clean :
rm -f test.js
rm -f test.wasm
rm -f test.o
rm -f lib.o
#include <stdio.h>
#include "lib.h"
static size_t fake_read(char *buffer, size_t n_bytes, void *user_data) {
for (size_t i = 0; i < n_bytes; i++) {
buffer[i] = 'A';
return n_bytes;
int main(int argc, const char **argv) {
state_t state;
state.fd = 0; = fake_read;
state.user_data = NULL;
size_t bytes_read = read_something(&state);
printf("read %zu bytes of fake stuff\n", bytes_read);
return 0;
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.