Skip to content

Commit

Permalink
Fix handling invalid utf8 characters in http paths (#492)
Browse files Browse the repository at this point in the history
* Possible fix for handling invalid http paths

* Try to use utf8_lossy_decoding and add dev dependencies

* Attempt to fix the tests

* Review tests

* Apply utf8 lossy patch for path also to RSGI

---------

Co-authored-by: Giovanni Barillari <giovanni.barillari@sentry.io>
  • Loading branch information
ritesh and gi0baro authored Jan 29, 2025
1 parent 3e89a94 commit 4a461dc
Show file tree
Hide file tree
Showing 4 changed files with 17 additions and 5 deletions.
2 changes: 1 addition & 1 deletion src/asgi/utils.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ macro_rules! scope_native_parts {
.uri
.path_and_query()
.map_or_else(|| ("", ""), |pq| (pq.path(), pq.query().unwrap_or("")));
let $path = percent_encoding::percent_decode_str(path_raw).decode_utf8().unwrap();
let $path = percent_encoding::percent_decode_str(path_raw).decode_utf8_lossy();
let $version = match $req.version {
hyper::Version::HTTP_10 => "1",
hyper::Version::HTTP_11 => "1.1",
Expand Down
4 changes: 2 additions & 2 deletions src/rsgi/types.rs
Original file line number Diff line number Diff line change
Expand Up @@ -184,8 +184,8 @@ macro_rules! rsgi_scope_cls {
}

#[getter(path)]
fn get_path(&self) -> Result<Cow<str>> {
Ok(percent_decode_str(self.uri.path()).decode_utf8()?)
fn get_path(&self) -> Cow<str> {
percent_decode_str(self.uri.path()).decode_utf8_lossy()
}

#[getter(query_string)]
Expand Down
4 changes: 2 additions & 2 deletions tests/apps/asgi.py
Original file line number Diff line number Diff line change
Expand Up @@ -174,5 +174,5 @@ def app(scope, receive, send):
'/err_app': err_app,
'/err_proto': err_proto,
'/timeout_n': timeout_n,
'/timeout_w': timeout_w,
}[scope['path']](scope, receive, send)
'/timeout_w': timeout_w
}.get(scope['path'], info)(scope, receive, send)
12 changes: 12 additions & 0 deletions tests/test_asgi.py
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,18 @@ async def test_scope(asgi_server, threading_mode):
assert data['state']['global'] == 'test'


@pytest.mark.asyncio
@pytest.mark.skipif(bool(os.getenv('PGO_RUN')), reason='PGO build')
@pytest.mark.parametrize('threading_mode', ['runtime', 'workers'])
async def test_scope_path_utf8_lossy(asgi_server, threading_mode):
async with asgi_server(threading_mode) as port:
res = httpx.get(f'http://localhost:{port}/%c0')

assert res.status_code == 200
data = res.json()
assert data['path'] == '/\ufffd'


@pytest.mark.asyncio
@pytest.mark.parametrize('threading_mode', ['runtime', 'workers'])
async def test_body(asgi_server, threading_mode):
Expand Down

0 comments on commit 4a461dc

Please sign in to comment.