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

fix(mmap): handle over-allocated files #10526

Merged

Conversation

petersalomonsen
Copy link
Contributor

@petersalomonsen petersalomonsen commented Feb 21, 2020

fix for not writing buffer contents from expanded files beyond allocated memory

fixes #10527

Copy link
Collaborator

@sbc100 sbc100 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for the fix!

A few style nits in the test but otherwise looks good.


char *map;

map = (char*)mmap(NULL, textsize, PROT_READ, 0, fd, 0);
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

these two lines can be a single line.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

should be ok now

{
const char* path = "/yolo/expandedfile.txt";

int fd = open(path, O_RDWR | O_CREAT, (mode_t)0600);
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just inline path since its only used once.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

should be ok now

size_t textsize = 33;

// multiple calls to write so that the file is expanded
for(int n=0;n<textsize;n++) {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

space after for and between all the operators.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

looking better now?

@@ -176,5 +176,53 @@ int main() {
printf("/yolo/sharedoffset.txt content=%s %d\n", buffer + offset, offset);
fclose(fd);
}

/**
* MMAP to and expanded file
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is "expanded file" terminology that is used elsewhere? How about "over-allocated memfs file"?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I chose the term expanded file because the "expansion" is done by a method called expandFileStorage which you can see here:

expandFileStorage: function(node, newCapacity) {

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

To me expanded file doesn't hold the right meaning. The expandFileStorage may or may not over-allocate, right? But its the fact the you over-allocate the storage that is key here IIUC, no? I could be wrong.. I didn't write the memfs code so maybe expanded file means more to the authors of this code.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

when appending to a file expandFileStorage will increase the buffer size for that file more than the bytes requested to be written. This is to avoid having to increase the buffer for every call to write (which would be very slow). So instead the actual file size is tracked in a separate property called usedBytes.

mmap allocates memory based on the usedBytes, and calls javascripts ArrayBuffer set method on the heap with the files buffer as parameter. The set method has no parameter for the length, and so it copies the full contents of the file buffer. To avoid copying more than the actual file size the file buffer is sliced before calling set, but before this fix, slicing would only occur if the requested length was less than used bytes (which is mostly not the case if mapping the entire file). So instead the criteria for slicing must be if the requested length is less than the length of the file buffer - which is normally more than usedBytes for expanded files.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

but yes - expandFileStorage does over-allocate file storage in that sense. Just wouldn't confuse it with over-allocating of heap, since the case here is that mmap writes beyond what it allocated on the heap.

not sure what the best term here is though. Maybe we need more opinions?

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I guess you could call it "over-sized" if you prefer? But I think over-allocated is pretty clear and applies to any object that is larger than needs to be to make room for future expansion. We can let @kripken have the final say :)

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't have a strong opinion on the term, but "over-allocated" does seem pretty reasonable, let's change to that?

Also and should be an in the comment.

@petersalomonsen
Copy link
Contributor Author

thanks for the review @sbc100 :-) Would be great to have this merged.

libgit2/libgit2#5345 depends on this

@sbc100
Copy link
Collaborator

sbc100 commented Feb 21, 2020

@kripken can you give final lgtm here?

Copy link
Member

@kripken kripken left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nice, thanks @petersalomonsen !

@@ -176,5 +176,53 @@ int main() {
printf("/yolo/sharedoffset.txt content=%s %d\n", buffer + offset, offset);
fclose(fd);
}

/**
* MMAP to and expanded file
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't have a strong opinion on the term, but "over-allocated" does seem pretty reasonable, let's change to that?

Also and should be an in the comment.

fix for files with buffers larger than the file size
where contents were written beyond memory allocated
for the map

fixes emscripten-core#10527
@petersalomonsen petersalomonsen changed the title fix(mmap): handle expanded files fix(mmap): handle over-allocated files Feb 25, 2020
@petersalomonsen
Copy link
Contributor Author

over-allocated it is then :-)

Thanks for reviewing!

@kripken kripken merged commit 73b81e2 into emscripten-core:master Feb 25, 2020
@petersalomonsen petersalomonsen deleted the fix-mmap-expanded-files branch February 25, 2020 19:43
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

Successfully merging this pull request may close these issues.

mmap on expanded files writes beyond allocated memory
3 participants