summaryrefslogtreecommitdiff
path: root/sapi/cli/php_cli_server.c
diff options
context:
space:
mode:
authorBouke van der Bijl <boukevanderbijl@gmail.com>2017-09-04 16:28:29 +0200
committerNikita Popov <nikita.ppv@gmail.com>2017-09-05 16:23:32 +0200
commitcd9d90f4d41c87494dee8ee72c7a48951213296b (patch)
treeac701b2137072f6c09afe46dede09999dfc94e9f /sapi/cli/php_cli_server.c
parent24da62d342d271b3d785741a48b7103fece6ed82 (diff)
downloadphp-git-cd9d90f4d41c87494dee8ee72c7a48951213296b.tar.gz
Fixed bug #70470
Diffstat (limited to 'sapi/cli/php_cli_server.c')
-rw-r--r--sapi/cli/php_cli_server.c110
1 files changed, 84 insertions, 26 deletions
diff --git a/sapi/cli/php_cli_server.c b/sapi/cli/php_cli_server.c
index 5d820743b6..4d5324f36c 100644
--- a/sapi/cli/php_cli_server.c
+++ b/sapi/cli/php_cli_server.c
@@ -171,6 +171,9 @@ typedef struct php_cli_server_client {
char *current_header_name;
size_t current_header_name_len;
unsigned int current_header_name_allocated:1;
+ char *current_header_value;
+ size_t current_header_value_len;
+ enum { HEADER_NONE=0, HEADER_FIELD, HEADER_VALUE } last_header_element;
size_t post_read_offset;
php_cli_server_request request;
unsigned int content_sender_initialized:1;
@@ -1469,7 +1472,7 @@ static void normalize_vpath(char **retval, size_t *retval_len, const char *vpath
#ifdef PHP_WIN32
{
char *p = decoded_vpath;
-
+
do {
if (*p == '\\') {
*p = '/';
@@ -1572,50 +1575,100 @@ static int php_cli_server_client_read_request_on_fragment(php_http_parser *parse
return 0;
}
-static int php_cli_server_client_read_request_on_header_field(php_http_parser *parser, const char *at, size_t length)
+static void php_cli_server_client_save_header(php_cli_server_client *client)
{
- php_cli_server_client *client = parser->data;
+ /* strip off the colon */
+ zend_string *orig_header_name = zend_string_init(client->current_header_name, client->current_header_name_len, 1);
+ char *lc_header_name = zend_str_tolower_dup(client->current_header_name, client->current_header_name_len);
+ zend_hash_str_add_ptr(&client->request.headers, lc_header_name, client->current_header_name_len, client->current_header_value);
+ zend_hash_add_ptr(&client->request.headers_original_case, orig_header_name, client->current_header_value);
+ efree(lc_header_name);
+ zend_string_release(orig_header_name);
+
if (client->current_header_name_allocated) {
pefree(client->current_header_name, 1);
client->current_header_name_allocated = 0;
}
- client->current_header_name = (char *)at;
- client->current_header_name_len = length;
- return 0;
+ client->current_header_name = NULL;
+ client->current_header_name_len = 0;
+ client->current_header_value = NULL;
+ client->current_header_value_len = 0;
}
-static int php_cli_server_client_read_request_on_header_value(php_http_parser *parser, const char *at, size_t length)
+static int php_cli_server_client_read_request_on_header_field(php_http_parser *parser, const char *at, size_t length)
{
php_cli_server_client *client = parser->data;
- char *value = pestrndup(at, length, 1);
- if (!value) {
- return 1;
- }
- {
- /* strip off the colon */
- zend_string *orig_header_name = zend_string_init(client->current_header_name, client->current_header_name_len, 1);
- char *lc_header_name = zend_str_tolower_dup(client->current_header_name, client->current_header_name_len);
- zend_hash_str_add_ptr(&client->request.headers, lc_header_name, client->current_header_name_len, value);
- zend_hash_add_ptr(&client->request.headers_original_case, orig_header_name, value);
- efree(lc_header_name);
- zend_string_release(orig_header_name);
+ switch (client->last_header_element) {
+ case HEADER_VALUE:
+ php_cli_server_client_save_header(client);
+ /* break missing intentionally */
+ case HEADER_NONE:
+ client->current_header_name = (char *)at;
+ client->current_header_name_len = length;
+ break;
+ case HEADER_FIELD:
+ if (client->current_header_name_allocated) {
+ size_t new_length = client->current_header_name_len + length;
+ client->current_header_name = perealloc(client->current_header_name, new_length + 1, 1);
+ memcpy(client->current_header_name + client->current_header_name_len, at, length);
+ client->current_header_name_len = new_length;
+ } else {
+ size_t new_length = client->current_header_name_len + length;
+ char* field = pemalloc(new_length + 1, 1);
+ memcpy(field, client->current_header_name, client->current_header_name_len);
+ memcpy(field + client->current_header_name_len, at, length);
+ client->current_header_name = field;
+ client->current_header_name_len = new_length;
+ client->current_header_name_allocated = 1;
+ }
+ break;
}
- if (client->current_header_name_allocated) {
- pefree(client->current_header_name, 1);
- client->current_header_name_allocated = 0;
+ client->last_header_element = HEADER_FIELD;
+ return 0;
+}
+
+static int php_cli_server_client_read_request_on_header_value(php_http_parser *parser, const char *at, size_t length)
+{
+ php_cli_server_client *client = parser->data;
+ switch (client->last_header_element) {
+ case HEADER_FIELD:
+ client->current_header_value = pestrndup(at, length, 1);
+ client->current_header_value_len = length;
+ break;
+ case HEADER_VALUE:
+ {
+ size_t new_length = client->current_header_value_len + length;
+ client->current_header_value = perealloc(client->current_header_value, new_length + 1, 1);
+ memcpy(client->current_header_value + client->current_header_value_len, at, length);
+ client->current_header_value_len = new_length;
+ }
+ break;
+ case HEADER_NONE:
+ // can't happen
+ assert(0);
+ break;
}
+ client->last_header_element = HEADER_VALUE;
return 0;
}
static int php_cli_server_client_read_request_on_headers_complete(php_http_parser *parser)
{
php_cli_server_client *client = parser->data;
- if (client->current_header_name_allocated) {
- pefree(client->current_header_name, 1);
- client->current_header_name_allocated = 0;
+ switch (client->last_header_element) {
+ case HEADER_NONE:
+ break;
+ case HEADER_FIELD:
+ client->current_header_value = pemalloc(1, 1);
+ *client->current_header_value = '\0';
+ client->current_header_value_len = 0;
+ /* break missing intentionally */
+ case HEADER_VALUE:
+ php_cli_server_client_save_header(client);
+ break;
}
- client->current_header_name = NULL;
+ client->last_header_element = HEADER_NONE;
return 0;
}
@@ -1791,9 +1844,14 @@ static int php_cli_server_client_ctor(php_cli_server_client *client, php_cli_ser
}
php_http_parser_init(&client->parser, PHP_HTTP_REQUEST);
client->request_read = 0;
+
+ client->last_header_element = HEADER_NONE;
client->current_header_name = NULL;
client->current_header_name_len = 0;
client->current_header_name_allocated = 0;
+ client->current_header_value = NULL;
+ client->current_header_value_len = 0;
+
client->post_read_offset = 0;
if (FAILURE == php_cli_server_request_ctor(&client->request)) {
return FAILURE;