Skip to content

Commit e9e05b8

Browse files
authored
[WasmFS] Fix length computation in fetch backend (#17578)
Fixes #17571
1 parent cab5be0 commit e9e05b8

File tree

4 files changed

+39
-3
lines changed

4 files changed

+39
-3
lines changed

src/library_wasmfs_js_file.js

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,10 @@ mergeInto(LibraryManager.library, {
3737
},
3838
read: (file, buffer, length, offset) => {
3939
var fileData = wasmFS$JSMemoryFiles[file];
40-
length = Math.max(0, fileData.length - offset);
40+
// We can't read past the end of the file's data.
41+
var dataAfterOffset = Math.max(0, fileData.length - offset);
42+
// We only read as much as we were asked.
43+
length = Math.min(length, dataAfterOffset);
4144
HEAPU8.set(fileData.subarray(offset, offset + length), buffer);
4245
return length;
4346
},

system/lib/wasmfs/syscalls.cpp

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -219,7 +219,12 @@ static __wasi_errno_t readAtOffset(OffsetHandling setOffset,
219219
}
220220
return -result;
221221
}
222+
222223
// The read was successful.
224+
225+
// Backends must only return len or less.
226+
assert(result <= len);
227+
223228
bytesRead += result;
224229
if (result < len) {
225230
// The read was short, so stop here.

test/test_browser.py

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5285,7 +5285,9 @@ def test(args):
52855285
@parameterized({
52865286
# the fetch backend works even on the main thread: we proxy to a background
52875287
# thread and busy-wait
5288-
'main_thread': (['-sPTHREAD_POOL_SIZE=4'],),
5288+
# this test requires one thread per fetch backend, so updates to the test
5289+
# will require bumping this
5290+
'main_thread': (['-sPTHREAD_POOL_SIZE=5'],),
52895291
# using proxy_to_pthread also works, of course
52905292
'proxy_to_pthread': (['-sPROXY_TO_PTHREAD', '-sINITIAL_MEMORY=32MB', '-DPROXYING'],),
52915293
})
@@ -5294,6 +5296,7 @@ def test_wasmfs_fetch_backend(self, args):
52945296
if is_firefox() and '-sPROXY_TO_PTHREAD' not in args:
52955297
return self.skipTest('ff hangs on the main_thread version. browser bug?')
52965298
create_file('data.dat', 'hello, fetch')
5299+
create_file('small.dat', 'hello')
52975300
create_file('test.txt', 'fetch 2')
52985301
delete_dir('subdir')
52995302
ensure_dir('subdir')

test/wasmfs/wasmfs_fetch.c

Lines changed: 26 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,10 @@
1616
#include <sys/stat.h>
1717
#include <unistd.h>
1818

19-
// NOTE: Each fetch backend runs in a separate thread.
19+
// NOTE: Each fetch backend runs in a separate thread. When not using
20+
// PROXY_TO_PTHREAD, that means we need a pool of at least one thread per
21+
// backend, so updating test_browser.py may be needed when adding more
22+
// here.
2023

2124
void getUrlOrigin(char* ptr, int len);
2225
char url_orig[256] = {};
@@ -126,12 +129,34 @@ void test_default() {
126129
assert(close(fd2) == 0);
127130
}
128131

132+
void test_small_reads() {
133+
// Read the file in small amounts.
134+
printf("Running %s...\n", __FUNCTION__);
135+
136+
char expected[] = "hello";
137+
size_t size = 5;
138+
139+
backend_t backend = wasmfs_create_fetch_backend("small.dat");
140+
int fd = wasmfs_create_file("/testfile3", 0777, backend);
141+
char buf[size + 1];
142+
for (size_t i = 0; i < size; i++) {
143+
int read_now = read(fd, buf + i, 1);
144+
assert(read_now == 1);
145+
printf("read one byte\n");
146+
}
147+
buf[size] = 0;
148+
assert(strcmp(buf, "hello") == 0);
149+
150+
assert(close(fd) == 0);
151+
}
152+
129153
int main() {
130154
getUrlOrigin(url_orig, sizeof(url_orig));
131155
test_default();
132156
test_url_relative();
133157
test_url_absolute();
134158
test_directory_abs();
159+
test_small_reads();
135160

136161
return 0;
137162
}

0 commit comments

Comments
 (0)