diff --git a/src/id3.c b/src/id3.c index bdd2800..9593567 100644 --- a/src/id3.c +++ b/src/id3.c @@ -272,12 +272,27 @@ _id3_parse_v2(id3info *id3) goto out; } - // tested with v2.3-ext-header.mp3 + // tested with v2.3-ext-header.mp3 & v2.4-ext-header.mp3 // We don't care about the value of the extended flags or CRC, so just read the size and skip it - ehsize = buffer_get_int(id3->buf); - // ehsize may be invalid, tested with v2.3-ext-header-invalid.mp3 + if (id3->version_major == 3) { + // v2.3: 'Extended header size' excludes itself + ehsize = buffer_get_int(id3->buf); + } + else { + // v2.4: 'Extended header size' includes itself, and is a synchsafe integer of 4 bytes + ehsize = buffer_get_syncsafe(id3->buf, 4); + // must be at least 4 bytes - tested with v2.4-ext-header-invalid-too-short.mp3 + if (ehsize < 4 ) { + warn("Error: Invalid ID3 extended header - too short (%s)\n", id3->file); + ret = 0; + goto out; + } + ehsize -= 4; // adjust to v2.3 basis + } + + // ehsize may be invalid, tested with v2.3-ext-header-invalid.mp3 & v2.4-ext-header-invalid.mp3 if (ehsize > id3->size_remain - 4) { warn("Error: Invalid ID3 extended header size (%s)\n", id3->file); ret = 0; diff --git a/t/mp3.t b/t/mp3.t index ed960ea..b6f860c 100644 --- a/t/mp3.t +++ b/t/mp3.t @@ -3,7 +3,7 @@ use strict; use Digest::MD5 qw(md5_hex); use File::Spec::Functions; use FindBin (); -use Test::More tests => 396; +use Test::More tests => 399; use Test::Warn; use Audio::Scan; @@ -1077,6 +1077,14 @@ eval { is( $tags->{TCON}, 'Blues', 'v2.3 extended header ok' ); } +# v2.4 extended header +{ + my $s = Audio::Scan->scan_tags( _f('v2.4-ext-header.mp3') ); + my $tags = $s->{tags}; + + is( $tags->{TCON}, 'Blues', 'v2.4 extended header ok' ); +} + # MCDI frame { my $s = Audio::Scan->scan( _f('v2.3-mcdi.mp3') ); @@ -1301,13 +1309,27 @@ eval { is( $info->{vbr}, 1, 'Xing without LAME marked as VBR ok' ); } -# File with extended header bit set but no extended header +# v2.3 file with extended header bit set but no extended header { warning_like { Audio::Scan->scan( _f('v2.3-ext-header-invalid.mp3') ); } [ qr/Error: Invalid ID3 extended header size/ ], 'v2.3 invalid extended header ok'; } +# v2.4 file with extended header bit set but invalid extended header size +{ + warning_like { Audio::Scan->scan( _f('v2.4-ext-header-invalid.mp3') ); } + [ qr/Error: Invalid ID3 extended header size/ ], + 'v2.4 invalid extended header ok'; +} + +# v2.4 file with extended header bit set but extended header too short +{ + warning_like { Audio::Scan->scan( _f('v2.4-ext-header-invalid-too-short.mp3') ); } + [ qr/Error: Invalid ID3 extended header - too short/ ], + 'v2.4 extended header too short ok'; +} + # Bug 15895, bad APE tag { my $s; diff --git a/t/mp3/v2.4-ext-header-invalid-too-short.mp3 b/t/mp3/v2.4-ext-header-invalid-too-short.mp3 new file mode 100755 index 0000000..516b235 Binary files /dev/null and b/t/mp3/v2.4-ext-header-invalid-too-short.mp3 differ diff --git a/t/mp3/v2.4-ext-header-invalid.mp3 b/t/mp3/v2.4-ext-header-invalid.mp3 new file mode 100755 index 0000000..305ebb8 Binary files /dev/null and b/t/mp3/v2.4-ext-header-invalid.mp3 differ diff --git a/t/mp3/v2.4-ext-header.mp3 b/t/mp3/v2.4-ext-header.mp3 new file mode 100755 index 0000000..8a3dd44 Binary files /dev/null and b/t/mp3/v2.4-ext-header.mp3 differ