Skip to content

Commit e79f10e

Browse files
authored
[WasmFS] Fix FS.readFile + WASM_BIGINT (#17316)
_wasmfs_read_file wrote a 32-bit unsigned integer, while makeGetValue in JS read this as a 64-bit integer. This caused the length to be returned incorrectly when linking with -sWASM_BIGINT. Resolves: #17444.
1 parent a41b1a3 commit e79f10e

File tree

6 files changed

+23
-6
lines changed

6 files changed

+23
-6
lines changed

src/library_wasmfs.js

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ mergeInto(LibraryManager.library, {
1818
'$PATH',
1919
'$allocateUTF8',
2020
'$allocateUTF8OnStack',
21+
'$readI53FromI64',
2122
],
2223
$FS : {
2324
// TODO: Clean up the following functions - currently copied from library_fs.js directly.
@@ -88,8 +89,8 @@ mergeInto(LibraryManager.library, {
8889

8990
// Copy the file into a JS buffer on the heap.
9091
var buf = __wasmfs_read_file(pathName);
91-
// The integer length is returned in the first 8 bytes of the buffer.
92-
var length = {{{ makeGetValue('buf', '0', 'i64') }}};
92+
// The signed integer length resides in the first 8 bytes of the buffer.
93+
var length = {{{ makeGetValue('buf', '0', 'i53') }}};
9394

9495
// Default return type is binary.
9596
// The buffer contents exist 8 bytes after the returned pointer.

src/parseTools.js

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -408,6 +408,9 @@ function makeGetValue(ptr, pos, type, noNeedFirst, unsigned, ignore, align) {
408408
}
409409

410410
const offset = calcFastOffset(ptr, pos, noNeedFirst);
411+
if (type === 'i53' || type === 'u53') {
412+
return 'readI53From' + (unsigned ? 'U' : 'I') + '64(' + offset + ')';
413+
}
411414

412415
const slab = getHeapForType(type);
413416
let ret = slab + '[' + getHeapOffset(offset, type) + ']';

system/lib/wasmfs/js_api.cpp

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,8 @@ __wasi_fd_t wasmfs_create_file(char* pathname, mode_t mode, backend_t backend);
2222
// The buffer will also contain the file length.
2323
// Caller must free the returned pointer.
2424
void* _wasmfs_read_file(char* path) {
25+
static_assert(sizeof(off_t) == 8, "File offset type must be 64-bit");
26+
2527
struct stat file;
2628
int err = 0;
2729
err = stat(path, &file);
@@ -34,8 +36,8 @@ void* _wasmfs_read_file(char* path) {
3436
// first 8 bytes. The remaining bytes will contain the buffer contents. This
3537
// allows the caller to use HEAPU8.subarray(buf + 8, buf + 8 + length).
3638
off_t size = file.st_size;
37-
uint8_t* result = (uint8_t*)malloc((size + sizeof(size)));
38-
*(uint32_t*)result = size;
39+
uint8_t* result = (uint8_t*)malloc(size + sizeof(size));
40+
*(off_t*)result = size;
3941

4042
int fd = open(path, O_RDONLY);
4143
if (fd < 0) {

tests/test_other.py

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11865,6 +11865,12 @@ def test_wasmfs_getdents(self):
1186511865
def test_wasmfs_readfile(self):
1186611866
self.do_run_in_out_file_test(test_file('wasmfs/wasmfs_readfile.c'))
1186711867

11868+
@wasmfs_all_backends
11869+
def test_wasmfs_readfile_bigint(self):
11870+
self.set_setting('WASM_BIGINT')
11871+
self.node_args += ['--experimental-wasm-bigint']
11872+
self.do_run_in_out_file_test(test_file('wasmfs/wasmfs_readfile.c'))
11873+
1186811874
def test_wasmfs_jsfile(self):
1186911875
self.set_setting('WASMFS')
1187011876
self.do_run_in_out_file_test('wasmfs/wasmfs_jsfile.c')

tests/wasmfs/wasmfs_readfile.c

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
#include <errno.h>
1212
#include <fcntl.h>
1313
#include <stdio.h>
14+
#include <stdlib.h>
1415
#include <string.h>
1516
#include <unistd.h>
1617

@@ -25,10 +26,13 @@ int main() {
2526
errno = 0;
2627
write(fd, msg, strlen(msg));
2728
assert(errno == 0);
29+
err = close(fd);
30+
assert(err == 0);
2831

2932
EM_ASM({
30-
var output = FS.readFile("/root/test", {encoding : 'utf8'});
31-
out(output);
33+
var output = FS.readFile("/root/test");
34+
out(UTF8ArrayToString(output, 0));
35+
out("Length: " + output.byteLength);
3236
});
3337

3438
EM_ASM({

tests/wasmfs/wasmfs_readfile.out

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
Success
22

3+
Length: 8
34
Fatal error in FS.readFile
45
Aborted(native code called abort())
56
Fatal error in FS.readFile

0 commit comments

Comments
 (0)