[PATCH] Mp4: added and updated sanity checks for "end" handling

Maxim Dounin mdounin at mdounin.ru
Tue Aug 20 02:18:03 UTC 2024


# HG changeset patch
# User Maxim Dounin <mdounin at 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;



More information about the nginx-devel mailing list