diff --git a/NEWS b/NEWS index 52768d60968bc..c34e839ab9f22 100644 --- a/NEWS +++ b/NEWS @@ -15,6 +15,9 @@ PHP NEWS . Fixed bug #68422 (Incorrect argument reflection info for array_multisort()). (Alexander Lisachenko) . Fixed bug #68446 (Array constant not accepted for array parameter default). (Bob) + . Fixed bug #68091 (Some Zend headers lack appropriate extern "C" blocks). + (Adam) + . Fixed bug #68370 ("unset($this)" can make the program crash). (Laruence) - FPM: . Fixed bug #68381 (fpm_unix_init_main ignores log_level). @@ -35,6 +38,7 @@ PHP NEWS - GMP: . Fixed bug #68419 (build error with gmp 4.1). (Remi) + . Fixed bug #68478 (access.log don't use prefix). (Remi) - PDO_pgsql: . Fixed bug #67462 (PDO_PGSQL::beginTransaction() wrongly throws exception @@ -49,6 +53,8 @@ PHP NEWS - Session: . Fixed bug #68331 (Session custom storage callable functions not being called) (Yasuo Ohgaki) + . Fixed bug #68091 (Some Zend headers lack appropriate extern "C" blocks). + (Adam) - SOAP: . Fixed bug #68361 (Segmentation fault on SoapClient::__getTypes). diff --git a/main/SAPI.c b/main/SAPI.c index f9e9ccb049d6a..a79fe2ed039bb 100644 --- a/main/SAPI.c +++ b/main/SAPI.c @@ -1095,6 +1095,54 @@ SAPI_API void sapi_terminate_process(TSRMLS_D) { } } +SAPI_API void sapi_add_request_header(char *var, unsigned int var_len, char *val, unsigned int val_len, void *arg TSRMLS_DC) /* {{{ */ +{ + zval *return_value = (zval*)arg; + char *str = NULL; + char *p; + ALLOCA_FLAG(use_heap) + + if (var_len > 5 && + var[0] == 'H' && + var[1] == 'T' && + var[2] == 'T' && + var[3] == 'P' && + var[4] == '_') { + + var_len -= 5; + p = var + 5; + var = str = do_alloca(var_len + 1, use_heap); + *str++ = *p++; + while (*p) { + if (*p == '_') { + *str++ = '-'; + p++; + if (*p) { + *str++ = *p++; + } + } else if (*p >= 'A' && *p <= 'Z') { + *str++ = (*p++ - 'A' + 'a'); + } else { + *str++ = *p++; + } + } + *str = 0; + } else if (var_len == sizeof("CONTENT_TYPE")-1 && + memcmp(var, "CONTENT_TYPE", sizeof("CONTENT_TYPE")-1) == 0) { + var = "Content-Type"; + } else if (var_len == sizeof("CONTENT_LENGTH")-1 && + memcmp(var, "CONTENT_LENGTH", sizeof("CONTENT_LENGTH")-1) == 0) { + var = "Content-Length"; + } else { + return; + } + + add_assoc_stringl_ex(return_value, var, var_len, val, val_len, 1); + if (str) { + free_alloca(var, use_heap); + } +} + /* * Local variables: * tab-width: 4 diff --git a/main/SAPI.h b/main/SAPI.h index 990ca6990c8f4..dd16e7abf4815 100644 --- a/main/SAPI.h +++ b/main/SAPI.h @@ -215,6 +215,7 @@ SAPI_API int sapi_get_target_uid(uid_t * TSRMLS_DC); SAPI_API int sapi_get_target_gid(gid_t * TSRMLS_DC); SAPI_API double sapi_get_request_time(TSRMLS_D); SAPI_API void sapi_terminate_process(TSRMLS_D); +SAPI_API void sapi_add_request_header(char *var, unsigned int var_len, char *val, unsigned int val_len, void *arg TSRMLS_DC); END_EXTERN_C() struct _sapi_module_struct { diff --git a/sapi/cgi/cgi_main.c b/sapi/cgi/cgi_main.c index c0b040a6d0c5d..86287888e991c 100644 --- a/sapi/cgi/cgi_main.c +++ b/sapi/cgi/cgi_main.c @@ -1530,54 +1530,6 @@ PHP_FUNCTION(apache_child_terminate) /* {{{ */ } /* }}} */ -static void add_request_header(char *var, unsigned int var_len, char *val, unsigned int val_len, void *arg TSRMLS_DC) /* {{{ */ -{ - zval *return_value = (zval*)arg; - char *str = NULL; - char *p; - ALLOCA_FLAG(use_heap) - - if (var_len > 5 && - var[0] == 'H' && - var[1] == 'T' && - var[2] == 'T' && - var[3] == 'P' && - var[4] == '_') { - - var_len -= 5; - p = var + 5; - var = str = do_alloca(var_len + 1, use_heap); - *str++ = *p++; - while (*p) { - if (*p == '_') { - *str++ = '-'; - p++; - if (*p) { - *str++ = *p++; - } - } else if (*p >= 'A' && *p <= 'Z') { - *str++ = (*p++ - 'A' + 'a'); - } else { - *str++ = *p++; - } - } - *str = 0; - } else if (var_len == sizeof("CONTENT_TYPE")-1 && - memcmp(var, "CONTENT_TYPE", sizeof("CONTENT_TYPE")-1) == 0) { - var = "Content-Type"; - } else if (var_len == sizeof("CONTENT_LENGTH")-1 && - memcmp(var, "CONTENT_LENGTH", sizeof("CONTENT_LENGTH")-1) == 0) { - var = "Content-Length"; - } else { - return; - } - add_assoc_stringl_ex(return_value, var, var_len+1, val, val_len, 1); - if (str) { - free_alloca(var, use_heap); - } -} -/* }}} */ - PHP_FUNCTION(apache_request_headers) /* {{{ */ { if (ZEND_NUM_ARGS() > 0) { @@ -1587,7 +1539,7 @@ PHP_FUNCTION(apache_request_headers) /* {{{ */ if (fcgi_is_fastcgi()) { fcgi_request *request = (fcgi_request*) SG(server_context); - fcgi_loadenv(request, add_request_header, return_value TSRMLS_CC); + fcgi_loadenv(request, sapi_add_request_header, return_value TSRMLS_CC); } else { char buf[128]; char **env, *p, *q, *var, *val, *t = buf; diff --git a/sapi/fpm/fpm/fpm_main.c b/sapi/fpm/fpm/fpm_main.c index 5b96dee038b79..e7fc22df2412d 100644 --- a/sapi/fpm/fpm/fpm_main.c +++ b/sapi/fpm/fpm/fpm_main.c @@ -115,6 +115,8 @@ struct sigaction act, old_term, old_quit, old_int; static void (*php_php_import_environment_variables)(zval *array_ptr TSRMLS_DC); +typedef void (*fcgi_apply_func)(char *var, unsigned int var_len, char *val, unsigned int val_len, void *arg TSRMLS_DC); + #ifndef PHP_WIN32 /* these globals used for forking children on unix systems */ @@ -1546,8 +1548,41 @@ PHP_FUNCTION(fastcgi_finish_request) /* {{{ */ } /* }}} */ +static inline void fcgi_hash_apply(HashTable *h, fcgi_apply_func func, void *arg TSRMLS_DC) /* {{{ */ +{ + Bucket *p = h->pListHead; + + while (p) { + if (EXPECTED(p->arKey != NULL)) { + /* Since request->env already has the terminating char, -1 to var_len */ + func((char*)p->arKey, p->nKeyLength, *(char**)p->pData, strlen(*(char**)p->pData), arg TSRMLS_CC); + } + p = p->pListNext; + } +} /* }}} */ + +PHP_FUNCTION(apache_request_headers) /* {{{ */ +{ + fcgi_request *request; + + if (zend_parse_parameters_none() == FAILURE) { + return; + } + + array_init(return_value); + + if ((request = (fcgi_request*) SG(server_context))) { + fcgi_hash_apply(request->env, sapi_add_request_header, return_value TSRMLS_CC); + } +} /* }}} */ + +ZEND_BEGIN_ARG_INFO(cgi_fcgi_sapi_no_arginfo, 0) +ZEND_END_ARG_INFO() + static const zend_function_entry cgi_fcgi_sapi_functions[] = { - PHP_FE(fastcgi_finish_request, NULL) + PHP_FE(fastcgi_finish_request, cgi_fcgi_sapi_no_arginfo) + PHP_FE(apache_request_headers, cgi_fcgi_sapi_no_arginfo) + PHP_FALIAS(getallheaders, apache_request_headers, cgi_fcgi_sapi_no_arginfo) {NULL, NULL, NULL} }; diff --git a/sapi/fpm/tests/018.phpt b/sapi/fpm/tests/018.phpt new file mode 100644 index 0000000000000..ca0e31b6b286a --- /dev/null +++ b/sapi/fpm/tests/018.phpt @@ -0,0 +1,76 @@ +--TEST-- +FPM: Test getallheaders() function +--SKIPIF-- + +--FILE-- + 'BAR', + 'HTTP_CONTENT_TYPE' => 'text/html; charset=UTF-8', + ]; + $req = run_request('127.0.0.1', $port, $srcfile, ''); + echo strstr($req, "Test Start"); + echo "Request ok\n"; + } catch (Exception $e) { + echo "Request error\n"; + } + proc_terminate($fpm); + echo stream_get_contents($tail); + fclose($tail); + proc_close($fpm); +} + +?> +Done +--EXPECTF-- +[%s] NOTICE: fpm is running, pid %d +[%s] NOTICE: ready to handle connections +Test Start +array(1) { + ["X-Foo"]=> + string(4) "Bar" +} +Test End + +Request ok +[%s] NOTICE: Terminating ... +[%s] NOTICE: exiting, bye-bye! +Done +--CLEAN-- + \ No newline at end of file diff --git a/sapi/fpm/tests/include.inc b/sapi/fpm/tests/include.inc index b195fad507325..a8b64f48b7eac 100644 --- a/sapi/fpm/tests/include.inc +++ b/sapi/fpm/tests/include.inc @@ -86,10 +86,10 @@ function fpm_display_log($tail, $n=1, $ignore='systemd') { } } -function run_request($host, $port, $uri='/ping', $query='') { +function run_request($host, $port, $uri='/ping', $query='', $headers=array()) { require_once 'fcgi.inc'; $client = new Adoy\FastCGI\Client($host, $port); - $params = array( + $params = array_merge(array( 'GATEWAY_INTERFACE' => 'FastCGI/1.0', 'REQUEST_METHOD' => 'GET', 'SCRIPT_FILENAME' => $uri, @@ -106,6 +106,6 @@ function run_request($host, $port, $uri='/ping', $query='') { 'SERVER_PROTOCOL' => 'HTTP/1.1', 'CONTENT_TYPE' => '', 'CONTENT_LENGTH' => 0 - ); + ), $headers); return $client->request($params, false)."\n"; }