From: Michiel W. Beijen Date: Tue, 17 Mar 2026 17:01:18 +0000 (+0100) Subject: gh-144975: Fix wave.Wave_write.setframerate() validation order (GH-144976) X-Git-Tag: v3.15.0a8~274 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=ff287a72de43e7fc6517aba9049cb23470e000b2;p=thirdparty%2FPython%2Fcpython.git gh-144975: Fix wave.Wave_write.setframerate() validation order (GH-144976) Validate the frame rate after rounding to an integer, not before. This prevents values like 0.5 from passing validation (0.5 > 0) but then rounding to 0, which would cause a confusing delayed error "sampling rate not specified" when writing frames. With this fix, setframerate(0.5) immediately raises "bad frame rate", providing clear feedback at the point of the error. --- diff --git a/Lib/test/test_wave.py b/Lib/test/test_wave.py index 4c21f1655377..05e7d3775177 100644 --- a/Lib/test/test_wave.py +++ b/Lib/test/test_wave.py @@ -207,6 +207,43 @@ class WaveLowLevelTest(unittest.TestCase): support.gc_collect() self.assertIsNone(cm.unraisable) + @support.subTests('arg', ( + # rounds to 0, should raise: + 0.5, + 0.4, + # Negative values should still raise: + -1, + -0.5, + -0.4, + # 0 should raise: + 0, + )) + def test_setframerate_validates_rounded_values(self, arg): + """Test that setframerate that round to 0 or negative are rejected""" + with wave.open(io.BytesIO(), 'wb') as f: + f.setnchannels(1) + f.setsampwidth(2) + with self.assertRaises(wave.Error): + f.setframerate(arg) + with self.assertRaises(wave.Error): + f.close() + + @support.subTests(('arg', 'expected'), ( + (1.4, 1), + (1.5, 2), + (1.6, 2), + (44100.4, 44100), + (44100.5, 44100), + (44100.6, 44101), + )) + def test_setframerate_rounds(self, arg, expected): + """Test that setframerate is rounded""" + with wave.open(io.BytesIO(), 'wb') as f: + f.setnchannels(1) + f.setsampwidth(2) + f.setframerate(arg) + self.assertEqual(f.getframerate(), expected) + class WaveOpen(unittest.TestCase): def test_open_pathlike(self): diff --git a/Lib/wave.py b/Lib/wave.py index 25ca9ef168e8..841da8c49e9a 100644 --- a/Lib/wave.py +++ b/Lib/wave.py @@ -493,9 +493,10 @@ class Wave_write: def setframerate(self, framerate): if self._datawritten: raise Error('cannot change parameters after starting to write') + framerate = int(round(framerate)) if framerate <= 0: raise Error('bad frame rate') - self._framerate = int(round(framerate)) + self._framerate = framerate def getframerate(self): if not self._framerate: diff --git a/Misc/NEWS.d/next/Library/2026-02-18-21-45-00.gh-issue-144975.Ab3XyZ.rst b/Misc/NEWS.d/next/Library/2026-02-18-21-45-00.gh-issue-144975.Ab3XyZ.rst new file mode 100644 index 000000000000..37658064c2c3 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2026-02-18-21-45-00.gh-issue-144975.Ab3XyZ.rst @@ -0,0 +1,3 @@ +:meth:`wave.Wave_write.setframerate` now validates the frame rate after +rounding to an integer, preventing values like ``0.5`` from being accepted +and causing confusing errors later. Patch by Michiel Beijen.