File tree Expand file tree Collapse file tree 4 files changed +38
-0
lines changed Expand file tree Collapse file tree 4 files changed +38
-0
lines changed Original file line number Diff line number Diff line change @@ -67,6 +67,7 @@ def file_move_safe(
67
67
| os .O_CREAT
68
68
| getattr (os , "O_BINARY" , 0 )
69
69
| (os .O_EXCL if not allow_overwrite else 0 )
70
+ | os .O_TRUNC
70
71
),
71
72
)
72
73
try :
Original file line number Diff line number Diff line change
1
+ ===========================
2
+ Django 4.2.21 release notes
3
+ ===========================
4
+
5
+ *Expected May 7, 2025*
6
+
7
+ Django 4.2.21 fixes a data loss bug in 4.2.20.
8
+
9
+ Bugfixes
10
+ ========
11
+
12
+ * Fixed a data corruption possibility in ``file_move_safe()`` when
13
+ ``allow_overwrite=True``, where leftover content from a previously larger
14
+ file could remain after overwriting with a smaller one due to lack of
15
+ truncation (:ticket:`36298`).
Original file line number Diff line number Diff line change @@ -26,6 +26,7 @@ versions of the documentation contain the release notes for any later releases.
26
26
.. toctree::
27
27
:maxdepth: 1
28
28
29
+ 4.2.21
29
30
4.2.20
30
31
4.2.19
31
32
4.2.18
Original file line number Diff line number Diff line change @@ -475,6 +475,27 @@ def test_file_move_permissionerror(self):
475
475
os .close (handle_b )
476
476
os .close (handle_c )
477
477
478
+ def test_file_move_ensure_truncation (self ):
479
+ with tempfile .NamedTemporaryFile (delete = False ) as src :
480
+ src .write (b"content" )
481
+ src_name = src .name
482
+ self .addCleanup (
483
+ lambda : os .remove (src_name ) if os .path .exists (src_name ) else None
484
+ )
485
+
486
+ with tempfile .NamedTemporaryFile (delete = False ) as dest :
487
+ dest .write (b"This is a longer content." )
488
+ dest_name = dest .name
489
+ self .addCleanup (os .remove , dest_name )
490
+
491
+ with mock .patch ("django.core.files.move.os.rename" , side_effect = OSError ()):
492
+ file_move_safe (src_name , dest_name , allow_overwrite = True )
493
+
494
+ with open (dest_name , "rb" ) as f :
495
+ content = f .read ()
496
+
497
+ self .assertEqual (content , b"content" )
498
+
478
499
479
500
class SpooledTempTests (unittest .TestCase ):
480
501
def test_in_memory_spooled_temp (self ):
You can’t perform that action at this time.
0 commit comments