Fix #1666: malformed binary data in SoundCheck

This commit is contained in:
Adrian Sampson 2015-11-13 12:21:36 -08:00
parent 2048aa660b
commit 9c968456c1
4 changed files with 15 additions and 6 deletions

View file

@ -215,9 +215,9 @@ def _sc_decode(soundcheck):
# SoundCheck tags consist of 10 numbers, each represented by 8
# characters of ASCII hex preceded by a space.
try:
soundcheck = soundcheck.replace(' ', '').decode('hex')
soundcheck = soundcheck.replace(b' ', b'').decode('hex')
soundcheck = struct.unpack(b'!iiiiiiiiii', soundcheck)
except (struct.error, TypeError, UnicodeEncodeError):
except (struct.error, TypeError):
# SoundCheck isn't in the format we expect, so return default
# values.
return 0.0, 0.0

View file

@ -56,6 +56,8 @@ Fixes:
* :doc:`/plugins/duplicates`: Fix a crash when merging items. :bug:`1699`
* :doc:`/plugins/smartplaylist`: More gracefully handle malformed queries and
missing configuration.
* Fix a crash with some files with unreadable iTunes SoundCheck metadata.
:bug:`1666`
.. _Emby Server: http://emby.media

Binary file not shown.

View file

@ -89,6 +89,13 @@ class EdgeTest(unittest.TestCase):
beets.mediafile._image_mime_type(jpg_data),
'image/jpeg')
def test_soundcheck_non_ascii(self):
# Make sure we don't crash when the iTunes SoundCheck field contains
# non-ASCII binary data.
f = beets.mediafile.MediaFile(os.path.join(_common.RSRC,
'soundcheck-nonascii.m4a'))
self.assertEqual(f.rg_track_gain, 0.0)
class InvalidValueToleranceTest(unittest.TestCase):
@ -269,19 +276,19 @@ class SoundCheckTest(unittest.TestCase):
self.assertEqual(peak, 1.0)
def test_decode_zero(self):
data = u' 80000000 80000000 00000000 00000000 00000000 00000000 ' \
u'00000000 00000000 00000000 00000000'
data = b' 80000000 80000000 00000000 00000000 00000000 00000000 ' \
b'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')
gain, peak = beets.mediafile._sc_decode(b'foo')
self.assertEqual(gain, 0.0)
self.assertEqual(peak, 0.0)
def test_special_characters(self):
gain, peak = beets.mediafile._sc_decode(u'caf\xe9')
gain, peak = beets.mediafile._sc_decode(u'caf\xe9'.encode('utf8'))
self.assertEqual(gain, 0.0)
self.assertEqual(peak, 0.0)