Skip to content

Commit 0e4bb32

Browse files
fix(mmap): handle expanded files
fix for not writing buffer contents from expanded files beyond allocated memory fixes #10527
1 parent b007756 commit 0e4bb32

File tree

2 files changed

+49
-1
lines changed

2 files changed

+49
-1
lines changed

src/library_memfs.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -367,7 +367,7 @@ mergeInto(LibraryManager.library, {
367367
ptr = contents.byteOffset;
368368
} else {
369369
// Try to avoid unnecessary slices.
370-
if (position > 0 || position + length < stream.node.usedBytes) {
370+
if (position > 0 || position + length < contents.length) {
371371
if (contents.subarray) {
372372
contents = contents.subarray(position, position + length);
373373
} else {

tests/fs/test_mmap.c

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -176,5 +176,53 @@ int main() {
176176
printf("/yolo/sharedoffset.txt content=%s %d\n", buffer + offset, offset);
177177
fclose(fd);
178178
}
179+
180+
/**
181+
* MMAP to and expanded file
182+
*
183+
* When appending to a file, the buffer is expanded in chunks, and so the actual length
184+
* of the file could be less than the buffer length.
185+
*
186+
* When using mmap for an expanded file, we have to make sure that content from the buffer
187+
* is not written beyond the allocated memory area for the mmap operation.
188+
*/
189+
{
190+
const char* path = "/yolo/expandedfile.txt";
191+
192+
int fd = open(path, O_RDWR | O_CREAT, (mode_t)0600);
193+
assert(fd != -1);
194+
195+
size_t textsize = 33;
196+
197+
// multiple calls to write so that the file is expanded
198+
for(int n=0;n<textsize;n++) {
199+
assert(write(fd, "a", 1) != -1);
200+
}
201+
202+
EM_ASM_({
203+
const stream = FS.streams.find(stream => stream.path.indexOf('/yolo/expandedfile.txt')>=0);
204+
assert(stream.node.usedBytes === $0,
205+
'Used bytes on the expanded file (' + stream.node.usedBytes+ ') ' +
206+
'should be 33'
207+
);
208+
assert(stream.node.contents.length > stream.node.usedBytes,
209+
'Used bytes on the expanded file (' + stream.node.usedBytes+ ') ' +
210+
'should be less than the length of the content buffer (' + stream.node.contents.length + ')'
211+
);
212+
stream.node.contents[stream.node.usedBytes] = 98; // 'b', we don't want to see this in the mmap area
213+
}, textsize);
214+
215+
char *map;
216+
217+
map = (char*)mmap(NULL, textsize, PROT_READ, 0, fd, 0);
218+
219+
assert(map[textsize-1] == 'a');
220+
221+
// Assert that content from the expanded file buffer are not written beyond the maps allocated memory
222+
assert(map[textsize] != 'b');
223+
224+
close(fd);
225+
}
226+
179227
return 0;
180228
}

0 commit comments

Comments
 (0)