diff --git a/starlette/staticfiles.py b/starlette/staticfiles.py index 5d0856ccc..afb09b56b 100644 --- a/starlette/staticfiles.py +++ b/starlette/staticfiles.py @@ -1,5 +1,6 @@ from __future__ import annotations +import errno import importlib.util import os import stat @@ -124,8 +125,12 @@ async def get_response(self, path: str, scope: Scope) -> Response: ) except PermissionError: raise HTTPException(status_code=401) - except OSError: - raise + except OSError as exc: + # Filename is too long, so it can't be a valid static file. + if exc.errno == errno.ENAMETOOLONG: + raise HTTPException(status_code=404) + + raise exc if stat_result and stat.S_ISREG(stat_result.st_mode): # We have a static file to serve. diff --git a/tests/test_staticfiles.py b/tests/test_staticfiles.py index d20bb7ef7..085301302 100644 --- a/tests/test_staticfiles.py +++ b/tests/test_staticfiles.py @@ -469,6 +469,19 @@ def test_staticfiles_access_file_as_dir_returns_404( assert response.text == "Not Found" +def test_staticfiles_filename_too_long( + tmpdir: Path, test_client_factory: TestClientFactory +) -> None: + routes = [Mount("/", app=StaticFiles(directory=tmpdir), name="static")] + app = Starlette(routes=routes) + client = test_client_factory(app) + + path_max_size = os.pathconf("/", "PC_PATH_MAX") + response = client.get(f"/{'a' * path_max_size}.txt") + assert response.status_code == 404 + assert response.text == "Not Found" + + def test_staticfiles_unhandled_os_error_returns_500( tmpdir: Path, test_client_factory: TestClientFactory,