mirror of
https://github.com/lieff/minimp3.git
synced 2026-10-28 08:36:26 +08:00
Fix seek truncation that can lead to OOB read in mp3dec_ex_read
This commit is contained in:
1 parent
f50682ba30
commit
7b590fdcfa
2 files changed
+50
-5
No files matched your search
+19
-5
@@ -757,8 +757,13 @@ int mp3dec_ex_seek(mp3dec_ex_t *dec, uint64_t position)
|
||||
dec->cur_sample = 0;
|
||||
goto do_exit;
|
||||
}
|
||||
if (dec->samples && position > dec->samples)
|
||||
position = dec->samples;
|
||||
dec->cur_sample = position;
|
||||
position += dec->start_delay;
|
||||
if (position > (UINT64_MAX - (uint64_t)dec->start_delay))
|
||||
position = UINT64_MAX;
|
||||
else
|
||||
position += dec->start_delay;
|
||||
if (0 == position)
|
||||
{ /* optimize seek to zero, no index needed */
|
||||
seek_zero:
|
||||
@@ -846,7 +851,12 @@ seek_zero:
|
||||
}
|
||||
}
|
||||
dec->offset = dec->index.frames[i].offset;
|
||||
dec->to_skip = position - dec->index.frames[i].sample;
|
||||
if (position > dec->index.frames[i].sample)
|
||||
{
|
||||
uint64_t to_skip64 = position - dec->index.frames[i].sample;
|
||||
dec->to_skip = (to_skip64 > (uint64_t)INT_MAX) ? INT_MAX : (int)to_skip64;
|
||||
} else
|
||||
dec->to_skip = 0;
|
||||
while ((i + 1) < dec->index.num_frames && !dec->index.frames[i].sample && !dec->index.frames[i + 1].sample)
|
||||
{ /* skip not decodable first frames */
|
||||
const uint8_t *hdr;
|
||||
@@ -860,7 +870,11 @@ seek_zero:
|
||||
return MP3D_E_IOERROR;
|
||||
} else
|
||||
hdr = dec->file.buffer + dec->index.frames[i].offset;
|
||||
dec->to_skip += hdr_frame_samples(hdr)*dec->info.channels;
|
||||
int frame_samples = hdr_frame_samples(hdr)*dec->info.channels;
|
||||
if (dec->to_skip > (INT_MAX - frame_samples))
|
||||
dec->to_skip = INT_MAX;
|
||||
else
|
||||
dec->to_skip += frame_samples;
|
||||
i++;
|
||||
}
|
||||
do_exit:
|
||||
@@ -938,7 +952,7 @@ return_e_decode:
|
||||
if (dec->buffer_samples)
|
||||
{
|
||||
dec->buffer_samples *= frame_info->channels;
|
||||
if (dec->to_skip)
|
||||
if (dec->to_skip > 0)
|
||||
{
|
||||
size_t skip = MINIMP3_MIN(dec->buffer_samples, dec->to_skip);
|
||||
dec->buffer_consumed += skip;
|
||||
@@ -952,7 +966,7 @@ return_e_decode:
|
||||
{
|
||||
goto return_e_decode;
|
||||
}
|
||||
} else if (dec->to_skip)
|
||||
} else if (dec->to_skip > 0)
|
||||
{ /* In mp3 decoding not always can start decode from any frame because of bit reservoir,
|
||||
count skip samples for such frames */
|
||||
int frame_samples = hdr_frame_samples(dec_buf)*frame_info->channels;
|
||||
|
||||
@@ -527,6 +527,37 @@ static int self_test(const char *input_file_name)
|
||||
ASSERT(0 == ret);
|
||||
mp3dec_ex_close(&dec);
|
||||
|
||||
{
|
||||
/* Regression: out-of-range sample seek must not corrupt to_skip and crash in mp3dec_ex_read(). */
|
||||
static const uint8_t seek_oob_buf[] = {
|
||||
0xff,0xfd,0x16,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
|
||||
0xa5,0xce,0xa7,0x8b,0xff,0xff,0x00,0x00,0x00,0x00,
|
||||
0x47,0x45,0x58,0x00,0xff,0xfd,0x18,0xd6,0x64,0x41,
|
||||
0xae,0xce,0xd6,0x97,0x8a,0x4e,0x18,0x8b,0x82,0xff,
|
||||
0xfd,0x18,0xd6,0x45,0x54,0x18,0x8b,0x82,0x47,0x45,
|
||||
0x58,0x00,0xff,0xfd,0x18,0xd6,0x64,0x41,0x50,0x45,
|
||||
0x54,0x41,0x01,0x18,0xd6,0x64,0x41,0x50,0x45,0x54,
|
||||
0x41,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x23,0xff,
|
||||
0xfd,0x18,0xd6,0x64,0x41,0x50,0x45,0x54,0x41,0x47,
|
||||
0x45,0x58,0x00,0xff,0xfd,0x18,0xd6
|
||||
};
|
||||
mp3d_sample_t pcm[MINIMP3_MAX_SAMPLES_PER_FRAME];
|
||||
size_t r, total = 0;
|
||||
ret = mp3dec_ex_open_buf(&dec, seek_oob_buf, sizeof(seek_oob_buf), MP3D_SEEK_TO_SAMPLE | MP3D_ALLOW_MONO_STEREO_TRANSITION);
|
||||
ASSERT(0 == ret);
|
||||
do
|
||||
{
|
||||
r = mp3dec_ex_read(&dec, pcm, MINIMP3_MAX_SAMPLES_PER_FRAME);
|
||||
total += r;
|
||||
} while (r);
|
||||
ASSERT(2304 == total);
|
||||
ret = mp3dec_ex_seek(&dec, 3888454656ULL);
|
||||
ASSERT(0 == ret);
|
||||
r = mp3dec_ex_read(&dec, pcm, MINIMP3_MAX_SAMPLES_PER_FRAME);
|
||||
ASSERT(0 == r);
|
||||
mp3dec_ex_close(&dec);
|
||||
}
|
||||
|
||||
ret = mp3dec_ex_open_cb(0, &io, MP3D_SEEK_TO_SAMPLE);
|
||||
ASSERT(MP3D_E_PARAM == ret);
|
||||
ret = mp3dec_ex_open_cb(&dec, 0, MP3D_SEEK_TO_SAMPLE);
|
||||
|
||||
Reference in new issue
Block a user