[AudioToolbox] MP4AudioFile::Close crashes writing large files
| Originator: | jeremyw.sherman | ||
| Number: | rdar://7230346 | Date Originated: | 16-Sep-2009 08:25 PM |
| Status: | Duplicate/7100093 | Resolved: | |
| Product: | Mac OS X | Product Version: | 10.6/10A432 |
| Classification: | Crash/Hang/Data Loss | Reproducible: | Always |
Summary: Calling ExtAudioFileDispose() on a sufficiently large MP4 audio file causes a crash. All crash reports have the same final several stack frames within the AudioToolbox. The salient details are: * ExtAudioFileDispose() calls AudioFileClose() * AudioFileClose() calls MP4AudioFile::Close() * As part of closing the mp4 file, MP4AudioFile::FillGaplessString() is called * MP4AudioFile::FillGaplessString() calls UInt32ToHexString with a sufficiently large value (value >= 0x10000000; see NOTES below) * UInt32ToHexString() calls sprintf() with a too-small stack-allocated buffer * At the end of UInt32ToHexString(), __stack_chk_guard is found to have been altered, and __stack_chk_fail() is called. * __stack_chk_fail() logs a message and calls __abort(), which terminates the process. See NOTES for the corresponding excerpt from a crash report and the attached crash reports for all details. This bug affects the AudioToolbox framework distributed with both Mac OS X 10.6 and 10.6.1. Steps to Reproduce: 1. Download ProfCast (see http://www.profcast.com/downloads/) 2. Install ProfCast. 3. Launch ProfCast. 4. Select Create a New Recording from the initial window (or hit Cmd-N, or choose File > New Recording). 5. Click the Start Recording button in the upper left portion of the window that appears. 6. Record for a long time – 2 hours works, 45 minutes does not. 7. Click "Pause Recording". Expected Results: Recording pauses and the button changes to say "Resume Recording". Clicking the button resumes recording. Actual Results: The application crashes while attempting to write the audio file. The audio file is incomplete and unusable, leading to total data loss. Regression: The code involved has worked fine for years for users running Mac OS X 10.4 and 10.5. MP4AudioFile::FillGaplessString and UInt32ToHexString do not exist in Mac OS X 10.5's AudioToolbox framework. This is a new bug introduced with Mac OS X 10.6 and still present in Mac OS X 10.6.1. Notes: Since upgrading to Mac OS X 10.6, some users of ProfCast have reported crashes leading to loss of the entire recording when they pause recording. Their crash reports are all due to this issue. This is a serious problem for institutional users of ProfCast who rely on the application to record lectures or other events. One workaround might be breaking up a long recording session into several smaller sessions, but this is less than ideal. The crash report stack frames within the AudioToolbox are these: Thread 0 Crashed: Dispatch queue: com.apple.main-thread 0 libSystem.B.dylib 0x965e0972 __kill + 10 1 libSystem.B.dylib 0x965e0964 kill$UNIX2003 + 32 2 libSystem.B.dylib 0x96673ba5 raise + 26 3 libSystem.B.dylib 0x96689bf1 __abort + 124 4 libSystem.B.dylib 0x9666c934 release_file_streams_for_task + 0 5 ....audio.toolbox.AudioToolbox 0x98267497 UInt32ToHexString(char*, unsigned long, unsigned long) + 183 6 ....audio.toolbox.AudioToolbox 0x98267556 MP4AudioFile::FillGaplessString(char*) + 110 7 ....audio.toolbox.AudioToolbox 0x9826a3ed MP4AudioFile::Close() + 627 8 ....audio.toolbox.AudioToolbox 0x981c7a25 AudioFileClose + 77 9 ....audio.toolbox.AudioToolbox 0x9822aef6 ExtAudioFile::Close() + 206 10 ....audio.toolbox.AudioToolbox 0x9822b03e ExtAudioFile::~ExtAudioFile() + 40 11 ....audio.toolbox.AudioToolbox 0x9822089c XExtAudioFile::~XExtAudioFile() + 92 12 ....audio.toolbox.AudioToolbox 0x98220554 ExtAudioFileDispose + 37 Note that release_file_streams_for_task + 0 is the instruction following the last instruction of __stack_chk_fail, which jumps directly to __abort and never returns. The stack check failure in UInt32ToHexString() is easy to trigger directly. It occurs whenever the most-significant half-byte of the UInt32 value supplied for conversion to a hex string is non-null, that is, for all UInt32 values >= 0x10000000 (1 + 7 zeros). This appears to be because the function supplies an 8-byte stack buffer to sprintf together with a "%X" format string. The crashing values require 9 characters: 8 characters to represent the value itself plus 1 string-final NUL byte. Using a 9-byte buffer in UInt32ToHexString() would fix the problem. Using snprintf() instead of sprintf() would mask the problem by failing to write the least significant hex digit. Attachments: * Crash Reports.zip: 4 different crash reports encountered by users of ProfCast, 3 under 10.6.0 and 1 under 10.6.1 * smash_test.zip: source code demonstrating UInt32ToHexString's stack-smashing and a crash report produced under 10.6.1 by compiling and running a messier ancestor of the supplied source code Calling UInt32ToHexString(buffer, buffer_length, 0x10000000) is enough to trigger the crash, but getting access to UInt32ToHexString, a private symbol, requires jumping through some hoops.
Comments
Please note: Reports posted here will not necessarily be seen by Apple. All problems should be submitted at bugreport.apple.com before they are posted here. Please only post information for Radars that you have filed yourself, and please do not include Apple confidential information in your posts. Thank you!
Duplicates rdar://problem/7226263, "Crash in ExtAudioFileDispose".
smash.mm
Email referenced original bug id of 7226263, but duplicate number in the status line differs (7100093, as reported in the Radar info here).