Projects
Eulaceura:Factory
python2
_service:obs_scm:CVE-2017-18207.patch
Sign Up
Log In
Username
Password
Overview
Repositories
Revisions
Requests
Users
Attributes
Meta
File _service:obs_scm:CVE-2017-18207.patch of Package python2
From 3c0a5a7c7ba8fbbc95dd1fe76cd7a1c0ce167371 Mon Sep 17 00:00:00 2001 From: "Miss Islington (bot)" <31488909+miss-islington@users.noreply.github.com> Date: Sun, 18 Mar 2018 13:50:41 -0700 Subject: [PATCH] bpo-32056: Improve exceptions in aifc, wave and sunau. (GH-5951) (cherry picked from commit 134cb01cda50f02725575808130b05d2d776693f) Co-authored-by: Serhiy Storchaka <storchaka@gmail.com> --- Lib/aifc.py | 4 ++ Lib/sunau.py | 2 + Lib/test/test_aifc.py | 35 +++++++++-- Lib/test/test_sunau.py | 36 +++++++++++ Lib/test/test_wave.py | 61 +++++++++++++++++++ Lib/wave.py | 14 ++++- .../2018-03-01-17-49-56.bpo-32056.IlpfgE.rst | 3 + 7 files changed, 148 insertions(+), 7 deletions(-) create mode 100644 Misc/NEWS.d/next/Library/2018-03-01-17-49-56.bpo-32056.IlpfgE.rst diff --git a/Lib/aifc.py b/Lib/aifc.py index 981f801..d0e5e02 100644 --- a/Lib/aifc.py +++ b/Lib/aifc.py @@ -465,6 +465,10 @@ class Aifc_read: self._nframes = _read_long(chunk) self._sampwidth = (_read_short(chunk) + 7) // 8 self._framerate = int(_read_float(chunk)) + if self._sampwidth <= 0: + raise Error('bad sample width') + if self._nchannels <= 0: + raise Error('bad # of channels') self._framesize = self._nchannels * self._sampwidth if self._aifc: #DEBUG: SGI's soundeditor produces a bad size :-( diff --git a/Lib/sunau.py b/Lib/sunau.py index b53044d..b5d83ea 100644 --- a/Lib/sunau.py +++ b/Lib/sunau.py @@ -194,6 +194,8 @@ class Au_read: raise Error, 'unknown encoding' self._framerate = int(_read_u32(file)) self._nchannels = int(_read_u32(file)) + if not self._nchannels: + raise Error('bad # of channels') self._framesize = self._framesize * self._nchannels if self._hdr_size > 24: self._info = file.read(self._hdr_size - 24) diff --git a/Lib/test/test_aifc.py b/Lib/test/test_aifc.py index 92bbe7b..6517c9f 100644 --- a/Lib/test/test_aifc.py +++ b/Lib/test/test_aifc.py @@ -216,7 +216,8 @@ class AIFCLowLevelTest(unittest.TestCase): def test_read_no_ssnd_chunk(self): b = b'FORM' + struct.pack('>L', 4) + b'AIFC' - b += b'COMM' + struct.pack('>LhlhhLL', 38, 0, 0, 0, 0, 0, 0) + b += b'COMM' + struct.pack('>LhlhhLL', 38, 1, 0, 8, + 0x4000 | 12, 11025<<18, 0) b += b'NONE' + struct.pack('B', 14) + b'not compressed' + b'\x00' with self.assertRaisesRegexp(aifc.Error, 'COMM chunk and/or SSND chunk' ' missing'): @@ -224,13 +225,35 @@ class AIFCLowLevelTest(unittest.TestCase): def test_read_wrong_compression_type(self): b = 'FORM' + struct.pack('>L', 4) + 'AIFC' - b += 'COMM' + struct.pack('>LhlhhLL', 23, 0, 0, 0, 0, 0, 0) + b += b'COMM' + struct.pack('>LhlhhLL', 23, 1, 0, 8, + 0x4000 | 12, 11025<<18, 0) b += 'WRNG' + struct.pack('B', 0) self.assertRaises(aifc.Error, aifc.open, io.BytesIO(b)) + def test_read_wrong_number_of_channels(self): + for nchannels in 0, -1: + b = b'FORM' + struct.pack('>L', 4) + b'AIFC' + b += b'COMM' + struct.pack('>LhlhhLL', 38, nchannels, 0, 8, + 0x4000 | 12, 11025<<18, 0) + b += b'NONE' + struct.pack('B', 14) + b'not compressed' + b'\x00' + b += b'SSND' + struct.pack('>L', 8) + b'\x00' * 8 + with self.assertRaisesRegex(aifc.Error, 'bad # of channels'): + aifc.open(io.BytesIO(b)) + + def test_read_wrong_sample_width(self): + for sampwidth in 0, -1: + b = b'FORM' + struct.pack('>L', 4) + b'AIFC' + b += b'COMM' + struct.pack('>LhlhhLL', 38, 1, 0, sampwidth, + 0x4000 | 12, 11025<<18, 0) + b += b'NONE' + struct.pack('B', 14) + b'not compressed' + b'\x00' + b += b'SSND' + struct.pack('>L', 8) + b'\x00' * 8 + with self.assertRaisesRegex(aifc.Error, 'bad sample width'): + aifc.open(io.BytesIO(b)) + def test_read_wrong_marks(self): b = 'FORM' + struct.pack('>L', 4) + 'AIFF' - b += 'COMM' + struct.pack('>LhlhhLL', 18, 0, 0, 0, 0, 0, 0) + b += b'COMM' + struct.pack('>LhlhhLL', 18, 1, 0, 8, + 0x4000 | 12, 11025<<18, 0) b += 'SSND' + struct.pack('>L', 8) + '\x00' * 8 b += 'MARK' + struct.pack('>LhB', 3, 1, 1) with captured_stdout() as s: @@ -241,7 +264,8 @@ class AIFCLowLevelTest(unittest.TestCase): def test_read_comm_kludge_compname_even(self): b = 'FORM' + struct.pack('>L', 4) + 'AIFC' - b += 'COMM' + struct.pack('>LhlhhLL', 18, 0, 0, 0, 0, 0, 0) + b += b'COMM' + struct.pack('>LhlhhLL', 18, 1, 0, 8, + 0x4000 | 12, 11025<<18, 0) b += 'NONE' + struct.pack('B', 4) + 'even' + '\x00' b += 'SSND' + struct.pack('>L', 8) + '\x00' * 8 with captured_stdout() as s: @@ -251,7 +275,8 @@ class AIFCLowLevelTest(unittest.TestCase): def test_read_comm_kludge_compname_odd(self): b = 'FORM' + struct.pack('>L', 4) + 'AIFC' - b += 'COMM' + struct.pack('>LhlhhLL', 18, 0, 0, 0, 0, 0, 0) + b += b'COMM' + struct.pack('>LhlhhLL', 18, 1, 0, 8, + 0x4000 | 12, 11025<<18, 0) b += 'NONE' + struct.pack('B', 3) + 'odd' b += 'SSND' + struct.pack('>L', 8) + '\x00' * 8 with captured_stdout() as s: diff --git a/Lib/test/test_sunau.py b/Lib/test/test_sunau.py index f682868..824bd91 100644 --- a/Lib/test/test_sunau.py +++ b/Lib/test/test_sunau.py @@ -1,6 +1,8 @@ from test.test_support import TESTFN, run_unittest import unittest from test import audiotests +import io +import struct import sys import sunau @@ -91,6 +93,40 @@ class SunauULAWTest(SunauTest, unittest.TestCase): if sys.byteorder != 'big': frames = audiotests.byteswap2(frames) +class SunauLowLevelTest(unittest.TestCase): + + def test_read_bad_magic_number(self): + b = b'SPA' + with self.assertRaises(EOFError): + sunau.open(io.BytesIO(b)) + b = b'SPAM' + with self.assertRaisesRegex(sunau.Error, 'bad magic number'): + sunau.open(io.BytesIO(b)) + + def test_read_too_small_header(self): + b = struct.pack('>LLLLL', sunau.AUDIO_FILE_MAGIC, 20, 0, + sunau.AUDIO_FILE_ENCODING_LINEAR_8, 11025) + with self.assertRaisesRegex(sunau.Error, 'header size too small'): + sunau.open(io.BytesIO(b)) + + def test_read_too_large_header(self): + b = struct.pack('>LLLLLL', sunau.AUDIO_FILE_MAGIC, 124, 0, + sunau.AUDIO_FILE_ENCODING_LINEAR_8, 11025, 1) + b += b'\0' * 100 + with self.assertRaisesRegex(sunau.Error, 'header size ridiculously large'): + sunau.open(io.BytesIO(b)) + + def test_read_wrong_encoding(self): + b = struct.pack('>LLLLLL', sunau.AUDIO_FILE_MAGIC, 24, 0, 0, 11025, 1) + with self.assertRaisesRegex(sunau.Error, r'encoding not \(yet\) supported'): + sunau.open(io.BytesIO(b)) + + def test_read_wrong_number_of_channels(self): + b = struct.pack('>LLLLLL', sunau.AUDIO_FILE_MAGIC, 24, 0, + sunau.AUDIO_FILE_ENCODING_LINEAR_8, 11025, 0) + with self.assertRaisesRegex(sunau.Error, 'bad # of channels'): + sunau.open(io.BytesIO(b)) + def test_main(): run_unittest(SunauPCM8Test, SunauPCM16Test, SunauPCM16Test, diff --git a/Lib/test/test_wave.py b/Lib/test/test_wave.py index 9513df4..b835746 100644 --- a/Lib/test/test_wave.py +++ b/Lib/test/test_wave.py @@ -1,6 +1,8 @@ from test.test_support import TESTFN, run_unittest import unittest from test import audiotests +import io +import struct import sys import wave @@ -115,6 +117,65 @@ class WavePCM32Test(WaveTest, unittest.TestCase): def test_unseekable_incompleted_write(self): super().test_unseekable_incompleted_write() +class WaveLowLevelTest(unittest.TestCase): + + def test_read_no_chunks(self): + b = b'SPAM' + with self.assertRaises(EOFError): + wave.open(io.BytesIO(b)) + + def test_read_no_riff_chunk(self): + b = b'SPAM' + struct.pack('<L', 0) + with self.assertRaisesRegex(wave.Error, + 'file does not start with RIFF id'): + wave.open(io.BytesIO(b)) + + def test_read_not_wave(self): + b = b'RIFF' + struct.pack('<L', 4) + b'SPAM' + with self.assertRaisesRegex(wave.Error, + 'not a WAVE file'): + wave.open(io.BytesIO(b)) + + def test_read_no_fmt_no_data_chunk(self): + b = b'RIFF' + struct.pack('<L', 4) + b'WAVE' + with self.assertRaisesRegex(wave.Error, + 'fmt chunk and/or data chunk missing'): + wave.open(io.BytesIO(b)) + + def test_read_no_data_chunk(self): + b = b'RIFF' + struct.pack('<L', 28) + b'WAVE' + b += b'fmt ' + struct.pack('<LHHLLHH', 16, 1, 1, 11025, 11025, 1, 8) + with self.assertRaisesRegex(wave.Error, + 'fmt chunk and/or data chunk missing'): + wave.open(io.BytesIO(b)) + + def test_read_no_fmt_chunk(self): + b = b'RIFF' + struct.pack('<L', 12) + b'WAVE' + b += b'data' + struct.pack('<L', 0) + with self.assertRaisesRegex(wave.Error, 'data chunk before fmt chunk'): + wave.open(io.BytesIO(b)) + + def test_read_wrong_form(self): + b = b'RIFF' + struct.pack('<L', 36) + b'WAVE' + b += b'fmt ' + struct.pack('<LHHLLHH', 16, 2, 1, 11025, 11025, 1, 1) + b += b'data' + struct.pack('<L', 0) + with self.assertRaisesRegex(wave.Error, 'unknown format: 2'): + wave.open(io.BytesIO(b)) + + def test_read_wrong_number_of_channels(self): + b = b'RIFF' + struct.pack('<L', 36) + b'WAVE' + b += b'fmt ' + struct.pack('<LHHLLHH', 16, 1, 0, 11025, 11025, 1, 8) + b += b'data' + struct.pack('<L', 0) + with self.assertRaisesRegex(wave.Error, 'bad # of channels'): + wave.open(io.BytesIO(b)) + + def test_read_wrong_sample_width(self): + b = b'RIFF' + struct.pack('<L', 36) + b'WAVE' + b += b'fmt ' + struct.pack('<LHHLLHH', 16, 1, 1, 11025, 11025, 1, 0) + b += b'data' + struct.pack('<L', 0) + with self.assertRaisesRegex(wave.Error, 'bad sample width'): + wave.open(io.BytesIO(b)) + def test_main(): run_unittest(WavePCM8Test, WavePCM16Test, WavePCM24Test, WavePCM32Test) diff --git a/Lib/wave.py b/Lib/wave.py index 28acaa6..63c196f 100644 --- a/Lib/wave.py +++ b/Lib/wave.py @@ -266,12 +266,22 @@ class Wave_read: # def _read_fmt_chunk(self, chunk): - wFormatTag, self._nchannels, self._framerate, dwAvgBytesPerSec, wBlockAlign = struct.unpack('<HHLLH', chunk.read(14)) + try: + wFormatTag, self._nchannels, self._framerate, dwAvgBytesPerSec, wBlockAlign = struct.unpack_from('<HHLLH', chunk.read(14)) + except struct.error: + raise EOFError if wFormatTag == WAVE_FORMAT_PCM: - sampwidth = struct.unpack('<H', chunk.read(2))[0] + try: + sampwidth = struct.unpack_from('<H', chunk.read(2))[0] + except struct.error: + raise EOFError self._sampwidth = (sampwidth + 7) // 8 + if not self._sampwidth: + raise Error('bad sample width') else: raise Error, 'unknown format: %r' % (wFormatTag,) + if not self._nchannels: + raise Error('bad # of channels') self._framesize = self._nchannels * self._sampwidth self._comptype = 'NONE' self._compname = 'not compressed' diff --git a/Misc/NEWS.d/next/Library/2018-03-01-17-49-56.bpo-32056.IlpfgE.rst b/Misc/NEWS.d/next/Library/2018-03-01-17-49-56.bpo-32056.IlpfgE.rst new file mode 100644 index 0000000..421aa37 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2018-03-01-17-49-56.bpo-32056.IlpfgE.rst @@ -0,0 +1,3 @@ +Improved exceptions raised for invalid number of channels and sample width +when read an audio file in modules :mod:`aifc`, :mod:`wave` and +:mod:`sunau`. -- 2.23.0
Locations
Projects
Search
Status Monitor
Help
Open Build Service
OBS Manuals
API Documentation
OBS Portal
Reporting a Bug
Contact
Mailing List
Forums
Chat (IRC)
Twitter
Open Build Service (OBS)
is an
openSUSE project
.
浙ICP备2022010568号-2