# HG changeset patch # User Maxim Dounin <mdou...@mdounin.ru> # Date 1724120272 -10800 # Tue Aug 20 05:17:52 2024 +0300 # Node ID 05355032b45dad2b2420592bb7dc77c0b05d1f4b # Parent cf73b65983c2d093f5b6651f8b45b9973a68e9f5 Mp4: added and updated sanity checks for "end" handling.
When handling incorrect data in ngx_http_mp4_crop_stsc_data(), trak->end_chunk_samples might end up being arbitrary large, leading to reading before the buffer in ngx_http_mp4_update_stsz_atom(). Fix is to check that trak->end_chunk_samples corresponds to a memory within the stsz atom data. For consistency, trak->start_chunk_samples is checked similarly. Similarly, trak->end_chunk might end up being smaller than trak->start_chunk, leading to reading memory after the buffer in ngx_http_mp4_update_stco_atom() and ngx_http_mp4_update_co64_atom(). Corresponding checks are updated to explicitly test (trak->end_chunk - trak->start_chunk) instead of just checking trak->end_chunk and assuming it is larger than trak->start_chunk. This is generally in line with existing checks of (trak->end_sample - trak->start_sample) in ngx_http_mp4_update_stsz_atom(), where trak->end_sample might also become smaller than trak->start_sample when handling incorrect data in ngx_http_mp4_crop_stts_data(). diff --git a/src/http/modules/ngx_http_mp4_module.c b/src/http/modules/ngx_http_mp4_module.c --- a/src/http/modules/ngx_http_mp4_module.c +++ b/src/http/modules/ngx_http_mp4_module.c @@ -3419,6 +3419,13 @@ ngx_http_mp4_update_stsz_atom(ngx_http_m data->pos += trak->start_sample * sizeof(uint32_t); end = (uint32_t *) data->pos; + if (trak->start_chunk_samples > trak->start_sample) { + ngx_log_error(NGX_LOG_ERR, mp4->file.log, 0, + "too many mp4 start chunk samples in \"%s\"", + mp4->file.name.data); + return NGX_ERROR; + } + for (pos = end - trak->start_chunk_samples; pos < end; pos++) { trak->start_chunk_samples_size += ngx_mp4_get_32value(pos); } @@ -3446,6 +3453,13 @@ ngx_http_mp4_update_stsz_atom(ngx_http_m data->last = data->pos + entries * sizeof(uint32_t); end = (uint32_t *) data->last; + if (trak->end_chunk_samples > entries) { + ngx_log_error(NGX_LOG_ERR, mp4->file.log, 0, + "too many mp4 end chunk samples in \"%s\"", + mp4->file.name.data); + return NGX_ERROR; + } + for (pos = end - trak->end_chunk_samples; pos < end; pos++) { trak->end_chunk_samples_size += ngx_mp4_get_32value(pos); } @@ -3612,7 +3626,9 @@ ngx_http_mp4_update_stco_atom(ngx_http_m if (mp4->length) { - if (trak->end_chunk > trak->chunks) { + if (trak->end_chunk - trak->start_chunk + > trak->chunks - trak->start_chunk) + { ngx_log_error(NGX_LOG_ERR, mp4->file.log, 0, "end time is out mp4 stco chunks in \"%s\"", mp4->file.name.data); @@ -3825,8 +3841,10 @@ ngx_http_mp4_update_co64_atom(ngx_http_m if (mp4->length) { - if (trak->end_chunk > trak->chunks) { - ngx_log_error(NGX_LOG_ERR, mp4->file.log, 0, + if (trak->end_chunk - trak->start_chunk + > trak->chunks - trak->start_chunk) + { + ngx_log_error(NGX_LOG_ALERT, mp4->file.log, 0, "end time is out mp4 co64 chunks in \"%s\"", mp4->file.name.data); return NGX_ERROR;