#37292: TemporaryUploadedFile raises OSError for a filename with a very long
extension
-------------------------------------+-------------------------------------
Reporter: Prakhar Pratyush | Type: Bug
Status: new | Component: File
| uploads/storage
Version: 5.2 | Severity: Normal
Keywords: | Triage Stage:
| Unreviewed
Has patch: 0 | Needs documentation: 0
Needs tests: 0 | Patch needs improvement: 0
Easy pickings: 0 | UI/UX: 0
-------------------------------------+-------------------------------------
Uploading a file whose extension is long enough makes the request die with
an unhandled `OSError` instead of the name being sanitized.
`TemporaryUploadedFile` takes the extension straight off the client-
supplied filename and uses it as the suffix of the temporary file:
{{{
_, ext = os.path.splitext(name)
file = tempfile.NamedTemporaryFile(
suffix=".upload" + ext, dir=settings.FILE_UPLOAD_TEMP_DIR
)
super().__init__(file, name, content_type, size, charset,
content_type_extra)
}}}
`NAME_MAX` is 255 bytes on ext4 and most other filesystems, and `tempfile`
adds "tmp" plus 8 random characters on top of the 7-byte ".upload", so an
extension of 238 bytes or more is enough to make `os.open()` fail.
=== Replication
{{{
>>> from django.core.files.uploadedfile import TemporaryUploadedFile
>>> TemporaryUploadedFile("x." + "a" * 250, "text/plain", 6, None)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "/srv/zulip/.venv/lib/python3.10/site-
packages/django/core/files/uploadedfile.py", line 77, in __init__
file = tempfile.NamedTemporaryFile(
File "/usr/lib/python3.10/tempfile.py", line 714, in NamedTemporaryFile
file = _io.open(dir, mode, buffering=buffering,
File "/usr/lib/python3.10/tempfile.py", line 711, in opener
fd, name = _mkstemp_inner(dir, prefix, suffix, flags, output_type)
File "/usr/lib/python3.10/tempfile.py", line 395, in _mkstemp_inner
fd = _os.open(file, flags, 0o600)
OSError: [Errno 36] File name too long:
'/tmp/tmpm5gby_up.upload.aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa'
}}}
**Also**:
Over a real request you need an upload larger than
`FILE_UPLOAD_MAX_MEMORY_SIZE` so that `MemoryFileUploadHandler` declines
it and the temporary file handler takes over. Anything that reads
`request.POST` on that request will then raise, it comes out as a 500.
--
Ticket URL: <
https://code.djangoproject.com/ticket/37292>
Django <
https://code.djangoproject.com/>
The Web framework for perfectionists with deadlines.