diff --git a/libavformat/mov.c b/libavformat/mov.c index 278dec6765..444aca5235 100644 --- a/libavformat/mov.c +++ b/libavformat/mov.c @@ -6650,38 +6650,6 @@ finish: return ret; } -/** - * Tries to read the given number of bytes from the stream and puts it in a - * newly allocated buffer. This reads in small chunks to avoid allocating large - * memory if the file contains an invalid/malicious size value. - */ -static int mov_try_read_block(AVIOContext *pb, size_t size, uint8_t **data) -{ - const unsigned int block_size = 1024 * 1024; - uint8_t *buffer = NULL; - unsigned int alloc_size = 0, offset = 0; - while (offset < size) { - unsigned int new_size = - alloc_size >= INT_MAX - block_size ? INT_MAX : alloc_size + block_size; - uint8_t *new_buffer = av_fast_realloc(buffer, &alloc_size, new_size); - unsigned int to_read = FFMIN(size, alloc_size) - offset; - if (!new_buffer) { - av_free(buffer); - return AVERROR(ENOMEM); - } - buffer = new_buffer; - - if (avio_read(pb, buffer + offset, to_read) != to_read) { - av_free(buffer); - return AVERROR_INVALIDDATA; - } - offset += to_read; - } - - *data = buffer; - return 0; -} - static int mov_read_saiz(MOVContext *c, AVIOContext *pb, MOVAtom atom) { MOVEncryptionIndex *encryption_index; @@ -6737,15 +6705,24 @@ static int mov_read_saiz(MOVContext *c, AVIOContext *pb, MOVAtom atom) encryption_index->auxiliary_info_default_size = avio_r8(pb); sample_count = avio_rb32(pb); - encryption_index->auxiliary_info_sample_count = sample_count; if (encryption_index->auxiliary_info_default_size == 0) { - ret = mov_try_read_block(pb, sample_count, &encryption_index->auxiliary_info_sizes); - if (ret < 0) { - av_log(c->fc, AV_LOG_ERROR, "Failed to read the auxiliary info\n"); + encryption_index->auxiliary_info_sizes = av_malloc(sample_count); + if (!encryption_index->auxiliary_info_sizes) + return AVERROR(ENOMEM); + + ret = avio_read(pb, encryption_index->auxiliary_info_sizes, sample_count); + if (ret != sample_count) { + av_freep(&encryption_index->auxiliary_info_sizes); + + if (ret >= 0) + ret = AVERROR_INVALIDDATA; + av_log(c->fc, AV_LOG_ERROR, "Failed to read the auxiliary info, %s\n", + av_err2str(ret)); return ret; } } + encryption_index->auxiliary_info_sample_count = sample_count; if (encryption_index->auxiliary_offsets_count) { return mov_parse_auxiliary_info(c, sc, pb, encryption_index); @@ -6914,9 +6891,19 @@ static int mov_read_pssh(MOVContext *c, AVIOContext *pb, MOVAtom atom) } extra_data_size = avio_rb32(pb); - ret = mov_try_read_block(pb, extra_data_size, &extra_data); - if (ret < 0) + extra_data = av_malloc(extra_data_size); + if (!extra_data) { + ret = AVERROR(ENOMEM); goto finish; + } + ret = avio_read(pb, extra_data, extra_data_size); + if (ret != extra_data_size) { + av_free(extra_data); + + if (ret >= 0) + ret = AVERROR_INVALIDDATA; + goto finish; + } av_freep(&info->data); // malloc(0) may still allocate something. info->data = extra_data;