diff options
author | Igor Sysoev <igor@sysoev.ru> | 2007-07-09 06:57:23 +0000 |
---|---|---|
committer | Jonathan Kolb <jon@b0g.us> | 2007-07-09 06:57:23 +0000 |
commit | 8aa92bfd2642d24b664564c39290185efe1ed670 (patch) | |
tree | 1a0c4d752006601faea51aee6a588b247464033c | |
parent | 373100239c2731609f7198bbe37d972052fe03be (diff) | |
download | nginx-8aa92bfd2642d24b664564c39290185efe1ed670.tar.gz |
Changes with nginx 0.6.2 09 Jul 2007v0.6.2
*) Bugfix: if the FastCGI header was split in records, then nginx
passed garbage in the header to a client.
-rw-r--r-- | CHANGES | 6 | ||||
-rw-r--r-- | CHANGES.ru | 6 | ||||
-rw-r--r-- | src/core/nginx.h | 2 | ||||
-rw-r--r-- | src/http/modules/ngx_http_fastcgi_module.c | 115 | ||||
-rw-r--r-- | src/http/modules/ngx_http_log_module.c | 5 | ||||
-rw-r--r-- | src/http/modules/perl/nginx.pm | 2 |
6 files changed, 113 insertions, 23 deletions
@@ -1,4 +1,10 @@ +Changes with nginx 0.6.2 09 Jul 2007 + + *) Bugfix: if the FastCGI header was split in records, then nginx + passed garbage in the header to a client. + + Changes with nginx 0.6.1 17 Jun 2007 *) Bugfix: in SSI parsing. diff --git a/CHANGES.ru b/CHANGES.ru index c2e14f312..356178611 100644 --- a/CHANGES.ru +++ b/CHANGES.ru @@ -1,4 +1,10 @@ +Изменения в nginx 0.6.2 09.07.2007 + + *) Исправление: если заголовок ответа был разделён в FastCGI-записях, + то nginx передавал клиенту мусор в таких заголовках. + + Изменения в nginx 0.6.1 17.06.2007 *) Исправление: в парсинге SSI. diff --git a/src/core/nginx.h b/src/core/nginx.h index b76532874..8a99384e8 100644 --- a/src/core/nginx.h +++ b/src/core/nginx.h @@ -8,7 +8,7 @@ #define _NGINX_H_INCLUDED_ -#define NGINX_VERSION "0.6.1" +#define NGINX_VERSION "0.6.2" #define NGINX_VER "nginx/" NGINX_VERSION #define NGINX_VAR "NGINX" diff --git a/src/http/modules/ngx_http_fastcgi_module.c b/src/http/modules/ngx_http_fastcgi_module.c index 6daf6ce39..246574b13 100644 --- a/src/http/modules/ngx_http_fastcgi_module.c +++ b/src/http/modules/ngx_http_fastcgi_module.c @@ -38,6 +38,12 @@ typedef enum { typedef struct { + u_char *start; + u_char *end; +} ngx_http_fastcgi_split_part_t; + + +typedef struct { ngx_http_fastcgi_state_e state; u_char *pos; u_char *last; @@ -45,7 +51,9 @@ typedef struct { size_t length; size_t padding; - ngx_uint_t fastcgi_stdout; + ngx_uint_t fastcgi_stdout; /* unsigned :1 */ + + ngx_array_t *split_parts; } ngx_http_fastcgi_ctx_t; @@ -840,15 +848,18 @@ 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 *start, *last; + u_char *p, *start, *last, *part_start; + size_t size; ngx_str_t *status_line, line, *pattern; ngx_int_t rc, status; + ngx_buf_t buf; ngx_uint_t i; ngx_table_elt_t *h; ngx_http_upstream_t *u; ngx_http_fastcgi_ctx_t *f; ngx_http_upstream_header_t *hh; ngx_http_fastcgi_loc_conf_t *flcf; + ngx_http_fastcgi_split_part_t *part; ngx_http_upstream_main_conf_t *umcf; f = ngx_http_get_module_ctx(r, ngx_http_fastcgi_module); @@ -1017,6 +1028,8 @@ ngx_http_fastcgi_process_header(ngx_http_request_t *r) for ( ;; ) { + part_start = u->buffer.pos; + rc = ngx_http_parse_header_line(r, &u->buffer); ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, @@ -1035,23 +1048,71 @@ ngx_http_fastcgi_process_header(ngx_http_request_t *r) return NGX_HTTP_INTERNAL_SERVER_ERROR; } - h->hash = r->header_hash; + if (f->split_parts && f->split_parts->nelts) { - h->key.len = r->header_name_end - r->header_name_start; - h->value.len = r->header_end - r->header_start; + part = f->split_parts->elts; + size = u->buffer.pos - part_start; - h->key.data = ngx_palloc(r->pool, - h->key.len + 1 + h->value.len + 1 + h->key.len); - if (h->key.data == NULL) { - return NGX_HTTP_INTERNAL_SERVER_ERROR; - } + for (i = 0; i < f->split_parts->nelts; i++) { + size += part[i].end - part[i].start; + } + + p = ngx_palloc(r->pool, size); + if (p == NULL) { + return NGX_HTTP_INTERNAL_SERVER_ERROR; + } + + buf.pos = p; + + for (i = 0; i < f->split_parts->nelts; i++) { + p = ngx_cpymem(p, part[i].start, + part[i].end - part[i].start); + } + + p = ngx_cpymem(p, part_start, u->buffer.pos - part_start); + + buf.last = p; + + f->split_parts->nelts = 0; + + rc = ngx_http_parse_header_line(r, &buf); + + h->key.len = r->header_name_end - r->header_name_start; + h->key.data = r->header_name_start; + h->key.data[h->key.len] = '\0'; - h->value.data = h->key.data + h->key.len + 1; - h->lowcase_key = h->key.data + h->key.len + 1 - + h->value.len + 1; + h->value.len = r->header_end - r->header_start; + h->value.data = r->header_start; + h->value.data[h->value.len] = '\0'; - ngx_cpystrn(h->key.data, r->header_name_start, h->key.len + 1); - ngx_cpystrn(h->value.data, r->header_start, h->value.len + 1); + h->lowcase_key = ngx_palloc(r->pool, h->key.len); + if (h->lowcase_key == NULL) { + return NGX_HTTP_INTERNAL_SERVER_ERROR; + } + + } else { + + h->key.len = r->header_name_end - r->header_name_start; + h->value.len = r->header_end - r->header_start; + + h->key.data = ngx_palloc(r->pool, + h->key.len + 1 + h->value.len + 1 + + h->key.len); + if (h->key.data == NULL) { + return NGX_HTTP_INTERNAL_SERVER_ERROR; + } + + h->value.data = h->key.data + h->key.len + 1; + h->lowcase_key = h->key.data + h->key.len + 1 + + h->value.len + 1; + + ngx_cpystrn(h->key.data, r->header_name_start, + h->key.len + 1); + ngx_cpystrn(h->value.data, r->header_start, + h->value.len + 1); + } + + h->hash = r->header_hash; if (h->key.len == r->lowcase_index) { ngx_memcpy(h->lowcase_key, r->lowcase_header, h->key.len); @@ -1123,7 +1184,6 @@ ngx_http_fastcgi_process_header(ngx_http_request_t *r) "upstream sent invalid header"); return NGX_HTTP_UPSTREAM_INVALID_HEADER; - } if (last) { @@ -1144,16 +1204,29 @@ ngx_http_fastcgi_process_header(ngx_http_request_t *r) return NGX_OK; } - if (u->buffer.pos == u->buffer.last) { + if (rc == NGX_OK) { return NGX_AGAIN; } - if (rc == NGX_AGAIN) { - ngx_log_error(NGX_LOG_ALERT, r->connection->log, 0, - "upstream split a header line in FastCGI records"); + /* rc == NGX_AGAIN */ - return NGX_HTTP_UPSTREAM_INVALID_HEADER; + ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, + "upstream split a header line in FastCGI records"); + + if (f->split_parts == NULL) { + f->split_parts = ngx_array_create(r->pool, 1, + sizeof(ngx_http_fastcgi_split_part_t)); + if (f->split_parts == NULL) { + return NGX_HTTP_INTERNAL_SERVER_ERROR; + } } + + part = ngx_array_push(f->split_parts); + + part->start = part_start; + part->end = u->buffer.last; + + return NGX_AGAIN; } } diff --git a/src/http/modules/ngx_http_log_module.c b/src/http/modules/ngx_http_log_module.c index d3ebca4f1..c06e556e4 100644 --- a/src/http/modules/ngx_http_log_module.c +++ b/src/http/modules/ngx_http_log_module.c @@ -423,6 +423,11 @@ ngx_http_log_bytes_sent(ngx_http_request_t *r, u_char *buf, } +/* + * although there is a real $body_bytes_sent variable, + * this log operation code function is more optimized for logging + */ + static u_char * ngx_http_log_body_bytes_sent(ngx_http_request_t *r, u_char *buf, ngx_http_log_op_t *op) diff --git a/src/http/modules/perl/nginx.pm b/src/http/modules/perl/nginx.pm index 51002d1dc..5cab67d3a 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.6.1'; +our $VERSION = '0.6.2'; require XSLoader; XSLoader::load('nginx', $VERSION); |