Repository navigation
Conversation
|
Thanks for your pull request! It looks like this may be your first contribution to a Google open source project. Before we can look at your pull request, you'll need to sign a Contributor License Agreement (CLA). View this failed invocation of the CLA check for more information. For the most up to date status, view the checks section at the bottom of the pull request. |
This branch has not been deployed
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
UncompressGzipAndAllocate sizes its output buffer from the four-byte ISIZE trailer of the gzip stream, which on the REST API path is simply whatever the client put at the end of the request body. It hands that same uLongf pointer to Uncompress, and Uncompress overwrites it with the number of bytes it actually inflated, so by the time the error branch runs the value no longer describes the allocation. The deallocate call on that branch therefore passes a size that differs from the one allocate was given, and std::allocator forwards it to the sized operator delete, which is undefined behaviour and corrupts the free lists on a size-class allocator. Two very short bodies reach it: a well-formed gzip stream with its ISIZE rewritten to a larger value (allocated 4096 bytes, released with size 32), and an eight-byte header truncated inside MTIME whose trailing bytes read back as an ISIZE of 16 (allocated 16, released with size 0). Both are unauthenticated, because RequestHandlerOptions defaults auto_uncompress_input to true and EvHTTPRequest::UncompressGzipBody routes any body with Content-Encoding: gzip straight into this function. I noticed it reading the error path while working out how short bodies behave, then confirmed it by interposing the sized operator delete around the real call, which reports both mismatches and reports none after the change. Holding the allocation length in a local is enough; the error path now also clears destLen so a caller cannot pick up a stale length, and the new test pins both inputs.