changeset 382:e9979466be2f NGINX_0_6_35

nginx 0.6.35 *) Bugfix: in shared memory allocations if nginx was built without debugging. Thanks to Andrey Kvasov. *) Bugfixes in an "Expect" request header line support. *) Bugfix: UTF-8 encoding usage in the ngx_http_autoindex_module.
author Igor Sysoev <http://sysoev.ru>
date Mon, 26 Jan 2009 00:00:00 +0300
parents 0d28fd57288c
children 3d40b0260a84
files CHANGES CHANGES.ru LICENSE src/core/nginx.h src/core/ngx_slab.c src/core/ngx_string.c src/core/ngx_string.h src/http/modules/ngx_http_autoindex_module.c src/http/modules/ngx_http_charset_filter_module.c src/http/modules/perl/nginx.pm src/http/ngx_http_core_module.c src/http/ngx_http_request_body.c src/http/ngx_http_special_response.c src/http/ngx_http_upstream.c src/os/unix/ngx_posix_init.c
diffstat 15 files changed, 140 insertions(+), 104 deletions(-) [+]
line wrap: on
line diff
--- a/CHANGES
+++ b/CHANGES
@@ -1,4 +1,15 @@
 
+Changes with nginx 0.6.35                                        26 Jan 2009
+
+    *) Bugfix: in shared memory allocations if nginx was built without 
+       debugging.
+       Thanks to Andrey Kvasov.
+
+    *) Bugfixes in an "Expect" request header line support.
+
+    *) Bugfix: UTF-8 encoding usage in the ngx_http_autoindex_module.
+
+
 Changes with nginx 0.6.34                                        27 Nov 2008
 
     *) Change: now the EAGAIN error returned by connect() is not considered 
--- a/CHANGES.ru
+++ b/CHANGES.ru
@@ -1,4 +1,16 @@
 
+Изменения в nginx 0.6.35                                          26.01.2009
+
+    *) Исправление: ошибки выделения больших блоков в разделяемой памяти, 
+       если nginx был собран без отладки.
+       Спасибо Андрею Квасову.
+
+    *) Исправления в поддержке строки "Expect" в заголовке запроса.
+
+    *) Исправление: ошибки при использовании кодировки UTF-8 в 
+       ngx_http_autoindex_module.
+
+
 Изменения в nginx 0.6.34                                          27.11.2008
 
     *) Изменение: теперь ошибка EAGAIN при вызове connect() не считается 
--- a/LICENSE
+++ b/LICENSE
@@ -1,5 +1,5 @@
 /* 
- * Copyright (C) 2002-2008 Igor Sysoev
+ * Copyright (C) 2002-2009 Igor Sysoev
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
@@ -21,5 +21,4 @@
  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  * SUCH DAMAGE.
- *
  */
--- a/src/core/nginx.h
+++ b/src/core/nginx.h
@@ -8,7 +8,7 @@
 #define _NGINX_H_INCLUDED_
 
 
-#define NGINX_VERSION      "0.6.34"
+#define NGINX_VERSION      "0.6.35"
 #define NGINX_VER          "nginx/" NGINX_VERSION
 
 #define NGINX_VAR          "NGINX"
--- a/src/core/ngx_slab.c
+++ b/src/core/ngx_slab.c
@@ -661,11 +661,8 @@ ngx_slab_alloc_pages(ngx_slab_pool_t *po
             }
 
             page->slab = pages | NGX_SLAB_PAGE_START;
-
-#if (NGX_DEBUG)
             page->next = NULL;
             page->prev = NGX_SLAB_PAGE;
-#endif
 
             if (--pages == 0) {
                 return page;
@@ -673,10 +670,8 @@ ngx_slab_alloc_pages(ngx_slab_pool_t *po
 
             for (p = page + 1; pages; pages--) {
                 p->slab = NGX_SLAB_PAGE_BUSY;
-#if (NGX_DEBUG)
                 p->next = NULL;
                 p->prev = NGX_SLAB_PAGE;
-#endif
                 p++;
             }
 
--- a/src/core/ngx_string.c
+++ b/src/core/ngx_string.c
@@ -952,16 +952,16 @@ ngx_decode_base64(ngx_str_t *dst, ngx_st
 
 
 /*
- * ngx_utf_decode() decodes two and more bytes UTF sequences only
+ * ngx_utf8_decode() decodes two and more bytes UTF sequences only
  * the return values:
  *    0x80 - 0x10ffff         valid character
- *    0x10ffff - 0xfffffffd   invalid sequence
+ *    0x110000 - 0xfffffffd   invalid sequence
  *    0xfffffffe              incomplete sequence
  *    0xffffffff              error
  */
 
 uint32_t
-ngx_utf_decode(u_char **p, size_t n)
+ngx_utf8_decode(u_char **p, size_t n)
 {
     size_t    len;
     uint32_t  u, i, valid;
@@ -1018,31 +1018,26 @@ ngx_utf_decode(u_char **p, size_t n)
 
 
 size_t
-ngx_utf_length(u_char *p, size_t n)
+ngx_utf8_length(u_char *p, size_t n)
 {
-    u_char      c;
-    size_t      len;
-    ngx_uint_t  i;
+    u_char  c, *last;
+    size_t  len;
 
-    for (len = 0, i = 0; i < n; len++, i++) {
+    last = p + n;
 
-        c = p[i];
+    for (len = 0; p < last; len++) {
+
+        c = *p;
 
         if (c < 0x80) {
+            p++;
             continue;
         }
 
-        if (c >= 0xc0) {
-            for (c <<= 1; c & 0x80; c <<= 1) {
-                i++;
-            }
-
-            continue;
+        if (ngx_utf8_decode(&p, n) > 0x10ffff) {
+            /* invalid UTF-8 */
+            return n;
         }
-
-        /* invalid utf */
-
-        return n;
     }
 
     return len;
@@ -1050,36 +1045,45 @@ ngx_utf_length(u_char *p, size_t n)
 
 
 u_char *
-ngx_utf_cpystrn(u_char *dst, u_char *src, size_t n)
+ngx_utf8_cpystrn(u_char *dst, u_char *src, size_t n, size_t len)
 {
-    u_char  c;
+    u_char  c, *next;
 
     if (n == 0) {
         return dst;
     }
 
-    for ( /* void */ ; --n; dst++, src++) {
+    while (--n) {
 
         c = *src;
         *dst = c;
 
         if (c < 0x80) {
-            if (*dst != '\0') {
+
+            if (c != '\0') {
+                dst++;
+                src++;
+                len--;
+
                 continue;
             }
 
             return dst;
         }
 
-        if (c >= 0xc0) {
-            for (c <<= 1; c & 0x80; c <<= 1) {
-               *++dst = *++src;
-            }
+        next = src;
 
-            continue;
+        if (ngx_utf8_decode(&next, len) > 0x10ffff) {
+            /* invalid UTF-8 */
+            break;
         }
 
-        /* invalid utf */
+        len--;
+
+        while (src < next) {
+            *++dst = *++src;
+            len--;
+        }
     }
 
     *dst = '\0';
--- a/src/core/ngx_string.h
+++ b/src/core/ngx_string.h
@@ -151,9 +151,9 @@ u_char *ngx_hex_dump(u_char *dst, u_char
 void ngx_encode_base64(ngx_str_t *dst, ngx_str_t *src);
 ngx_int_t ngx_decode_base64(ngx_str_t *dst, ngx_str_t *src);
 
-uint32_t ngx_utf_decode(u_char **p, size_t n);
-size_t ngx_utf_length(u_char *p, size_t n);
-u_char *ngx_utf_cpystrn(u_char *dst, u_char *src, size_t n);
+uint32_t ngx_utf8_decode(u_char **p, size_t n);
+size_t ngx_utf8_length(u_char *p, size_t n);
+u_char *ngx_utf8_cpystrn(u_char *dst, u_char *src, size_t n, size_t len);
 
 
 #define NGX_ESCAPE_URI         0
--- a/src/http/modules/ngx_http_autoindex_module.c
+++ b/src/http/modules/ngx_http_autoindex_module.c
@@ -135,7 +135,7 @@ ngx_http_autoindex_handler(ngx_http_requ
 {
     u_char                         *last, *filename, scale;
     off_t                           length;
-    size_t                          len, copy, allocated, root;
+    size_t                          len, utf_len, allocated, root;
     ngx_tm_t                        tm;
     ngx_err_t                       err;
     ngx_buf_t                      *b;
@@ -329,7 +329,7 @@ ngx_http_autoindex_handler(ngx_http_requ
                                            NGX_ESCAPE_HTML);
 
         if (r->utf8) {
-            entry->utf_len = ngx_utf_length(entry->name.data, entry->name.len);
+            entry->utf_len = ngx_utf8_length(entry->name.data, entry->name.len);
         } else {
             entry->utf_len = len;
         }
@@ -412,15 +412,16 @@ ngx_http_autoindex_handler(ngx_http_requ
 
         len = entry[i].utf_len;
 
-        if (entry[i].name.len - len) {
+        if (entry[i].name.len != len) {
             if (len > NGX_HTTP_AUTOINDEX_NAME_LEN) {
-                copy = NGX_HTTP_AUTOINDEX_NAME_LEN - 3 + 1;
+                utf_len = NGX_HTTP_AUTOINDEX_NAME_LEN - 3 + 1;
 
             } else {
-                copy = NGX_HTTP_AUTOINDEX_NAME_LEN + 1;
+                utf_len = NGX_HTTP_AUTOINDEX_NAME_LEN + 1;
             }
 
-            b->last = ngx_utf_cpystrn(b->last, entry[i].name.data, copy);
+            b->last = ngx_utf8_cpystrn(b->last, entry[i].name.data,
+                                       utf_len, entry[i].name.len + 1);
             last = b->last;
 
         } else {
--- a/src/http/modules/ngx_http_charset_filter_module.c
+++ b/src/http/modules/ngx_http_charset_filter_module.c
@@ -642,7 +642,7 @@ ngx_http_charset_recode_from_utf8(ngx_po
                 size = buf->last - src;
 
                 saved = src;
-                n = ngx_utf_decode(&saved, size);
+                n = ngx_utf8_decode(&saved, size);
 
                 if (n == 0xfffffffe) {
                     /* incomplete UTF-8 symbol */
@@ -710,7 +710,7 @@ ngx_http_charset_recode_from_utf8(ngx_po
     }
 
     saved = ctx->saved;
-    n = ngx_utf_decode(&saved, i);
+    n = ngx_utf8_decode(&saved, i);
 
     c = '\0';
 
@@ -818,7 +818,7 @@ recode:
 
         len = buf->last - src;
 
-        n = ngx_utf_decode(&src, len);
+        n = ngx_utf8_decode(&src, len);
 
         if (n < 0x10000) {
 
@@ -1270,7 +1270,7 @@ ngx_http_charset_map(ngx_conf_t *cf, ngx
 
         p = &table->src2dst[src * NGX_UTF_LEN] + 1;
 
-        n = ngx_utf_decode(&p, i);
+        n = ngx_utf8_decode(&p, i);
 
         if (n > 0xffff) {
             ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
--- 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.6.34';
+our $VERSION = '0.6.35';
 
 require XSLoader;
 XSLoader::load('nginx', $VERSION);
--- a/src/http/ngx_http_core_module.c
+++ b/src/http/ngx_http_core_module.c
@@ -30,7 +30,6 @@ typedef struct {
 
 static ngx_int_t ngx_http_core_find_location(ngx_http_request_t *r,
     ngx_array_t *locations, ngx_uint_t regex_start, size_t len);
-static ngx_int_t ngx_http_core_send_continue(ngx_http_request_t *r);
 
 static ngx_int_t ngx_http_core_preconfiguration(ngx_conf_t *cf);
 static void *ngx_http_core_create_main_conf(ngx_conf_t *cf);
@@ -786,7 +785,7 @@ ngx_http_core_find_config_phase(ngx_http
 {
     u_char                    *p;
     size_t                     len;
-    ngx_int_t                  rc, expect;
+    ngx_int_t                  rc;
     ngx_http_core_loc_conf_t  *clcf;
     ngx_http_core_srv_conf_t  *cscf;
 
@@ -833,15 +832,6 @@ ngx_http_core_find_config_phase(ngx_http
         return NGX_OK;
     }
 
-    if (r->headers_in.expect) {
-        expect = ngx_http_core_send_continue(r);
-
-        if (expect != NGX_OK) {
-            ngx_http_finalize_request(r, expect);
-            return NGX_OK;
-        }
-    }
-
     if (rc == NGX_HTTP_LOCATION_AUTO_REDIRECT) {
         r->headers_out.location = ngx_list_push(&r->headers_out.headers);
         if (r->headers_out.location == NULL) {
@@ -1261,45 +1251,6 @@ ngx_http_core_find_location(ngx_http_req
 }
 
 
-static ngx_int_t
-ngx_http_core_send_continue(ngx_http_request_t *r)
-{
-    ngx_int_t   n;
-    ngx_str_t  *expect;
-
-    if (r->expect_tested) {
-        return NGX_OK;
-    }
-
-    r->expect_tested = 1;
-
-    expect = &r->headers_in.expect->value;
-
-    if (expect->len != sizeof("100-continue") - 1
-        || ngx_strncasecmp(expect->data, (u_char *) "100-continue",
-                           sizeof("100-continue") - 1)
-           != 0)
-    {
-        return NGX_OK;
-    }
-
-    ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
-                   "send 100 Continue");
-
-    n = r->connection->send(r->connection,
-                            (u_char *) "HTTP/1.1 100 Continue" CRLF CRLF,
-                            sizeof("HTTP/1.1 100 Continue" CRLF CRLF) - 1);
-
-    if (n == sizeof("HTTP/1.1 100 Continue" CRLF CRLF) - 1) {
-        return NGX_OK;
-    }
-
-    /* we assume that such small packet should be send successfully */
-
-    return NGX_HTTP_INTERNAL_SERVER_ERROR;
-}
-
-
 ngx_int_t
 ngx_http_set_content_type(ngx_http_request_t *r)
 {
@@ -1861,6 +1812,7 @@ ngx_http_subrequest(ngx_http_request_t *
     sr->fast_subrequest = 1;
 
     sr->discard_body = r->discard_body;
+    sr->expect_tested = 1;
     sr->main_filter_need_in_memory = r->main_filter_need_in_memory;
 
     sr->uri_changes = NGX_HTTP_MAX_URI_CHANGES + 1;
--- a/src/http/ngx_http_request_body.c
+++ b/src/http/ngx_http_request_body.c
@@ -16,6 +16,7 @@ static ngx_int_t ngx_http_write_request_
     ngx_chain_t *body);
 static void ngx_http_read_discarded_request_body_handler(ngx_http_request_t *r);
 static ngx_int_t ngx_http_read_discarded_request_body(ngx_http_request_t *r);
+static ngx_int_t ngx_http_test_expect(ngx_http_request_t *r);
 
 
 /*
@@ -42,6 +43,10 @@ ngx_http_read_client_request_body(ngx_ht
         return NGX_OK;
     }
 
+    if (ngx_http_test_expect(r) != NGX_OK) {
+        return NGX_HTTP_INTERNAL_SERVER_ERROR;
+    }
+
     rb = ngx_pcalloc(r->pool, sizeof(ngx_http_request_body_t));
     if (rb == NULL) {
         return NGX_HTTP_INTERNAL_SERVER_ERROR;
@@ -434,6 +439,10 @@ ngx_http_discard_request_body(ngx_http_r
         return NGX_OK;
     }
 
+    if (ngx_http_test_expect(r) != NGX_OK) {
+        return NGX_HTTP_INTERNAL_SERVER_ERROR;
+    }
+
     rev = r->connection->read;
 
     ngx_log_debug0(NGX_LOG_DEBUG_HTTP, rev->log, 0, "http set discard body");
@@ -582,3 +591,45 @@ ngx_http_read_discarded_request_body(ngx
 
     return NGX_AGAIN;
 }
+
+
+static ngx_int_t
+ngx_http_test_expect(ngx_http_request_t *r)
+{
+    ngx_int_t   n;
+    ngx_str_t  *expect;
+
+    if (r->expect_tested
+        || r->headers_in.expect == NULL
+        || r->http_version < NGX_HTTP_VERSION_11)
+    {
+        return NGX_OK;
+    }
+
+    r->expect_tested = 1;
+
+    expect = &r->headers_in.expect->value;
+
+    if (expect->len != sizeof("100-continue") - 1
+        || ngx_strncasecmp(expect->data, (u_char *) "100-continue",
+                           sizeof("100-continue") - 1)
+           != 0)
+    {
+        return NGX_OK;
+    }
+
+    ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
+                   "send 100 Continue");
+
+    n = r->connection->send(r->connection,
+                            (u_char *) "HTTP/1.1 100 Continue" CRLF CRLF,
+                            sizeof("HTTP/1.1 100 Continue" CRLF CRLF) - 1);
+
+    if (n == sizeof("HTTP/1.1 100 Continue" CRLF CRLF) - 1) {
+        return NGX_OK;
+    }
+
+    /* we assume that such small packet should be send successfully */
+
+    return NGX_ERROR;
+}
--- a/src/http/ngx_http_special_response.c
+++ b/src/http/ngx_http_special_response.c
@@ -378,6 +378,8 @@ ngx_http_special_response_handler(ngx_ht
         }
     }
 
+    r->expect_tested = 1;
+
     if (ngx_http_discard_request_body(r) != NGX_OK) {
         error = NGX_HTTP_INTERNAL_SERVER_ERROR;
     }
@@ -430,11 +432,18 @@ static ngx_int_t
 ngx_http_send_error_page(ngx_http_request_t *r, ngx_http_err_page_t *err_page)
 {
     u_char                     ch, *p, *last;
+    ngx_int_t                  overwrite;
     ngx_str_t                 *uri, *args, u, a;
     ngx_table_elt_t           *location;
     ngx_http_core_loc_conf_t  *clcf;
 
-    r->err_status = err_page->overwrite;
+    overwrite = err_page->overwrite;
+
+    if (overwrite && overwrite != NGX_HTTP_OK) {
+        r->expect_tested = 1;
+    }
+
+    r->err_status = overwrite;
 
     r->zero_in_uri = 0;
 
--- a/src/http/ngx_http_upstream.c
+++ b/src/http/ngx_http_upstream.c
@@ -2345,7 +2345,9 @@ ngx_http_upstream_finalize_request(ngx_h
     ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
                    "finalize http upstream request: %i", rc);
 
-    *u->cleanup = NULL;
+    if (u->cleanup) {
+        *u->cleanup = NULL;
+    }
 
     if (u->state && u->state->response_sec) {
         tp = ngx_timeofday();
--- a/src/os/unix/ngx_posix_init.c
+++ b/src/os/unix/ngx_posix_init.c
@@ -22,7 +22,7 @@ ngx_os_io_t ngx_os_io = {
     ngx_unix_recv,
     ngx_readv_chain,
     ngx_udp_unix_recv,
-    NULL,
+    ngx_unix_send,
     ngx_writev_chain,
     0
 };