comparison src/http/ngx_http_parse.c @ 500:ed3d382670c7 NGINX_0_7_62

nginx 0.7.62 *) Security: a segmentation fault might occur in worker process while specially crafted request handling. Thanks to Chris Ries. *) Feature: the $upstream_cache_status variable. *) Bugfix: an expired cached response might stick in the "UPDATING" state. *) Bugfix: a segmentation fault might occur in worker process, if error_log was set to info or debug level. Thanks to Sergey Bochenkov. *) Bugfix: in handling FastCGI headers split in records. *) Bugfix: XSLT filter may fail with message "not well formed XML document" for valid XML document. Thanks to Kuramoto Eiji. *) Bugfix: now in MacOSX, Cygwin, and nginx/Windows locations given by a regular expression are always tested in case insensitive mode. *) Bugfix: now nginx/Windows ignores trailing dots in URI. Thanks to Hugo Leisink. *) Bugfix: name of file specified in --conf-path was not honored during installation; the bug had appeared in 0.6.6. Thanks to Maxim Dounin. *) Bugfix: a 500 error code was returned for invalid login/password while HTTP Basic authentication on Windows.
author Igor Sysoev <http://sysoev.ru>
date Mon, 14 Sep 2009 00:00:00 +0400
parents 392c16f2d858
children 89dc5654117c
comparison
equal deleted inserted replaced
499:f2c782e5161f 500:ed3d382670c7
737 737
738 switch (state) { 738 switch (state) {
739 739
740 /* first char */ 740 /* first char */
741 case sw_start: 741 case sw_start:
742 r->header_name_start = p;
742 r->invalid_header = 0; 743 r->invalid_header = 0;
743 744
744 switch (ch) { 745 switch (ch) {
745 case CR: 746 case CR:
746 r->header_end = p; 747 r->header_end = p;
749 case LF: 750 case LF:
750 r->header_end = p; 751 r->header_end = p;
751 goto header_done; 752 goto header_done;
752 default: 753 default:
753 state = sw_name; 754 state = sw_name;
754 r->header_name_start = p;
755 755
756 c = lowcase[ch]; 756 c = lowcase[ch];
757 757
758 if (c) { 758 if (c) {
759 hash = ngx_hash(0, c); 759 hash = ngx_hash(0, c);
948 enum { 948 enum {
949 sw_usual = 0, 949 sw_usual = 0,
950 sw_slash, 950 sw_slash,
951 sw_dot, 951 sw_dot,
952 sw_dot_dot, 952 sw_dot_dot,
953 #if (NGX_WIN32)
954 sw_dot_dot_dot,
955 #endif
956 sw_quoted, 953 sw_quoted,
957 sw_quoted_second 954 sw_quoted_second
958 } state, quoted_state; 955 } state, quoted_state;
959 956
960 #if (NGX_SUPPRESS_WARN) 957 #if (NGX_SUPPRESS_WARN)
1135 #if (NGX_WIN32) 1132 #if (NGX_WIN32)
1136 case '\\': 1133 case '\\':
1137 #endif 1134 #endif
1138 case '/': 1135 case '/':
1139 state = sw_slash; 1136 state = sw_slash;
1140 u -= 4; 1137 u -= 5;
1141 if (u < r->uri.data) { 1138 for ( ;; ) {
1142 return NGX_HTTP_PARSE_INVALID_REQUEST; 1139 if (u < r->uri.data) {
1143 } 1140 return NGX_HTTP_PARSE_INVALID_REQUEST;
1144 while (*(u - 1) != '/') { 1141 }
1142 if (*u == '/') {
1143 u++;
1144 break;
1145 }
1145 u--; 1146 u--;
1146 } 1147 }
1147 break; 1148 break;
1148 case '%': 1149 case '%':
1149 quoted_state = state; 1150 quoted_state = state;
1152 case '?': 1153 case '?':
1153 r->args_start = p; 1154 r->args_start = p;
1154 goto args; 1155 goto args;
1155 case '#': 1156 case '#':
1156 goto done; 1157 goto done;
1157 #if (NGX_WIN32)
1158 case '.':
1159 state = sw_dot_dot_dot;
1160 *u++ = ch;
1161 break;
1162 #endif
1163 case '+': 1158 case '+':
1164 r->plus_in_uri = 1; 1159 r->plus_in_uri = 1;
1165 default: 1160 default:
1166 state = sw_usual; 1161 state = sw_usual;
1167 *u++ = ch; 1162 *u++ = ch;
1168 break; 1163 break;
1169 } 1164 }
1170 1165
1171 ch = *p++; 1166 ch = *p++;
1172 break; 1167 break;
1173
1174 #if (NGX_WIN32)
1175 case sw_dot_dot_dot:
1176
1177 if (usual[ch >> 5] & (1 << (ch & 0x1f))) {
1178 state = sw_usual;
1179 *u++ = ch;
1180 ch = *p++;
1181 break;
1182 }
1183
1184 switch(ch) {
1185 case '\\':
1186 case '/':
1187 state = sw_slash;
1188 u -= 5;
1189 if (u < r->uri.data) {
1190 return NGX_HTTP_PARSE_INVALID_REQUEST;
1191 }
1192 while (*u != '/') {
1193 u--;
1194 }
1195 if (u < r->uri.data) {
1196 return NGX_HTTP_PARSE_INVALID_REQUEST;
1197 }
1198 while (*(u - 1) != '/') {
1199 u--;
1200 }
1201 break;
1202 case '%':
1203 quoted_state = state;
1204 state = sw_quoted;
1205 break;
1206 case '?':
1207 r->args_start = p;
1208 goto args;
1209 case '#':
1210 goto done;
1211 case '+':
1212 r->plus_in_uri = 1;
1213 default:
1214 state = sw_usual;
1215 *u++ = ch;
1216 break;
1217 }
1218
1219 ch = *p++;
1220 break;
1221 #endif
1222 1168
1223 case sw_quoted: 1169 case sw_quoted:
1224 r->quoted_uri = 1; 1170 r->quoted_uri = 1;
1225 1171
1226 if (ch >= '0' && ch <= '9') { 1172 if (ch >= '0' && ch <= '9') {
1367 /* detect "/../" */ 1313 /* detect "/../" */
1368 1314
1369 if (p[0] == '.' && p[1] == '.' && ngx_path_separator(p[2])) { 1315 if (p[0] == '.' && p[1] == '.' && ngx_path_separator(p[2])) {
1370 goto unsafe; 1316 goto unsafe;
1371 } 1317 }
1372
1373 #if (NGX_WIN32)
1374
1375 if (len > 3) {
1376
1377 /* detect "/.../" */
1378
1379 if (p[0] == '.' && p[1] == '.' && p[2] == '.'
1380 && ngx_path_separator(p[3]))
1381 {
1382 goto unsafe;
1383 }
1384 }
1385 #endif
1386 } 1318 }
1387 } 1319 }
1388 1320
1389 return NGX_OK; 1321 return NGX_OK;
1390 1322