Fixed #32718 -- Relaxed file name validation in FileField.

- Validate filename returned by FileField.upload_to() not a filename
  passed to the FileField.generate_filename() (upload_to() may
  completely ignored passed filename).
- Allow relative paths (without dot segments) in the generated filename.

Thanks to Jakub Kleň for the report and review.
Thanks to all folks for checking this patch on existing projects.
Thanks Florian Apolloner and Markus Holtermann for the discussion and
implementation idea.

Regression in 0b79eb3691.
This commit is contained in:
Mariusz Felisiak 2021-05-13 08:53:44 +02:00 committed by GitHub
parent b81c7562fc
commit b55699968f
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
8 changed files with 140 additions and 17 deletions

View file

@ -5,6 +5,7 @@ import tempfile
import unittest
from pathlib import Path
from django.core.exceptions import SuspiciousFileOperation
from django.core.files import File, temp
from django.core.files.base import ContentFile
from django.core.files.uploadedfile import TemporaryUploadedFile
@ -63,6 +64,15 @@ class FileFieldTests(TestCase):
d.refresh_from_db()
self.assertIs(d.myfile.instance, d)
@unittest.skipIf(sys.platform == 'win32', "Crashes with OSError on Windows.")
def test_save_without_name(self):
with tempfile.NamedTemporaryFile(suffix='.txt') as tmp:
document = Document.objects.create(myfile='something.txt')
document.myfile = File(tmp)
msg = f"Detected path traversal attempt in '{tmp.name}'"
with self.assertRaisesMessage(SuspiciousFileOperation, msg):
document.save()
def test_defer(self):
Document.objects.create(myfile='something.txt')
self.assertEqual(Document.objects.defer('myfile')[0].myfile, 'something.txt')