相关文章推荐
火星上的烤地瓜  ·  vue中使用keep- ...·  6 月前    · 
神勇威武的葫芦  ·  python ...·  1 年前    · 
才高八斗的人字拖  ·  Finding Elements in ...·  1 年前    · 
风流倜傥的消炎药  ·  android ...·  1 年前    · 
Collectives™ on Stack Overflow

Find centralized, trusted content and collaborate around the technologies you use most.

Learn more about Collectives

Teams

Q&A for work

Connect and share knowledge within a single location that is structured and easy to search.

Learn more about Teams

"Uncaught RuntimeError: memory access out of bounds" when trying to load file in WASM of C-program

Ask Question

I try to load a file from my local filesystem, which is then loaded into MEMFS (provided by Emscripten) and pass the file name as one argument to a C program which is cross compiled as WebAssembly using Emscripten. When calling the function to load the file I get the error: Uncaught RuntimeError: memory access out of bounds. What am I doing wrong? Are the parameters handed-over incorrectly or is the file access not correct?

C program, has standard main and parameters are passed correctly, loading the file looks like this (in an abstract):

int CLASS main(int argc, const char **argv)
   FILE *ifp;
   const char *ifname;
   // Start - debug code
   for (int i = 0; i < argc; i++)
      // ==> This prints the arguments correctly in the browser console, so the hand-over works.
      printf("argv[%d] = %s\n", i, argv[i]);
   char cwd[1024];
   if (getcwd(cwd, sizeof(cwd)) != NULL)
       // Also prints the MEMFS directory structure correctly.
       printf("Current working directory: %s\n", cwd);
   // End - debug code
   ifname = argv[arg];
   if (!(ifp = fopen(ifname, "rb")))
       perror(ifname);
       continue;

In JavaScript it's called like this:

async _runProgram(args) {
    // Load the emscripten wrapper
    this._dcrawModule = await Module();
    // Convert the JavaScript array to a C-style null-terminated string array
    const paramStrings = args.map((str) => this._dcrawModule.allocateUTF8(str));
    // Allocate memory for the array of pointers
    const paramArray = this._dcrawModule.stackAlloc((paramStrings.length + 1) * 4); 
    paramStrings.forEach((strPtr, i) => {
        this._dcrawModule.setValue(paramArray + i * 4, strPtr, 'i32');
    // Null-terminate the array
    this._dcrawModule.setValue(paramArray + paramStrings.length * 4, 0, 'i32');
    // Call the `_main` method with the parameter array
    return this._dcrawModule['_main'](paramStrings.length + 1, paramArray, 0);

The file itself is loaded into MEMFS doing the following and then the '_runProgram' function is called:

// Create a workspace directory in the emscripten virtual file system and go to it FS.mkdir('/workspace'); FS.chdir('/workspace'); if (raw_file) { FS.createDataFile('/workspace/', 'raw_buf', raw_file, true, true); args.push('/workspace/raw_buf'); //args.push('raw_buf'); //Tried also this and other variants, no success. this._runProgram(args);

Does anyone has experience with Emscripten, MEMFS, WebAssembly and opening a file in a C-program? My preference would be to not change the C-program as this is not mine and I want to avoid having to adapt it every time it might be updated in the future (in addition my C knowledge is quite limited :-P) (full c program can be found here: https://dechifro.org/dcraw/dcraw.c)

Flags used to run the emcc compiler are the following:

FLAGS = -O0 \
          -s ALLOW_MEMORY_GROWTH=1 \
          -s TOTAL_MEMORY=134217728 \
          -s NO_EXIT_RUNTIME=1 \
          -s FORCE_FILESYSTEM=1 \
          --memory-init-file 0 \
          -s MODULARIZE=1 \
          -s WASM=1 \
          -s EXPORT_ES6=1 \
          -s EXPORTED_FUNCTIONS="['_main']" \
          -s EXPORTED_RUNTIME_METHODS=FS,setValue,stringToUTF8,allocateUTF8,stackAlloc  \
          -DNODEPS=1
                What is argv[arg] in the C code? I can see it is supposed to be a pointer to the file name, but what is arg?
– Weather Vane
                Apr 12 at 18:14
                It's the value set in in JavaScript "args.push()" in the snippet above. I tried to pass the fullpath "/workspace/raw_buf", relative "./raw_buf" and only filename "raw_buf".
– niels_h
                Apr 12 at 18:19
                The link containing the full C code shows that arg is a local variable in int CLASS main (int argc, const char **argv) undergoing extensive manipulation.... and then it's the control variable of for ( ; arg < argc; arg++) and there is no break from this loop, so arg ends up out of range of the supplied program arguments.
– Weather Vane
                Apr 12 at 18:24
                Value of "arg" is 2, while parameters passed from JavaScript are for example: argv[0] = -v argv[1] = -i argv[2] = /workspace/raw_buf argv[3] = (null)
– niels_h
                Apr 12 at 18:27
                I am an not interested in arg in the javascript, but in the C code, which has too much knotty code to easily follow: you could use a debugger to find out what the filename being opened is, in the C file. I have not used Emscripten.
– Weather Vane
                Apr 12 at 18:28
        

Thanks for contributing an answer to Stack Overflow!

  • Please be sure to answer the question. Provide details and share your research!

But avoid

  • Asking for help, clarification, or responding to other answers.
  • Making statements based on opinion; back them up with references or personal experience.

To learn more, see our tips on writing great answers.