From: Michael Wallner Date: Fri, 6 Feb 2015 11:13:19 +0000 (+0100) Subject: reduce cost of parsing http start line X-Git-Tag: RELEASE_2_3_0_RC1~51 X-Git-Url: https://git.m6w6.name/?p=m6w6%2Fext-http;a=commitdiff_plain;h=401e7e3f740efedb5e543948fe89e1c2dfad47c5 reduce cost of parsing http start line --- diff --git a/php_http_info.c b/php_http_info.c index 876c720..9050919 100644 --- a/php_http_info.c +++ b/php_http_info.c @@ -90,13 +90,22 @@ php_http_info_t *php_http_info_parse(php_http_info_t *info, const char *pre_head /* is response */ if (pre_header == http) { - char *status = NULL; - const char *code = http + sizeof("HTTP/X.x"); + const char *status = NULL, *code = http + sizeof("HTTP/X.x"); info->type = PHP_HTTP_RESPONSE; while (' ' == *code) ++code; if (code && end > code) { - PHP_HTTP_INFO(info).response.code = strtol(code, &status, 10); + /* rfc7230#3.1.2 The status-code element is a 3-digit integer code */ + PHP_HTTP_INFO(info).response.code = 100*(*code++ - '0'); + PHP_HTTP_INFO(info).response.code += 10*(*code++ - '0'); + PHP_HTTP_INFO(info).response.code += *code++ - '0'; + if (PHP_HTTP_INFO(info).response.code < 100 || PHP_HTTP_INFO(info).response.code > 599) { + if (free_info) { + php_http_info_free(&info); + } + return NULL; + } + status = code; } else { PHP_HTTP_INFO(info).response.code = 0; } diff --git a/php_http_version.c b/php_http_version.c index f4fcfc8..7adef9d 100644 --- a/php_http_version.c +++ b/php_http_version.c @@ -27,7 +27,7 @@ php_http_version_t *php_http_version_init(php_http_version_t *v, unsigned major, php_http_version_t *php_http_version_parse(php_http_version_t *v, const char *str TSRMLS_DC) { long major, minor; - char separator = 0, *stop = NULL; + char separator = 0; register const char *ptr = str; switch (*ptr) { @@ -40,16 +40,16 @@ php_http_version_t *php_http_version_parse(php_http_version_t *v, const char *st ++ptr; /* no break */ default: - major = strtol(ptr, &stop, 10); - if (stop && stop != ptr && major != LONG_MIN && major != LONG_MAX) { - separator = *stop; + /* rfc7230#2.6 The HTTP version number consists of two decimal digits separated by a "." (period or decimal point) */ + major = *ptr++ - '0'; + if (major >= 0 && major <= 9) { + separator = *ptr++; if (separator) { if (separator != '.' && separator != ',') { - php_error_docref(NULL TSRMLS_CC, E_NOTICE, "Non-standard version separator '%c' in HTTP protocol version '%s'", separator, ptr); + php_error_docref(NULL TSRMLS_CC, E_NOTICE, "Non-standard version separator '%c' in HTTP protocol version '%s'", separator, ptr - 2); } - ptr = stop + 1; - minor = strtol(ptr, &stop, 10); - if (minor != LONG_MIN && minor != LONG_MAX) { + minor = *ptr - '0'; + if (minor >= 0 && minor <= 9) { return php_http_version_init(v, major, minor TSRMLS_CC); } }