diff options
-rw-r--r-- | ChangeLog | 3 | ||||
-rw-r--r-- | src/audio_dec/xine_lpcm_decoder.c | 26 | ||||
-rw-r--r-- | src/demuxers/demux_4xm.c | 2 | ||||
-rw-r--r-- | src/demuxers/demux_aiff.c | 35 | ||||
-rw-r--r-- | src/demuxers/demux_avi.c | 10 | ||||
-rw-r--r-- | src/demuxers/demux_flac.c | 2 | ||||
-rw-r--r-- | src/demuxers/demux_iff.c | 10 | ||||
-rw-r--r-- | src/demuxers/demux_ipmovie.c | 5 | ||||
-rw-r--r-- | src/demuxers/demux_qt.c | 29 | ||||
-rw-r--r-- | src/demuxers/demux_realaudio.c | 2 | ||||
-rw-r--r-- | src/demuxers/demux_wav.c | 2 |
11 files changed, 113 insertions, 13 deletions
@@ -71,6 +71,9 @@ xine-lib (1.1.11.1) 2008-??-?? possibly execute arbitrary code. (CVE-2008-1482) * Added a few more memory allocation checks to the above demuxers. * WAV file playback fix: don't assume that the first chunk is "fmt ". + * Don't try to play partial 24-bit AIFF frames (decoder would lose data). + * Fixed AIFF comment chunk handling and sample rate reading. + * LPCM fixes: input over-reading, conversion of 24-bit samples. xine-lib (1.1.11) 2008-03-19 * Security fixes: diff --git a/src/audio_dec/xine_lpcm_decoder.c b/src/audio_dec/xine_lpcm_decoder.c index e84b112f4..83043cec9 100644 --- a/src/audio_dec/xine_lpcm_decoder.c +++ b/src/audio_dec/xine_lpcm_decoder.c @@ -192,18 +192,34 @@ static void lpcm_decode_data (audio_decoder_t *this_gen, buf_element_t *buf) { uint8_t *d = (uint8_t *)audio_buffer->mem; int n = buf->size; - while (n >= 0) { + while (n >= 3) { if ( stream_be ) { - *d++ = s[0]; - *d++ = s[1]; + if ( stream_be == this->cpu_be ) { + *d++ = s[0]; + *d++ = s[1]; + } else { + *d++ = s[1]; + *d++ = s[0]; + } } else { - *d++ = s[1]; - *d++ = s[2]; + if ( stream_be == this->cpu_be ) { + *d++ = s[1]; + *d++ = s[2]; + } + else + { + *d++ = s[2]; + *d++ = s[1]; + } } s += 3; n -= 3; } + + if ( (d - (uint8_t*)audio_buffer->mem)/2*3 < buf->size ) + xprintf(this->stream->xine, XINE_VERBOSITY_DEBUG, "lpcm_decoder: lost %i bytes\n", (int)(buf->size - (d - (uint8_t*)audio_buffer->mem))/2*3); + } else { memcpy (audio_buffer->mem, sample_buffer, buf->size); } diff --git a/src/demuxers/demux_4xm.c b/src/demuxers/demux_4xm.c index 6256cb042..264806421 100644 --- a/src/demuxers/demux_4xm.c +++ b/src/demuxers/demux_4xm.c @@ -159,7 +159,7 @@ static int open_fourxm_file(demux_fourxm_t *fourxm) { /* read the whole header */ header_size = _X_LE_32(&preview[4]) - 4; header = xine_xmalloc(header_size); - if (fourxm->input->read(fourxm->input, header, header_size) != header_size) { + if (!header || fourxm->input->read(fourxm->input, header, header_size) != header_size) { free(header); return 0; } diff --git a/src/demuxers/demux_aiff.c b/src/demuxers/demux_aiff.c index 51bc624e3..06ff65680 100644 --- a/src/demuxers/demux_aiff.c +++ b/src/demuxers/demux_aiff.c @@ -46,6 +46,10 @@ #define COMM_TAG FOURCC_TAG('C', 'O', 'M', 'M') #define SSND_TAG FOURCC_TAG('S', 'S', 'N', 'D') #define APCM_TAG FOURCC_TAG('A', 'P', 'C', 'M') +#define NAME_TAG FOURCC_TAG('N', 'A', 'M', 'E') +#define AUTH_TAG FOURCC_TAG('A', 'U', 'T', 'H') +#define COPY_TAG FOURCC_TAG('(', 'c', ')', ' ') +#define ANNO_TAG FOURCC_TAG('A', 'N', 'N', 'O') #define PREAMBLE_SIZE 8 #define AIFF_SIGNATURE_SIZE 12 @@ -80,6 +84,24 @@ typedef struct { demux_class_t demux_class; } demux_aiff_class_t; +/* converts IEEE 80bit extended into int, based on FFMPEG code */ +int extended_to_int(const unsigned char p[10]) +{ + uint64_t m = 0; + int e, i; + + for (i = 0; i < 8; i++) + m = (m<<8) + p[2+i];; + e = (((int)p[0]&0x7f)<<8) | p[1]; + if (e == 0x7fff && m) + return 0.0/0.0; + e -= 16383 + 63; + + if (p[0]&0x80) + m= -m; + return (int) ldexp(m, e); +} + /* returns 1 if the AIFF file was opened successfully, 0 otherwise */ static int open_aiff_file(demux_aiff_t *this) { @@ -87,6 +109,7 @@ static int open_aiff_file(demux_aiff_t *this) { unsigned char preamble[PREAMBLE_SIZE]; unsigned int chunk_type; unsigned int chunk_size; + unsigned char extended_sample_rate[10]; if (_x_demux_read_header(this->input, signature, AIFF_SIGNATURE_SIZE) != AIFF_SIGNATURE_SIZE) return 0; @@ -135,7 +158,8 @@ static int open_aiff_file(demux_aiff_t *this) { this->audio_channels = _X_BE_16(&buffer[0]); this->audio_frames = _X_BE_32(&buffer[2]); this->audio_bits = _X_BE_16(&buffer[6]); - this->audio_sample_rate = _X_BE_16(&buffer[0x0A]); + memcpy(&extended_sample_rate, &buffer[8], sizeof(extended_sample_rate)); + this->audio_sample_rate = extended_to_int(extended_sample_rate); this->audio_bytes_per_second = this->audio_channels * (this->audio_bits / 8) * this->audio_sample_rate; @@ -150,11 +174,18 @@ static int open_aiff_file(demux_aiff_t *this) { (this->audio_bits / 8); this->running_time = (this->audio_frames / this->audio_sample_rate) * 1000; - this->audio_block_align = PCM_BLOCK_ALIGN; + /* we should send only complete frames to decoder, as it + * doesn't handle underconsumption yet */ + this->audio_block_align = PCM_BLOCK_ALIGN - PCM_BLOCK_ALIGN % (this->audio_bits / 8 * this->audio_channels); break; } else { + /* if chunk contains metadata, it will be word-aligned (as seen at sox and ffmpeg) */ + if ( ((chunk_type == NAME_TAG) || (chunk_type==AUTH_TAG) || + (chunk_type == COPY_TAG) || (chunk_type==ANNO_TAG)) && (chunk_size&1)) + chunk_size++; + /* unrecognized; skip it */ this->input->seek(this->input, chunk_size, SEEK_CUR); } diff --git a/src/demuxers/demux_avi.c b/src/demuxers/demux_avi.c index 27dfce443..e06caf94f 100644 --- a/src/demuxers/demux_avi.c +++ b/src/demuxers/demux_avi.c @@ -973,6 +973,10 @@ static avi_t *AVI_init(demux_avi_t *this) { xine_waveformatex *wavex; wavex = (xine_waveformatex *)malloc(n); + if (!wavex) { + this->AVI_errno = AVI_ERR_NO_MEM; + return 0; + } memcpy((void *)wavex, hdrl_data+i, n); _x_waveformatex_le2me( wavex ); @@ -1237,6 +1241,9 @@ static avi_t *AVI_init(demux_avi_t *this) { /* read from file */ chunk_start = en = malloc (AVI->video_superindex->aIndex[j].dwSize+hdrl_len); + if (!chunk_start) + ERR_EXIT(AVI_ERR_NO_MEM); + if (this->input->seek(this->input, AVI->video_superindex->aIndex[j].qwOffset, SEEK_SET) == (off_t)-1) { lprintf("cannot seek to 0x%" PRIx64 "\n", AVI->video_superindex->aIndex[j].qwOffset); free(chunk_start); @@ -1308,6 +1315,9 @@ static avi_t *AVI_init(demux_avi_t *this) { /* read from file */ chunk_start = en = malloc (audio->audio_superindex->aIndex[j].dwSize+hdrl_len); + if (!chunk_start) + ERR_EXIT(AVI_ERR_NO_MEM); + if (this->input->seek(this->input, audio->audio_superindex->aIndex[j].qwOffset, SEEK_SET) == (off_t)-1) { lprintf("cannot seek to 0x%" PRIx64 "\n", audio->audio_superindex->aIndex[j].qwOffset); free(chunk_start); diff --git a/src/demuxers/demux_flac.c b/src/demuxers/demux_flac.c index ed974a69c..94c599562 100644 --- a/src/demuxers/demux_flac.c +++ b/src/demuxers/demux_flac.c @@ -166,6 +166,8 @@ static int open_flac_file(demux_flac_t *flac) { flac->seekpoint_count = block_length / FLAC_SEEKPOINT_SIZE; flac->seekpoints = xine_xcalloc(flac->seekpoint_count, sizeof(flac_seekpoint_t)); + if (flac->seekpoint_count && !flac->seekpoints) + return 0; for (i = 0; i < flac->seekpoint_count; i++) { if (flac->input->read(flac->input, buffer, FLAC_SEEKPOINT_SIZE) != FLAC_SEEKPOINT_SIZE) return 0; diff --git a/src/demuxers/demux_iff.c b/src/demuxers/demux_iff.c index 665d29cd2..dcef148b4 100644 --- a/src/demuxers/demux_iff.c +++ b/src/demuxers/demux_iff.c @@ -401,7 +401,7 @@ static int read_iff_chunk(demux_iff_t *this) { this->cmap_num = junk_size / PIC_SIZE_OF_COLOR_REGISTER; this->cmap = (ColorRegister *)xine_xmalloc(junk_size); this->video_send_palette = 1; - if (this->input->read(this->input, (char *)this->cmap, junk_size) != junk_size) + if (!this->cmap || this->input->read(this->input, (char *)this->cmap, junk_size) != junk_size) return 0; break; case IFF_GRAB_CHUNK: @@ -709,11 +709,19 @@ static int demux_iff_send_chunk(demux_plugin_t *this_gen) { /* load the whole chunk into the buffer */ if (this->audio_buffer_filled == 0) { if (this->audio_interleave_buffer_size > 0) + { this->audio_interleave_buffer = xine_xmalloc(this->audio_interleave_buffer_size); + if (!this->audio_interleave_buffer) + return this->status = DEMUX_FINISHED; + } if (this->audio_read_buffer_size > 0) + { this->audio_read_buffer = xine_xmalloc(this->audio_read_buffer_size); + if (!this->audio_read_buffer) + return this->status = DEMUX_FINISHED; + } if (this->audio_read_buffer) { if (this->input->read(this->input, this->audio_read_buffer, this->data_size) != this->data_size) { diff --git a/src/demuxers/demux_ipmovie.c b/src/demuxers/demux_ipmovie.c index 4d08af6fa..88fd70811 100644 --- a/src/demuxers/demux_ipmovie.c +++ b/src/demuxers/demux_ipmovie.c @@ -283,9 +283,10 @@ static int process_ipmovie_chunk(demux_ipmovie_t *this) { this->bih.biWidth = _X_LE_16(&scratch[0]) * 8; this->bih.biHeight = _X_LE_16(&scratch[2]) * 8; /* set up staging area for decode map */ - this->decode_map_size = (this->bih.biWidth * this->bih.biHeight) / - (8 * 8) / 2; + this->decode_map_size = (this->bih.biWidth / 8) * (this->bih.biHeight / 8) / 2; this->decode_map = xine_xmalloc(this->decode_map_size); + if (!this->decode_map) + this->status = DEMUX_FINISHED; lprintf("video resolution: %d x %d\n", this->bih.biWidth, this->bih.biHeight); break; diff --git a/src/demuxers/demux_qt.c b/src/demuxers/demux_qt.c index 15b2773eb..9207a97e0 100644 --- a/src/demuxers/demux_qt.c +++ b/src/demuxers/demux_qt.c @@ -939,6 +939,11 @@ static qt_error parse_trak_atom (qt_trak *trak, const uint32_t current_atom_size = _X_BE_32(&trak_atom[i - 4]); const qt_atom current_atom = _X_BE_32(&trak_atom[i]); + if (current_atom_size > trak_atom_size - i) { + last_error = QT_NOT_A_VALID_FILE; + goto free_trak; + } + switch(current_atom) { case TKHD_ATOM: trak->flags = _X_BE_16(&trak_atom[i + 6]); @@ -1025,6 +1030,10 @@ static qt_error parse_trak_atom (qt_trak *trak, trak->stsd_atoms[k].video.properties_atom_size = current_stsd_atom_size - 4; trak->stsd_atoms[k].video.properties_atom = xine_xmalloc(trak->stsd_atoms[k].video.properties_atom_size); + if (!trak->stsd_atoms[k].video.properties_atom) { + last_error = QT_NO_MEMORY; + goto free_trak; + } memcpy(trak->stsd_atoms[k].video.properties_atom, &trak_atom[atom_pos], trak->stsd_atoms[k].video.properties_atom_size); @@ -1164,6 +1173,10 @@ static qt_error parse_trak_atom (qt_trak *trak, trak->stsd_atoms[k].audio.properties_atom_size = current_stsd_atom_size - 4; trak->stsd_atoms[k].audio.properties_atom = xine_xmalloc(trak->stsd_atoms[k].audio.properties_atom_size); + if (!trak->stsd_atoms[k].audio.properties_atom) { + last_error = QT_NO_MEMORY; + goto free_trak; + } memcpy(trak->stsd_atoms[k].audio.properties_atom, &trak_atom[atom_pos], trak->stsd_atoms[k].audio.properties_atom_size); @@ -1280,6 +1293,10 @@ static qt_error parse_trak_atom (qt_trak *trak, trak->stsd_atoms[k].audio.properties_atom_size = 36; trak->stsd_atoms[k].audio.properties_atom = xine_xmalloc(trak->stsd_atoms[k].audio.properties_atom_size); + if (!trak->stsd_atoms[k].audio.properties_atom) { + last_error = QT_NO_MEMORY; + goto free_trak; + } memcpy(trak->stsd_atoms[k].audio.properties_atom, &trak_atom[atom_pos + 0x20], trak->stsd_atoms[k].audio.properties_atom_size); @@ -1301,6 +1318,10 @@ static qt_error parse_trak_atom (qt_trak *trak, (current_atom_size >= (0x4C + wave_size))) { trak->stsd_atoms[k].audio.wave_size = wave_size; trak->stsd_atoms[k].audio.wave = xine_xmalloc(wave_size); + if (!trak->stsd_atoms[k].audio.wave) { + last_error = QT_NO_MEMORY; + goto free_trak; + } memcpy(trak->stsd_atoms[k].audio.wave, &trak_atom[atom_pos + 0x4C], wave_size); _x_waveformatex_le2me(trak->stsd_atoms[k].audio.wave); @@ -1370,8 +1391,16 @@ static qt_error parse_trak_atom (qt_trak *trak, j += mp4_read_descr_len( &trak_atom[j], &len ); debug_atom_load(" decoder config is %d (0x%X) bytes long\n", len, len); + if (len > current_atom_size - (j - i)) { + last_error = QT_NOT_A_VALID_FILE; + goto free_trak; + } trak->decoder_config = realloc(trak->decoder_config, len); trak->decoder_config_len = len; + if (!trak->decoder_config) { + last_error = QT_NO_MEMORY; + goto free_trak; + } memcpy(trak->decoder_config,&trak_atom[j],len); } } diff --git a/src/demuxers/demux_realaudio.c b/src/demuxers/demux_realaudio.c index 732ddfcc4..7ee608c83 100644 --- a/src/demuxers/demux_realaudio.c +++ b/src/demuxers/demux_realaudio.c @@ -103,7 +103,7 @@ static int open_ra_file(demux_ra_t *this) { /* allocate for and read header data */ this->header = xine_xmalloc(this->header_size); - if (_x_demux_read_header(this->input, this->header, this->header_size) != this->header_size) { + if (!this->header || _x_demux_read_header(this->input, this->header, this->header_size) != this->header_size) { xprintf(this->stream->xine, XINE_VERBOSITY_DEBUG, "demux_realaudio: unable to read header\n"); free(this->header); return 0; diff --git a/src/demuxers/demux_wav.c b/src/demuxers/demux_wav.c index 0c17c836a..2beb43291 100644 --- a/src/demuxers/demux_wav.c +++ b/src/demuxers/demux_wav.c @@ -131,7 +131,7 @@ static int open_wav_file(demux_wav_t *this) { this->input->seek(this->input, wave_pos, SEEK_SET); this->wave = xine_xmalloc( this->wave_size ); - if (this->input->read(this->input, (void *)this->wave, this->wave_size) != + if (!this->wave || this->input->read(this->input, (void *)this->wave, this->wave_size) != this->wave_size) { free (this->wave); return 0; |