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
commited2df87c83d3a68ab2a395d4c2549dbe26e86ab0 (patch)
treeff91c69d84d5e4b84a15a12b873c3cb2193fd481
parent60a50f7b445d1ac18ea0b1ff140745b6844c6794 (diff)
downloadnginx-ed2df87c83d3a68ab2a395d4c2549dbe26e86ab0.tar.gz
Changes with nginx 1.1.19 12 Apr 2012v1.1.19nginx-1.1
*) 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.
-rw-r--r--CHANGES24
-rw-r--r--CHANGES.ru25
-rw-r--r--src/core/nginx.h4
-rw-r--r--src/core/ngx_conf_file.h2
-rw-r--r--src/core/ngx_connection.c2
-rw-r--r--src/core/ngx_file.c2
-rw-r--r--src/core/ngx_inet.c19
-rw-r--r--src/core/ngx_murmurhash.h2
-rw-r--r--src/core/ngx_rbtree.c3
-rw-r--r--src/core/ngx_times.c4
-rw-r--r--src/event/modules/ngx_epoll_module.c4
-rw-r--r--src/event/modules/ngx_eventport_module.c2
-rw-r--r--src/event/modules/ngx_kqueue_module.c2
-rw-r--r--src/event/ngx_event_openssl.c2
-rw-r--r--src/event/ngx_event_timer.c5
-rw-r--r--src/http/modules/ngx_http_access_module.c13
-rw-r--r--src/http/modules/ngx_http_browser_module.c8
-rw-r--r--src/http/modules/ngx_http_degradation_module.c2
-rw-r--r--src/http/modules/ngx_http_mp4_module.c278
-rw-r--r--src/http/modules/ngx_http_ssi_filter_module.c2
-rw-r--r--src/http/modules/perl/nginx.pm2
-rw-r--r--src/http/ngx_http.c2
-rw-r--r--src/http/ngx_http_core_module.c19
-rw-r--r--src/http/ngx_http_parse.c2
-rw-r--r--src/http/ngx_http_upstream.c2
-rw-r--r--src/http/ngx_http_upstream_round_robin.c7
-rw-r--r--src/http/ngx_http_variables.c2
-rw-r--r--src/os/unix/ngx_daemon.c3
-rw-r--r--src/os/unix/ngx_freebsd_rfork_thread.c4
-rw-r--r--src/os/unix/ngx_freebsd_sendfile_chain.c2
-rw-r--r--src/os/unix/ngx_gcc_atomic_sparc64.h2
-rw-r--r--src/os/unix/ngx_setproctitle.c2
32 files changed, 335 insertions, 119 deletions
diff --git a/CHANGES b/CHANGES
index 57eab3f40..61de9a629 100644
--- a/CHANGES
+++ b/CHANGES
@@ -1,4 +1,28 @@
+Changes with nginx 1.1.19 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: 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.
+
+
Changes with nginx 1.1.18 28 Mar 2012
*) Change: keepalive connections are no longer disabled for Safari by
diff --git a/CHANGES.ru b/CHANGES.ru
index cdca077a9..551ab53cf 100644
--- a/CHANGES.ru
+++ b/CHANGES.ru
@@ -1,4 +1,29 @@
+Изменения в nginx 1.1.19 12.04.2012
+
+ *) Безопасность: при обработке специально созданного mp4 файла модулем
+ ngx_http_mp4_module могли перезаписываться области памяти рабочего
+ процесса, что могло приводить к выполнению произвольного кода
+ (CVE-2012-2089).
+ Спасибо Matthew Daley.
+
+ *) Исправление: nginx/Windows мог завершаться аварийно.
+ Спасибо Vincent Lee.
+
+ *) Исправление: nginx нагружал процессор, если все серверы в upstream'е
+ были помечены флагом backup.
+
+ *) Исправление: директивы allow и deny могли наследоваться некорректно,
+ если в них использовались IPv6 адреса.
+
+ *) Исправление: директивы modern_browser и ancient_browser могли
+ наследоваться некорректно.
+
+ *) Исправление: таймауты могли работать некорректно на Solaris/SPARC.
+
+ *) Исправление: в модуле ngx_http_mp4_module.
+
+
Изменения в nginx 1.1.18 28.03.2012
*) Изменение: теперь keepalive соединения не запрещены для Safari по
diff --git a/src/core/nginx.h b/src/core/nginx.h
index f23bbf4d0..3e147dcb7 100644
--- a/src/core/nginx.h
+++ b/src/core/nginx.h
@@ -9,8 +9,8 @@
#define _NGINX_H_INCLUDED_
-#define nginx_version 1001018
-#define NGINX_VERSION "1.1.18"
+#define nginx_version 1001019
+#define NGINX_VERSION "1.1.19"
#define NGINX_VER "nginx/" NGINX_VERSION
#define NGINX_VAR "NGINX"
diff --git a/src/core/ngx_conf_file.h b/src/core/ngx_conf_file.h
index e92668cd4..4b87f1aad 100644
--- a/src/core/ngx_conf_file.h
+++ b/src/core/ngx_conf_file.h
@@ -14,7 +14,7 @@
/*
- * AAAA number of agruments
+ * AAAA number of arguments
* FF command flags
* TT command type, i.e. HTTP "location" or "server" command
*/
diff --git a/src/core/ngx_connection.c b/src/core/ngx_connection.c
index 4d1aa0d1b..ba1b3f9e2 100644
--- a/src/core/ngx_connection.c
+++ b/src/core/ngx_connection.c
@@ -708,7 +708,7 @@ ngx_close_listening_sockets(ngx_cycle_t *cycle)
/*
* it seems that Linux-2.6.x OpenVZ sends events
* for closed shared listening sockets unless
- * the events was explicity deleted
+ * the events was explicitly deleted
*/
ngx_del_event(c->read, NGX_READ_EVENT, 0);
diff --git a/src/core/ngx_file.c b/src/core/ngx_file.c
index ce3a0a282..d9b30f844 100644
--- a/src/core/ngx_file.c
+++ b/src/core/ngx_file.c
@@ -808,7 +808,7 @@ failed:
* reallocated if ctx->alloc is nonzero
*
* ctx->alloc - a size of data structure that is allocated at every level
- * and is initilialized by ctx->init_handler()
+ * and is initialized by ctx->init_handler()
*
* ctx->log - a log
*
diff --git a/src/core/ngx_inet.c b/src/core/ngx_inet.c
index 2785c8c8c..d2bbbfb58 100644
--- a/src/core/ngx_inet.c
+++ b/src/core/ngx_inet.c
@@ -44,11 +44,7 @@ ngx_inet_addr(u_char *text, size_t len)
return INADDR_NONE;
}
- if (n != 3) {
- return INADDR_NONE;
- }
-
- if (octet < 256) {
+ if (n == 3 && octet < 256) {
addr = (addr << 8) + octet;
return htonl(addr);
}
@@ -407,6 +403,10 @@ ngx_ptocidr(ngx_str_t *text, ngx_cidr_t *cidr)
#if (NGX_HAVE_INET6)
case AF_INET6:
+ if (shift > 128) {
+ return NGX_ERROR;
+ }
+
addr = cidr->u.in6.addr.s6_addr;
mask = cidr->u.in6.mask.s6_addr;
rc = NGX_OK;
@@ -416,7 +416,7 @@ ngx_ptocidr(ngx_str_t *text, ngx_cidr_t *cidr)
s = (shift > 8) ? 8 : shift;
shift -= s;
- mask[i] = (u_char) (0 - (1 << (8 - s)));
+ mask[i] = (u_char) (0xffu << (8 - s));
if (addr[i] != (addr[i] & mask[i])) {
rc = NGX_DONE;
@@ -428,9 +428,12 @@ ngx_ptocidr(ngx_str_t *text, ngx_cidr_t *cidr)
#endif
default: /* AF_INET */
+ if (shift > 32) {
+ return NGX_ERROR;
+ }
if (shift) {
- cidr->u.in.mask = htonl((ngx_uint_t) (0 - (1 << (32 - shift))));
+ cidr->u.in.mask = htonl((uint32_t) (0xffffffffu << (32 - shift)));
} else {
/* x86 compilers use a shl instruction that shifts by modulo 32 */
@@ -459,7 +462,7 @@ ngx_parse_addr(ngx_pool_t *pool, ngx_addr_t *addr, u_char *text, size_t len)
struct sockaddr_in6 *sin6;
/*
- * prevent MSVC8 waring:
+ * prevent MSVC8 warning:
* potentially uninitialized local variable 'inaddr6' used
*/
ngx_memzero(inaddr6.s6_addr, sizeof(struct in6_addr));
diff --git a/src/core/ngx_murmurhash.h b/src/core/ngx_murmurhash.h
index 2b2b70d6c..54e867d30 100644
--- a/src/core/ngx_murmurhash.h
+++ b/src/core/ngx_murmurhash.h
@@ -16,4 +16,4 @@
uint32_t ngx_murmur_hash2(u_char *data, size_t len);
-#endif /* _NGX_CRC_H_INCLUDED_ */
+#endif /* _NGX_MURMURHASH_H_INCLUDED_ */
diff --git a/src/core/ngx_rbtree.c b/src/core/ngx_rbtree.c
index 6ae4d5c05..914ca7e88 100644
--- a/src/core/ngx_rbtree.c
+++ b/src/core/ngx_rbtree.c
@@ -136,8 +136,7 @@ ngx_rbtree_insert_timer_value(ngx_rbtree_node_t *temp, ngx_rbtree_node_t *node,
/* node->key < temp->key */
- p = ((ngx_rbtree_key_int_t) node->key - (ngx_rbtree_key_int_t) temp->key
- < 0)
+ p = ((ngx_rbtree_key_int_t) (node->key - temp->key) < 0)
? &temp->left : &temp->right;
if (*p == sentinel) {
diff --git a/src/core/ngx_times.c b/src/core/ngx_times.c
index 6a5808fe2..ed1bf64bc 100644
--- a/src/core/ngx_times.c
+++ b/src/core/ngx_times.c
@@ -33,7 +33,7 @@ volatile ngx_str_t ngx_cached_http_log_iso8601;
#if !(NGX_WIN32)
/*
- * locatime() and localtime_r() are not Async-Signal-Safe functions, therefore,
+ * localtime() and localtime_r() are not Async-Signal-Safe functions, therefore,
* they must not be called by a signal handler, so we use the cached
* GMT offset value. Fortunately the value is changed only two times a year.
*/
@@ -308,7 +308,7 @@ ngx_gmtime(time_t t, ngx_tm_t *tp)
/*
* The "days" should be adjusted to 1 only, however, some March 1st's go
* to previous year, so we adjust them to 2. This causes also shift of the
- * last Feburary days to next year, but we catch the case when "yday"
+ * last February days to next year, but we catch the case when "yday"
* becomes negative.
*/
diff --git a/src/event/modules/ngx_epoll_module.c b/src/event/modules/ngx_epoll_module.c
index ddf178927..a73394906 100644
--- a/src/event/modules/ngx_epoll_module.c
+++ b/src/event/modules/ngx_epoll_module.c
@@ -445,7 +445,7 @@ ngx_epoll_del_event(ngx_event_t *ev, ngx_int_t event, ngx_uint_t flags)
/*
* when the file descriptor is closed, the epoll automatically deletes
- * it from its queue, so we do not need to delete explicity the event
+ * it from its queue, so we do not need to delete explicitly the event
* before the closing the file descriptor
*/
@@ -524,7 +524,7 @@ ngx_epoll_del_connection(ngx_connection_t *c, ngx_uint_t flags)
/*
* when the file descriptor is closed the epoll automatically deletes
- * it from its queue so we do not need to delete explicity the event
+ * it from its queue so we do not need to delete explicitly the event
* before the closing the file descriptor
*/
diff --git a/src/event/modules/ngx_eventport_module.c b/src/event/modules/ngx_eventport_module.c
index 0bfb47e5c..bbcd6dd6b 100644
--- a/src/event/modules/ngx_eventport_module.c
+++ b/src/event/modules/ngx_eventport_module.c
@@ -322,7 +322,7 @@ ngx_eventport_del_event(ngx_event_t *ev, ngx_int_t event, ngx_uint_t flags)
/*
* when the file descriptor is closed, the event port automatically
- * dissociates it from the port, so we do not need to dissociate explicity
+ * dissociates it from the port, so we do not need to dissociate explicitly
* the event before the closing the file descriptor
*/
diff --git a/src/event/modules/ngx_kqueue_module.c b/src/event/modules/ngx_kqueue_module.c
index c0f70752f..30e456c4d 100644
--- a/src/event/modules/ngx_kqueue_module.c
+++ b/src/event/modules/ngx_kqueue_module.c
@@ -377,7 +377,7 @@ ngx_kqueue_del_event(ngx_event_t *ev, ngx_int_t event, ngx_uint_t flags)
/*
* when the file descriptor is closed the kqueue automatically deletes
- * its filters so we do not need to delete explicity the event
+ * its filters so we do not need to delete explicitly the event
* before the closing the file descriptor.
*/
diff --git a/src/event/ngx_event_openssl.c b/src/event/ngx_event_openssl.c
index fe5cc337d..21deefda9 100644
--- a/src/event/ngx_event_openssl.c
+++ b/src/event/ngx_event_openssl.c
@@ -489,7 +489,7 @@ ngx_ssl_ecdh_curve(ngx_conf_t *cf, ngx_ssl_t *ssl, ngx_str_t *name)
/*
* Elliptic-Curve Diffie-Hellman parameters are either "named curves"
- * from RFC 4492 section 5.1.1, or explicitely described curves over
+ * from RFC 4492 section 5.1.1, or explicitly described curves over
* binary fields. OpenSSL only supports the "named curves", which provide
* maximum interoperability.
*/
diff --git a/src/event/ngx_event_timer.c b/src/event/ngx_event_timer.c
index 7a8107209..177ac1cf1 100644
--- a/src/event/ngx_event_timer.c
+++ b/src/event/ngx_event_timer.c
@@ -67,7 +67,7 @@ ngx_event_find_timer(void)
ngx_mutex_unlock(ngx_event_timer_mutex);
- timer = (ngx_msec_int_t) node->key - (ngx_msec_int_t) ngx_current_msec;
+ timer = (ngx_msec_int_t) (node->key - ngx_current_msec);
return (ngx_msec_t) (timer > 0 ? timer : 0);
}
@@ -95,8 +95,7 @@ ngx_event_expire_timers(void)
/* node->key <= ngx_current_time */
- if ((ngx_msec_int_t) node->key - (ngx_msec_int_t) ngx_current_msec <= 0)
- {
+ if ((ngx_msec_int_t) (node->key - ngx_current_msec) <= 0) {
ev = (ngx_event_t *) ((char *) node - offsetof(ngx_event_t, timer));
#if (NGX_THREADS)
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
*/
diff --git a/src/os/unix/ngx_daemon.c b/src/os/unix/ngx_daemon.c
index f18860bbe..ab6721108 100644
--- a/src/os/unix/ngx_daemon.c
+++ b/src/os/unix/ngx_daemon.c
@@ -9,7 +9,8 @@
#include <ngx_core.h>
-ngx_int_t ngx_daemon(ngx_log_t *log)
+ngx_int_t
+ngx_daemon(ngx_log_t *log)
{
int fd;
diff --git a/src/os/unix/ngx_freebsd_rfork_thread.c b/src/os/unix/ngx_freebsd_rfork_thread.c
index 9506b9de3..530ec4a53 100644
--- a/src/os/unix/ngx_freebsd_rfork_thread.c
+++ b/src/os/unix/ngx_freebsd_rfork_thread.c
@@ -11,14 +11,14 @@
/*
* The threads implementation uses the rfork(RFPROC|RFTHREAD|RFMEM) syscall
* to create threads. All threads use the stacks of the same size mmap()ed
- * below the main stack. Thus the current thread id is determinated via
+ * below the main stack. Thus the current thread id is determined via
* the stack pointer value.
*
* The mutex implementation uses the ngx_atomic_cmp_set() operation
* to acquire a mutex and the SysV semaphore to wait on a mutex and to wake up
* the waiting threads. The light mutex does not use semaphore, so after
* spinning in the lock the thread calls sched_yield(). However the light
- * mutecies are intended to be used with the "trylock" operation only.
+ * mutexes are intended to be used with the "trylock" operation only.
* The SysV semop() is a cheap syscall, particularly if it has little sembuf's
* and does not use SEM_UNDO.
*
diff --git a/src/os/unix/ngx_freebsd_sendfile_chain.c b/src/os/unix/ngx_freebsd_sendfile_chain.c
index 26b326705..724bb0d70 100644
--- a/src/os/unix/ngx_freebsd_sendfile_chain.c
+++ b/src/os/unix/ngx_freebsd_sendfile_chain.c
@@ -18,7 +18,7 @@
* as the 11 full 1460-bytes packets, then one incomplete 324-bytes packet,
* and then again the 11 full 1460-bytes packets.
*
- * Threfore we use the TCP_NOPUSH option (similar to Linux's TCP_CORK)
+ * Therefore we use the TCP_NOPUSH option (similar to Linux's TCP_CORK)
* to postpone the sending - it not only sends a header and the first part of
* the file in one packet, but also sends the file pages in the full packets.
*
diff --git a/src/os/unix/ngx_gcc_atomic_sparc64.h b/src/os/unix/ngx_gcc_atomic_sparc64.h
index d26e1307c..a84db3544 100644
--- a/src/os/unix/ngx_gcc_atomic_sparc64.h
+++ b/src/os/unix/ngx_gcc_atomic_sparc64.h
@@ -15,7 +15,7 @@
* r0 = [r1];
* }
*
- * so "r0 == r2" means that the operation was successfull.
+ * so "r0 == r2" means that the operation was successful.
*
*
* The "r" means the general register.
diff --git a/src/os/unix/ngx_setproctitle.c b/src/os/unix/ngx_setproctitle.c
index a61fe1b94..91afa5191 100644
--- a/src/os/unix/ngx_setproctitle.c
+++ b/src/os/unix/ngx_setproctitle.c
@@ -21,7 +21,7 @@
* from argv[0] for our process title.
*
* The Solaris's standard /bin/ps does not show the changed process title.
- * You have to use "/usr/ucb/ps -w" instead. Besides, the UCB ps dos not
+ * You have to use "/usr/ucb/ps -w" instead. Besides, the UCB ps does not
* show a new title if its length less than the origin command line length.
* To avoid it we append to a new title the origin command line in the
* parenthesis.