this bug <span style="border-collapse:separate;color:rgb(0, 0, 0);font-family:'Times New Roman';font-style:normal;font-variant:normal;font-weight:normal;letter-spacing:normal;line-height:normal;text-indent:0px;text-transform:none;white-space:normal;word-spacing:0px;font-size:medium"><span style="font-family:Arial;font-size:14px;line-height:18px">will give rise to nginx</span></span><span style="border-collapse:separate;color:rgb(0, 0, 0);font-family:'Times New Roman';font-style:normal;font-variant:normal;font-weight:normal;letter-spacing:normal;line-height:normal;text-indent:0px;text-transform:none;white-space:normal;word-spacing:0px;font-size:medium"><span style="font-family:Arial;font-size:14px;line-height:18px">(</span></span>version >= 0.8.40)<span style="border-collapse:separate;color:rgb(0, 0, 0);font-family:'Times New Roman';font-style:normal;font-variant:normal;font-weight:normal;letter-spacing:normal;line-height:normal;text-align:-webkit-auto;text-indent:0px;text-transform:none;white-space:normal;word-spacing:0px;font-size:medium"><span style="font-family:Arial;font-size:14px;line-height:18px"></span></span><span style="border-collapse:separate;color:rgb(0, 0, 0);font-family:'Times New Roman';font-style:normal;font-variant:normal;font-weight:normal;letter-spacing:normal;line-height:normal;text-indent:0px;text-transform:none;white-space:normal;word-spacing:0px;font-size:medium"><span style="font-family:Arial;font-size:14px;line-height:18px"> core dump</span></span><span style="border-collapse:separate;color:rgb(0, 0, 0);font-family:'Times New Roman';font-style:normal;font-variant:normal;font-weight:normal;letter-spacing:normal;line-height:normal;text-align:-webkit-auto;text-indent:0px;text-transform:none;white-space:normal;word-spacing:0px;font-size:medium"><span style="font-family:Arial;font-size:14px;line-height:18px"></span></span>, and it was caused by this feature:<br>
<br> *) Feature: a "fastcgi_param" directive with value starting with <br> "HTTP_" overrides a client request header line.<br><br><br>When we difine fastcgi_param directive with value starting with "HTTP_", nginx malloc a array(size is header_params that is <span style="border-collapse:separate;color:rgb(0, 0, 0);font-family:'Times New Roman';font-style:normal;font-variant:normal;font-weight:normal;letter-spacing:normal;line-height:normal;text-align:-webkit-auto;text-indent:0px;text-transform:none;white-space:normal;word-spacing:0px;font-size:medium"><span style="color:rgb(43, 43, 43);font-family:Arial, sans-serif;font-size:12px;line-height:14px">number</span></span> of value starting with "HTTP_"), and if request header contain this value(HTTTP_xxx), nginx will add this header pointer to array, but if header is duplicated, this array will <span style="border-collapse:separate;color:rgb(0, 0, 0);font-family:'Times New Roman';font-style:normal;font-variant:normal;font-weight:normal;letter-spacing:normal;line-height:normal;text-align:-webkit-auto;text-indent:0px;text-transform:none;white-space:normal;word-spacing:0px;font-size:medium"><span style="color:rgb(49, 49, 49);font-family:Arial, sans-serif;font-size:13px;line-height:18px">cross-border.<br>
<br></span></span>e.g. if the config contain this directive (fastcgi_param HTTP_HOST $http_host), and then request header send <meta charset="utf-8"><span class="Apple-style-span" style="color: rgb(43, 43, 43); font-family: Arial, sans-serif; font-size: 12px; line-height: 14px; ">multi-</span>duplicated header(Host), nginx will core dump.<br>
<br><br>Index: src/http/modules/ngx_http_fastcgi_module.c<br>
===================================================================<br>--- src/http/modules/ngx_http_fastcgi_module.c (revision 3929)<br>+++ src/http/modules/ngx_http_fastcgi_module.c (working copy)<br>@@ -165,7 +165,10 @@<br>
static char *ngx_http_fastcgi_lowat_check(ngx_conf_t *cf, void *post,<br> void *data);<br> <br>+static ngx_inline ngx_int_t ngx_http_fastcgi_ignored_header(ngx_uint_t hash,<br>+ ngx_uint_t header_params, ngx_uint_t *ignored);<br>
<br>+<br> static ngx_conf_post_t ngx_http_fastcgi_lowat_post =<br> { ngx_http_fastcgi_lowat_check };<br> <br>@@ -684,18 +687,32 @@<br> #endif<br> <br> <br>+static ngx_inline ngx_int_t<br>+ngx_http_fastcgi_ignored_header(ngx_uint_t hash, ngx_uint_t header_params, ngx_uint_t *ignored)<br>
+{<br>+ ngx_uint_t n;<br>+<br>+ for (n = 0; n < header_params; n++) {<br>+ if (hash == ignored[n]) {<br>+ return NGX_OK;<br>+ }<br>+ }<br>+<br>+ return NGX_DECLINED;<br>+}<br>
+<br>+<br> static ngx_int_t<br> ngx_http_fastcgi_create_request(ngx_http_request_t *r)<br> {<br> off_t file_pos;<br>- u_char ch, *pos, *lowcase_key;<br>- size_t size, len, key_len, val_len, padding,<br>
- allocated;<br>- ngx_uint_t i, n, next, hash, header_params;<br>+ u_char ch, *pos;<br>+ size_t size, len, key_len, val_len, padding;<br>
+ ngx_uint_t i, n, next, header_params, *ignored;<br> ngx_buf_t *b;<br> ngx_chain_t *cl, *body;<br> ngx_list_part_t *part;<br>- ngx_table_elt_t *header, **ignored;<br>
+ ngx_table_elt_t *header;<br> ngx_http_script_code_pt code;<br> ngx_http_script_engine_t e, le;<br> ngx_http_fastcgi_header_t *h;<br>@@ -733,11 +750,8 @@<br> <br> if (flcf->upstream.pass_request_headers) {<br>
<br>- allocated = 0;<br>- lowcase_key = NULL;<br>-<br> if (flcf->header_params) {<br>- ignored = ngx_palloc(r->pool, flcf->header_params * sizeof(void *));<br>+ ignored = ngx_palloc(r->pool, flcf->header_params * sizeof(ngx_uint_t));<br>
if (ignored == NULL) {<br> return NGX_ERROR;<br> }<br>@@ -759,43 +773,21 @@<br> }<br> <br> if (flcf->header_params) {<br>- if (allocated < header[i].key.len) {<br>
- allocated = header[i].key.len + 16;<br>- lowcase_key = ngx_pnalloc(r->pool, allocated);<br>- if (lowcase_key == NULL) {<br>- return NGX_ERROR;<br>
- }<br>- }<br> <br>- hash = 0;<br>-<br>- for (n = 0; n < header[i].key.len; n++) {<br>- ch = header[i].key.data[n];<br>-<br>- if (ch >= 'A' && ch <= 'Z') {<br>
- ch |= 0x20;<br>-<br>- } else if (ch == '-') {<br>- ch = '_';<br>+ if (ngx_hash_find(&flcf->headers_hash, header[i].hash,<br>
+ header[i].lowcase_key, header[i].key.len)) {<br>+ if (ngx_http_fastcgi_ignored_header(header[i].hash,<br>+ header_params, ignored) == NGX_OK) {<br>
+ continue;<br> }<br>-<br>- hash = ngx_hash(hash, ch);<br>- lowcase_key[n] = ch;<br>- }<br>-<br>- if (ngx_hash_find(&flcf->headers_hash, hash, lowcase_key, n)) {<br>
- ignored[header_params++] = &header[i];<br>+ ignored[header_params++] = header[i].hash;<br> continue;<br> }<br>-<br>- n += sizeof("HTTP_") - 1;<br>
-<br>- } else {<br>- n = sizeof("HTTP_") - 1 + header[i].key.len;<br> }<br>-<br>- len += ((n > 127) ? 4 : 1) + ((header[i].value.len > 127) ? 4 : 1)<br>- + n + header[i].value.len;<br>
+ <br>+ len += ((sizeof("HTTP_") - 1 + header[i].key.len > 127) ? 4 : 1)<br>+ + ((header[i].value.len > 127) ? 4 : 1)<br>+ + sizeof("HTTP_") - 1 + header[i].key.len + header[i].value.len;<br>
}<br> }<br> <br>@@ -915,10 +907,9 @@<br> i = 0;<br> }<br> <br>- for (n = 0; n < header_params; n++) {<br>- if (&header[i] == ignored[n]) {<br>- goto next;<br>
- }<br>+ if (ngx_http_fastcgi_ignored_header(header[i].hash,<br>+ header_params, ignored) == NGX_OK) {<br>+ continue;<br> }<br> <br> key_len = sizeof("HTTP_") - 1 + header[i].key.len;<br>
@@ -964,8 +955,6 @@<br> "fastcgi param: \"%*s: %*s\"",<br> key_len, b->last - (key_len + val_len),<br> val_len, b->last - val_len);<br>
- next:<br>-<br> continue;<br> }<br> }<br>@@ -2013,10 +2002,10 @@<br> ngx_http_fastcgi_loc_conf_t *prev = parent;<br> ngx_http_fastcgi_loc_conf_t *conf = child;<br> <br>- u_char *p;<br>
+ u_char ch, *p;<br> size_t size;<br> uintptr_t *code;<br>- ngx_uint_t i;<br>+ ngx_uint_t i, n, params_hash;<br>
ngx_array_t headers_names;<br> ngx_keyval_t *src;<br> ngx_hash_key_t *hk;<br>@@ -2374,7 +2363,22 @@<br> <br> hk->key.len = src[i].key.len - 5;<br>
hk->key.data = src[i].key.data + 5;<br>- hk->key_hash = ngx_hash_key_lc(hk->key.data, hk->key.len);<br>+<br>+ params_hash = 0;<br>+ for (n = 5; n < src[i].key.len; n++) {<br>
+ ch = src[i].key.data[n];<br>+<br>+ if (ch >= 'A' && ch <= 'Z') {<br>+ ch |= 0x20;<br>+<br>+ } else if (ch == '_') {<br>
+ ch = '-';<br>+ }<br>+<br>+ params_hash = ngx_hash(params_hash, ch);<br>+ }<br>+<br>+ hk->key_hash = params_hash;<br> hk->value = (void *) 1;<br>
<br> if (src[i].value.len == 0) {<br clear="all"><br>-- <br>博观约取<br><br>豆瓣:<a href="http://www.douban.com/people/mustang/" target="_blank">www.douban.com/people/mustang/</a><br><br>blog: <a href="http://www.pagefault.info" target="_blank">www.pagefault.info</a><br>
<br>twitter: <a href="http://www.twitter.com/minibobo" target="_blank">www.twitter.com/minibobo</a><br><br>sina 微博: <a href="http://www.weibo.com/diaoliang" target="_blank">www.weibo.com/diaoliang</a><br><br>