diff options
author | NGINX team <nginx@nginx.org> | 2012-04-12 13:05:40 +0000 |
---|---|---|
committer | Jon Kolb <jon@b0g.us> | 2012-04-12 13:05:40 +0000 |
commit | ed2df87c83d3a68ab2a395d4c2549dbe26e86ab0 (patch) | |
tree | ff91c69d84d5e4b84a15a12b873c3cb2193fd481 /src/http | |
parent | 60a50f7b445d1ac18ea0b1ff140745b6844c6794 (diff) | |
download | nginx-1.1.tar.gz |
*) 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: nginx/Windows might be terminated abnormally.
Thanks to Vincent Lee.
*) Bugfix: nginx hogged CPU if all servers in an upstream were marked as
"backup".
*) Bugfix: the "allow" and "deny" directives might be inherited
incorrectly if they were used with IPv6 addresses.
*) Bugfix: the "modern_browser" and "ancient_browser" directives might
be inherited incorrectly.
*) Bugfix: timeouts might be handled incorrectly on Solaris/SPARC.
*) Bugfix: in the ngx_http_mp4_module.
Diffstat (limited to 'src/http')
-rw-r--r-- | src/http/modules/ngx_http_access_module.c | 13 | ||||
-rw-r--r-- | src/http/modules/ngx_http_browser_module.c | 8 | ||||
-rw-r--r-- | src/http/modules/ngx_http_degradation_module.c | 2 | ||||
-rw-r--r-- | src/http/modules/ngx_http_mp4_module.c | 278 | ||||
-rw-r--r-- | src/http/modules/ngx_http_ssi_filter_module.c | 2 | ||||
-rw-r--r-- | src/http/modules/perl/nginx.pm | 2 | ||||
-rw-r--r-- | src/http/ngx_http.c | 2 | ||||
-rw-r--r-- | src/http/ngx_http_core_module.c | 19 | ||||
-rw-r--r-- | src/http/ngx_http_parse.c | 2 | ||||
-rw-r--r-- | src/http/ngx_http_upstream.c | 2 | ||||
-rw-r--r-- | src/http/ngx_http_upstream_round_robin.c | 7 | ||||
-rw-r--r-- | src/http/ngx_http_variables.c | 2 |
12 files changed, 252 insertions, 87 deletions
diff --git a/src/http/modules/ngx_http_access_module.c b/src/http/modules/ngx_http_access_module.c index 84a75d777..70a4262fc 100644 --- a/src/http/modules/ngx_http_access_module.c +++ b/src/http/modules/ngx_http_access_module.c @@ -351,14 +351,19 @@ ngx_http_access_merge_loc_conf(ngx_conf_t *cf, void *parent, void *child) ngx_http_access_loc_conf_t *prev = parent; ngx_http_access_loc_conf_t *conf = child; - if (conf->rules == NULL) { +#if (NGX_HAVE_INET6) + + if (conf->rules == NULL && conf->rules6 == NULL) { conf->rules = prev->rules; + conf->rules6 = prev->rules6; } -#if (NGX_HAVE_INET6) - if (conf->rules6 == NULL) { - conf->rules6 = prev->rules6; +#else + + if (conf->rules == NULL) { + conf->rules = prev->rules; } + #endif return NGX_CONF_OK; diff --git a/src/http/modules/ngx_http_browser_module.c b/src/http/modules/ngx_http_browser_module.c index 13a714538..80da0d8fa 100644 --- a/src/http/modules/ngx_http_browser_module.c +++ b/src/http/modules/ngx_http_browser_module.c @@ -458,10 +458,11 @@ ngx_http_browser_merge_conf(ngx_conf_t *cf, void *parent, void *child) * with a real skip value. The zero value means Opera. */ - if (conf->modern_browsers == NULL) { + if (conf->modern_browsers == NULL && conf->modern_unlisted_browsers == 0) { conf->modern_browsers = prev->modern_browsers; + conf->modern_unlisted_browsers = prev->modern_unlisted_browsers; - } else { + } else if (conf->modern_browsers != NULL) { browsers = conf->modern_browsers->elts; for (i = 0; i < conf->modern_browsers->nelts; i++) { @@ -501,8 +502,9 @@ found: } } - if (conf->ancient_browsers == NULL) { + if (conf->ancient_browsers == NULL && conf->netscape4 == 0) { conf->ancient_browsers = prev->ancient_browsers; + conf->netscape4 = prev->netscape4; } if (conf->modern_browser_value == NULL) { diff --git a/src/http/modules/ngx_http_degradation_module.c b/src/http/modules/ngx_http_degradation_module.c index 0b1368f3b..b9c65cdc9 100644 --- a/src/http/modules/ngx_http_degradation_module.c +++ b/src/http/modules/ngx_http_degradation_module.c @@ -126,7 +126,7 @@ ngx_http_degraded(ngx_http_request_t *r) * ELF/i386 is loaded at 0x08000000, 128M * ELF/amd64 is loaded at 0x00400000, 4M * - * use a function address to substract the loading address + * use a function address to subtract the loading address */ sbrk_size = (size_t) sbrk(0) - ((uintptr_t) ngx_palloc & ~0x3FFFFF); diff --git a/src/http/modules/ngx_http_mp4_module.c b/src/http/modules/ngx_http_mp4_module.c index 384125a03..433e118a2 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); @@ -701,7 +702,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) { @@ -752,7 +755,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) { @@ -793,10 +796,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; @@ -813,17 +814,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); @@ -835,20 +833,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) { @@ -875,14 +879,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) { @@ -890,7 +904,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, @@ -900,11 +913,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; } @@ -919,7 +936,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); @@ -1168,6 +1187,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); @@ -1175,6 +1200,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); } @@ -1345,12 +1378,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); } @@ -1474,6 +1521,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); @@ -1481,6 +1534,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); } @@ -1756,12 +1817,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; } @@ -1825,21 +1883,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; @@ -1910,7 +1975,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; } @@ -1973,6 +2038,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, @@ -1988,14 +2059,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; @@ -2118,6 +2191,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, @@ -2133,14 +2212,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; @@ -2251,21 +2332,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; @@ -2317,6 +2405,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; @@ -2458,6 +2553,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); @@ -2477,15 +2578,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; @@ -2507,7 +2610,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) { @@ -2528,6 +2631,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; @@ -2548,6 +2658,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; } @@ -2577,19 +2689,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; @@ -2638,6 +2758,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; @@ -2713,19 +2840,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; @@ -2774,6 +2909,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/ngx_http_ssi_filter_module.c b/src/http/modules/ngx_http_ssi_filter_module.c index 0d86e692a..f47cb429d 100644 --- a/src/http/modules/ngx_http_ssi_filter_module.c +++ b/src/http/modules/ngx_http_ssi_filter_module.c @@ -714,7 +714,7 @@ ngx_http_ssi_body_filter(ngx_http_request_t *r, ngx_chain_t *in) if (ctx->params.nelts > NGX_HTTP_SSI_MAX_PARAMS) { ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, - "too many SSI command paramters: \"%V\"", + "too many SSI command parameters: \"%V\"", &ctx->command); goto ssi_error; } diff --git a/src/http/modules/perl/nginx.pm b/src/http/modules/perl/nginx.pm index 364f70897..7ec70472d 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.1.18'; +our $VERSION = '1.1.19'; require XSLoader; XSLoader::load('nginx', $VERSION); diff --git a/src/http/ngx_http.c b/src/http/ngx_http.c index 27580f195..3e077fb95 100644 --- a/src/http/ngx_http.c +++ b/src/http/ngx_http.c @@ -1417,7 +1417,7 @@ ngx_http_optimize_servers(ngx_conf_t *cf, ngx_http_core_main_conf_t *cmcf, /* * check whether all name-based servers have the same - * configuraiton as a default server for given address:port + * configuration as a default server for given address:port */ addr = port[p].addrs.elts; diff --git a/src/http/ngx_http_core_module.c b/src/http/ngx_http_core_module.c index f0ba7c705..5b7f44aa1 100644 --- a/src/http/ngx_http_core_module.c +++ b/src/http/ngx_http_core_module.c @@ -1228,20 +1228,29 @@ ngx_http_core_try_files_phase(ngx_http_request_t *r, len = tf->name.len; } - /* 16 bytes are preallocation */ - reserve = ngx_abs((ssize_t) (len - r->uri.len)) + alias + 16; + if (!alias) { + reserve = len > r->uri.len ? len - r->uri.len : 0; + +#if (NGX_PCRE) + } else if (clcf->regex) { + reserve = len; +#endif + + } else { + reserve = len > r->uri.len - alias ? len - (r->uri.len - alias) : 0; + } if (reserve > allocated) { - /* we just need to allocate path and to copy a root */ + /* 16 bytes are preallocation */ + allocated = reserve + 16; - if (ngx_http_map_uri_to_path(r, &path, &root, reserve) == NULL) { + if (ngx_http_map_uri_to_path(r, &path, &root, allocated) == NULL) { ngx_http_finalize_request(r, NGX_HTTP_INTERNAL_SERVER_ERROR); return NGX_OK; } name = path.data + root; - allocated = path.len - root - (r->uri.len - alias); } if (tf->values == NULL) { diff --git a/src/http/ngx_http_parse.c b/src/http/ngx_http_parse.c index ace6cfe9a..0a10a340e 100644 --- a/src/http/ngx_http_parse.c +++ b/src/http/ngx_http_parse.c @@ -1097,7 +1097,7 @@ ngx_http_parse_complex_uri(ngx_http_request_t *r, ngx_uint_t merge_slashes) /* * we use "ch = *p++" inside the cycle, but this operation is safe, - * because after the URI there is always at least one charcter: + * because after the URI there is always at least one character: * the line feed */ diff --git a/src/http/ngx_http_upstream.c b/src/http/ngx_http_upstream.c index a5ed15c42..70a4e1668 100644 --- a/src/http/ngx_http_upstream.c +++ b/src/http/ngx_http_upstream.c @@ -1196,7 +1196,7 @@ ngx_http_upstream_connect(ngx_http_request_t *r, ngx_http_upstream_t *u) { /* * the r->request_body->buf can be reused for one request only, - * the subrequests should allocate their own temporay bufs + * the subrequests should allocate their own temporary bufs */ u->output.free = ngx_alloc_chain_link(r->pool); diff --git a/src/http/ngx_http_upstream_round_robin.c b/src/http/ngx_http_upstream_round_robin.c index 410559d50..f0fac8736 100644 --- a/src/http/ngx_http_upstream_round_robin.c +++ b/src/http/ngx_http_upstream_round_robin.c @@ -49,6 +49,13 @@ ngx_http_upstream_init_round_robin(ngx_conf_t *cf, n += server[i].naddrs; } + if (n == 0) { + ngx_log_error(NGX_LOG_EMERG, cf->log, 0, + "no servers in upstream \"%V\" in %s:%ui", + &us->host, us->file_name, us->line); + return NGX_ERROR; + } + peers = ngx_pcalloc(cf->pool, sizeof(ngx_http_upstream_rr_peers_t) + sizeof(ngx_http_upstream_rr_peer_t) * (n - 1)); if (peers == NULL) { diff --git a/src/http/ngx_http_variables.c b/src/http/ngx_http_variables.c index 744bd0b68..949cef910 100644 --- a/src/http/ngx_http_variables.c +++ b/src/http/ngx_http_variables.c @@ -112,7 +112,7 @@ static ngx_int_t ngx_http_variable_pid(ngx_http_request_t *r, /* * the $http_host, $http_user_agent, $http_referer, $http_via, * and $http_x_forwarded_for variables may be handled by generic - * ngx_http_variable_unknown_header_in(), but for perfomance reasons + * ngx_http_variable_unknown_header_in(), but for performance reasons * they are handled using dedicated entries */ |