Menu

#40 ArrayOutOfBoundsException in MP3File.writeTags()

open-accepted
nobody
None
6
2004-02-22
2004-02-21
Ron Smits
No

I found a condition in ID3v2Tag method getbytes where an
ArrayOutOfBoundsException occurs. Now I might be doing
something wrong here :)

Attached is a testcase in jar format. Rename an mp3
file to test.mp3 and run the program twice

Scenario:
Open an mp3 using MP3File remove all the tags and write
new tags. Like
this:

public void save() throws IOException,
NoMPEGFramesException,
ID3v2FormatException,
CorruptHeaderException{
MP3File f = new MP3File (filename,
MP3File.BOTH_TAGS);
f.removeTags(MP3File.EXISTING_TAGS_ONLY);
f.setAlbum (Album);
f.setArtist(Artist);
f.setTitle (Song);
f.writeTags();
}
The class where this is in does NOT go out of scope and
gets called a
second time. The application will crash with the
exception. I added some
debug code around the problem:

if (padding > 0) {
System.err.println ("padding: " + padding+" b: "
+ b.length+" bytesCopied: " + bytesCopied);
System.arraycopy(new byte[padding], 0, b,
bytesCopied, padding);
bytesCopied += padding;
}

This will show:
padding: 16 b: 67 bytesCopied: 67
Apparently it tries to add 16 bytes beyond the allotted
length of the b
[].

Discussion

  • Ron Smits

    Ron Smits - 2004-02-21

    testcase

     
  • Andreas Grunewald

    • priority: 5 --> 6
    • status: open --> pending-accepted
     
  • Andreas Grunewald

    Logged In: YES
    user_id=571171

    Ok i verified the Bug but i have not the time to solve it
    right away.
    Take look at the newest CVS. To reproduce run the JUnit
    test for this Bug.

     
  • Ron Smits

    Ron Smits - 2004-02-22
    • status: pending-accepted --> open-accepted
     
  • Ron Smits

    Ron Smits - 2004-02-22

    Logged In: YES
    user_id=215617

    After reading the ID3 specs and re-reading the source code,
    I think I have determined at least what the problem is.

    Somewhere the padding calculation goes bonkers.

    I made 3 very simple classes Read, Set and Remove. in
    MP3File I added a debug statement that will print the
    toString from ID3v2Tag
    Read will only open the test.mp3. this will cause the the
    info to be printed.
    Set will set a tag containing of artist, title and album.
    Album will be supplied on the command line.
    Remove will only open the file and remove the existing tags.

    I started with a mp3 file without tags:
    java Read:
    --
    ID3v2.3.0
    TagSize: 0 bytes
    Unsynchronisation: false
    Extended Header: false
    Experimental: false
    Footer: false
    Padding: 0 bytes
    TotalSize: 10 bytes
    --
    note that the totalsize comes NOT from the file but from the
    internal representation of the tag. also note that padding is 0

    Now write a tag (java Set 1, this will set the album to "1)
    and read it with Read again:
    --
    ID3v2.3.0
    TagSize: 54 bytes
    Unsynchronisation: false
    Extended Header: false
    Experimental: false
    Footer: false
    Padding: 0 bytes
    TotalSize: 64 bytes
    TALB
    TagAlterDiscard: false
    FileAlterDiscard: false
    ReadOnly: false
    Grouped: false
    Compressed: false
    Encrypted: false
    Unsynchronised: false
    LengthIndicator: false
    Data: 1
    TIT2
    TagAlterDiscard: false
    FileAlterDiscard: false
    ReadOnly: false
    Grouped: false
    Compressed: false
    Encrypted: false
    Unsynchronised: false
    LengthIndicator: false
    Data: The Letter
    TPE1
    TagAlterDiscard: false
    FileAlterDiscard: false
    ReadOnly: false
    Grouped: false
    Compressed: false
    Encrypted: false
    Unsynchronised: false
    LengthIndicator: false
    Data: Joe Cocker

    --
    Note that the total size 64 is the 54 bytes data plus the
    header this is correct.

    Now set another album using the Set class (java Set 2
    meaning set the album to "2")
    The program does not crash BUT look at the padding:
    --
    ID3v2.3.0
    TagSize: 54 bytes
    Unsynchronisation: false
    Extended Header: false
    Experimental: false
    Footer: false
    Padding: 353 bytes
    TotalSize: 64 bytes
    <rest of the output removed. TALB was set to 2>
    Where does the 353 come from?

    Running the Set program a third time will give the crash:
    --
    padding: 353 b: 64 bytesCopied: 64
    java.lang.ArrayIndexOutOfBoundsException
    at java.lang.System.arraycopy(Native Method)
    at helliker.id3.ID3v2Tag.getBytes(ID3v2Tag.java:374)
    at helliker.id3.ID3v2Tag.writeTag(ID3v2Tag.java:265)
    at helliker.id3.MP3File.writeTags(MP3File.java:478)
    at Set.save(Set.java:16)
    at Set.main(Set.java:28)
    --

    Continueing the search :)

     
  • Moritz Ringler

    Moritz Ringler - 2004-07-09

    Logged In: YES
    user_id=730046

    I've recently had a similar problem. IMHO
    padding = getUpdatedPadding();
    has to be called *before* getTotalSize() because
    getTotalSize() internally uses the padding property.
    You can achieve this by moving the above statement to the
    beginning of
    getBytes() as I've done here:
    http://tinyurl.com/2dxa6
    My latest revision, where I've indepently fixed bug 916695,
    too can be found at
    http://cvs.sourceforge.net/viewcvs.py/mp3dings/helliker.id3/ID3v2Tag.java?view=markup
    I hope this solves your problem (I haven't checked).

     
  • Moritz Ringler

    Moritz Ringler - 2004-07-09

    Logged In: YES
    user_id=730046

    Someone else had already solved this: see bug 681321

     

Log in to post a comment.