Skip to content

Commit

Permalink
Error on bad body length (#2979)
Browse files Browse the repository at this point in the history
* Error on bad body length

* Explicit bytes strings
  • Loading branch information
ahopkins authored Jun 30, 2024
1 parent 90e3beb commit fee71dd
Show file tree
Hide file tree
Showing 4 changed files with 72 additions and 6 deletions.
18 changes: 14 additions & 4 deletions sanic/http/http1.py
Original file line number Diff line number Diff line change
Expand Up @@ -273,9 +273,12 @@ async def http1_request_header(self): # no cov
pos -= 2 # One CRLF stays in buffer
else:
self.request_body = True
self.request_bytes_left = self.request_bytes = int(
headers["content-length"]
)
try:
self.request_bytes_left = self.request_bytes = (
self._safe_int(headers["content-length"])
)
except Exception:
raise BadRequest("Bad content-length")

# Remove header and its trailing CRLF
del buf[: pos + 4]
Expand Down Expand Up @@ -514,7 +517,8 @@ async def read(self) -> Optional[bytes]: # no cov
await self._receive_more()

try:
size = int(buf[2:pos].split(b";", 1)[0].decode(), 16)
raw = buf[2:pos].split(b";", 1)[0].decode()
size = self._safe_int(raw, 16)
except Exception:
self.keep_alive = False
raise BadRequest("Bad chunked encoding")
Expand Down Expand Up @@ -600,3 +604,9 @@ def set_header_max_size(cls, *sizes: int):
*sizes,
cls.HEADER_CEILING,
)

@staticmethod
def _safe_int(value: str, base: int = 10) -> int:
if "-" in value or "+" in value or "_" in value:
raise ValueError
return int(value, base)
3 changes: 2 additions & 1 deletion tests/test_cookies.py
Original file line number Diff line number Diff line change
Expand Up @@ -402,7 +402,8 @@ def test_cookie_jar_delete_existing_cookie():
encoded = [cookie.encode("ascii") for cookie in jar.cookies]
# deletion cookie contains samesite=Strict as was in original cookie
assert encoded == [
b'foo=""; Path=/; Domain=example.com; Max-Age=0; SameSite=Strict; Secure',
b'foo=""; Path=/; Domain=example.com; Max-Age=0; '
b"SameSite=Strict; Secure",
]


Expand Down
2 changes: 1 addition & 1 deletion tests/test_exceptions.py
Original file line number Diff line number Diff line change
Expand Up @@ -423,7 +423,7 @@ def test_request_middleware_exception_on_404(app: Sanic):

@app.on_request
def request_middleware(request):
value = next(counter)
next(counter)
raise Exception

@app.route("/")
Expand Down
55 changes: 55 additions & 0 deletions tests/test_http.py
Original file line number Diff line number Diff line change
Expand Up @@ -110,3 +110,58 @@ def test_url_encoding(client):

assert b"400 Bad Request" in headers
assert b"URL may only contain US-ASCII characters." in body


@pytest.mark.parametrize(
"content_length",
(
b"-50",
b"+50",
b"5_0",
b"50.5",
),
)
def test_invalid_content_length(content_length, client):
body = b"Hello" * 10
client.send(
b"POST /upload HTTP/1.1\r\n"
+ b"content-length: "
+ content_length
+ b"\r\n\r\n"
+ body
+ b"\r\n\r\n"
)

response = client.recv()
headers, body = response.rsplit(b"\r\n\r\n", 1)

assert b"400 Bad Request" in headers
assert b"Bad content-length" in body


@pytest.mark.parametrize(
"chunk_length",
(
b"-50",
b"+50",
b"5_0",
b"50.5",
),
)
def test_invalid_chunk_length(chunk_length, client):
body = b"Hello" * 10
client.send(
b"POST /upload HTTP/1.1\r\n"
+ b"transfer-encoding: chunked\r\n\r\n"
+ chunk_length
+ b"\r\n"
+ body
+ b"\r\n"
+ b"0\r\n\r\n"
)

response = client.recv()
headers, body = response.rsplit(b"\r\n\r\n", 1)

assert b"400 Bad Request" in headers
assert b"Bad chunked encoding" in body

0 comments on commit fee71dd

Please sign in to comment.