From 134cb01cda50f02725575808130b05d2d776693f Mon Sep 17 00:00:00 2001
From: Serhiy Storchaka <storchaka@gmail.com>
Date: Sun, 18 Mar 2018 09:55:53 +0200
Subject: [PATCH] bpo-32056: Improve exceptions in aifc, wave and sunau.
 (GH-5951)

---
 Lib/aifc.py                                        |  4 ++
 Lib/sunau.py                                       |  2 +
 Lib/test/test_aifc.py                              | 35 ++++++++++--
 Lib/test/test_sunau.py                             | 37 +++++++++++++
 Lib/test/test_wave.py                              | 62 ++++++++++++++++++++++
 Lib/wave.py                                        | 14 ++++-
 .../2018-03-01-17-49-56.bpo-32056.IlpfgE.rst       |  3 ++
 7 files changed, 150 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 3d2dc56de198..1916e7ef8e7e 100644
--- a/Lib/aifc.py
+++ b/Lib/aifc.py
@@ -467,6 +467,10 @@ def _read_comm_chunk(self, chunk):
         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 dbad3db8392d..129502b0b417 100644
--- a/Lib/sunau.py
+++ b/Lib/sunau.py
@@ -208,6 +208,8 @@ def initfp(self, file):
             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)
--- a/Lib/wave.py
+++ b/Lib/wave.py
@@ -253,12 +253,22 @@ def readframes(self, nframes):
     #
 
     def _read_fmt_chunk(self, chunk):
-        wFormatTag, self._nchannels, self._framerate, dwAvgBytesPerSec, wBlockAlign = struct.unpack_from('<HHLLH', chunk.read(14))
+        try:
+            wFormatTag, self._nchannels, self._framerate, dwAvgBytesPerSec, wBlockAlign = struct.unpack_from('<HHLLH', chunk.read(14))
+        except struct.error:
+            raise EOFError from None
         if wFormatTag == WAVE_FORMAT_PCM:
-            sampwidth = struct.unpack_from('<H', chunk.read(2))[0]
+            try:
+                sampwidth = struct.unpack_from('<H', chunk.read(2))[0]
+            except struct.error:
+                raise EOFError from None
             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 000000000000..421aa3767794
--- /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`.