changeset 512:e1f4748dc78e NGINX_0_7_68

nginx 0.7.68 *) Bugfix: if there was a single server for given IPv6 address:port pair, then captures in regular expressions in a "server_name" directive did not work. *) Bugfix: a segmentation fault might occur in a worker process, if the "auth_basic" directive was used. Thanks to Michail Laletin. *) Bugfix: SSI response might be truncated after include with wait="yes"; the bug had appeared in 0.7.25. Thanks to Maxim Dounin. *) Bugfix: the "sub_filter" directive might change character case on partial match. *) Bugfix: nginx treated large SSLv2 packets as plain requests. Thanks to Miroslaw Jaworski. *) Bugfix: nginx might close IPv6 listen socket during reconfiguration. Thanks to Maxim Dounin.
author Igor Sysoev <http://sysoev.ru>
date Tue, 14 Dec 2010 00:00:00 +0300
parents 647973d42a2a
children f275e3826ebf
files CHANGES CHANGES.ru src/core/nginx.h src/core/ngx_cycle.c src/http/modules/ngx_http_ssi_filter_module.c src/http/modules/ngx_http_sub_filter_module.c src/http/modules/perl/nginx.pm src/http/ngx_http.c src/http/ngx_http_core_module.c src/http/ngx_http_request.c src/os/unix/ngx_user.c
diffstat 11 files changed, 118 insertions(+), 37 deletions(-) [+]
line wrap: on
line diff
--- a/CHANGES
+++ b/CHANGES
@@ -1,4 +1,29 @@
 
+Changes with nginx 0.7.68                                        14 Dec 2010
+
+    *) Bugfix: if there was a single server for given IPv6 address:port 
+       pair, then captures in regular expressions in a "server_name" 
+       directive did not work.
+
+    *) Bugfix: a segmentation fault might occur in a worker process, if the 
+       "auth_basic" directive was used.
+       Thanks to Michail Laletin.
+
+    *) Bugfix: SSI response might be truncated after include with 
+       wait="yes"; the bug had appeared in 0.7.25.
+       Thanks to Maxim Dounin.
+
+    *) Bugfix: the "sub_filter" directive might change character case on 
+       partial match.
+
+    *) Bugfix: nginx treated large SSLv2 packets as plain requests.
+       Thanks to Miroslaw Jaworski.
+
+    *) Bugfix: nginx might close IPv6 listen socket during 
+       reconfiguration.
+       Thanks to Maxim Dounin.
+
+
 Changes with nginx 0.7.67                                        15 Jun 2010
 
     *) Security: nginx/Windows worker might be terminated abnormally if a 
@@ -697,7 +722,7 @@ Changes with nginx 0.7.44               
 
     *) Bugfix: the "try_files" directive might test incorrectly directories.
 
-    *) Bugfix: if there is the single server for given address:port pair, 
+    *) Bugfix: if there was a single server for given address:port pair, 
        then captures in regular expressions in a "server_name" directive 
        did not work.
 
@@ -1051,7 +1076,7 @@ Changes with nginx 0.7.18               
     *) Bugfix: the "http_503" parameter of the "proxy_next_upstream" or 
        "fastcgi_next_upstream" directives did not work.
 
-    *) Bugfix: nginx might send a "Transfer-Encoding: chunked" heaer line 
+    *) Bugfix: nginx might send a "Transfer-Encoding: chunked" header line 
        for HEAD requests.
 
     *) Bugfix: now accept threshold depends on worker_connections.
--- a/CHANGES.ru
+++ b/CHANGES.ru
@@ -1,4 +1,30 @@
 
+Изменения в nginx 0.7.68                                          14.12.2010
+
+    *) Исправление: если для пары IPv6-адрес:порт описан только один 
+       сервер, то выделения в регулярных выражениях в директиве server_name 
+       не работали.
+
+    *) Исправление: при использовании директивы auth_basic в рабочем 
+       процессе мог произойти segmentation fault.
+       Спасибо Михаилу Лалетину.
+
+    *) Исправление: ответ SSI модуля мог передаваться не полностью после 
+       команды include с параметром wait="yes"; ошибка появилась в 0.7.25. 
+       Спасибо Максиму Дунину.
+
+    *) Исправление: директива sub_filter могла изменять регистр букв при 
+       частичном совпадении.
+
+    *) Исправление: nginx считал большие пакеты SSLv2 как обычные текстовые 
+       запросы.
+       Спасибо Miroslaw Jaworski.
+
+    *) Исправление: nginx мог закрывать IPv6 listen сокет во время 
+       переконфигурации.
+       Спасибо Максиму Дунину.
+
+
 Изменения в nginx 0.7.67                                          15.06.2010
 
     *) Безопасность: рабочий процесс nginx/Windows мог завершаться аварийно 
@@ -1504,7 +1530,7 @@
 
     *) Исправление: nginx неверно определял длину строки кэша на 
        Pentium 4.
-       Спасибо Gena Makhomed.
+       Спасибо Геннадию Махомеду.
 
     *) Исправление: в проксированных подзапросах и подзапросах к 
        FastCGI-серверу вместо метода GET использовался оригинальный метод 
--- a/src/core/nginx.h
+++ b/src/core/nginx.h
@@ -8,8 +8,8 @@
 #define _NGINX_H_INCLUDED_
 
 
-#define nginx_version         7067
-#define NGINX_VERSION      "0.7.67"
+#define nginx_version         7068
+#define NGINX_VERSION      "0.7.68"
 #define NGINX_VER          "nginx/" NGINX_VERSION
 
 #define NGINX_VAR          "NGINX"
--- a/src/core/ngx_cycle.c
+++ b/src/core/ngx_cycle.c
@@ -847,7 +847,7 @@ ngx_cmp_sockaddr(struct sockaddr *sa1, s
         sin61 = (struct sockaddr_in6 *) sa1;
         sin62 = (struct sockaddr_in6 *) sa2;
 
-        if (sin61->sin6_port != sin61->sin6_port) {
+        if (sin61->sin6_port != sin62->sin6_port) {
             return NGX_DECLINED;
         }
 
--- a/src/http/modules/ngx_http_ssi_filter_module.c
+++ b/src/http/modules/ngx_http_ssi_filter_module.c
@@ -70,6 +70,8 @@ typedef enum {
 
 static ngx_int_t ngx_http_ssi_output(ngx_http_request_t *r,
     ngx_http_ssi_ctx_t *ctx);
+static void ngx_http_ssi_buffered(ngx_http_request_t *r,
+    ngx_http_ssi_ctx_t *ctx);
 static ngx_int_t ngx_http_ssi_parse(ngx_http_request_t *r,
     ngx_http_ssi_ctx_t *ctx);
 static ngx_str_t *ngx_http_ssi_get_variable(ngx_http_request_t *r,
@@ -797,6 +799,7 @@ ngx_http_ssi_body_filter(ngx_http_reques
                 }
 
                 if (rc == NGX_DONE || rc == NGX_AGAIN || rc == NGX_ERROR) {
+                    ngx_http_ssi_buffered(r, ctx);
                     return rc;
                 }
             }
@@ -949,14 +952,21 @@ ngx_http_ssi_output(ngx_http_request_t *
         }
     }
 
+    ngx_http_ssi_buffered(r, ctx);
+
+    return rc;
+}
+
+
+static void
+ngx_http_ssi_buffered(ngx_http_request_t *r, ngx_http_ssi_ctx_t *ctx)
+{
     if (ctx->in || ctx->buf) {
         r->buffered |= NGX_HTTP_SSI_BUFFERED;
 
     } else {
         r->buffered &= ~NGX_HTTP_SSI_BUFFERED;
     }
-
-    return rc;
 }
 
 
--- a/src/http/modules/ngx_http_sub_filter_module.c
+++ b/src/http/modules/ngx_http_sub_filter_module.c
@@ -29,6 +29,8 @@ typedef enum {
 
 typedef struct {
     ngx_str_t                  match;
+    ngx_str_t                  saved;
+    ngx_str_t                  looked;
 
     ngx_uint_t                 once;   /* unsigned  once:1 */
 
@@ -47,8 +49,6 @@ typedef struct {
     ngx_str_t                  sub;
 
     ngx_uint_t                 state;
-    size_t                     saved;
-    size_t                     looked;
 } ngx_http_sub_ctx_t;
 
 
@@ -147,6 +147,16 @@ ngx_http_sub_header_filter(ngx_http_requ
         return NGX_ERROR;
     }
 
+    ctx->saved.data = ngx_pnalloc(r->pool, slcf->match.len);
+    if (ctx->saved.data == NULL) {
+        return NGX_ERROR;
+    }
+
+    ctx->looked.data = ngx_pnalloc(r->pool, slcf->match.len);
+    if (ctx->looked.data == NULL) {
+        return NGX_ERROR;
+    }
+
     ngx_http_set_ctx(r, ctx, ngx_http_sub_filter_module);
 
     ctx->match = slcf->match;
@@ -226,13 +236,13 @@ ngx_http_sub_body_filter(ngx_http_reques
         while (ctx->pos < ctx->buf->last) {
 
             ngx_log_debug2(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
-                           "saved: %d state: %d", ctx->saved, ctx->state);
+                           "saved: \"%V\" state: %d", &ctx->saved, ctx->state);
 
             rc = ngx_http_sub_parse(r, ctx);
 
             ngx_log_debug4(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
-                           "parse: %d, looked: %d %p-%p",
-                           rc, ctx->looked, ctx->copy_start, ctx->copy_end);
+                           "parse: %d, looked: \"%V\" %p-%p",
+                           rc, &ctx->looked, ctx->copy_start, ctx->copy_end);
 
             if (rc == NGX_ERROR) {
                 return rc;
@@ -241,9 +251,9 @@ ngx_http_sub_body_filter(ngx_http_reques
             if (ctx->copy_start != ctx->copy_end) {
 
                 ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
-                               "saved: %d", ctx->saved);
+                               "saved: \"%V\"", &ctx->saved);
 
-                if (ctx->saved) {
+                if (ctx->saved.len) {
 
                     if (ctx->free) {
                         cl = ctx->free;
@@ -265,14 +275,19 @@ ngx_http_sub_body_filter(ngx_http_reques
                         cl->buf = b;
                     }
 
+                    b->pos = ngx_pnalloc(r->pool, ctx->saved.len);
+                    if (b->pos == NULL) {
+                        return NGX_ERROR;
+                    }
+
+                    ngx_memcpy(b->pos, ctx->saved.data, ctx->saved.len);
+                    b->last = b->pos + ctx->saved.len;
                     b->memory = 1;
-                    b->pos = ctx->match.data;
-                    b->last = ctx->match.data + ctx->saved;
 
                     *ctx->last_out = cl;
                     ctx->last_out = &cl->next;
 
-                    ctx->saved = 0;
+                    ctx->saved.len = 0;
                 }
 
                 if (ctx->free) {
@@ -405,7 +420,8 @@ ngx_http_sub_body_filter(ngx_http_reques
 
         ctx->buf = NULL;
 
-        ctx->saved = ctx->looked;
+        ctx->saved.len = ctx->looked.len;
+        ngx_memcpy(ctx->saved.data, ctx->looked.data, ctx->looked.len);
     }
 
     if (ctx->out == NULL && ctx->busy == NULL) {
@@ -496,7 +512,7 @@ ngx_http_sub_parse(ngx_http_request_t *r
         ctx->copy_start = ctx->pos;
         ctx->copy_end = ctx->buf->last;
         ctx->pos = ctx->buf->last;
-        ctx->looked = 0;
+        ctx->looked.len = 0;
 
         ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, "once");
 
@@ -504,7 +520,7 @@ ngx_http_sub_parse(ngx_http_request_t *r
     }
 
     state = ctx->state;
-    looked = ctx->looked;
+    looked = ctx->looked.len;
     last = ctx->buf->last;
     copy_end = ctx->copy_end;
 
@@ -522,6 +538,7 @@ ngx_http_sub_parse(ngx_http_request_t *r
             for ( ;; ) {
                 if (ch == match) {
                     copy_end = p;
+                    ctx->looked.data[0] = *p;
                     looked = 1;
                     state = sub_match_state;
 
@@ -538,7 +555,7 @@ ngx_http_sub_parse(ngx_http_request_t *r
 
             ctx->state = state;
             ctx->pos = p;
-            ctx->looked = looked;
+            ctx->looked.len = looked;
             ctx->copy_end = p;
 
             if (ctx->copy_start == NULL) {
@@ -555,16 +572,17 @@ ngx_http_sub_parse(ngx_http_request_t *r
         /* state == sub_match_state */
 
         if (ch == ctx->match.data[looked]) {
+            ctx->looked.data[looked] = *p;
             looked++;
 
             if (looked == ctx->match.len) {
                 if ((size_t) (p - ctx->pos) < looked) {
-                    ctx->saved = 0;
+                    ctx->saved.len = 0;
                 }
 
                 ctx->state = sub_start_state;
                 ctx->pos = p + 1;
-                ctx->looked = 0;
+                ctx->looked.len = 0;
                 ctx->copy_end = copy_end;
 
                 if (ctx->copy_start == NULL && copy_end) {
@@ -576,6 +594,7 @@ ngx_http_sub_parse(ngx_http_request_t *r
 
         } else if (ch == ctx->match.data[0]) {
             copy_end = p;
+            ctx->looked.data[0] = *p;
             looked = 1;
 
         } else {
@@ -587,7 +606,7 @@ ngx_http_sub_parse(ngx_http_request_t *r
 
     ctx->state = state;
     ctx->pos = p;
-    ctx->looked = looked;
+    ctx->looked.len = looked;
 
     ctx->copy_end = (state == sub_start_state) ? p : copy_end;
 
--- 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.67';
+our $VERSION = '0.7.68';
 
 require XSLoader;
 XSLoader::load('nginx', $VERSION);
--- a/src/http/ngx_http.c
+++ b/src/http/ngx_http.c
@@ -1831,8 +1831,12 @@ ngx_http_add_addrs6(ngx_conf_t *cf, ngx_
         if (addr[i].hash.buckets == NULL
             && (addr[i].wc_head == NULL
                 || addr[i].wc_head->hash.buckets == NULL)
-            && (addr[i].wc_head == NULL
-                || addr[i].wc_head->hash.buckets == NULL))
+            && (addr[i].wc_tail == NULL
+                || addr[i].wc_tail->hash.buckets == NULL)
+#if (NGX_PCRE)
+            && addr[i].nregex == 0
+#endif
+            )
         {
             continue;
         }
--- a/src/http/ngx_http_core_module.c
+++ b/src/http/ngx_http_core_module.c
@@ -785,10 +785,6 @@ ngx_http_handler(ngx_http_request_t *r)
         r->phase_handler = cmcf->phase_engine.server_rewrite_index;
     }
 
-    if (r->unparsed_uri.len) {
-        r->valid_unparsed_uri = 1;
-    }
-
     r->valid_location = 1;
 #if (NGX_HTTP_GZIP)
     r->gzip_tested = 0;
--- a/src/http/ngx_http_request.c
+++ b/src/http/ngx_http_request.c
@@ -551,7 +551,7 @@ ngx_http_ssl_handshake(ngx_event_t *rev)
     }
 
     if (n == 1) {
-        if (buf[0] == 0x80 /* SSLv2 */ || buf[0] == 0x16 /* SSLv3/TLSv1 */) {
+        if (buf[0] & 0x80 /* SSLv2 */ || buf[0] == 0x16 /* SSLv3/TLSv1 */) {
             ngx_log_debug1(NGX_LOG_DEBUG_HTTP, rev->log, 0,
                            "https ssl handshake: 0x%02Xd", buf[0]);
 
@@ -752,6 +752,7 @@ ngx_http_process_request_line(ngx_event_
             r->unparsed_uri.len = r->uri_end - r->uri_start;
             r->unparsed_uri.data = r->uri_start;
 
+            r->valid_unparsed_uri = 1;
 
             r->method_name.len = r->method_end - r->request_start + 1;
             r->method_name.data = r->request_line.data;
--- a/src/os/unix/ngx_user.c
+++ b/src/os/unix/ngx_user.c
@@ -41,11 +41,11 @@ ngx_crypt(ngx_pool_t *pool, u_char *key,
     err = ngx_errno;
 
     if (err == 0) {
-        len = ngx_strlen(value);
+        len = ngx_strlen(value) + 1;
 
         *encrypted = ngx_pnalloc(pool, len);
         if (*encrypted) {
-            ngx_memcpy(*encrypted, value, len + 1);
+            ngx_memcpy(*encrypted, value, len);
             return NGX_OK;
         }
     }
@@ -79,11 +79,11 @@ ngx_crypt(ngx_pool_t *pool, u_char *key,
     value = crypt((char *) key, (char *) salt);
 
     if (value) {
-        len = ngx_strlen(value);
+        len = ngx_strlen(value) + 1;
 
         *encrypted = ngx_pnalloc(pool, len);
         if (*encrypted) {
-            ngx_memcpy(*encrypted, value, len + 1);
+            ngx_memcpy(*encrypted, value, len);
         }
 
 #if (NGX_THREADS && NGX_NONREENTRANT_CRYPT)