diff --git a/beets/mediafile.py b/beets/mediafile.py index 927cb389b..39c9ee21c 100644 --- a/beets/mediafile.py +++ b/beets/mediafile.py @@ -204,7 +204,12 @@ def _sc_decode(soundcheck): # compared to a reference value of 1000 to get our gain in dB. We # play it safe by using the larger of the two values (i.e., the most # attenuation). - gain = math.log10((max(*soundcheck[:2]) or 1000) / 1000.0) * -10 + maxgain = max(soundcheck[:2]) + if maxgain > 0: + gain = math.log10(maxgain / 1000.0) * -10 + else: + # Invalid gain value found. + gain = 0.0 # SoundCheck stores peak values as the actual value of the sample, # and again separately for the left and right channels. We need to diff --git a/docs/changelog.rst b/docs/changelog.rst index 2d9cd9729..720c5d54c 100644 --- a/docs/changelog.rst +++ b/docs/changelog.rst @@ -7,6 +7,7 @@ Changelog * :doc:`/plugins/echonest_tempo`: API errors now issue a warning instead of exiting with an exception. We also avoid an error when track metadata contains newlines. +* Fix a crash when iTunes Sound Check tags contained invalid data. 1.1b2 (February 16, 2013) ------------------------- diff --git a/test/test_mediafile.py b/test/test_mediafile.py index 970bfd356..7050b0651 100644 --- a/test/test_mediafile.py +++ b/test/test_mediafile.py @@ -205,6 +205,25 @@ class TypeTest(unittest.TestCase): self.mf.year = '2009' self.assertEqual(self.mf.year, 2009) +class SoundCheckTest(unittest.TestCase): + def test_round_trip(self): + data = beets.mediafile._sc_encode(1.0, 1.0) + gain, peak = beets.mediafile._sc_decode(data) + self.assertEqual(gain, 1.0) + self.assertEqual(peak, 1.0) + + def test_decode_zero(self): + data = u' 80000000 80000000 00000000 00000000 00000000 00000000 ' \ + u'00000000 00000000 00000000 00000000' + gain, peak = beets.mediafile._sc_decode(data) + self.assertEqual(gain, 0.0) + self.assertEqual(peak, 0.0) + + def test_malformatted(self): + gain, peak = beets.mediafile._sc_decode(u'foo') + self.assertEqual(gain, 0.0) + self.assertEqual(peak, 0.0) + def suite(): return unittest.TestLoader().loadTestsFromName(__name__)