Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

malloc Fails Silently in wasi-sdk #518

Closed
khordadi opened this issue Feb 25, 2025 · 3 comments
Closed

malloc Fails Silently in wasi-sdk #518

khordadi opened this issue Feb 25, 2025 · 3 comments

Comments

@khordadi
Copy link

Description

When running the following C program, different behaviors are observed between wasi-sdk and emscripten. Specifically, wasi-sdk fails to detect unsuccessful memory allocations, leading to an infinite loop.

Reproduction Steps

  1. Compile the following program with wasi-sdk and emscripten:
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>

int allocate(const uint64_t size) {
    printf("Allocating %llu Bytes\n", size);
    void *mem = malloc(size);
    if (mem == NULL) return 0;
    free(mem);
    return 1;
}

int main() {
    uint64_t upper_bound = 1;
    while (allocate(upper_bound))
        upper_bound *= 2;
    printf("Failed to allocate %llu Bytes\n", upper_bound);
    return 0;
}
  1. Compile and run with wasi-sdk:
/opt/wasi-sdk/bin/clang main.c -o main.wasi-sdk.wasm
wasmtime main.wasi-sdk.wasm

Output (wasi-sdk)

Allocating 1 Bytes
Allocating 2 Bytes
...
Allocating 9223372036854775808 Bytes
Allocating 0 Bytes
Allocating 0 Bytes
Allocating 0 Bytes
... infinite loop ...
  1. Compile and run with emscripten:
emcc main.c -o main.emcc.wasm
wasmtime main.emcc.wasm

Output (emscripten)

Allocating 1 Bytes
Allocating 2 Bytes
...
Allocating 33554432 Bytes
Failed to allocate 33554432 Bytes

Expected Behavior

  • malloc should return NULL when memory allocation fails.
  • The program should terminate gracefully rather than looping indefinitely.

Actual Behavior (wasi-sdk)

  • malloc continues returning non-NULL pointers even for unreasonably large allocations.
  • This causes an infinite loop instead of terminating when allocation fails.
@alexcrichton
Copy link
Collaborator

You're unfortunately running up against the world of integer casts in C. malloc is defined as taking a usize, but you're passing a uint64_t, so it's silently truncating to the 32-bits that wasm32 defines usize to be. That means that the final request that actually allocates bytes is 0x80000000 bytes, and that succeeds because that's a valid request to grow memory that much. This works in Wasmtime because there is by default no limit to memory allocated on the CLI. My guess is that web browsers place more stringent limits by default.

Then you're running into the fact that *= 2 exhibits overflow eventually so the number wraps back around to zero and stays zero.

More-or-less I don't think there's a bug here.

@kripken
Copy link
Member

kripken commented Feb 25, 2025

To add to that, the emscripten program stops at 32MB because of the default memory size, and that growth is disabled by default (the defaults are motivated by what is generally best for programs running on the web). But you can allow more, -sALLOW_MEMORY_GROWTH to allow memory to grow, and -sMAXIMUM_MEMORY=4gb to allow 4GB (rather than 2GB). If you build that way, the code executes the same as wasi-sdk (infinite loop due to the integer truncation issue @alexcrichton points out).

@khordadi
Copy link
Author

Thank you, @kripken and @alexcrichton. That makes sense.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants