-
-
Notifications
You must be signed in to change notification settings - Fork 2.2k
Allow decompression to continue after exceeding max_length #11966
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
Open
Dreamsorcerer
wants to merge
183
commits into
master
Choose a base branch
from
Dreamsorcerer-patch-5
base: master
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
Open
Changes from all commits
Commits
Show all changes
183 commits
Select commit
Hold shift + click to select a range
5968707
Test chunk splits after pause
Dreamsorcerer 2eeeb5e
Update tests/test_http_parser.py
Dreamsorcerer 8b0cfee
Apply suggestions from code review
Dreamsorcerer 9cd9154
Update tests/test_http_parser.py
Dreamsorcerer 83fc87c
Update tests/test_http_parser.py
Dreamsorcerer efe2ca9
Read small chunks from decompressors
Dreamsorcerer 57bf4a2
[pre-commit.ci] auto fixes from pre-commit.com hooks
pre-commit-ci[bot] 82a4dfb
Fix
Dreamsorcerer c44fd1e
Merge branch 'Dreamsorcerer-patch-5' of github.com:aio-libs/aiohttp i…
Dreamsorcerer a85f38b
[pre-commit.ci] auto fixes from pre-commit.com hooks
pre-commit-ci[bot] 602eb51
Update compression_utils.py
Dreamsorcerer 32f0a84
Update test_http_parser.py
Dreamsorcerer 94c70a9
[pre-commit.ci] auto fixes from pre-commit.com hooks
pre-commit-ci[bot] bd34cea
Update test_http_parser.py
Dreamsorcerer 0d4683c
Update test_http_parser.py
Dreamsorcerer d3df801
[pre-commit.ci] auto fixes from pre-commit.com hooks
pre-commit-ci[bot] b81f901
Update test_http_parser.py
Dreamsorcerer 4dd2279
Fix
Dreamsorcerer 3a604a4
Update test_http_parser.py
Dreamsorcerer 10feb8b
Fix
Dreamsorcerer d02bbf5
[pre-commit.ci] auto fixes from pre-commit.com hooks
pre-commit-ci[bot] 67bd57d
Update test_http_parser.py
Dreamsorcerer 04b717f
Fix
Dreamsorcerer 53ac968
Update test_http_parser.py
Dreamsorcerer 44c12a1
Fix
Dreamsorcerer 7986da3
Merge branch 'Dreamsorcerer-patch-5' of github.com:aio-libs/aiohttp i…
Dreamsorcerer 75794c2
[pre-commit.ci] auto fixes from pre-commit.com hooks
pre-commit-ci[bot] ab73626
Update test_http_parser.py
Dreamsorcerer ae46ee1
Update test_http_parser.py
Dreamsorcerer d738031
Update test_http_parser.py
Dreamsorcerer 1d5fc0e
[pre-commit.ci] auto fixes from pre-commit.com hooks
pre-commit-ci[bot] 28dffda
Update test_http_parser.py
Dreamsorcerer 2eb92be
Update test_http_parser.py
Dreamsorcerer 3dbf9c8
Update test_http_parser.py
Dreamsorcerer 3ea25ca
Fix
Dreamsorcerer d99fc34
Update streams.py
Dreamsorcerer 11cf432
[pre-commit.ci] auto fixes from pre-commit.com hooks
pre-commit-ci[bot] de6fca2
Update http_parser.py
Dreamsorcerer 3a80456
[pre-commit.ci] auto fixes from pre-commit.com hooks
pre-commit-ci[bot] 7da23c1
Update http_parser.py
Dreamsorcerer a4fc7c1
Update _http_parser.pyx
Dreamsorcerer b3c77d7
[pre-commit.ci] auto fixes from pre-commit.com hooks
pre-commit-ci[bot] f26edc0
Update _http_parser.pyx
Dreamsorcerer 1997c8b
Update _http_parser.pyx
Dreamsorcerer b4443b7
Apply suggestions from code review
Dreamsorcerer b17c013
Fix
Dreamsorcerer d628cee
Update _http_parser.pyx
Dreamsorcerer cd2e07a
Update http_parser.py
Dreamsorcerer fd74c03
Update compression_utils.py
Dreamsorcerer 087de36
Update streams.py
Dreamsorcerer 103c4a6
Update _http_parser.pyx
Dreamsorcerer a249c04
Update _http_parser.pyx
Dreamsorcerer f20ddc7
Update http_parser.py
Dreamsorcerer 0fe7000
Update web_protocol.py
Dreamsorcerer 5130266
Fix
Dreamsorcerer 7db0120
Update web_protocol.py
Dreamsorcerer d113ccb
Update http_parser.py
Dreamsorcerer 185db0b
Update aiohttp/_http_parser.pyx
Dreamsorcerer 3be7ac6
Update base_protocol.py
Dreamsorcerer 80eb8c7
Update _http_parser.pyx
Dreamsorcerer 5183441
Update _http_parser.pyx
Dreamsorcerer 60c61e3
Update test_http_parser.py
Dreamsorcerer 2a6eff8
Update _http_parser.pyx
Dreamsorcerer dbfc0c8
Update _http_parser.pyx
Dreamsorcerer eac561e
Update _http_parser.pyx
Dreamsorcerer 1a40781
Update _http_parser.pyx
Dreamsorcerer 520b64a
Update _http_parser.pyx
Dreamsorcerer 9c2987b
Update _http_parser.pyx
Dreamsorcerer c4b058d
Update _http_parser.pyx
Dreamsorcerer fa644c7
Update test_client_functional.py
Dreamsorcerer dd82b9f
Update test_base_protocol.py
Dreamsorcerer 3099a40
Update _http_parser.pyx
Dreamsorcerer 7775793
Update _http_parser.pyx
Dreamsorcerer 9525459
Update base_protocol.py
Dreamsorcerer f4985a2
Update client_proto.py
Dreamsorcerer 32d5c5f
Update web_protocol.py
Dreamsorcerer afa2b55
Update test_base_protocol.py
Dreamsorcerer 30c23d4
Update test_client_proto.py
Dreamsorcerer 6a5a2c7
Update test_http_parser.py
Dreamsorcerer 45f66d1
Update test_http_parser.py
Dreamsorcerer 80d955f
Update test_flowcontrol_streams.py
Dreamsorcerer 0cc6275
Update test_client_proto.py
Dreamsorcerer 69e3bbd
Update test_http_parser.py
Dreamsorcerer 397e905
Update test_http_parser.py
Dreamsorcerer aed6863
Update test_websocket_parser.py
Dreamsorcerer a0fb83b
Update test_base_protocol.py
Dreamsorcerer 360f6de
Update test_client_proto.py
Dreamsorcerer 6e04d89
Update test_http_parser.py
Dreamsorcerer 698e0cc
Update compression_utils.py
Dreamsorcerer 48d4119
Update streams.py
Dreamsorcerer 6598ff6
Update base_protocol.py
Dreamsorcerer 3f76e2c
Update base_protocol.py
Dreamsorcerer faf6e40
Update client_proto.py
Dreamsorcerer add2b70
Update base_protocol.py
Dreamsorcerer 3396079
Update compression_utils.py
Dreamsorcerer 69a59a8
Update compression_utils.py
Dreamsorcerer c5f6e6a
Update compression_utils.py
Dreamsorcerer 51eda1b
Update compression_utils.py
Dreamsorcerer 156fb3c
Update base_protocol.py
Dreamsorcerer 8b05bfc
Update streams.py
Dreamsorcerer f1bfba5
Update test_http_parser.py
Dreamsorcerer 9c1ffa9
Update test_base_protocol.py
Dreamsorcerer 79c9da6
Update test_streams.py
Dreamsorcerer 9467ad2
Update test_http_parser.py
Dreamsorcerer 5e8068f
Apply suggestions from code review
Dreamsorcerer e1de722
Update http_parser.py
Dreamsorcerer 46713f5
Update test_client_functional.py
Dreamsorcerer 67c210d
Update http_exceptions.py
Dreamsorcerer 2bc5d17
Update test_multipart.py
Dreamsorcerer 46eeeda
[pre-commit.ci] auto fixes from pre-commit.com hooks
pre-commit-ci[bot] 618309f
Update test_web_functional.py
Dreamsorcerer 2cc7567
Apply suggestions from code review
Dreamsorcerer 1f256df
Update test_multipart.py
Dreamsorcerer 70a51f5
Update multipart.py
Dreamsorcerer 06c5ec9
Update multipart.py
Dreamsorcerer 69c1602
Update multipart.py
Dreamsorcerer 36c2bc3
Update web_request.py
Dreamsorcerer 78e7099
[pre-commit.ci] auto fixes from pre-commit.com hooks
pre-commit-ci[bot] 2c47750
Update test_multipart.py
Dreamsorcerer e47504c
Update multipart.py
Dreamsorcerer d92ed4c
Apply suggestions from code review
Dreamsorcerer ad2c9ab
Update multipart.py
Dreamsorcerer bd7c69c
Update multipart.py
Dreamsorcerer 2106fbe
Update multipart.py
Dreamsorcerer 4f7f928
Update multipart.py
Dreamsorcerer 2677720
Update web_request.py
Dreamsorcerer 5cb6324
Update multipart.py
Dreamsorcerer bd6b520
[pre-commit.ci] auto fixes from pre-commit.com hooks
pre-commit-ci[bot] bd625ba
Apply suggestion from @Dreamsorcerer
Dreamsorcerer ef3b5d9
[pre-commit.ci] auto fixes from pre-commit.com hooks
pre-commit-ci[bot] c2ba043
Update multipart.py
Dreamsorcerer dcdc386
Update multipart.py
Dreamsorcerer 3525d3d
[pre-commit.ci] auto fixes from pre-commit.com hooks
pre-commit-ci[bot] 271d10b
Update multipart.py
Dreamsorcerer 6749571
Update multipart.py
Dreamsorcerer 28c6bcf
Merge branch 'master' into Dreamsorcerer-patch-5
Dreamsorcerer e874ebe
Apply suggestion from @Dreamsorcerer
Dreamsorcerer 389b0e6
Update test_multipart.py
Dreamsorcerer df03906
Merge branch 'master' into Dreamsorcerer-patch-5
Dreamsorcerer b420704
[pre-commit.ci] auto fixes from pre-commit.com hooks
pre-commit-ci[bot] 045ffb0
Apply suggestion from @Dreamsorcerer
Dreamsorcerer 09062db
Merge branch 'master' into Dreamsorcerer-patch-5
Dreamsorcerer 1c1ea45
[pre-commit.ci] auto fixes from pre-commit.com hooks
pre-commit-ci[bot] 7f4e807
Fix when compressed data just trips the high water mark
Dreamsorcerer 8256f07
attempt to fix connection closed cleanly while decompression still in…
bdraco 6b08dee
rely on timeout instead
bdraco 97c9b1c
check parser as its the source of truth
bdraco d719a0d
Revert "check parser as its the source of truth"
bdraco d6df346
Revert "rely on timeout instead"
bdraco e093db5
Revert "attempt to fix connection closed cleanly while decompression …
bdraco f5aa703
one more attempt
bdraco cb380ef
Revert "one more attempt"
bdraco bda59d2
Update _http_parser.pyx
Dreamsorcerer e2c7e07
Update test_multipart.py
Dreamsorcerer 010c507
Update test_multipart.py
Dreamsorcerer 7d5a9be
Update test_http_parser.py
Dreamsorcerer e499e20
Update test_http_parser.py
Dreamsorcerer aece402
Update test_http_parser.py
Dreamsorcerer 7659f5b
Update test_web_protocol.py
Dreamsorcerer d748132
Apply suggestions from code review
Dreamsorcerer c009eed
Merge branch 'master' into Dreamsorcerer-patch-5
Dreamsorcerer 518bb35
Update test_web_protocol.py
Dreamsorcerer 0e6bea5
Update _http_parser.pyx
Dreamsorcerer 7380568
[pre-commit.ci] auto fixes from pre-commit.com hooks
pre-commit-ci[bot] 742436d
Update test_web_protocol.py
Dreamsorcerer 4ac1cec
Update test_web_protocol.py
Dreamsorcerer ae697a2
Update test_web_protocol.py
Dreamsorcerer a6d8f5e
Update test_web_protocol.py
Dreamsorcerer b5ea384
Update test_web_protocol.py
Dreamsorcerer c4dadbe
Update test_web_protocol.py
Dreamsorcerer ee9bc19
Update test_web_protocol.py
Dreamsorcerer 5f00f8d
Update _http_parser.pyx
Dreamsorcerer 54d16f9
Update client_proto.py
Dreamsorcerer a7a7c73
Update multipart.py
Dreamsorcerer b45b20f
[pre-commit.ci] auto fixes from pre-commit.com hooks
pre-commit-ci[bot] f4b7166
Update web_request.py
Dreamsorcerer ab02eef
Update test_http_parser.py
Dreamsorcerer d038681
[pre-commit.ci] auto fixes from pre-commit.com hooks
pre-commit-ci[bot] ac0dc88
Update _http_parser.pyx
Dreamsorcerer d2220d3
Another test
9f09578
[pre-commit.ci] auto fixes from pre-commit.com hooks
pre-commit-ci[bot] aaefa3c
Another test
d09ca51
[pre-commit.ci] auto fixes from pre-commit.com hooks
pre-commit-ci[bot] File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
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
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
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -46,7 +46,8 @@ include "_headers.pxi" | |
|
|
||
| from aiohttp cimport _find_header | ||
|
|
||
| ALLOWED_UPGRADES = frozenset({"websocket"}) | ||
|
|
||
| cdef frozenset ALLOWED_UPGRADES = frozenset({"websocket"}) | ||
| DEF DEFAULT_FREELIST_SIZE = 250 | ||
|
|
||
| cdef extern from "Python.h": | ||
|
|
@@ -69,7 +70,7 @@ cdef object CONTENT_ENCODING = hdrs.CONTENT_ENCODING | |
| cdef object EMPTY_PAYLOAD = _EMPTY_PAYLOAD | ||
| cdef object StreamReader = _StreamReader | ||
| cdef object DeflateBuffer = _DeflateBuffer | ||
| cdef bytes EMPTY_BYTES = b"" | ||
| cdef tuple EMPTY_FEED_DATA_RESULT = ((), False, b"") | ||
|
|
||
| # RFC 9110 singleton headers — duplicates are rejected in strict mode. | ||
| # In lax mode (response parser default), the check is skipped entirely | ||
|
|
@@ -298,7 +299,7 @@ cdef class HttpParser: | |
| bint _has_value | ||
| int _header_name_size | ||
|
|
||
| object _protocol | ||
| readonly object protocol | ||
| object _loop | ||
| object _timer | ||
|
|
||
|
|
@@ -309,6 +310,7 @@ cdef class HttpParser: | |
| bint _read_until_eof | ||
| bint _lax | ||
|
|
||
| bytes _tail | ||
| bint _started | ||
| object _url | ||
| bytearray _buf | ||
|
|
@@ -319,6 +321,8 @@ cdef class HttpParser: | |
| list _raw_headers | ||
| bint _upgraded | ||
| list _messages | ||
| bint _more_data_available | ||
| bint _paused | ||
| object _payload | ||
| bint _payload_error | ||
| object _payload_exception | ||
|
|
@@ -359,18 +363,21 @@ cdef class HttpParser: | |
| self._cparser.data = <void*>self | ||
| self._cparser.content_length = 0 | ||
|
|
||
| self._protocol = protocol | ||
| self.protocol = protocol | ||
| self._loop = loop | ||
| self._timer = timer | ||
|
|
||
| self._buf = bytearray() | ||
| self._more_data_available = False | ||
| self._paused = False | ||
| self._payload = None | ||
| self._payload_error = 0 | ||
| self._payload_exception = payload_exception | ||
| self._messages = [] | ||
|
|
||
| self._raw_name = EMPTY_BYTES | ||
| self._raw_value = EMPTY_BYTES | ||
| self._raw_name = b"" | ||
| self._raw_value = b"" | ||
| self._tail = b"" | ||
| self._has_value = False | ||
| self._header_name_size = 0 | ||
|
|
||
|
|
@@ -401,7 +408,7 @@ cdef class HttpParser: | |
|
|
||
| cdef _process_header(self): | ||
| cdef str value | ||
| if self._raw_name is not EMPTY_BYTES: | ||
| if self._raw_name is not b"": | ||
| name = find_header(self._raw_name) | ||
| value = self._raw_value.decode('utf-8', 'surrogateescape') | ||
|
|
||
|
|
@@ -426,20 +433,20 @@ cdef class HttpParser: | |
| self._has_value = False | ||
| self._header_name_size = 0 | ||
| self._raw_headers.append((self._raw_name, self._raw_value)) | ||
| self._raw_name = EMPTY_BYTES | ||
| self._raw_value = EMPTY_BYTES | ||
| self._raw_name = b"" | ||
| self._raw_value = b"" | ||
|
|
||
| cdef _on_header_field(self, char* at, size_t length): | ||
| if self._has_value: | ||
| self._process_header() | ||
|
|
||
| if self._raw_name is EMPTY_BYTES: | ||
| if self._raw_name is b"": | ||
| self._raw_name = at[:length] | ||
| else: | ||
| self._raw_name += at[:length] | ||
|
|
||
| cdef _on_header_value(self, char* at, size_t length): | ||
| if self._raw_value is EMPTY_BYTES: | ||
| if self._raw_value is b"": | ||
| self._raw_value = at[:length] | ||
| else: | ||
| self._raw_value += at[:length] | ||
|
|
@@ -495,7 +502,7 @@ cdef class HttpParser: | |
| self._read_until_eof) | ||
| ): | ||
| payload = StreamReader( | ||
| self._protocol, timer=self._timer, loop=self._loop, | ||
| self.protocol, timer=self._timer, loop=self._loop, | ||
| limit=self._limit) | ||
| else: | ||
| payload = EMPTY_PAYLOAD | ||
|
|
@@ -535,6 +542,10 @@ cdef class HttpParser: | |
|
|
||
| ### Public API ### | ||
|
|
||
| def pause_reading(self): | ||
| assert self._payload is not None | ||
| self._paused = True | ||
|
|
||
| def feed_eof(self): | ||
| cdef bytes desc | ||
|
|
||
|
|
@@ -562,6 +573,21 @@ cdef class HttpParser: | |
| char* base | ||
| cdef cparser.llhttp_errno_t errno | ||
|
|
||
| # Proactor loop sends bytearray. | ||
| if type(data) is not bytes: | ||
| data = bytes(data) | ||
|
|
||
| if self._tail: | ||
| data, self._tail = self._tail + data, b"" | ||
|
|
||
| had_more_data = self._more_data_available | ||
| if self._more_data_available: | ||
| result = cb_on_body(self._cparser, b"", 0) | ||
| if result is cparser.HPE_PAUSED: | ||
| self._tail = data | ||
| return EMPTY_FEED_DATA_RESULT | ||
| # TODO: Do we need to handle error case (-1)? | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I think this is already covered, but could use a test. Marked with |
||
|
|
||
| PyObject_GetBuffer(data, &self.py_buf, PyBUF_SIMPLE) | ||
| # Cache buffer pointer before PyBuffer_Release to avoid use-after-release. | ||
| base = <char*>self.py_buf.buf | ||
|
|
@@ -574,12 +600,15 @@ cdef class HttpParser: | |
|
|
||
| if errno is cparser.HPE_PAUSED_UPGRADE: | ||
| cparser.llhttp_resume_after_upgrade(self._cparser) | ||
|
|
||
| nb = cparser.llhttp_get_error_pos(self._cparser) - base | ||
| elif errno is cparser.HPE_PAUSED: | ||
| cparser.llhttp_resume(self._cparser) | ||
| pos = cparser.llhttp_get_error_pos(self._cparser) - base | ||
| self._tail = data[pos:] | ||
|
|
||
| PyBuffer_Release(&self.py_buf) | ||
|
|
||
| if errno not in (cparser.HPE_OK, cparser.HPE_PAUSED_UPGRADE): | ||
| if errno not in (cparser.HPE_OK, cparser.HPE_PAUSED, cparser.HPE_PAUSED_UPGRADE): | ||
| if self._payload_error == 0: | ||
| if self._last_error is not None: | ||
| ex = self._last_error | ||
|
|
@@ -603,8 +632,9 @@ cdef class HttpParser: | |
|
|
||
| if self._upgraded: | ||
| return messages, True, data[nb:] | ||
| else: | ||
| return messages, False, b"" | ||
| if not messages: # Shortcut to reduce Python overhead | ||
| return EMPTY_FEED_DATA_RESULT | ||
| return messages, False, b"" | ||
|
|
||
| def set_upgraded(self, val): | ||
| self._upgraded = val | ||
|
|
@@ -799,19 +829,26 @@ cdef int cb_on_body(cparser.llhttp_t* parser, | |
| const char *at, size_t length) except -1: | ||
| cdef HttpParser pyparser = <HttpParser>parser.data | ||
| cdef bytes body = at[:length] | ||
| try: | ||
| pyparser._payload.feed_data(body) | ||
| except BaseException as underlying_exc: | ||
| reraised_exc = underlying_exc | ||
| if pyparser._payload_exception is not None: | ||
| reraised_exc = pyparser._payload_exception(str(underlying_exc)) | ||
|
|
||
| set_exception(pyparser._payload, reraised_exc, underlying_exc) | ||
|
|
||
| pyparser._payload_error = 1 | ||
| return -1 | ||
| else: | ||
| return 0 | ||
| while body or pyparser._more_data_available: | ||
| try: | ||
| pyparser._more_data_available = pyparser._payload.feed_data(body) | ||
| except BaseException as underlying_exc: | ||
| reraised_exc = underlying_exc | ||
| if pyparser._payload_exception is not None: | ||
| reraised_exc = pyparser._payload_exception(str(underlying_exc)) | ||
|
|
||
| set_exception(pyparser._payload, reraised_exc, underlying_exc) | ||
|
|
||
| pyparser._payload_error = 1 | ||
| pyparser._paused = False | ||
| return -1 | ||
| body = b"" | ||
|
|
||
| if pyparser._paused: | ||
| pyparser._paused = False | ||
| return cparser.HPE_PAUSED | ||
| pyparser._paused = False | ||
| return 0 | ||
|
|
||
|
|
||
| cdef int cb_on_message_complete(cparser.llhttp_t* parser) except -1: | ||
|
|
||
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
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
Oops, something went wrong.
Oops, something went wrong.
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.
Uh oh!
There was an error while loading. Please reload this page.