summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorIgor Sysoev <igor@sysoev.ru>2009-09-14 13:10:00 +0000
committerJonathan Kolb <jon@b0g.us>2009-09-14 13:10:00 +0000
commit8a41cb8620c2f1ee221a787d601de0766fa7ae2e (patch)
tree2dace3e5d945924f58224761f88553baefefe84f
parentc4d9293fabee88ab2e424824af1f475968774d82 (diff)
downloadnginx-0.7.62.tar.gz
Changes with nginx 0.7.62 14 Sep 2009v0.7.62
*) Security: a segmentation fault might occur in worker process while specially crafted request handling. Thanks to Chris Ries. *) Feature: the $upstream_cache_status variable. *) Bugfix: an expired cached response might stick in the "UPDATING" state. *) Bugfix: a segmentation fault might occur in worker process, if error_log was set to info or debug level. Thanks to Sergey Bochenkov. *) Bugfix: in handling FastCGI headers split in records. *) Bugfix: XSLT filter may fail with message "not well formed XML document" for valid XML document. Thanks to Kuramoto Eiji. *) Bugfix: now in MacOSX, Cygwin, and nginx/Windows locations given by a regular expression are always tested in case insensitive mode. *) Bugfix: now nginx/Windows ignores trailing dots in URI. Thanks to Hugo Leisink. *) Bugfix: name of file specified in --conf-path was not honored during installation; the bug had appeared in 0.6.6. Thanks to Maxim Dounin. *) Bugfix: a 500 error code was returned for invalid login/password while HTTP Basic authentication on Windows.
-rw-r--r--CHANGES49
-rw-r--r--CHANGES.ru45
-rw-r--r--auto/install2
-rw-r--r--auto/os/linux2
-rw-r--r--src/core/nginx.h4
-rw-r--r--src/core/ngx_buf.h10
-rw-r--r--src/core/ngx_string.c2
-rw-r--r--src/http/modules/ngx_http_fastcgi_module.c56
-rw-r--r--src/http/modules/ngx_http_xslt_filter_module.c9
-rw-r--r--src/http/modules/perl/nginx.pm2
-rw-r--r--src/http/ngx_http_cache.h10
-rw-r--r--src/http/ngx_http_core_module.c26
-rw-r--r--src/http/ngx_http_core_module.h2
-rw-r--r--src/http/ngx_http_file_cache.c9
-rw-r--r--src/http/ngx_http_parse.c86
-rw-r--r--src/http/ngx_http_request.c52
-rw-r--r--src/http/ngx_http_script.c6
-rw-r--r--src/http/ngx_http_upstream.c99
-rw-r--r--src/http/ngx_http_upstream.h2
-rw-r--r--src/os/unix/ngx_process.c1
-rw-r--r--src/os/unix/ngx_process_cycle.c11
-rw-r--r--src/os/unix/ngx_process_cycle.h1
22 files changed, 297 insertions, 189 deletions
diff --git a/CHANGES b/CHANGES
index eca01fd63..7938a05a2 100644
--- a/CHANGES
+++ b/CHANGES
@@ -1,8 +1,42 @@
+Changes with nginx 0.7.62 14 Sep 2009
+
+ *) Security: a segmentation fault might occur in worker process while
+ specially crafted request handling.
+ Thanks to Chris Ries.
+
+ *) Feature: the $upstream_cache_status variable.
+
+ *) Bugfix: an expired cached response might stick in the "UPDATING"
+ state.
+
+ *) Bugfix: a segmentation fault might occur in worker process, if
+ error_log was set to info or debug level.
+ Thanks to Sergey Bochenkov.
+
+ *) Bugfix: in handling FastCGI headers split in records.
+
+ *) Bugfix: XSLT filter may fail with message "not well formed XML
+ document" for valid XML document.
+ Thanks to Kuramoto Eiji.
+
+ *) Bugfix: now in MacOSX, Cygwin, and nginx/Windows locations given by
+ a regular expression are always tested in case insensitive mode.
+
+ *) Bugfix: now nginx/Windows ignores trailing dots in URI.
+ Thanks to Hugo Leisink.
+
+ *) Bugfix: name of file specified in --conf-path was not honored during
+ installation; the bug had appeared in 0.6.6.
+ Thanks to Maxim Dounin.
+
+ *) Bugfix: a 500 error code was returned for invalid login/password
+ while HTTP Basic authentication on Windows.
+
+
Changes with nginx 0.7.61 22 Jun 2009
- *) Bugfix: nginx could not be built on MacOSX 10.6. the bug had
- appeared in 0.8.2.
+ *) Bugfix: nginx could not be built on MacOSX 10.6.
*) Bugfix: nginx could not be built --without-http-cache; the bug had
appeared in 0.7.60.
@@ -23,7 +57,8 @@ Changes with nginx 0.7.60 15 Jun 2009
*) Bugfix: in open_file_cache and proxy/fastcgi cache interaction on
start up.
- *) Bugfix: open_file_cache might cache open file descriptors too long.
+ *) Bugfix: open_file_cache might cache open file descriptors too long;
+ the bug had appeared in 0.7.4.
*) Bugfix: the "If-Modified-Since", "If-Range", etc. client request
header lines were passed to backend while caching if no
@@ -1828,8 +1863,8 @@ Changes with nginx 0.5.12 12 Feb 2007
amd64, sparc, and ppc; the bug had appeared in 0.5.8.
*) Bugfix: a segmentation fault might occur in worker process if the
- temporarily files were used while working with FastCGI server; the
- bug had appeared in 0.5.8.
+ temporary files were used while working with FastCGI server; the bug
+ had appeared in 0.5.8.
*) Bugfix: a segmentation fault might occur in worker process if the
$fastcgi_script_name variable was logged.
@@ -2732,8 +2767,8 @@ Changes with nginx 0.3.31 10 Mar 2006
in 0.3.18.
*) Bugfix: if the HTTPS protocol was used in the "proxy_pass" directive
- and the request body was in temporarily file then the request was
- not transferred.
+ and the request body was in temporary file then the request was not
+ transferred.
*) Bugfix: perl 5.8.8 compatibility.
diff --git a/CHANGES.ru b/CHANGES.ru
index 5a0caf797..a789b0e39 100644
--- a/CHANGES.ru
+++ b/CHANGES.ru
@@ -1,4 +1,41 @@
+Изменения в nginx 0.7.62 14.09.2009
+
+ *) Безопасность: при обработке специально созданного запроса в рабочем
+ процессе мог произойти segmentation fault.
+ Спасибо Chris Ries.
+
+ *) Добавление: переменная $upstream_cache_status.
+
+ *) Исправление: устаревший закэшированный запрос мог залипнуть в
+ состоянии "UPDATING".
+
+ *) Исправление: при использовании error_log на уровне info или debug в
+ рабочем процессе мог произойти segmentation fault.
+ Спасибо Сергею Боченкову.
+
+ *) Исправление: в обработке заголовков ответа, разделённых в
+ FastCGI-записях.
+
+ *) Исправление: XSLT-фильтр мог выдавать ошибку "not well formed XML
+ document" для правильного документа.
+ Спасибо Kuramoto Eiji.
+
+ *) Исправление: в MacOSX, Cygwin и nginx/Windows при проверке
+ location'ов, заданных регулярным выражением, теперь всегда делается
+ сравнение без учёта регистра символов.
+
+ *) Исправление: теперь nginx/Windows игнорирует точки в конце URI.
+ Спасибо Hugo Leisink.
+
+ *) Исправление: имя файла указанного в --conf-path игнорировалось при
+ установке; ошибка появилась в 0.6.6.
+ Спасибо Максиму Дунину.
+
+ *) Исправление: при использовании HTTP Basic-аутентификации на Windows
+ для неверных имени/пароля возвращалась 500-ая ошибка.
+
+
Изменения в nginx 0.7.61 22.06.2009
*) Исправление: nginx не собирался на MacOSX 10.6.
@@ -6,9 +43,9 @@
*) Исправление: nginx не собирался с параметром --without-http-cache;
ошибка появилась в 0.7.60.
- *) Исправление: если было использовался перехват 401 ошибки от бэкенда
- и бэкенд не возвращал строку "WWW-Authenticate" в заголовке ответа,
- то в рабочем процессе происходил segmentation fault.
+ *) Исправление: если использовался перехват 401 ошибки от бэкенда и
+ бэкенд не возвращал строку "WWW-Authenticate" в заголовке ответа, то
+ в рабочем процессе происходил segmentation fault.
Спасибо Евгению Мычло.
@@ -23,7 +60,7 @@
на старте.
*) Исправление: open_file_cache мог кэшировать открытые файлы очень
- долго.
+ долго; ошибка появилась в 0.7.4.
*) Исправление: строки "If-Modified-Since", "If-Range" и им подобные в
заголовке запроса клиента передавались бэкенду при кэшировании, если
diff --git a/auto/install b/auto/install
index c17dac612..f876891f8 100644
--- a/auto/install
+++ b/auto/install
@@ -102,7 +102,7 @@ install: $NGX_OBJS${ngx_dirsep}nginx${ngx_binext} \
'\$(DESTDIR)$NGX_CONF_PREFIX/fastcgi_params.default'
test -f '\$(DESTDIR)$NGX_CONF_PATH' \
- || cp conf/nginx.conf '\$(DESTDIR)$NGX_CONF_PREFIX'
+ || cp conf/nginx.conf '\$(DESTDIR)$NGX_CONF_PATH'
cp conf/nginx.conf '\$(DESTDIR)$NGX_CONF_PREFIX/nginx.conf.default'
test -d '\$(DESTDIR)`dirname "$NGX_PID_PATH"`' \
diff --git a/auto/os/linux b/auto/os/linux
index 0bd04880d..ed296ce90 100644
--- a/auto/os/linux
+++ b/auto/os/linux
@@ -18,7 +18,7 @@ CC_AUX_FLAGS="$cc_aux_flags -D_GNU_SOURCE -D_FILE_OFFSET_BITS=64"
# Linux kernel version
version=$((`uname -r \
- | sed 's/^\([^.]*\)\.\([^.]*\)\.\([^.-]*\).*/\1*256*256+\2*256+\3/'`))
+ | sed 's/^\([0-9]*\)\.\([0-9]*\)\.\([0-9]*\).*/\1*256*256+\2*256+\3/'`))
version=${version:-0}
diff --git a/src/core/nginx.h b/src/core/nginx.h
index 4c2722007..83bafc613 100644
--- a/src/core/nginx.h
+++ b/src/core/nginx.h
@@ -8,8 +8,8 @@
#define _NGINX_H_INCLUDED_
-#define nginx_version 7061
-#define NGINX_VERSION "0.7.61"
+#define nginx_version 7062
+#define NGINX_VERSION "0.7.62"
#define NGINX_VER "nginx/" NGINX_VERSION
#define NGINX_VAR "NGINX"
diff --git a/src/core/ngx_buf.h b/src/core/ngx_buf.h
index 8649bdb9e..56e03992d 100644
--- a/src/core/ngx_buf.h
+++ b/src/core/ngx_buf.h
@@ -75,13 +75,13 @@ typedef struct {
ngx_chain_t *free;
ngx_chain_t *busy;
- unsigned sendfile;
- unsigned directio;
+ unsigned sendfile:1;
+ unsigned directio:1;
#if (NGX_HAVE_ALIGNED_DIRECTIO)
- unsigned unaligned;
+ unsigned unaligned:1;
#endif
- unsigned need_in_memory;
- unsigned need_in_temp;
+ unsigned need_in_memory:1;
+ unsigned need_in_temp:1;
ngx_pool_t *pool;
ngx_int_t allocated;
diff --git a/src/core/ngx_string.c b/src/core/ngx_string.c
index d73cb8699..e73dc41d8 100644
--- a/src/core/ngx_string.c
+++ b/src/core/ngx_string.c
@@ -87,7 +87,7 @@ ngx_pstrdup(ngx_pool_t *pool, ngx_str_t *src)
*
* reserved:
* %t ptrdiff_t
- * %S null-teminated wchar string
+ * %S null-terminated wchar string
* %C wchar
*/
diff --git a/src/http/modules/ngx_http_fastcgi_module.c b/src/http/modules/ngx_http_fastcgi_module.c
index f752398db..736a68600 100644
--- a/src/http/modules/ngx_http_fastcgi_module.c
+++ b/src/http/modules/ngx_http_fastcgi_module.c
@@ -1072,9 +1072,10 @@ ngx_http_fastcgi_reinit_request(ngx_http_request_t *r)
static ngx_int_t
ngx_http_fastcgi_process_header(ngx_http_request_t *r)
{
- u_char *p, *start, *last, *part_start;
+ u_char *p, *msg, *start, *last,
+ *part_start, *part_end;
size_t size;
- ngx_str_t *status_line, line, *pattern;
+ ngx_str_t *status_line, *pattern;
ngx_int_t rc, status;
ngx_buf_t buf;
ngx_uint_t i;
@@ -1158,40 +1159,39 @@ ngx_http_fastcgi_process_header(ngx_http_request_t *r)
if (f->type == NGX_HTTP_FASTCGI_STDERR) {
if (f->length) {
- line.data = u->buffer.pos;
+ msg = u->buffer.pos;
if (u->buffer.pos + f->length <= u->buffer.last) {
- line.len = f->length;
u->buffer.pos += f->length;
f->length = 0;
f->state = ngx_http_fastcgi_st_padding;
} else {
- line.len = u->buffer.last - u->buffer.pos;
f->length -= u->buffer.last - u->buffer.pos;
u->buffer.pos = u->buffer.last;
}
- while (line.data[line.len - 1] == LF
- || line.data[line.len - 1] == CR
- || line.data[line.len - 1] == '.'
- || line.data[line.len - 1] == ' ')
- {
- line.len--;
+ for (p = u->buffer.pos - 1; msg < p; p--) {
+ if (*p != LF && *p != CR && *p != '.' && *p != ' ') {
+ break;
+ }
}
+ p++;
+
ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
- "FastCGI sent in stderr: \"%V\"", &line);
+ "FastCGI sent in stderr: \"%*s\"", p - msg, msg);
flcf = ngx_http_get_module_loc_conf(r, ngx_http_fastcgi_module);
if (flcf->catch_stderr) {
pattern = flcf->catch_stderr->elts;
- line.data[line.len - 1] = '\0';
-
for (i = 0; i < flcf->catch_stderr->nelts; i++) {
- if (ngx_strstr(line.data, pattern[i].data)) {
+ if (ngx_strnstr(msg, (char *) pattern[i].data,
+ p - msg)
+ != NULL)
+ {
return NGX_HTTP_UPSTREAM_INVALID_HEADER;
}
}
@@ -1244,6 +1244,7 @@ ngx_http_fastcgi_process_header(ngx_http_request_t *r)
for ( ;; ) {
part_start = u->buffer.pos;
+ part_end = u->buffer.last;
rc = ngx_http_parse_header_line(r, &u->buffer, 1);
@@ -1444,7 +1445,11 @@ ngx_http_fastcgi_process_header(ngx_http_request_t *r)
part = ngx_array_push(f->split_parts);
part->start = part_start;
- part->end = u->buffer.last;
+ part->end = part_end;
+
+ if (u->buffer.pos < u->buffer.last) {
+ continue;
+ }
return NGX_AGAIN;
}
@@ -1454,9 +1459,9 @@ ngx_http_fastcgi_process_header(ngx_http_request_t *r)
static ngx_int_t
ngx_http_fastcgi_input_filter(ngx_event_pipe_t *p, ngx_buf_t *buf)
{
+ u_char *m, *msg;
ngx_int_t rc;
ngx_buf_t *b, **prev;
- ngx_str_t line;
ngx_chain_t *cl;
ngx_http_request_t *r;
ngx_http_fastcgi_ctx_t *f;
@@ -1540,30 +1545,27 @@ ngx_http_fastcgi_input_filter(ngx_event_pipe_t *p, ngx_buf_t *buf)
break;
}
- line.data = f->pos;
+ msg = f->pos;
if (f->pos + f->length <= f->last) {
- line.len = f->length;
f->pos += f->length;
f->length = 0;
f->state = ngx_http_fastcgi_st_padding;
} else {
- line.len = f->last - f->pos;
f->length -= f->last - f->pos;
f->pos = f->last;
}
- while (line.data[line.len - 1] == LF
- || line.data[line.len - 1] == CR
- || line.data[line.len - 1] == '.'
- || line.data[line.len - 1] == ' ')
- {
- line.len--;
+ for (m = f->pos - 1; msg < m; m--) {
+ if (*m != LF && *m != CR && *m != '.' && *m != ' ') {
+ break;
+ }
}
ngx_log_error(NGX_LOG_ERR, p->log, 0,
- "FastCGI sent in stderr: \"%V\"", &line);
+ "FastCGI sent in stderr: \"%*s\"",
+ m + 1 - msg, msg);
if (f->pos == f->last) {
break;
diff --git a/src/http/modules/ngx_http_xslt_filter_module.c b/src/http/modules/ngx_http_xslt_filter_module.c
index ab3118f78..afa605a23 100644
--- a/src/http/modules/ngx_http_xslt_filter_module.c
+++ b/src/http/modules/ngx_http_xslt_filter_module.c
@@ -194,7 +194,7 @@ ngx_module_t ngx_http_xslt_filter_module = {
NULL, /* init process */
NULL, /* init thread */
NULL, /* exit thread */
- ngx_http_xslt_filter_exit, /* exit process */
+ ngx_http_xslt_filter_exit, /* exit process */
ngx_http_xslt_filter_exit, /* exit master */
NGX_MODULE_V1_PADDING
};
@@ -247,6 +247,7 @@ ngx_http_xslt_header_filter(ngx_http_request_t *r)
static ngx_int_t
ngx_http_xslt_body_filter(ngx_http_request_t *r, ngx_chain_t *in)
{
+ int wellFormed;
ngx_chain_t *cl;
ngx_http_xslt_filter_ctx_t *ctx;
@@ -288,9 +289,11 @@ ngx_http_xslt_body_filter(ngx_http_request_t *r, ngx_chain_t *in)
ctx->doc->extSubset = NULL;
#endif
+ wellFormed = ctx->ctxt->wellFormed;
+
xmlFreeParserCtxt(ctx->ctxt);
- if (ctx->ctxt->wellFormed) {
+ if (wellFormed) {
return ngx_http_xslt_send(r, ctx,
ngx_http_xslt_apply_stylesheet(r, ctx));
}
@@ -717,7 +720,7 @@ ngx_http_xslt_sax_error(void *data, const char *msg, ...)
while (--n && (buf[n] == CR || buf[n] == LF)) { /* void */ }
ngx_log_error(NGX_LOG_ERR, ctx->request->connection->log, 0,
- "libxml2 error: \"%*s\"", n, buf);
+ "libxml2 error: \"%*s\"", n + 1, buf);
}
diff --git a/src/http/modules/perl/nginx.pm b/src/http/modules/perl/nginx.pm
index 84459d444..144d4927c 100644
--- a/src/http/modules/perl/nginx.pm
+++ b/src/http/modules/perl/nginx.pm
@@ -47,7 +47,7 @@ our @EXPORT = qw(
HTTP_INSUFFICIENT_STORAGE
);
-our $VERSION = '0.7.61';
+our $VERSION = '0.7.62';
require XSLoader;
XSLoader::load('nginx', $VERSION);
diff --git a/src/http/ngx_http_cache.h b/src/http/ngx_http_cache.h
index cf909cc3d..1ee80751d 100644
--- a/src/http/ngx_http_cache.h
+++ b/src/http/ngx_http_cache.h
@@ -13,8 +13,11 @@
#include <ngx_http.h>
-#define NGX_HTTP_CACHE_STALE 1
-#define NGX_HTTP_CACHE_UPDATING 2
+#define NGX_HTTP_CACHE_MISS 1
+#define NGX_HTTP_CACHE_EXPIRED 2
+#define NGX_HTTP_CACHE_STALE 3
+#define NGX_HTTP_CACHE_UPDATING 4
+#define NGX_HTTP_CACHE_HIT 5
#define NGX_HTTP_CACHE_KEY_LEN 16
@@ -124,11 +127,12 @@ ngx_int_t ngx_http_cache_send(ngx_http_request_t *);
void ngx_http_file_cache_free(ngx_http_request_t *r, ngx_temp_file_t *tf);
time_t ngx_http_file_cache_valid(ngx_array_t *cache_valid, ngx_uint_t status);
-
char *ngx_http_file_cache_set_slot(ngx_conf_t *cf, ngx_command_t *cmd,
void *conf);
char *ngx_http_file_cache_valid_set_slot(ngx_conf_t *cf, ngx_command_t *cmd,
void *conf);
+extern ngx_str_t ngx_http_cache_status[];
+
#endif /* _NGX_HTTP_CACHE_H_INCLUDED_ */
diff --git a/src/http/ngx_http_core_module.c b/src/http/ngx_http_core_module.c
index 538ef7214..2e3b91393 100644
--- a/src/http/ngx_http_core_module.c
+++ b/src/http/ngx_http_core_module.c
@@ -1220,10 +1220,7 @@ ngx_http_core_try_files_phase(ngx_http_request_t *r,
ngx_memcpy(p, name, path.len);
}
- if (ngx_http_set_exten(r) != NGX_OK) {
- ngx_http_finalize_request(r, NGX_HTTP_INTERNAL_SERVER_ERROR);
- return NGX_OK;
- }
+ ngx_http_set_exten(r);
ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
"try file uri: \"%V\"", &r->uri);
@@ -1633,7 +1630,7 @@ ngx_http_set_content_type(ngx_http_request_t *r)
}
-ngx_int_t
+void
ngx_http_set_exten(ngx_http_request_t *r)
{
ngx_int_t i;
@@ -1647,14 +1644,14 @@ ngx_http_set_exten(ngx_http_request_t *r)
r->exten.len = r->uri.len - i - 1;
r->exten.data = &r->uri.data[i + 1];
- break;
+ return;
} else if (r->uri.data[i] == '/') {
- break;
+ return;
}
}
- return NGX_OK;
+ return;
}
@@ -2079,9 +2076,7 @@ ngx_http_subrequest(ngx_http_request_t *r,
sr->method_name = ngx_http_core_get_method;
sr->http_protocol = r->http_protocol;
- if (ngx_http_set_exten(sr) != NGX_OK) {
- return NGX_ERROR;
- }
+ ngx_http_set_exten(sr);
sr->main = r->main;
sr->parent = r;
@@ -2160,10 +2155,7 @@ ngx_http_internal_redirect(ngx_http_request_t *r,
ngx_log_debug2(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
"internal redirect: \"%V?%V\"", uri, &r->args);
- if (ngx_http_set_exten(r) != NGX_OK) {
- ngx_http_finalize_request(r, NGX_HTTP_INTERNAL_SERVER_ERROR);
- return NGX_DONE;
- }
+ ngx_http_set_exten(r);
/* clear the modules contexts */
ngx_memzero(r->ctx, sizeof(void *) * ngx_http_max_module);
@@ -2566,6 +2558,10 @@ ngx_http_core_regex_location(ngx_conf_t *cf, ngx_http_core_loc_conf_t *clcf,
err.len = NGX_MAX_CONF_ERRSTR;
err.data = errstr;
+#if (NGX_HAVE_CASELESS_FILESYSTEM)
+ caseless = 1;
+#endif
+
clcf->regex = ngx_regex_compile(regex, caseless ? NGX_REGEX_CASELESS: 0,
cf->pool, &err);
diff --git a/src/http/ngx_http_core_module.h b/src/http/ngx_http_core_module.h
index 650183f05..e5b68f330 100644
--- a/src/http/ngx_http_core_module.h
+++ b/src/http/ngx_http_core_module.h
@@ -437,7 +437,7 @@ ngx_int_t ngx_http_core_content_phase(ngx_http_request_t *r,
void *ngx_http_test_content_type(ngx_http_request_t *r, ngx_hash_t *types_hash);
ngx_int_t ngx_http_set_content_type(ngx_http_request_t *r);
-ngx_int_t ngx_http_set_exten(ngx_http_request_t *r);
+void ngx_http_set_exten(ngx_http_request_t *r);
u_char *ngx_http_map_uri_to_path(ngx_http_request_t *r, ngx_str_t *name,
size_t *root_length, size_t reserved);
ngx_int_t ngx_http_auth_basic_user(ngx_http_request_t *r);
diff --git a/src/http/ngx_http_file_cache.c b/src/http/ngx_http_file_cache.c
index 323358742..8e908a1dc 100644
--- a/src/http/ngx_http_file_cache.c
+++ b/src/http/ngx_http_file_cache.c
@@ -35,6 +35,15 @@ static ngx_int_t ngx_http_file_cache_delete_file(ngx_tree_ctx_t *ctx,
ngx_str_t *path);
+ngx_str_t ngx_http_cache_status[] = {
+ ngx_string("MISS"),
+ ngx_string("EXPIRED"),
+ ngx_string("STALE"),
+ ngx_string("UPDATING"),
+ ngx_string("HIT")
+};
+
+
static u_char ngx_http_file_cache_key[] = { LF, 'K', 'E', 'Y', ':', ' ' };
diff --git a/src/http/ngx_http_parse.c b/src/http/ngx_http_parse.c
index 4aa1be8ed..160f96dbe 100644
--- a/src/http/ngx_http_parse.c
+++ b/src/http/ngx_http_parse.c
@@ -739,6 +739,7 @@ ngx_http_parse_header_line(ngx_http_request_t *r, ngx_buf_t *b,
/* first char */
case sw_start:
+ r->header_name_start = p;
r->invalid_header = 0;
switch (ch) {
@@ -751,7 +752,6 @@ ngx_http_parse_header_line(ngx_http_request_t *r, ngx_buf_t *b,
goto header_done;
default:
state = sw_name;
- r->header_name_start = p;
c = lowcase[ch];
@@ -950,9 +950,6 @@ ngx_http_parse_complex_uri(ngx_http_request_t *r, ngx_uint_t merge_slashes)
sw_slash,
sw_dot,
sw_dot_dot,
-#if (NGX_WIN32)
- sw_dot_dot_dot,
-#endif
sw_quoted,
sw_quoted_second
} state, quoted_state;
@@ -1137,65 +1134,15 @@ ngx_http_parse_complex_uri(ngx_http_request_t *r, ngx_uint_t merge_slashes)
#endif
case '/':
state = sw_slash;
- u -= 4;
- if (u < r->uri.data) {
- return NGX_HTTP_PARSE_INVALID_REQUEST;
- }
- while (*(u - 1) != '/') {
- u--;
- }
- break;
- case '%':
- quoted_state = state;
- state = sw_quoted;
- break;
- case '?':
- r->args_start = p;
- goto args;
- case '#':
- goto done;
-#if (NGX_WIN32)
- case '.':
- state = sw_dot_dot_dot;
- *u++ = ch;
- break;
-#endif
- case '+':
- r->plus_in_uri = 1;
- default:
- state = sw_usual;
- *u++ = ch;
- break;
- }
-
- ch = *p++;
- break;
-
-#if (NGX_WIN32)
- case sw_dot_dot_dot:
-
- if (usual[ch >> 5] & (1 << (ch & 0x1f))) {
- state = sw_usual;
- *u++ = ch;
- ch = *p++;
- break;
- }
-
- switch(ch) {
- case '\\':
- case '/':
- state = sw_slash;
u -= 5;
- if (u < r->uri.data) {
- return NGX_HTTP_PARSE_INVALID_REQUEST;
- }
- while (*u != '/') {
- u--;
- }
- if (u < r->uri.data) {
- return NGX_HTTP_PARSE_INVALID_REQUEST;
- }
- while (*(u - 1) != '/') {
+ for ( ;; ) {
+ if (u < r->uri.data) {
+ return NGX_HTTP_PARSE_INVALID_REQUEST;
+ }
+ if (*u == '/') {
+ u++;
+ break;
+ }
u--;
}
break;
@@ -1218,7 +1165,6 @@ ngx_http_parse_complex_uri(ngx_http_request_t *r, ngx_uint_t merge_slashes)
ch = *p++;
break;
-#endif
case sw_quoted:
r->quoted_uri = 1;
@@ -1369,20 +1315,6 @@ ngx_http_parse_unsafe_uri(ngx_http_request_t *r, ngx_str_t *uri,
if (p[0] == '.' && p[1] == '.' && ngx_path_separator(p[2])) {
goto unsafe;
}
-
-#if (NGX_WIN32)
-
- if (len > 3) {
-
- /* detect "/.../" */
-
- if (p[0] == '.' && p[1] == '.' && p[2] == '.'
- && ngx_path_separator(p[3]))
- {
- goto unsafe;
- }
- }
-#endif
}
}
diff --git a/src/http/ngx_http_request.c b/src/http/ngx_http_request.c
index b108394bf..4930b502f 100644
--- a/src/http/ngx_http_request.c
+++ b/src/http/ngx_http_request.c
@@ -763,6 +763,22 @@ ngx_http_process_request_line(ngx_event_t *rev)
r->args.data = r->args_start;
}
+#if (NGX_WIN32)
+ {
+ u_char *p;
+
+ p = r->uri.data + r->uri.len - 1;
+
+ if (*p == '.') {
+
+ while (--p > r->uri.data && *p == '.') { /* void */ }
+
+ r->uri.len = p + 1 - r->uri.data;
+
+ ngx_http_set_exten(r);
+ }
+ }
+#endif
ngx_log_debug1(NGX_LOG_DEBUG_HTTP, c->log, 0,
"http request line: \"%V\"", &r->request_line);
@@ -869,9 +885,10 @@ ngx_http_process_request_line(ngx_event_t *rev)
static void
ngx_http_process_request_headers(ngx_event_t *rev)
{
+ u_char *p;
+ size_t len;
ssize_t n;
ngx_int_t rc, rv;
- ngx_str_t header;
ngx_table_elt_t *h;
ngx_connection_t *c;
ngx_http_header_t *hh;
@@ -911,19 +928,17 @@ ngx_http_process_request_headers(ngx_event_t *rev)
}
if (rv == NGX_DECLINED) {
- header.len = r->header_in->end - r->header_name_start;
- header.data = r->header_name_start;
-
- if (header.len > NGX_MAX_ERROR_STR - 300) {
- header.len = NGX_MAX_ERROR_STR - 300;
- header.data[header.len++] = '.';
- header.data[header.len++] = '.';
- header.data[header.len++] = '.';
+ len = r->header_in->end - r->header_name_start;
+ p = r->header_name_start;
+
+ if (len > NGX_MAX_ERROR_STR - 300) {
+ len = NGX_MAX_ERROR_STR - 300;
+ p[len++] = '.'; p[len++] = '.'; p[len++] = '.';
}
ngx_log_error(NGX_LOG_INFO, c->log, 0,
- "client sent too long header line: \"%V\"",
- &header);
+ "client sent too long header line: \"%*s\"",
+ len, r->header_name_start);
ngx_http_finalize_request(r, NGX_HTTP_BAD_REQUEST);
return;
}
@@ -945,12 +960,10 @@ ngx_http_process_request_headers(ngx_event_t *rev)
/* there was error while a header line parsing */
- header.len = r->header_end - r->header_name_start;
- header.data = r->header_name_start;
-
ngx_log_error(NGX_LOG_INFO, c->log, 0,
- "client sent invalid header line: \"%V\"",
- &header);
+ "client sent invalid header line: \"%*s\"",
+ r->header_end - r->header_name_start,
+ r->header_name_start);
continue;
}
@@ -1030,11 +1043,10 @@ ngx_http_process_request_headers(ngx_event_t *rev)
/* rc == NGX_HTTP_PARSE_INVALID_HEADER: "\r" is not followed by "\n" */
- header.len = r->header_end - r->header_name_start;
- header.data = r->header_name_start;
ngx_log_error(NGX_LOG_INFO, c->log, 0,
- "client sent invalid header line: \"%V\\r...\"",
- &header);
+ "client sent invalid header line: \"%*s\\r...\"",
+ r->header_end - r->header_name_start,
+ r->header_name_start);
ngx_http_finalize_request(r, NGX_HTTP_BAD_REQUEST);
return;
}
diff --git a/src/http/ngx_http_script.c b/src/http/ngx_http_script.c
index b8e998abb..f67c6628d 100644
--- a/src/http/ngx_http_script.c
+++ b/src/http/ngx_http_script.c
@@ -1074,11 +1074,7 @@ ngx_http_script_regex_end_code(ngx_http_script_engine_t *e)
return;
}
- if (ngx_http_set_exten(r) != NGX_OK) {
- e->ip = ngx_http_script_exit;
- e->status = NGX_HTTP_INTERNAL_SERVER_ERROR;
- return;
- }
+ ngx_http_set_exten(r);
}
e->ip += sizeof(ngx_http_script_regex_end_code_t);
diff --git a/src/http/ngx_http_upstream.c b/src/http/ngx_http_upstream.c
index c04e643fb..8c7f9a473 100644
--- a/src/http/ngx_http_upstream.c
+++ b/src/http/ngx_http_upstream.c
@@ -14,6 +14,8 @@ static ngx_int_t ngx_http_upstream_cache(ngx_http_request_t *r,
ngx_http_upstream_t *u);
static ngx_int_t ngx_http_upstream_cache_send(ngx_http_request_t *r,
ngx_http_upstream_t *u);
+static ngx_int_t ngx_http_upstream_cache_status(ngx_http_request_t *r,
+ ngx_http_variable_value_t *v, uintptr_t data);
#endif
static void ngx_http_upstream_resolve_handler(ngx_resolver_ctx_t *ctx);
@@ -159,6 +161,12 @@ ngx_http_upstream_header_t ngx_http_upstream_headers_in[] = {
offsetof(ngx_http_upstream_headers_in_t, last_modified),
ngx_http_upstream_copy_last_modified, 0, 0 },
+ { ngx_string("ETag"),
+ ngx_http_upstream_process_header_line,
+ offsetof(ngx_http_upstream_headers_in_t, etag),
+ ngx_http_upstream_copy_header_line,
+ offsetof(ngx_http_headers_out_t, etag), 0 },
+
{ ngx_string("Server"),
ngx_http_upstream_process_header_line,
offsetof(ngx_http_upstream_headers_in_t, server),
@@ -316,6 +324,14 @@ static ngx_http_variable_t ngx_http_upstream_vars[] = {
ngx_http_upstream_response_length_variable, 0,
NGX_HTTP_VAR_NOHASH|NGX_HTTP_VAR_NOCACHEABLE, 0 },
+#if (NGX_HTTP_CACHE)
+
+ { ngx_string("upstream_cache_status"), NULL,
+ ngx_http_upstream_cache_status, 0,
+ NGX_HTTP_VAR_NOHASH|NGX_HTTP_VAR_NOCACHEABLE, 0 },
+
+#endif
+
{ ngx_null_string, NULL, NULL, 0, 0, 0 }
};
@@ -575,21 +591,34 @@ ngx_http_upstream_cache(ngx_http_request_t *r, ngx_http_upstream_t *u)
c->body_start = u->conf->buffer_size;
c->file_cache = u->conf->cache->data;
+ u->cache_status = NGX_HTTP_CACHE_MISS;
+
rc = ngx_http_file_cache_open(r);
ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
"http upstream cache: %i", rc);
- if (rc == NGX_HTTP_CACHE_UPDATING) {
+ switch (rc) {
+
+ case NGX_HTTP_CACHE_UPDATING:
+
if (u->conf->cache_use_stale & NGX_HTTP_UPSTREAM_FT_UPDATING) {
+ u->cache_status = rc;
rc = NGX_OK;
} else {
rc = NGX_HTTP_CACHE_STALE;
}
+
+ break;
+
+ case NGX_OK:
+ u->cache_status = NGX_HTTP_CACHE_HIT;
}
- if (rc == NGX_OK) {
+ switch (rc) {
+
+ case NGX_OK:
rc = ngx_http_upstream_cache_send(r, u);
@@ -597,17 +626,21 @@ ngx_http_upstream_cache(ngx_http_request_t *r, ngx_http_upstream_t *u)
return rc;
}
- } else if (rc == NGX_ERROR) {
+ break;
+
+ case NGX_ERROR:
return NGX_ERROR;
- } else if (rc == NGX_HTTP_CACHE_STALE) {
+ case NGX_HTTP_CACHE_STALE:
c->valid_sec = 0;
- u->stale_cache = 1;
u->buffer.start = NULL;
+ u->cache_status = NGX_HTTP_CACHE_EXPIRED;
- } else if (rc == NGX_DECLINED) {
+ break;
+
+ case NGX_DECLINED:
if ((size_t) (u->buffer.end - u->buffer.start) < u->conf->buffer_size) {
u->buffer.start = NULL;
@@ -617,14 +650,20 @@ ngx_http_upstream_cache(ngx_http_request_t *r, ngx_http_upstream_t *u)
u->buffer.last = u->buffer.pos;
}
- } else if (rc == NGX_AGAIN) {
+ break;
+
+ case NGX_AGAIN:
u->cacheable = 0;
- } else {
+ break;
+
+ default:
/* cached NGX_HTTP_BAD_GATEWAY, NGX_HTTP_GATEWAY_TIME_OUT, etc. */
+ u->cache_status = NGX_HTTP_CACHE_HIT;
+
return rc;
}
@@ -640,6 +679,7 @@ ngx_http_upstream_cache_send(ngx_http_request_t *r, ngx_http_upstream_t *u)
ngx_int_t rc;
ngx_http_cache_t *c;
+ r->cached = 1;
c = r->cache;
/* TODO: cache stack */
@@ -1521,12 +1561,15 @@ ngx_http_upstream_test_next(ngx_http_request_t *r, ngx_http_upstream_t *u)
#if (NGX_HTTP_CACHE)
- if (u->stale_cache && (u->conf->cache_use_stale & un->mask)) {
+ if (u->cache_status == NGX_HTTP_CACHE_EXPIRED
+ && (u->conf->cache_use_stale & un->mask))
+ {
ngx_int_t rc;
rc = u->reinit_request(r);
if (rc == NGX_OK) {
+ u->cache_status = NGX_HTTP_CACHE_STALE;
rc = ngx_http_upstream_cache_send(r, u);
}
@@ -2007,6 +2050,10 @@ ngx_http_upstream_send_response(ngx_http_request_t *r, ngx_http_upstream_t *u)
ngx_log_debug1(NGX_LOG_DEBUG_HTTP, c->log, 0,
"http cacheable: %d", u->cacheable);
+ if (u->cacheable == 0 && r->cache) {
+ ngx_http_file_cache_free(r, u->pipe->temp_file);
+ }
+
#endif
p = u->pipe;
@@ -2681,12 +2728,15 @@ ngx_http_upstream_next(ngx_http_request_t *r, ngx_http_upstream_t *u,
#if (NGX_HTTP_CACHE)
- if (u->stale_cache && (u->conf->cache_use_stale & ft_type)) {
+ if (u->cache_status == NGX_HTTP_CACHE_EXPIRED
+ && (u->conf->cache_use_stale & ft_type))
+ {
ngx_int_t rc;
rc = u->reinit_request(r);
if (rc == NGX_OK) {
+ u->cache_status = NGX_HTTP_CACHE_STALE;
rc = ngx_http_upstream_cache_send(r, u);
}
@@ -3263,7 +3313,7 @@ ngx_http_upstream_copy_last_modified(ngx_http_request_t *r, ngx_table_elt_t *h,
#if (NGX_HTTP_CACHE)
- if (r->cached || r->upstream->cacheable) {
+ if (r->upstream->cacheable) {
r->headers_out.last_modified = ho;
r->headers_out.last_modified_time = ngx_http_parse_time(h->value.data,
h->value.len);
@@ -3714,6 +3764,33 @@ ngx_http_upstream_header_variable(ngx_http_request_t *r,
}
+#if (NGX_HTTP_CACHE)
+
+ngx_int_t
+ngx_http_upstream_cache_status(ngx_http_request_t *r,
+ ngx_http_variable_value_t *v, uintptr_t data)
+{
+ ngx_uint_t n;
+
+ if (r->upstream == NULL || r->upstream->cache_status == 0) {
+ v->not_found = 1;
+ return NGX_OK;
+ }
+
+ n = r->upstream->cache_status - 1;
+
+ v->valid = 1;
+ v->no_cacheable = 0;
+ v->not_found = 0;
+ v->len = ngx_http_cache_status[n].len;
+ v->data = ngx_http_cache_status[n].data;
+
+ return NGX_OK;
+}
+
+#endif
+
+
static char *
ngx_http_upstream(ngx_conf_t *cf, ngx_command_t *cmd, void *dummy)
{
diff --git a/src/http/ngx_http_upstream.h b/src/http/ngx_http_upstream.h
index eb97d3989..fc777670e 100644
--- a/src/http/ngx_http_upstream.h
+++ b/src/http/ngx_http_upstream.h
@@ -298,7 +298,7 @@ struct ngx_http_upstream_s {
unsigned accel:1;
unsigned ssl:1;
#if (NGX_HTTP_CACHE)
- unsigned stale_cache:1;
+ unsigned cache_status:3;
#endif
unsigned buffering:1;
diff --git a/src/os/unix/ngx_process.c b/src/os/unix/ngx_process.c
index 7446c138b..c480d6899 100644
--- a/src/os/unix/ngx_process.c
+++ b/src/os/unix/ngx_process.c
@@ -359,6 +359,7 @@ ngx_signal_handler(int signo)
break;
case SIGALRM:
+ ngx_sigalrm = 1;
break;
case SIGIO:
diff --git a/src/os/unix/ngx_process_cycle.c b/src/os/unix/ngx_process_cycle.c
index 92f6bf6f3..1ee278fe8 100644
--- a/src/os/unix/ngx_process_cycle.c
+++ b/src/os/unix/ngx_process_cycle.c
@@ -34,6 +34,7 @@ ngx_uint_t ngx_threaded;
sig_atomic_t ngx_reap;
sig_atomic_t ngx_sigio;
+sig_atomic_t ngx_sigalrm;
sig_atomic_t ngx_terminate;
sig_atomic_t ngx_quit;
sig_atomic_t ngx_debug_quit;
@@ -130,10 +131,13 @@ ngx_master_process_cycle(ngx_cycle_t *cycle)
for ( ;; ) {
if (delay) {
- delay *= 2;
+ if (ngx_sigalrm) {
+ delay *= 2;
+ ngx_sigalrm = 0;
+ }
ngx_log_debug1(NGX_LOG_DEBUG_EVENT, cycle->log, 0,
- "temination cycle: %d", delay);
+ "termination cycle: %d", delay);
itv.it_interval.tv_sec = 0;
itv.it_interval.tv_usec = 0;
@@ -492,8 +496,7 @@ ngx_signal_worker_processes(ngx_cycle_t *cycle, int signo)
if (kill(ngx_processes[i].pid, signo) == -1) {
err = ngx_errno;
ngx_log_error(NGX_LOG_ALERT, cycle->log, err,
- "kill(%P, %d) failed",
- ngx_processes[i].pid, signo);
+ "kill(%P, %d) failed", ngx_processes[i].pid, signo);
if (err == NGX_ESRCH) {
ngx_processes[i].exited = 1;
diff --git a/src/os/unix/ngx_process_cycle.h b/src/os/unix/ngx_process_cycle.h
index c52b6f0e1..9bf04749f 100644
--- a/src/os/unix/ngx_process_cycle.h
+++ b/src/os/unix/ngx_process_cycle.h
@@ -39,6 +39,7 @@ extern ngx_uint_t ngx_exiting;
extern sig_atomic_t ngx_reap;
extern sig_atomic_t ngx_sigio;
+extern sig_atomic_t ngx_sigalrm;
extern sig_atomic_t ngx_quit;
extern sig_atomic_t ngx_debug_quit;
extern sig_atomic_t ngx_terminate;