Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commite65b3fa

Browse files
authored
bpo-26730: Fix SpooledTemporaryFile data corruption (GH-17400)
SpooledTemporaryFile.rollback() might cause data corruptionwhen it is in text mode.Co-Authored-By: Serhiy Storchaka <storchaka@gmail.com>.(cherry picked from commitea9835c)
1 parentcd27d22 commite65b3fa

File tree

4 files changed

+23
-16
lines changed

4 files changed

+23
-16
lines changed

‎Doc/library/tempfile.rst‎

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -95,8 +95,8 @@ The module defines the following user-callable items:
9595
causes the file to roll over to an on-disk file regardless of its size.
9696

9797
The returned object is a file-like object whose:attr:`_file` attribute
98-
is either an:class:`io.BytesIO` or:class:`io.StringIO` object (depending on
99-
whether binary or text *mode* was specified) or a true file
98+
is either an:class:`io.BytesIO` or:class:`io.TextIOWrapper` object
99+
(depending onwhether binary or text *mode* was specified) or a true file
100100
object, depending on whether:func:`rollover` has been called. This
101101
file-like object can be used in a:keyword:`with` statement, just like
102102
a normal file.

‎Lib/tempfile.py‎

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -637,10 +637,8 @@ def __init__(self, max_size=0, mode='w+b', buffering=-1,
637637
if'b'inmode:
638638
self._file=_io.BytesIO()
639639
else:
640-
# Setting newline="\n" avoids newline translation;
641-
# this is important because otherwise on Windows we'd
642-
# get double newline translation upon rollover().
643-
self._file=_io.StringIO(newline="\n")
640+
self._file=_io.TextIOWrapper(_io.BytesIO(),
641+
encoding=encoding,newline=newline)
644642
self._max_size=max_size
645643
self._rolled=False
646644
self._TemporaryFileArgs= {'mode':mode,'buffering':buffering,
@@ -660,8 +658,12 @@ def rollover(self):
660658
newfile=self._file=TemporaryFile(**self._TemporaryFileArgs)
661659
delself._TemporaryFileArgs
662660

663-
newfile.write(file.getvalue())
664-
newfile.seek(file.tell(),0)
661+
pos=file.tell()
662+
ifhasattr(newfile,'buffer'):
663+
newfile.buffer.write(file.detach().getvalue())
664+
else:
665+
newfile.write(file.getvalue())
666+
newfile.seek(pos,0)
665667

666668
self._rolled=True
667669

‎Lib/test/test_tempfile.py‎

Lines changed: 11 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1119,7 +1119,8 @@ def test_properties(self):
11191119
deftest_text_mode(self):
11201120
# Creating a SpooledTemporaryFile with a text mode should produce
11211121
# a file object reading and writing (Unicode) text strings.
1122-
f=tempfile.SpooledTemporaryFile(mode='w+',max_size=10)
1122+
f=tempfile.SpooledTemporaryFile(mode='w+',max_size=10,
1123+
encoding="utf-8")
11231124
f.write("abc\n")
11241125
f.seek(0)
11251126
self.assertEqual(f.read(),"abc\n")
@@ -1129,8 +1130,8 @@ def test_text_mode(self):
11291130
self.assertFalse(f._rolled)
11301131
self.assertEqual(f.mode,'w+')
11311132
self.assertIsNone(f.name)
1132-
self.assertIsNone(f.newlines)
1133-
self.assertIsNone(f.encoding)
1133+
self.assertEqual(f.newlines,os.linesep)
1134+
self.assertEqual(f.encoding,"utf-8")
11341135

11351136
f.write("xyzzy\n")
11361137
f.seek(0)
@@ -1143,7 +1144,7 @@ def test_text_mode(self):
11431144
self.assertEqual(f.mode,'w+')
11441145
self.assertIsNotNone(f.name)
11451146
self.assertEqual(f.newlines,os.linesep)
1146-
self.assertIsNotNone(f.encoding)
1147+
self.assertEqual(f.encoding,"utf-8")
11471148

11481149
deftest_text_newline_and_encoding(self):
11491150
f=tempfile.SpooledTemporaryFile(mode='w+',max_size=10,
@@ -1154,12 +1155,14 @@ def test_text_newline_and_encoding(self):
11541155
self.assertFalse(f._rolled)
11551156
self.assertEqual(f.mode,'w+')
11561157
self.assertIsNone(f.name)
1157-
self.assertIsNone(f.newlines)
1158-
self.assertIsNone(f.encoding)
1158+
self.assertIsNotNone(f.newlines)
1159+
self.assertEqual(f.encoding,"utf-8")
11591160

1160-
f.write("\u039B"*20+"\r\n")
1161+
f.write("\u039C"*10+"\r\n")
1162+
f.write("\u039D"*20)
11611163
f.seek(0)
1162-
self.assertEqual(f.read(),"\u039B\r\n"+ ("\u039B"*20)+"\r\n")
1164+
self.assertEqual(f.read(),
1165+
"\u039B\r\n"+ ("\u039C"*10)+"\r\n"+ ("\u039D"*20))
11631166
self.assertTrue(f._rolled)
11641167
self.assertEqual(f.mode,'w+')
11651168
self.assertIsNotNone(f.name)
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
Fix ``SpooledTemporaryFile.rollover()`` might corrupt the file when it is in
2+
text mode. Patch by Serhiy Storchaka.

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2026 Movatter.jp