id3v2: re-fix handling of v2.4 extended headers
authorEdward Hervey <edward@centricular.com>
Mon, 12 Feb 2018 15:26:01 +0000 (16:26 +0100)
committerTim-Philipp Müller <tim@centricular.com>
Thu, 1 Mar 2018 12:42:10 +0000 (12:42 +0000)
The various id3v2 specs handle the extended header sizes differently
(because hey, it wouldn't be fun otherwise).

http://id3.org/id3v2.3.0 states:
"Where the 'Extended header size', currently 6 or 10 bytes, excludes
 itself."

http://id3.org/id3v2.4.0-structure states:
  Extended header size   4 * %0xxxxxxx
     Number of flag bytes       $01
     Extended Flags             $xx

   Where the 'Extended header size' is the size of the whole extended
   header, stored as a 32 bit synchsafe integer. An extended header can
   thus never have a size of fewer than six bytes.

So in id3v2.4.0 it's the *whole* extended header size (a-la ISOBMFF
atom), whereas in id3v2.3.0 it's the extended header size *excluding*
those 4 initial bytes.

And for other versions, god knows..

Fixes regression introduced in commit da607005.

https://bugzilla.gnome.org/show_bug.cgi?id=792983

gst-libs/gst/tag/id3v2.c

index 4d9a11f..3f351c9 100644 (file)
@@ -447,8 +447,30 @@ id3v2_frames_to_tag_list (ID3TagsWorking * work, guint size)
   /* Extended header if present */
   if (work->hdr.flags & ID3V2_HDR_FLAG_EXTHDR) {
     work->hdr.ext_hdr_size = id3v2_read_synch_uint (work->hdr.frame_data, 4);
+
+    /* In id3v2.4.x the header size is the size of the *whole*
+     * extended header.
+     * In id3v2.3.x the header size does *not* include itself.
+     * In older versions it's undefined but let's assume it follow 2.3.x
+     */
+    switch (ID3V2_VER_MAJOR (work->hdr.version)) {
+      case 0:
+      case 1:
+      case 2:
+      case 3:
+        work->hdr.ext_hdr_size += 4;
+        break;
+      case 4:
+        break;
+      default:
+        GST_WARNING
+            ("Don't know how to handled Extended Header for this id3 version");
+        break;
+    }
+    GST_LOG ("extended header size %d", work->hdr.ext_hdr_size);
+
     if (work->hdr.ext_hdr_size < 6 ||
-        (work->hdr.ext_hdr_size + 4) > work->hdr.frame_data_size) {
+        work->hdr.ext_hdr_size > work->hdr.frame_data_size) {
       GST_DEBUG ("Invalid extended header. Broken tag");
       return FALSE;
     }
@@ -458,10 +480,9 @@ id3v2_frames_to_tag_list (ID3TagsWorking * work, guint size)
           ("Tag claims extended header, but doesn't have enough bytes. Broken tag");
       return FALSE;
     }
-
     work->hdr.ext_flag_data = work->hdr.frame_data + 5;
-    work->hdr.frame_data += work->hdr.ext_hdr_size + 4;
-    work->hdr.frame_data_size -= work->hdr.ext_hdr_size + 4;
+    work->hdr.frame_data += work->hdr.ext_hdr_size;
+    work->hdr.frame_data_size -= work->hdr.ext_hdr_size;
   }
 
   frame_hdr_size = id3v2_frame_hdr_size (work->hdr.version);