From 84d28b4ee5983bcb048323a0e56ea4c5498a0652 Mon Sep 17 00:00:00 2001 From: Serhiy Storchaka Date: Sat, 14 Dec 2013 20:35:04 +0200 Subject: Issue #19623: Fixed writing to unseekable files in the aifc module. --- Lib/aifc.py | 11 ++++++--- Lib/test/audiotests.py | 62 ++++++++++++++++++++++++++++++++++++++++++++++++++ Lib/test/test_aifc.py | 41 ++++++++++----------------------- Lib/test/test_sunau.py | 23 +++++++------------ Lib/test/test_wave.py | 26 +++++++++------------ Misc/NEWS | 2 ++ 6 files changed, 103 insertions(+), 62 deletions(-) diff --git a/Lib/aifc.py b/Lib/aifc.py index 86a5edc..db0924a 100644 --- a/Lib/aifc.py +++ b/Lib/aifc.py @@ -771,7 +771,10 @@ class Aifc_write: self._datalength = (self._datalength + 3) // 4 if self._datalength & 1: self._datalength = self._datalength + 1 - self._form_length_pos = self._file.tell() + try: + self._form_length_pos = self._file.tell() + except (AttributeError, OSError): + self._form_length_pos = None commlength = self._write_form_length(self._datalength) if self._aifc: self._file.write(b'AIFC') @@ -783,7 +786,8 @@ class Aifc_write: self._file.write(b'COMM') _write_ulong(self._file, commlength) _write_short(self._file, self._nchannels) - self._nframes_pos = self._file.tell() + if self._form_length_pos is not None: + self._nframes_pos = self._file.tell() _write_ulong(self._file, self._nframes) if self._comptype in (b'ULAW', b'ulaw', b'ALAW', b'alaw', b'G722'): _write_short(self._file, 8) @@ -794,7 +798,8 @@ class Aifc_write: self._file.write(self._comptype) _write_string(self._file, self._compname) self._file.write(b'SSND') - self._ssnd_length_pos = self._file.tell() + if self._form_length_pos is not None: + self._ssnd_length_pos = self._file.tell() _write_ulong(self._file, self._datalength + 8) _write_ulong(self._file, 0) _write_ulong(self._file, 0) diff --git a/Lib/test/audiotests.py b/Lib/test/audiotests.py index 008281f..6ff5bb8 100644 --- a/Lib/test/audiotests.py +++ b/Lib/test/audiotests.py @@ -5,6 +5,13 @@ import io import pickle import sys +class UnseekableIO(io.FileIO): + def tell(self): + raise io.UnsupportedOperation + + def seek(self, *args, **kwargs): + raise io.UnsupportedOperation + def byteswap2(data): a = array.array('h') a.frombytes(data) @@ -129,6 +136,61 @@ class AudioWriteTests(AudioTests): self.assertEqual(testfile.read(13), b'ababagalamaga') self.check_file(testfile, self.nframes, self.frames) + def test_unseekable_read(self): + f = self.create_file(TESTFN) + f.setnframes(self.nframes) + f.writeframes(self.frames) + f.close() + + with UnseekableIO(TESTFN, 'rb') as testfile: + self.check_file(testfile, self.nframes, self.frames) + + def test_unseekable_write(self): + with UnseekableIO(TESTFN, 'wb') as testfile: + f = self.create_file(testfile) + f.setnframes(self.nframes) + f.writeframes(self.frames) + f.close() + + self.check_file(TESTFN, self.nframes, self.frames) + + def test_unseekable_incompleted_write(self): + with UnseekableIO(TESTFN, 'wb') as testfile: + testfile.write(b'ababagalamaga') + f = self.create_file(testfile) + f.setnframes(self.nframes + 1) + try: + f.writeframes(self.frames) + except OSError: + pass + try: + f.close() + except OSError: + pass + + with open(TESTFN, 'rb') as testfile: + self.assertEqual(testfile.read(13), b'ababagalamaga') + self.check_file(testfile, self.nframes + 1, self.frames) + + def test_unseekable_overflowed_write(self): + with UnseekableIO(TESTFN, 'wb') as testfile: + testfile.write(b'ababagalamaga') + f = self.create_file(testfile) + f.setnframes(self.nframes - 1) + try: + f.writeframes(self.frames) + except OSError: + pass + try: + f.close() + except OSError: + pass + + with open(TESTFN, 'rb') as testfile: + self.assertEqual(testfile.read(13), b'ababagalamaga') + framesize = self.nchannels * self.sampwidth + self.check_file(testfile, self.nframes - 1, self.frames[:-framesize]) + class AudioTestsWithSourceFile(AudioTests): diff --git a/Lib/test/test_aifc.py b/Lib/test/test_aifc.py index b77354b..10260e3 100644 --- a/Lib/test/test_aifc.py +++ b/Lib/test/test_aifc.py @@ -8,10 +8,14 @@ import struct import aifc -class AifcPCM8Test(audiotests.AudioWriteTests, - audiotests.AudioTestsWithSourceFile, - unittest.TestCase): +class AifcTest(audiotests.AudioWriteTests, + audiotests.AudioTestsWithSourceFile): module = aifc + close_fd = True + test_unseekable_read = None + + +class AifcPCM8Test(AifcTest, unittest.TestCase): sndfilename = 'pluck-pcm8.aiff' sndfilenframes = 3307 nchannels = 2 @@ -26,13 +30,9 @@ class AifcPCM8Test(audiotests.AudioWriteTests, 11FA 3EFB BCFC 66FF CF04 4309 C10E 5112 EE17 8216 7F14 8012 \ 490E 520D EF0F CE0F E40C 630A 080A 2B0B 510E 8B11 B60E 440A \ """) - close_fd = True -class AifcPCM16Test(audiotests.AudioWriteTests, - audiotests.AudioTestsWithSourceFile, - unittest.TestCase): - module = aifc +class AifcPCM16Test(AifcTest, unittest.TestCase): sndfilename = 'pluck-pcm16.aiff' sndfilenframes = 3307 nchannels = 2 @@ -49,13 +49,9 @@ class AifcPCM16Test(audiotests.AudioWriteTests, EEE21753 82071665 7FFF1443 8004128F 49A20EAF 52BB0DBA EFB40F60 CE3C0FBF \ E4B30CEC 63430A5C 08C80A20 2BBB0B08 514A0E43 8BCF1139 B6F60EEB 44120A5E \ """) - close_fd = True -class AifcPCM24Test(audiotests.AudioWriteTests, - audiotests.AudioTestsWithSourceFile, - unittest.TestCase): - module = aifc +class AifcPCM24Test(AifcTest, unittest.TestCase): sndfilename = 'pluck-pcm24.aiff' sndfilenframes = 3307 nchannels = 2 @@ -78,13 +74,9 @@ class AifcPCM24Test(audiotests.AudioWriteTests, E4B49C0CEA2D 6344A80A5A7C 08C8FE0A1FFE 2BB9860B0A0E \ 51486F0E44E1 8BCC64113B05 B6F4EC0EEB36 4413170A5B48 \ """) - close_fd = True -class AifcPCM32Test(audiotests.AudioWriteTests, - audiotests.AudioTestsWithSourceFile, - unittest.TestCase): - module = aifc +class AifcPCM32Test(AifcTest, unittest.TestCase): sndfilename = 'pluck-pcm32.aiff' sndfilenframes = 3307 nchannels = 2 @@ -107,13 +99,9 @@ class AifcPCM32Test(audiotests.AudioWriteTests, E4B49CC00CEA2D90 6344A8800A5A7CA0 08C8FE800A1FFEE0 2BB986C00B0A0E00 \ 51486F800E44E190 8BCC6480113B0580 B6F4EC000EEB3630 441317800A5B48A0 \ """) - close_fd = True -class AifcULAWTest(audiotests.AudioWriteTests, - audiotests.AudioTestsWithSourceFile, - unittest.TestCase): - module = aifc +class AifcULAWTest(AifcTest, unittest.TestCase): sndfilename = 'pluck-ulaw.aifc' sndfilenframes = 3307 nchannels = 2 @@ -132,13 +120,9 @@ class AifcULAWTest(audiotests.AudioWriteTests, """) if sys.byteorder != 'big': frames = audiotests.byteswap2(frames) - close_fd = True -class AifcALAWTest(audiotests.AudioWriteTests, - audiotests.AudioTestsWithSourceFile, - unittest.TestCase): - module = aifc +class AifcALAWTest(AifcTest, unittest.TestCase): sndfilename = 'pluck-alaw.aifc' sndfilenframes = 3307 nchannels = 2 @@ -157,7 +141,6 @@ class AifcALAWTest(audiotests.AudioWriteTests, """) if sys.byteorder != 'big': frames = audiotests.byteswap2(frames) - close_fd = True class AifcMiscTest(audiotests.AudioTests, unittest.TestCase): diff --git a/Lib/test/test_sunau.py b/Lib/test/test_sunau.py index 767314f..1655317 100644 --- a/Lib/test/test_sunau.py +++ b/Lib/test/test_sunau.py @@ -5,10 +5,12 @@ import sys import sunau -class SunauPCM8Test(audiotests.AudioWriteTests, - audiotests.AudioTestsWithSourceFile, - unittest.TestCase): +class SunauTest(audiotests.AudioWriteTests, + audiotests.AudioTestsWithSourceFile): module = sunau + + +class SunauPCM8Test(SunauTest, unittest.TestCase): sndfilename = 'pluck-pcm8.au' sndfilenframes = 3307 nchannels = 2 @@ -25,10 +27,7 @@ class SunauPCM8Test(audiotests.AudioWriteTests, """) -class SunauPCM16Test(audiotests.AudioWriteTests, - audiotests.AudioTestsWithSourceFile, - unittest.TestCase): - module = sunau +class SunauPCM16Test(SunauTest, unittest.TestCase): sndfilename = 'pluck-pcm16.au' sndfilenframes = 3307 nchannels = 2 @@ -47,10 +46,7 @@ class SunauPCM16Test(audiotests.AudioWriteTests, """) -class SunauPCM32Test(audiotests.AudioWriteTests, - audiotests.AudioTestsWithSourceFile, - unittest.TestCase): - module = sunau +class SunauPCM32Test(SunauTest, unittest.TestCase): sndfilename = 'pluck-pcm32.au' sndfilenframes = 3307 nchannels = 2 @@ -75,10 +71,7 @@ class SunauPCM32Test(audiotests.AudioWriteTests, """) -class SunauULAWTest(audiotests.AudioWriteTests, - audiotests.AudioTestsWithSourceFile, - unittest.TestCase): - module = sunau +class SunauULAWTest(SunauTest, unittest.TestCase): sndfilename = 'pluck-ulaw.au' sndfilenframes = 3307 nchannels = 2 diff --git a/Lib/test/test_wave.py b/Lib/test/test_wave.py index 5be1251..f64201f 100644 --- a/Lib/test/test_wave.py +++ b/Lib/test/test_wave.py @@ -5,10 +5,15 @@ import sys import wave -class WavePCM8Test(audiotests.AudioWriteTests, - audiotests.AudioTestsWithSourceFile, - unittest.TestCase): +class WaveTest(audiotests.AudioWriteTests, + audiotests.AudioTestsWithSourceFile): module = wave + test_unseekable_write = None + test_unseekable_overflowed_write = None + test_unseekable_incompleted_write = None + + +class WavePCM8Test(WaveTest, unittest.TestCase): sndfilename = 'pluck-pcm8.wav' sndfilenframes = 3307 nchannels = 2 @@ -25,10 +30,7 @@ class WavePCM8Test(audiotests.AudioWriteTests, """) -class WavePCM16Test(audiotests.AudioWriteTests, - audiotests.AudioTestsWithSourceFile, - unittest.TestCase): - module = wave +class WavePCM16Test(WaveTest, unittest.TestCase): sndfilename = 'pluck-pcm16.wav' sndfilenframes = 3307 nchannels = 2 @@ -55,10 +57,7 @@ class WavePCM16Test(audiotests.AudioWriteTests, -class WavePCM24Test(audiotests.AudioWriteTests, - audiotests.AudioTestsWithSourceFile, - unittest.TestCase): - module = wave +class WavePCM24Test(WaveTest, unittest.TestCase): sndfilename = 'pluck-pcm24.wav' sndfilenframes = 3307 nchannels = 2 @@ -85,10 +84,7 @@ class WavePCM24Test(audiotests.AudioWriteTests, frames = audiotests.byteswap3(frames) -class WavePCM32Test(audiotests.AudioWriteTests, - audiotests.AudioTestsWithSourceFile, - unittest.TestCase): - module = wave +class WavePCM32Test(WaveTest, unittest.TestCase): sndfilename = 'pluck-pcm32.wav' sndfilenframes = 3307 nchannels = 2 diff --git a/Misc/NEWS b/Misc/NEWS index b5f1ece..462d649 100644 --- a/Misc/NEWS +++ b/Misc/NEWS @@ -32,6 +32,8 @@ Core and Builtins Library ------- +- Issue #19623: Fixed writing to unseekable files in the aifc module. + - Issue #17919: select.poll.register() again works with poll.POLLNVAL on AIX. Fixed integer overflow in the eventmask parameter. -- cgit v0.12