From 283f56af6696f57400bdbf8ce29ee66e64249c0d Mon Sep 17 00:00:00 2001 From: Adam Harvey Date: Wed, 19 Jun 2013 11:32:37 -0700 Subject: Change the search in get_status_string() to correctly handle unknown codes. This previously used a buggy implementation of binary search that would loop infinitely for unknown codes when searching in reason arrays of particular sizes (such as the one we have at the moment). Since C provides bsearch(), we'll just use that instead, since libc authors hopefully get this right. There was also an additional bug that was masked by the first one: the design was that an unknown code would result in get_status_string() returning NULL, which would then result in a segfault in append_http_status_line(), since it assumed that it would always receive a valid string pointer that could be handed off to smart_str_appends_ex(). We'll now return a placeholder in that case. Fixes bug #65066 (Cli server not responsive when responding with 422 http status code). --- sapi/cli/php_cli_server.c | 42 +++++++++++++++++++++++++++++------------- 1 file changed, 29 insertions(+), 13 deletions(-) (limited to 'sapi/cli/php_cli_server.c') diff --git a/sapi/cli/php_cli_server.c b/sapi/cli/php_cli_server.c index 903f042125..268beebcba 100644 --- a/sapi/cli/php_cli_server.c +++ b/sapi/cli/php_cli_server.c @@ -20,6 +20,7 @@ /* $Id: php_cli.c 306938 2011-01-01 02:17:06Z felipe $ */ #include +#include #include #include @@ -333,23 +334,38 @@ static char *get_last_error() /* {{{ */ return pestrdup(strerror(errno), 1); } /* }}} */ +static int status_comp(const void *a, const void *b) /* {{{ */ +{ + const php_cli_server_http_reponse_status_code_pair *pa = (const php_cli_server_http_reponse_status_code_pair *) a; + const php_cli_server_http_reponse_status_code_pair *pb = (const php_cli_server_http_reponse_status_code_pair *) b; + + if (pa->code < pb->code) { + return -1; + } else if (pa->code > pb->code) { + return 1; + } + + return 0; +} /* }}} */ + static const char *get_status_string(int code) /* {{{ */ { - size_t e = (sizeof(status_map) / sizeof(php_cli_server_http_reponse_status_code_pair)); - size_t s = 0; + php_cli_server_http_reponse_status_code_pair needle, *result = NULL; - while (e != s) { - size_t c = MIN((e + s + 1) / 2, e - 1); - int d = status_map[c].code; - if (d > code) { - e = c; - } else if (d < code) { - s = c; - } else { - return status_map[c].str; - } + needle.code = code; + needle.str = NULL; + + result = bsearch(&needle, status_map, sizeof(status_map) / sizeof(needle), sizeof(needle), status_comp); + + if (result) { + return result->str; } - return NULL; + + /* Returning NULL would require complicating append_http_status_line() to + * not segfault in that case, so let's just return a placeholder, since RFC + * 2616 requires a reason phrase. This is basically what a lot of other Web + * servers do in this case anyway. */ + return "Unknown Status Code"; } /* }}} */ static const char *get_template_string(int code) /* {{{ */ -- cgit v1.2.1 From f5c7fe92020fd7b8e81c94658da4813a7e6dea17 Mon Sep 17 00:00:00 2001 From: Adam Harvey Date: Thu, 20 Jun 2013 09:34:21 -0700 Subject: Fix the spelling of the php_cli_server_http_response_status_code_pair typedef. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Specifically: php_cli_server_http_reponse_status_code_pair → php_cli_server_http_response_status_code_pair. --- sapi/cli/php_cli_server.c | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) (limited to 'sapi/cli/php_cli_server.c') diff --git a/sapi/cli/php_cli_server.c b/sapi/cli/php_cli_server.c index 268beebcba..335d589a67 100644 --- a/sapi/cli/php_cli_server.c +++ b/sapi/cli/php_cli_server.c @@ -193,17 +193,17 @@ typedef struct php_cli_server { HashTable clients; } php_cli_server; -typedef struct php_cli_server_http_reponse_status_code_pair { +typedef struct php_cli_server_http_response_status_code_pair { int code; const char *str; -} php_cli_server_http_reponse_status_code_pair; +} php_cli_server_http_response_status_code_pair; typedef struct php_cli_server_ext_mime_type_pair { const char *ext; const char *mime_type; } php_cli_server_ext_mime_type_pair; -static php_cli_server_http_reponse_status_code_pair status_map[] = { +static php_cli_server_http_response_status_code_pair status_map[] = { { 100, "Continue" }, { 101, "Switching Protocols" }, { 200, "OK" }, @@ -250,7 +250,7 @@ static php_cli_server_http_reponse_status_code_pair status_map[] = { { 511, "Network Authentication Required" }, }; -static php_cli_server_http_reponse_status_code_pair template_map[] = { +static php_cli_server_http_response_status_code_pair template_map[] = { { 400, "

%s

Your browser sent a request that this server could not understand.

" }, { 404, "

%s

The requested resource %s was not found on this server.

" }, { 500, "

%s

The server is temporarily unavailable.

" }, @@ -336,8 +336,8 @@ static char *get_last_error() /* {{{ */ static int status_comp(const void *a, const void *b) /* {{{ */ { - const php_cli_server_http_reponse_status_code_pair *pa = (const php_cli_server_http_reponse_status_code_pair *) a; - const php_cli_server_http_reponse_status_code_pair *pb = (const php_cli_server_http_reponse_status_code_pair *) b; + const php_cli_server_http_response_status_code_pair *pa = (const php_cli_server_http_response_status_code_pair *) a; + const php_cli_server_http_response_status_code_pair *pb = (const php_cli_server_http_response_status_code_pair *) b; if (pa->code < pb->code) { return -1; @@ -350,7 +350,7 @@ static int status_comp(const void *a, const void *b) /* {{{ */ static const char *get_status_string(int code) /* {{{ */ { - php_cli_server_http_reponse_status_code_pair needle, *result = NULL; + php_cli_server_http_response_status_code_pair needle, *result = NULL; needle.code = code; needle.str = NULL; @@ -370,7 +370,7 @@ static const char *get_status_string(int code) /* {{{ */ static const char *get_template_string(int code) /* {{{ */ { - size_t e = (sizeof(template_map) / sizeof(php_cli_server_http_reponse_status_code_pair)); + size_t e = (sizeof(template_map) / sizeof(php_cli_server_http_response_status_code_pair)); size_t s = 0; while (e != s) { -- cgit v1.2.1