Title: SIGSEGV in mpg123 v1.23.7
Brought to you by:
sobukus
Summary: Segfault (unsigned long underflow) in mpg123 when parsing malformed ID3 header size in id3.c:755:765. Discovered by : Han Lee & Jerold Hoong - beep.mp3 id3 header : 4944 3303 0000 0000 0026 - crash.mp3 id3 header : 4944 3303 0040 0000 0006 ---------------------------- RUN with legit beep.mp3 file ---------------------------- Breakpoint 1, INT123_parse_new_id3 (fr=fr@entry=0x7421b0, first4bytes=<optimized out>) at src/libmpg123/id3.c:755 755 while(tagpos < length-10) /* I want to read at least a full header */ (gdb) print tagpos $1 = 0 (gdb) print length $2 = 38 (gdb) print length-10 $3 = 28 (gdb) ---------------------------- RUN with malformed crash.mp3 ---------------------------- Breakpoint 1, INT123_parse_new_id3 (fr=fr@entry=0x7421c0, first4bytes=<optimized out>) at src/libmpg123/id3.c:755 755 while(tagpos < length-10) /* I want to read at least a full header */ (gdb) print tagpos $1 = 1414546737 (gdb) print length $2 = 6 (gdb) print length-10 $3 = 18446744073709551612 (gdb) n Breakpoint 2, INT123_parse_new_id3 (fr=fr@entry=0x7421b0, first4bytes=<optimized out>) at src/libmpg123/id3.c:765 765 if( !( ((tagdata[tagpos+i] > 47) && (tagdata[tagpos+i] < 58)) (gdb) n 759 int head_part = fr->id3v2.version == 2 ? 3 : 4; /* bytes of frame title and of framesize value */ (gdb) n 765 if( !( ((tagdata[tagpos+i] > 47) && (tagdata[tagpos+i] < 58)) (gdb) n Program received signal SIGSEGV, Segmentation fault. INT123_parse_new_id3 (fr=fr@entry=0x7421b0, first4bytes=<optimized out>) at src/libmpg123/id3.c:765 765 if( !( ((tagdata[tagpos+i] > 47) && (tagdata[tagpos+i] < 58)) (gdb) bt #0 INT123_parse_new_id3 (fr=fr@entry=0x7421b0, first4bytes=<optimized out>) at src/libmpg123/id3.c:765 #1 0x0000000000448ac3 in handle_id3v2 (newhead=<optimized out>, fr=0x7421b0) at src/libmpg123/parse.c:1071 #2 wetwork (newheadp=<optimized out>, fr=<optimized out>) at src/libmpg123/parse.c:1241 #3 INT123_read_frame (fr=fr@entry=0x7421b0) at src/libmpg123/parse.c:536 #4 0x0000000000493862 in get_next_frame (mh=0x7421b0) at src/libmpg123/libmpg123.c:623 #5 mpg123_decode_frame (mh=0x7421b0, num=num@entry=0x741968 <framenum>, audio=audio@entry=0x7fffffffe2e0, bytes=bytes@entry=0x7fffffffe2e8) at src/libmpg123/libmpg123.c:859 #6 0x000000000042ecc8 in play_frame () at src/mpg123.c:763 #7 0x0000000000406735 in main (sys_argc=<optimized out>, sys_argv=<optimized out>) at src/mpg123.c:1369 (gdb) -------- Analysis -------- Description: Access violation on source operand Short description: SourceAv (19/22) Hash: 6bd52e79e6017b9e236d4d9edea21a67.d278ec4c10e616aa909c08fc399072bd Exploitability Classification: UNKNOWN Explanation: The target crashed on an access violation at an address matching the source operand of the current instruction. This likely indicates a read access violation. Other tags: AccessViolation (21/22)
Oh dear … thanks for that detailed report. What a usual blunder that
was there from the beginning of ID3v2 parsing support in mpg123.
I prepared a release tarball with a verbose fix:
Would you please verify that it fixes this? Also, I will put this into
the announcement for a hotfix for any affected mpg123 release:
Can you confirm that it works, too? Just pick any random version since
0.60. I tested it with 0.60 and 1.12.2 . I want to give this quick fix
to distros shipping older versions than 1.23.x .
Looks like the length check fix in id3.c:726 is sufficient. Here is the output I get:
I have also tested the perl one-liner fix on versions 1.0.0, 1.4.3 and 1.11.0. It worked without any issues.
Thank you very much … announcing the release now.