summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNGINX team <nginx@nginx.org>2012-04-12 13:05:40 +0000
committerJon Kolb <jon@b0g.us>2012-04-12 13:05:40 +0000
commit1554f54c85425c48afeaae58bf24aba352bed692 (patch)
tree80be10cdf234d2a68a131a9769f92998eede0f92
parentfc2138af6a178a6ae68b2f35bfaf7017412954d4 (diff)
downloadnginx-1.0.tar.gz
Changes with nginx 1.0.15 12 Apr 2012v1.0.15nginx-1.0
*) Security: specially crafted mp4 file might allow to overwrite memory locations in a worker process if the ngx_http_mp4_module was used, potentially resulting in arbitrary code execution (CVE-2012-2089). Thanks to Matthew Daley. *) Bugfix: in the ngx_http_mp4_module.
-rw-r--r--CHANGES10
-rw-r--r--CHANGES.ru11
-rw-r--r--src/core/nginx.h4
-rw-r--r--src/http/modules/ngx_http_mp4_module.c278
-rw-r--r--src/http/modules/perl/nginx.pm2
5 files changed, 234 insertions, 71 deletions
diff --git a/CHANGES b/CHANGES
index 3a9e0aa72..e5ceff6d1 100644
--- a/CHANGES
+++ b/CHANGES
@@ -1,4 +1,14 @@
+Changes with nginx 1.0.15 12 Apr 2012
+
+ *) Security: specially crafted mp4 file might allow to overwrite memory
+ locations in a worker process if the ngx_http_mp4_module was used,
+ potentially resulting in arbitrary code execution (CVE-2012-2089).
+ Thanks to Matthew Daley.
+
+ *) Bugfix: in the ngx_http_mp4_module.
+
+
Changes with nginx 1.0.14 15 Mar 2012
*) Security: content of previously freed memory might be sent to a
diff --git a/CHANGES.ru b/CHANGES.ru
index 50266386a..0bfe8f75a 100644
--- a/CHANGES.ru
+++ b/CHANGES.ru
@@ -1,4 +1,15 @@
+Изменения в nginx 1.0.15 12.04.2012
+
+ *) Безопасность: при обработке специально созданного mp4 файла модулем
+ ngx_http_mp4_module могли перезаписываться области памяти рабочего
+ процесса, что могло приводить к выполнению произвольного кода
+ (CVE-2012-2089).
+ Спасибо Matthew Daley.
+
+ *) Исправление: в модуле ngx_http_mp4_module.
+
+
Изменения в nginx 1.0.14 15.03.2012
*) Безопасность: содержимое ранее освобождённой памяти могло быть
diff --git a/src/core/nginx.h b/src/core/nginx.h
index dce94adfc..fdc2c925c 100644
--- a/src/core/nginx.h
+++ b/src/core/nginx.h
@@ -9,8 +9,8 @@
#define _NGINX_H_INCLUDED_
-#define nginx_version 1000014
-#define NGINX_VERSION "1.0.14"
+#define nginx_version 1000015
+#define NGINX_VERSION "1.0.15"
#define NGINX_VER "nginx/" NGINX_VERSION
#define NGINX_VAR "NGINX"
diff --git a/src/http/modules/ngx_http_mp4_module.c b/src/http/modules/ngx_http_mp4_module.c
index 816cc4c83..92dfbd411 100644
--- a/src/http/modules/ngx_http_mp4_module.c
+++ b/src/http/modules/ngx_http_mp4_module.c
@@ -156,6 +156,7 @@ typedef struct {
#define ngx_mp4_atom_header(mp4) (mp4->buffer_pos - 8)
#define ngx_mp4_atom_data(mp4) mp4->buffer_pos
+#define ngx_mp4_atom_data_size(t) (uint64_t) (sizeof(t) - 8)
#define ngx_mp4_atom_next(mp4, n) mp4->buffer_pos += n; mp4->offset += n
@@ -204,7 +205,7 @@ typedef struct {
static ngx_int_t ngx_http_mp4_process(ngx_http_mp4_file_t *mp4);
static ngx_int_t ngx_http_mp4_read_atom(ngx_http_mp4_file_t *mp4,
ngx_http_mp4_atom_handler_t *atom, uint64_t atom_data_size);
-static ngx_int_t ngx_http_mp4_read(ngx_http_mp4_file_t *mp4);
+static ngx_int_t ngx_http_mp4_read(ngx_http_mp4_file_t *mp4, size_t size);
static ngx_int_t ngx_http_mp4_read_ftyp_atom(ngx_http_mp4_file_t *mp4,
uint64_t atom_data_size);
static ngx_int_t ngx_http_mp4_read_moov_atom(ngx_http_mp4_file_t *mp4,
@@ -265,7 +266,7 @@ static ngx_int_t ngx_http_mp4_update_stsc_atom(ngx_http_mp4_file_t *mp4,
ngx_http_mp4_trak_t *trak);
static ngx_int_t ngx_http_mp4_read_stsz_atom(ngx_http_mp4_file_t *mp4,
uint64_t atom_data_size);
-static void ngx_http_mp4_update_stsz_atom(ngx_http_mp4_file_t *mp4,
+static ngx_int_t ngx_http_mp4_update_stsz_atom(ngx_http_mp4_file_t *mp4,
ngx_http_mp4_trak_t *trak);
static ngx_int_t ngx_http_mp4_read_stco_atom(ngx_http_mp4_file_t *mp4,
uint64_t atom_data_size);
@@ -693,7 +694,9 @@ ngx_http_mp4_process(ngx_http_mp4_file_t *mp4)
return NGX_ERROR;
}
- ngx_http_mp4_update_stsz_atom(mp4, &trak[i]);
+ if (ngx_http_mp4_update_stsz_atom(mp4, &trak[i]) != NGX_OK) {
+ return NGX_ERROR;
+ }
if (trak[i].out[NGX_HTTP_MP4_CO64_DATA].buf) {
if (ngx_http_mp4_update_co64_atom(mp4, &trak[i]) != NGX_OK) {
@@ -744,7 +747,7 @@ ngx_http_mp4_process(ngx_http_mp4_file_t *mp4)
- start_offset;
ngx_log_debug1(NGX_LOG_DEBUG_HTTP, mp4->file.log, 0,
- "mp4 adjustment:%D", adjustment);
+ "mp4 adjustment:%O", adjustment);
for (i = 0; i < mp4->trak.nelts; i++) {
if (trak[i].out[NGX_HTTP_MP4_CO64_DATA].buf) {
@@ -785,10 +788,8 @@ ngx_http_mp4_read_atom(ngx_http_mp4_file_t *mp4,
while (mp4->offset < end) {
- if (mp4->buffer_pos + sizeof(uint32_t) > mp4->buffer_end) {
- if (ngx_http_mp4_read(mp4) != NGX_OK) {
- return NGX_ERROR;
- }
+ if (ngx_http_mp4_read(mp4, sizeof(uint32_t)) != NGX_OK) {
+ return NGX_ERROR;
}
atom_header = mp4->buffer_pos;
@@ -805,17 +806,14 @@ ngx_http_mp4_read_atom(ngx_http_mp4_file_t *mp4,
if (atom_size == 1) {
- if (mp4->buffer_pos + sizeof(ngx_mp4_atom_header64_t)
- > mp4->buffer_end)
+ if (ngx_http_mp4_read(mp4, sizeof(ngx_mp4_atom_header64_t))
+ != NGX_OK)
{
- if (ngx_http_mp4_read(mp4) != NGX_OK) {
- return NGX_ERROR;
- }
-
- atom_header = mp4->buffer_pos;
+ return NGX_ERROR;
}
/* 64-bit atom size */
+ atom_header = mp4->buffer_pos;
atom_size = ngx_mp4_get_64value(atom_header + 8);
atom_header_size = sizeof(ngx_mp4_atom_header64_t);
@@ -827,20 +825,26 @@ ngx_http_mp4_read_atom(ngx_http_mp4_file_t *mp4,
}
}
- if (mp4->buffer_pos + sizeof(ngx_mp4_atom_header_t) > mp4->buffer_end) {
- if (ngx_http_mp4_read(mp4) != NGX_OK) {
- return NGX_ERROR;
- }
-
- atom_header = mp4->buffer_pos;
+ if (ngx_http_mp4_read(mp4, sizeof(ngx_mp4_atom_header_t)) != NGX_OK) {
+ return NGX_ERROR;
}
+ atom_header = mp4->buffer_pos;
atom_name = atom_header + sizeof(uint32_t);
ngx_log_debug4(NGX_LOG_DEBUG_HTTP, mp4->file.log, 0,
"mp4 atom: %*s @%O:%uL",
4, atom_name, mp4->offset, atom_size);
+ if (atom_size > (uint64_t) (NGX_MAX_OFF_T_VALUE - mp4->offset)
+ || mp4->offset + (off_t) atom_size > end)
+ {
+ ngx_log_error(NGX_LOG_ERR, mp4->file.log, 0,
+ "\"%s\" mp4 atom too large:%uL",
+ mp4->file.name.data, atom_size);
+ return NGX_ERROR;
+ }
+
for (n = 0; atom[n].name; n++) {
if (ngx_strncmp(atom_name, atom[n].name, 4) == 0) {
@@ -867,14 +871,24 @@ ngx_http_mp4_read_atom(ngx_http_mp4_file_t *mp4,
static ngx_int_t
-ngx_http_mp4_read(ngx_http_mp4_file_t *mp4)
+ngx_http_mp4_read(ngx_http_mp4_file_t *mp4, size_t size)
{
- ngx_int_t n;
+ ssize_t n;
+
+ if (mp4->buffer_pos + size <= mp4->buffer_end) {
+ return NGX_OK;
+ }
if (mp4->offset + (off_t) mp4->buffer_size > mp4->end) {
mp4->buffer_size = (size_t) (mp4->end - mp4->offset);
}
+ if (mp4->buffer_size < size) {
+ ngx_log_error(NGX_LOG_ERR, mp4->file.log, 0,
+ "\"%s\" mp4 file truncated", mp4->file.name.data);
+ return NGX_ERROR;
+ }
+
if (mp4->buffer == NULL) {
mp4->buffer = ngx_palloc(mp4->request->pool, mp4->buffer_size);
if (mp4->buffer == NULL) {
@@ -882,7 +896,6 @@ ngx_http_mp4_read(ngx_http_mp4_file_t *mp4)
}
mp4->buffer_start = mp4->buffer;
- mp4->buffer_end = mp4->buffer + mp4->buffer_size;
}
n = ngx_read_file(&mp4->file, mp4->buffer_start, mp4->buffer_size,
@@ -892,11 +905,15 @@ ngx_http_mp4_read(ngx_http_mp4_file_t *mp4)
return NGX_ERROR;
}
- if (n == 0) {
- return NGX_OK;
+ if ((size_t) n != mp4->buffer_size) {
+ ngx_log_error(NGX_LOG_CRIT, mp4->file.log, 0,
+ ngx_read_file_n " read only %z of %z from \"%s\"",
+ n, mp4->buffer_size, mp4->file.name.data);
+ return NGX_ERROR;
}
mp4->buffer_pos = mp4->buffer_start;
+ mp4->buffer_end = mp4->buffer_start + mp4->buffer_size;
return NGX_OK;
}
@@ -911,7 +928,9 @@ ngx_http_mp4_read_ftyp_atom(ngx_http_mp4_file_t *mp4, uint64_t atom_data_size)
ngx_log_debug0(NGX_LOG_DEBUG_HTTP, mp4->file.log, 0, "mp4 ftyp atom");
- if (atom_data_size > 1024) {
+ if (atom_data_size > 1024
+ || ngx_mp4_atom_data(mp4) + atom_data_size > mp4->buffer_end)
+ {
ngx_log_error(NGX_LOG_ERR, mp4->file.log, 0,
"\"%s\" mp4 ftyp atom is too large:%uL",
mp4->file.name.data, atom_data_size);
@@ -1160,6 +1179,12 @@ ngx_http_mp4_read_mvhd_atom(ngx_http_mp4_file_t *mp4, uint64_t atom_data_size)
mvhd64_atom = (ngx_mp4_mvhd64_atom_t *) atom_header;
ngx_mp4_set_atom_name(atom_header, 'm', 'v', 'h', 'd');
+ if (ngx_mp4_atom_data_size(ngx_mp4_mvhd_atom_t) > atom_data_size) {
+ ngx_log_error(NGX_LOG_ERR, mp4->file.log, 0,
+ "\"%s\" mp4 mvhd atom too small", mp4->file.name.data);
+ return NGX_ERROR;
+ }
+
if (mvhd_atom->version[0] == 0) {
/* version 0: 32-bit duration */
timescale = ngx_mp4_get_32value(mvhd_atom->timescale);
@@ -1167,6 +1192,14 @@ ngx_http_mp4_read_mvhd_atom(ngx_http_mp4_file_t *mp4, uint64_t atom_data_size)
} else {
/* version 1: 64-bit duration */
+
+ if (ngx_mp4_atom_data_size(ngx_mp4_mvhd64_atom_t) > atom_data_size) {
+ ngx_log_error(NGX_LOG_ERR, mp4->file.log, 0,
+ "\"%s\" mp4 mvhd atom too small",
+ mp4->file.name.data);
+ return NGX_ERROR;
+ }
+
timescale = ngx_mp4_get_32value(mvhd64_atom->timescale);
duration = ngx_mp4_get_64value(mvhd64_atom->duration);
}
@@ -1337,12 +1370,26 @@ ngx_http_mp4_read_tkhd_atom(ngx_http_mp4_file_t *mp4, uint64_t atom_data_size)
tkhd64_atom = (ngx_mp4_tkhd64_atom_t *) atom_header;
ngx_mp4_set_atom_name(tkhd_atom, 't', 'k', 'h', 'd');
+ if (ngx_mp4_atom_data_size(ngx_mp4_tkhd_atom_t) > atom_data_size) {
+ ngx_log_error(NGX_LOG_ERR, mp4->file.log, 0,
+ "\"%s\" mp4 tkhd atom too small", mp4->file.name.data);
+ return NGX_ERROR;
+ }
+
if (tkhd_atom->version[0] == 0) {
/* version 0: 32-bit duration */
duration = ngx_mp4_get_32value(tkhd_atom->duration);
} else {
/* version 1: 64-bit duration */
+
+ if (ngx_mp4_atom_data_size(ngx_mp4_tkhd64_atom_t) > atom_data_size) {
+ ngx_log_error(NGX_LOG_ERR, mp4->file.log, 0,
+ "\"%s\" mp4 tkhd atom too small",
+ mp4->file.name.data);
+ return NGX_ERROR;
+ }
+
duration = ngx_mp4_get_64value(tkhd64_atom->duration);
}
@@ -1466,6 +1513,12 @@ ngx_http_mp4_read_mdhd_atom(ngx_http_mp4_file_t *mp4, uint64_t atom_data_size)
mdhd64_atom = (ngx_mp4_mdhd64_atom_t *) atom_header;
ngx_mp4_set_atom_name(mdhd_atom, 'm', 'd', 'h', 'd');
+ if (ngx_mp4_atom_data_size(ngx_mp4_mdhd_atom_t) > atom_data_size) {
+ ngx_log_error(NGX_LOG_ERR, mp4->file.log, 0,
+ "\"%s\" mp4 mdhd atom too small", mp4->file.name.data);
+ return NGX_ERROR;
+ }
+
if (mdhd_atom->version[0] == 0) {
/* version 0: everything is 32-bit */
timescale = ngx_mp4_get_32value(mdhd_atom->timescale);
@@ -1473,6 +1526,14 @@ ngx_http_mp4_read_mdhd_atom(ngx_http_mp4_file_t *mp4, uint64_t atom_data_size)
} else {
/* version 1: 64-bit duration and 32-bit timescale */
+
+ if (ngx_mp4_atom_data_size(ngx_mp4_mdhd64_atom_t) > atom_data_size) {
+ ngx_log_error(NGX_LOG_ERR, mp4->file.log, 0,
+ "\"%s\" mp4 mdhd atom too small",
+ mp4->file.name.data);
+ return NGX_ERROR;
+ }
+
timescale = ngx_mp4_get_32value(mdhd64_atom->timescale);
duration = ngx_mp4_get_64value(mdhd64_atom->duration);
}
@@ -1748,12 +1809,9 @@ ngx_http_mp4_read_stsd_atom(ngx_http_mp4_file_t *mp4, uint64_t atom_data_size)
ngx_mp4_set_32value(stsd_atom->size, atom_size);
ngx_mp4_set_atom_name(stsd_atom, 's', 't', 's', 'd');
- if ((uint64_t) (sizeof(ngx_mp4_stsd_atom_t) - sizeof(ngx_mp4_atom_header_t))
- > atom_data_size)
- {
+ if (ngx_mp4_atom_data_size(ngx_mp4_stsd_atom_t) > atom_data_size) {
ngx_log_error(NGX_LOG_ERR, mp4->file.log, 0,
- "\"%s\" mp4 stsd atom too large",
- mp4->file.name.data);
+ "\"%s\" mp4 stsd atom too small", mp4->file.name.data);
return NGX_ERROR;
}
@@ -1817,21 +1875,28 @@ ngx_http_mp4_read_stts_atom(ngx_http_mp4_file_t *mp4, uint64_t atom_data_size)
stts_atom = (ngx_mp4_stts_atom_t *) atom_header;
ngx_mp4_set_atom_name(stts_atom, 's', 't', 't', 's');
+ if (ngx_mp4_atom_data_size(ngx_mp4_stts_atom_t) > atom_data_size) {
+ ngx_log_error(NGX_LOG_ERR, mp4->file.log, 0,
+ "\"%s\" mp4 stts atom too small", mp4->file.name.data);
+ return NGX_ERROR;
+ }
+
entries = ngx_mp4_get_32value(stts_atom->entries);
ngx_log_debug1(NGX_LOG_DEBUG_HTTP, mp4->file.log, 0,
"mp4 time-to-sample entries:%uD", entries);
- atom_table = atom_header + sizeof(ngx_mp4_stts_atom_t);
- atom_end = atom_table + entries * sizeof(ngx_mp4_stts_entry_t);
-
- if ((uint64_t) (atom_end - stts_atom->version) > atom_data_size) {
+ if (ngx_mp4_atom_data_size(ngx_mp4_stts_atom_t)
+ + entries * sizeof(ngx_mp4_stts_entry_t) > atom_data_size)
+ {
ngx_log_error(NGX_LOG_ERR, mp4->file.log, 0,
- "\"%s\" mp4 stts atom too large",
- mp4->file.name.data);
+ "\"%s\" mp4 stts atom too small", mp4->file.name.data);
return NGX_ERROR;
}
+ atom_table = atom_header + sizeof(ngx_mp4_stts_atom_t);
+ atom_end = atom_table + entries * sizeof(ngx_mp4_stts_entry_t);
+
trak = ngx_mp4_last_trak(mp4);
trak->time_to_sample_entries = entries;
@@ -1902,7 +1967,7 @@ ngx_http_mp4_update_stts_atom(ngx_http_mp4_file_t *mp4,
if (start_time < (uint64_t) count * duration) {
start_sample += (ngx_uint_t) (start_time / duration);
- count -= start_sample;
+ count -= (uint32_t) (start_time / duration);
ngx_mp4_set_32value(entry->count, count);
goto found;
}
@@ -1965,6 +2030,12 @@ ngx_http_mp4_read_stss_atom(ngx_http_mp4_file_t *mp4, uint64_t atom_data_size)
stss_atom = (ngx_http_mp4_stss_atom_t *) atom_header;
ngx_mp4_set_atom_name(stss_atom, 's', 't', 's', 's');
+ if (ngx_mp4_atom_data_size(ngx_http_mp4_stss_atom_t) > atom_data_size) {
+ ngx_log_error(NGX_LOG_ERR, mp4->file.log, 0,
+ "\"%s\" mp4 stss atom too small", mp4->file.name.data);
+ return NGX_ERROR;
+ }
+
entries = ngx_mp4_get_32value(stss_atom->entries);
ngx_log_debug1(NGX_LOG_DEBUG_HTTP, mp4->file.log, 0,
@@ -1980,14 +2051,16 @@ ngx_http_mp4_read_stss_atom(ngx_http_mp4_file_t *mp4, uint64_t atom_data_size)
atom->pos = atom_header;
atom->last = atom_table;
- atom_end = atom_table + entries * sizeof(uint32_t);
-
- if ((uint64_t) (atom_end - stss_atom->version) > atom_data_size) {
+ if (ngx_mp4_atom_data_size(ngx_http_mp4_stss_atom_t)
+ + entries * sizeof(uint32_t) > atom_data_size)
+ {
ngx_log_error(NGX_LOG_ERR, mp4->file.log, 0,
- "\"%s\" mp4 stss atom too large", mp4->file.name.data);
+ "\"%s\" mp4 stss atom too small", mp4->file.name.data);
return NGX_ERROR;
}
+ atom_end = atom_table + entries * sizeof(uint32_t);
+
data = &trak->stss_data_buf;
data->temporary = 1;
data->pos = atom_table;
@@ -2110,6 +2183,12 @@ ngx_http_mp4_read_ctts_atom(ngx_http_mp4_file_t *mp4, uint64_t atom_data_size)
ctts_atom = (ngx_mp4_ctts_atom_t *) atom_header;
ngx_mp4_set_atom_name(ctts_atom, 'c', 't', 't', 's');
+ if (ngx_mp4_atom_data_size(ngx_mp4_ctts_atom_t) > atom_data_size) {
+ ngx_log_error(NGX_LOG_ERR, mp4->file.log, 0,
+ "\"%s\" mp4 ctts atom too small", mp4->file.name.data);
+ return NGX_ERROR;
+ }
+
entries = ngx_mp4_get_32value(ctts_atom->entries);
ngx_log_debug1(NGX_LOG_DEBUG_HTTP, mp4->file.log, 0,
@@ -2125,14 +2204,16 @@ ngx_http_mp4_read_ctts_atom(ngx_http_mp4_file_t *mp4, uint64_t atom_data_size)
atom->pos = atom_header;
atom->last = atom_table;
- atom_end = atom_table + entries * sizeof(ngx_mp4_ctts_entry_t);
-
- if ((uint64_t) (atom_end - ctts_atom->version) > atom_data_size) {
+ if (ngx_mp4_atom_data_size(ngx_mp4_ctts_atom_t)
+ + entries * sizeof(ngx_mp4_ctts_entry_t) > atom_data_size)
+ {
ngx_log_error(NGX_LOG_ERR, mp4->file.log, 0,
- "\"%s\" mp4 ctts atom too large", mp4->file.name.data);
+ "\"%s\" mp4 ctts atom too small", mp4->file.name.data);
return NGX_ERROR;
}
+ atom_end = atom_table + entries * sizeof(ngx_mp4_ctts_entry_t);
+
data = &trak->ctts_data_buf;
data->temporary = 1;
data->pos = atom_table;
@@ -2243,21 +2324,28 @@ ngx_http_mp4_read_stsc_atom(ngx_http_mp4_file_t *mp4, uint64_t atom_data_size)
stsc_atom = (ngx_mp4_stsc_atom_t *) atom_header;
ngx_mp4_set_atom_name(stsc_atom, 's', 't', 's', 'c');
+ if (ngx_mp4_atom_data_size(ngx_mp4_stsc_atom_t) > atom_data_size) {
+ ngx_log_error(NGX_LOG_ERR, mp4->file.log, 0,
+ "\"%s\" mp4 stsc atom too small", mp4->file.name.data);
+ return NGX_ERROR;
+ }
+
entries = ngx_mp4_get_32value(stsc_atom->entries);
ngx_log_debug1(NGX_LOG_DEBUG_HTTP, mp4->file.log, 0,
"sample-to-chunk entries:%uD", entries);
- atom_table = atom_header + sizeof(ngx_mp4_stsc_atom_t);
- atom_end = atom_table + entries * sizeof(ngx_mp4_stsc_entry_t);
-
- if ((uint64_t) (atom_end - stsc_atom->version) > atom_data_size) {
+ if (ngx_mp4_atom_data_size(ngx_mp4_stsc_atom_t)
+ + entries * sizeof(ngx_mp4_stsc_entry_t) > atom_data_size)
+ {
ngx_log_error(NGX_LOG_ERR, mp4->file.log, 0,
- "\"%s\" mp4 stsc atom too large",
- mp4->file.name.data);
+ "\"%s\" mp4 stsc atom too small", mp4->file.name.data);
return NGX_ERROR;
}
+ atom_table = atom_header + sizeof(ngx_mp4_stsc_atom_t);
+ atom_end = atom_table + entries * sizeof(ngx_mp4_stsc_entry_t);
+
trak = ngx_mp4_last_trak(mp4);
trak->sample_to_chunk_entries = entries;
@@ -2309,6 +2397,13 @@ ngx_http_mp4_update_stsc_atom(ngx_http_mp4_file_t *mp4,
return NGX_ERROR;
}
+ if (trak->sample_to_chunk_entries == 0) {
+ ngx_log_error(NGX_LOG_ERR, mp4->file.log, 0,
+ "zero number of entries in stsc atom in \"%s\"",
+ mp4->file.name.data);
+ return NGX_ERROR;
+ }
+
start_sample = (uint32_t) trak->start_sample;
entries = trak->sample_to_chunk_entries - 1;
@@ -2450,6 +2545,12 @@ ngx_http_mp4_read_stsz_atom(ngx_http_mp4_file_t *mp4, uint64_t atom_data_size)
stsz_atom = (ngx_mp4_stsz_atom_t *) atom_header;
ngx_mp4_set_atom_name(stsz_atom, 's', 't', 's', 'z');
+ if (ngx_mp4_atom_data_size(ngx_mp4_stsz_atom_t) > atom_data_size) {
+ ngx_log_error(NGX_LOG_ERR, mp4->file.log, 0,
+ "\"%s\" mp4 stsz atom too small", mp4->file.name.data);
+ return NGX_ERROR;
+ }
+
size = ngx_mp4_get_32value(stsz_atom->uniform_size);
entries = ngx_mp4_get_32value(stsz_atom->entries);
@@ -2469,15 +2570,17 @@ ngx_http_mp4_read_stsz_atom(ngx_http_mp4_file_t *mp4, uint64_t atom_data_size)
trak->out[NGX_HTTP_MP4_STSZ_ATOM].buf = atom;
if (size == 0) {
- atom_end = atom_table + entries * sizeof(uint32_t);
-
- if ((uint64_t) (atom_end - stsz_atom->version) > atom_data_size) {
+ if (ngx_mp4_atom_data_size(ngx_mp4_stsz_atom_t)
+ + entries * sizeof(uint32_t) > atom_data_size)
+ {
ngx_log_error(NGX_LOG_ERR, mp4->file.log, 0,
- "\"%s\" mp4 stsz atom too large",
+ "\"%s\" mp4 stsz atom too small",
mp4->file.name.data);
return NGX_ERROR;
}
+ atom_end = atom_table + entries * sizeof(uint32_t);
+
data = &trak->stsz_data_buf;
data->temporary = 1;
data->pos = atom_table;
@@ -2499,7 +2602,7 @@ ngx_http_mp4_read_stsz_atom(ngx_http_mp4_file_t *mp4, uint64_t atom_data_size)
}
-static void
+static ngx_int_t
ngx_http_mp4_update_stsz_atom(ngx_http_mp4_file_t *mp4,
ngx_http_mp4_trak_t *trak)
{
@@ -2520,6 +2623,13 @@ ngx_http_mp4_update_stsz_atom(ngx_http_mp4_file_t *mp4,
data = trak->out[NGX_HTTP_MP4_STSZ_DATA].buf;
if (data) {
+ if (trak->start_sample > trak->sample_sizes_entries) {
+ ngx_log_error(NGX_LOG_ERR, mp4->file.log, 0,
+ "start time is out mp4 stsz samples in \"%s\"",
+ mp4->file.name.data);
+ return NGX_ERROR;
+ }
+
data->pos += trak->start_sample * sizeof(uint32_t);
end = (uint32_t *) data->pos;
@@ -2540,6 +2650,8 @@ ngx_http_mp4_update_stsz_atom(ngx_http_mp4_file_t *mp4,
ngx_mp4_set_32value(stsz_atom->entries,
trak->sample_sizes_entries - trak->start_sample);
}
+
+ return NGX_OK;
}
@@ -2569,19 +2681,27 @@ ngx_http_mp4_read_stco_atom(ngx_http_mp4_file_t *mp4, uint64_t atom_data_size)
stco_atom = (ngx_mp4_stco_atom_t *) atom_header;
ngx_mp4_set_atom_name(stco_atom, 's', 't', 'c', 'o');
+ if (ngx_mp4_atom_data_size(ngx_mp4_stco_atom_t) > atom_data_size) {
+ ngx_log_error(NGX_LOG_ERR, mp4->file.log, 0,
+ "\"%s\" mp4 stco atom too small", mp4->file.name.data);
+ return NGX_ERROR;
+ }
+
entries = ngx_mp4_get_32value(stco_atom->entries);
ngx_log_debug1(NGX_LOG_DEBUG_HTTP, mp4->file.log, 0, "chunks:%uD", entries);
- atom_table = atom_header + sizeof(ngx_mp4_stco_atom_t);
- atom_end = atom_table + entries * sizeof(uint32_t);
-
- if ((uint64_t) (atom_end - stco_atom->version) > atom_data_size) {
+ if (ngx_mp4_atom_data_size(ngx_mp4_stco_atom_t)
+ + entries * sizeof(uint32_t) > atom_data_size)
+ {
ngx_log_error(NGX_LOG_ERR, mp4->file.log, 0,
- "\"%s\" mp4 stco atom too large", mp4->file.name.data);
+ "\"%s\" mp4 stco atom too small", mp4->file.name.data);
return NGX_ERROR;
}
+ atom_table = atom_header + sizeof(ngx_mp4_stco_atom_t);
+ atom_end = atom_table + entries * sizeof(uint32_t);
+
trak = ngx_mp4_last_trak(mp4);
trak->chunks = entries;
@@ -2630,6 +2750,13 @@ ngx_http_mp4_update_stco_atom(ngx_http_mp4_file_t *mp4,
return NGX_ERROR;
}
+ if (trak->start_chunk > trak->chunks) {
+ ngx_log_error(NGX_LOG_ERR, mp4->file.log, 0,
+ "start time is out mp4 stco chunks in \"%s\"",
+ mp4->file.name.data);
+ return NGX_ERROR;
+ }
+
data->pos += trak->start_chunk * sizeof(uint32_t);
atom_size = sizeof(ngx_mp4_stco_atom_t) + (data->last - data->pos);
trak->size += atom_size;
@@ -2705,19 +2832,27 @@ ngx_http_mp4_read_co64_atom(ngx_http_mp4_file_t *mp4, uint64_t atom_data_size)
co64_atom = (ngx_mp4_co64_atom_t *) atom_header;
ngx_mp4_set_atom_name(co64_atom, 'c', 'o', '6', '4');
+ if (ngx_mp4_atom_data_size(ngx_mp4_co64_atom_t) > atom_data_size) {
+ ngx_log_error(NGX_LOG_ERR, mp4->file.log, 0,
+ "\"%s\" mp4 co64 atom too small", mp4->file.name.data);
+ return NGX_ERROR;
+ }
+
entries = ngx_mp4_get_32value(co64_atom->entries);
ngx_log_debug1(NGX_LOG_DEBUG_HTTP, mp4->file.log, 0, "chunks:%uD", entries);
- atom_table = atom_header + sizeof(ngx_mp4_co64_atom_t);
- atom_end = atom_table + entries * sizeof(uint64_t);
-
- if ((uint64_t) (atom_end - co64_atom->version) > atom_data_size) {
+ if (ngx_mp4_atom_data_size(ngx_mp4_co64_atom_t)
+ + entries * sizeof(uint64_t) > atom_data_size)
+ {
ngx_log_error(NGX_LOG_ERR, mp4->file.log, 0,
- "\"%s\" mp4 co64 atom too large", mp4->file.name.data);
+ "\"%s\" mp4 co64 atom too small", mp4->file.name.data);
return NGX_ERROR;
}
+ atom_table = atom_header + sizeof(ngx_mp4_co64_atom_t);
+ atom_end = atom_table + entries * sizeof(uint64_t);
+
trak = ngx_mp4_last_trak(mp4);
trak->chunks = entries;
@@ -2766,6 +2901,13 @@ ngx_http_mp4_update_co64_atom(ngx_http_mp4_file_t *mp4,
return NGX_ERROR;
}
+ if (trak->start_chunk > trak->chunks) {
+ ngx_log_error(NGX_LOG_ERR, mp4->file.log, 0,
+ "start time is out mp4 co64 chunks in \"%s\"",
+ mp4->file.name.data);
+ return NGX_ERROR;
+ }
+
data->pos += trak->start_chunk * sizeof(uint64_t);
atom_size = sizeof(ngx_mp4_co64_atom_t) + (data->last - data->pos);
trak->size += atom_size;
diff --git a/src/http/modules/perl/nginx.pm b/src/http/modules/perl/nginx.pm
index 056a62b22..76ec1d391 100644
--- a/src/http/modules/perl/nginx.pm
+++ b/src/http/modules/perl/nginx.pm
@@ -50,7 +50,7 @@ our @EXPORT = qw(
HTTP_INSUFFICIENT_STORAGE
);
-our $VERSION = '1.0.14';
+our $VERSION = '1.0.15';
require XSLoader;
XSLoader::load('nginx', $VERSION);