comparison src/http/modules/ngx_http_fastcgi_module.c @ 316:a6d84efa5106 NGINX_0_6_2

nginx 0.6.2 *) Bugfix: if the FastCGI header was split in records, then nginx passed garbage in the header to a client.
author Igor Sysoev <http://sysoev.ru>
date Mon, 09 Jul 2007 00:00:00 +0400
parents 55328d69b335
children fc223117327f
comparison
equal deleted inserted replaced
315:f51e5273589b 316:a6d84efa5106
36 ngx_http_fastcgi_st_padding 36 ngx_http_fastcgi_st_padding
37 } ngx_http_fastcgi_state_e; 37 } ngx_http_fastcgi_state_e;
38 38
39 39
40 typedef struct { 40 typedef struct {
41 u_char *start;
42 u_char *end;
43 } ngx_http_fastcgi_split_part_t;
44
45
46 typedef struct {
41 ngx_http_fastcgi_state_e state; 47 ngx_http_fastcgi_state_e state;
42 u_char *pos; 48 u_char *pos;
43 u_char *last; 49 u_char *last;
44 ngx_uint_t type; 50 ngx_uint_t type;
45 size_t length; 51 size_t length;
46 size_t padding; 52 size_t padding;
47 53
48 ngx_uint_t fastcgi_stdout; 54 ngx_uint_t fastcgi_stdout; /* unsigned :1 */
55
56 ngx_array_t *split_parts;
49 } ngx_http_fastcgi_ctx_t; 57 } ngx_http_fastcgi_ctx_t;
50 58
51 59
52 #define NGX_HTTP_FASTCGI_RESPONDER 1 60 #define NGX_HTTP_FASTCGI_RESPONDER 1
53 61
838 846
839 847
840 static ngx_int_t 848 static ngx_int_t
841 ngx_http_fastcgi_process_header(ngx_http_request_t *r) 849 ngx_http_fastcgi_process_header(ngx_http_request_t *r)
842 { 850 {
843 u_char *start, *last; 851 u_char *p, *start, *last, *part_start;
852 size_t size;
844 ngx_str_t *status_line, line, *pattern; 853 ngx_str_t *status_line, line, *pattern;
845 ngx_int_t rc, status; 854 ngx_int_t rc, status;
855 ngx_buf_t buf;
846 ngx_uint_t i; 856 ngx_uint_t i;
847 ngx_table_elt_t *h; 857 ngx_table_elt_t *h;
848 ngx_http_upstream_t *u; 858 ngx_http_upstream_t *u;
849 ngx_http_fastcgi_ctx_t *f; 859 ngx_http_fastcgi_ctx_t *f;
850 ngx_http_upstream_header_t *hh; 860 ngx_http_upstream_header_t *hh;
851 ngx_http_fastcgi_loc_conf_t *flcf; 861 ngx_http_fastcgi_loc_conf_t *flcf;
862 ngx_http_fastcgi_split_part_t *part;
852 ngx_http_upstream_main_conf_t *umcf; 863 ngx_http_upstream_main_conf_t *umcf;
853 864
854 f = ngx_http_get_module_ctx(r, ngx_http_fastcgi_module); 865 f = ngx_http_get_module_ctx(r, ngx_http_fastcgi_module);
855 866
856 umcf = ngx_http_get_module_main_conf(r, ngx_http_upstream_module); 867 umcf = ngx_http_get_module_main_conf(r, ngx_http_upstream_module);
1015 last = NULL; 1026 last = NULL;
1016 } 1027 }
1017 1028
1018 for ( ;; ) { 1029 for ( ;; ) {
1019 1030
1031 part_start = u->buffer.pos;
1032
1020 rc = ngx_http_parse_header_line(r, &u->buffer); 1033 rc = ngx_http_parse_header_line(r, &u->buffer);
1021 1034
1022 ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, 1035 ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
1023 "http fastcgi parser: %d", rc); 1036 "http fastcgi parser: %d", rc);
1024 1037
1033 h = ngx_list_push(&u->headers_in.headers); 1046 h = ngx_list_push(&u->headers_in.headers);
1034 if (h == NULL) { 1047 if (h == NULL) {
1035 return NGX_HTTP_INTERNAL_SERVER_ERROR; 1048 return NGX_HTTP_INTERNAL_SERVER_ERROR;
1036 } 1049 }
1037 1050
1051 if (f->split_parts && f->split_parts->nelts) {
1052
1053 part = f->split_parts->elts;
1054 size = u->buffer.pos - part_start;
1055
1056 for (i = 0; i < f->split_parts->nelts; i++) {
1057 size += part[i].end - part[i].start;
1058 }
1059
1060 p = ngx_palloc(r->pool, size);
1061 if (p == NULL) {
1062 return NGX_HTTP_INTERNAL_SERVER_ERROR;
1063 }
1064
1065 buf.pos = p;
1066
1067 for (i = 0; i < f->split_parts->nelts; i++) {
1068 p = ngx_cpymem(p, part[i].start,
1069 part[i].end - part[i].start);
1070 }
1071
1072 p = ngx_cpymem(p, part_start, u->buffer.pos - part_start);
1073
1074 buf.last = p;
1075
1076 f->split_parts->nelts = 0;
1077
1078 rc = ngx_http_parse_header_line(r, &buf);
1079
1080 h->key.len = r->header_name_end - r->header_name_start;
1081 h->key.data = r->header_name_start;
1082 h->key.data[h->key.len] = '\0';
1083
1084 h->value.len = r->header_end - r->header_start;
1085 h->value.data = r->header_start;
1086 h->value.data[h->value.len] = '\0';
1087
1088 h->lowcase_key = ngx_palloc(r->pool, h->key.len);
1089 if (h->lowcase_key == NULL) {
1090 return NGX_HTTP_INTERNAL_SERVER_ERROR;
1091 }
1092
1093 } else {
1094
1095 h->key.len = r->header_name_end - r->header_name_start;
1096 h->value.len = r->header_end - r->header_start;
1097
1098 h->key.data = ngx_palloc(r->pool,
1099 h->key.len + 1 + h->value.len + 1
1100 + h->key.len);
1101 if (h->key.data == NULL) {
1102 return NGX_HTTP_INTERNAL_SERVER_ERROR;
1103 }
1104
1105 h->value.data = h->key.data + h->key.len + 1;
1106 h->lowcase_key = h->key.data + h->key.len + 1
1107 + h->value.len + 1;
1108
1109 ngx_cpystrn(h->key.data, r->header_name_start,
1110 h->key.len + 1);
1111 ngx_cpystrn(h->value.data, r->header_start,
1112 h->value.len + 1);
1113 }
1114
1038 h->hash = r->header_hash; 1115 h->hash = r->header_hash;
1039
1040 h->key.len = r->header_name_end - r->header_name_start;
1041 h->value.len = r->header_end - r->header_start;
1042
1043 h->key.data = ngx_palloc(r->pool,
1044 h->key.len + 1 + h->value.len + 1 + h->key.len);
1045 if (h->key.data == NULL) {
1046 return NGX_HTTP_INTERNAL_SERVER_ERROR;
1047 }
1048
1049 h->value.data = h->key.data + h->key.len + 1;
1050 h->lowcase_key = h->key.data + h->key.len + 1
1051 + h->value.len + 1;
1052
1053 ngx_cpystrn(h->key.data, r->header_name_start, h->key.len + 1);
1054 ngx_cpystrn(h->value.data, r->header_start, h->value.len + 1);
1055 1116
1056 if (h->key.len == r->lowcase_index) { 1117 if (h->key.len == r->lowcase_index) {
1057 ngx_memcpy(h->lowcase_key, r->lowcase_header, h->key.len); 1118 ngx_memcpy(h->lowcase_key, r->lowcase_header, h->key.len);
1058 1119
1059 } else { 1120 } else {
1121 1182
1122 ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, 1183 ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
1123 "upstream sent invalid header"); 1184 "upstream sent invalid header");
1124 1185
1125 return NGX_HTTP_UPSTREAM_INVALID_HEADER; 1186 return NGX_HTTP_UPSTREAM_INVALID_HEADER;
1126
1127 } 1187 }
1128 1188
1129 if (last) { 1189 if (last) {
1130 u->buffer.last = last; 1190 u->buffer.last = last;
1131 } 1191 }
1142 1202
1143 if (rc == NGX_HTTP_PARSE_HEADER_DONE) { 1203 if (rc == NGX_HTTP_PARSE_HEADER_DONE) {
1144 return NGX_OK; 1204 return NGX_OK;
1145 } 1205 }
1146 1206
1147 if (u->buffer.pos == u->buffer.last) { 1207 if (rc == NGX_OK) {
1148 return NGX_AGAIN; 1208 return NGX_AGAIN;
1149 } 1209 }
1150 1210
1151 if (rc == NGX_AGAIN) { 1211 /* rc == NGX_AGAIN */
1152 ngx_log_error(NGX_LOG_ALERT, r->connection->log, 0, 1212
1153 "upstream split a header line in FastCGI records"); 1213 ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
1154 1214 "upstream split a header line in FastCGI records");
1155 return NGX_HTTP_UPSTREAM_INVALID_HEADER; 1215
1156 } 1216 if (f->split_parts == NULL) {
1217 f->split_parts = ngx_array_create(r->pool, 1,
1218 sizeof(ngx_http_fastcgi_split_part_t));
1219 if (f->split_parts == NULL) {
1220 return NGX_HTTP_INTERNAL_SERVER_ERROR;
1221 }
1222 }
1223
1224 part = ngx_array_push(f->split_parts);
1225
1226 part->start = part_start;
1227 part->end = u->buffer.last;
1228
1229 return NGX_AGAIN;
1157 } 1230 }
1158 } 1231 }
1159 1232
1160 1233
1161 static ngx_int_t 1234 static ngx_int_t