Skip to content

FPM status page - JSON escape #11050

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
wants to merge 2 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 15 additions & 0 deletions ext/json/json.c
Original file line number Diff line number Diff line change
Expand Up @@ -142,6 +142,21 @@ static PHP_MINFO_FUNCTION(json)
}
/* }}} */

PHP_JSON_API zend_string *php_json_encode_string(const char *s, size_t len, int options)
{
smart_str buf = {0};
php_json_encoder encoder;

php_json_encode_init(&encoder);

if (php_json_escape_string(&buf, s, len, options, &encoder) == FAILURE) {
smart_str_free(&buf);
return NULL;
}

return smart_str_extract(&buf);
}

PHP_JSON_API int php_json_encode_ex(smart_str *buf, zval *val, int options, zend_long depth) /* {{{ */
{
php_json_encoder encoder;
Expand Down
6 changes: 1 addition & 5 deletions ext/json/json_encoder.c
Original file line number Diff line number Diff line change
Expand Up @@ -31,10 +31,6 @@

static const char digits[] = "0123456789abcdef";

static int php_json_escape_string(
smart_str *buf, const char *s, size_t len,
int options, php_json_encoder *encoder);

static int php_json_determine_array_type(zval *val) /* {{{ */
{
zend_array *myht = Z_ARRVAL_P(val);
Expand Down Expand Up @@ -312,7 +308,7 @@ static int php_json_encode_array(smart_str *buf, zval *val, int options, php_jso
}
/* }}} */

static int php_json_escape_string(
int php_json_escape_string(
smart_str *buf, const char *s, size_t len,
int options, php_json_encoder *encoder) /* {{{ */
{
Expand Down
2 changes: 2 additions & 0 deletions ext/json/php_json.h
Original file line number Diff line number Diff line change
Expand Up @@ -97,6 +97,8 @@ PHP_JSON_API ZEND_EXTERN_MODULE_GLOBALS(json)
ZEND_TSRMLS_CACHE_EXTERN()
#endif

PHP_JSON_API zend_string *php_json_encode_string(const char *s, size_t len, int options);

PHP_JSON_API int php_json_encode_ex(smart_str *buf, zval *val, int options, zend_long depth);
PHP_JSON_API int php_json_encode(smart_str *buf, zval *val, int options);
PHP_JSON_API int php_json_decode_ex(zval *return_value, const char *str, size_t str_len, zend_long options, zend_long depth);
Expand Down
2 changes: 2 additions & 0 deletions ext/json/php_json_encoder.h
Original file line number Diff line number Diff line change
Expand Up @@ -35,4 +35,6 @@ static inline void php_json_encode_init(php_json_encoder *encoder)

int php_json_encode_zval(smart_str *buf, zval *val, int options, php_json_encoder *encoder);

int php_json_escape_string(smart_str *buf, const char *s, size_t len, int options, php_json_encoder *encoder);

#endif /* PHP_JSON_ENCODER_H */
34 changes: 26 additions & 8 deletions sapi/fpm/fpm/fpm_status.c
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,8 @@
#include "fpm_atomic.h"
#include "fpm_conf.h"
#include "fpm_php.h"
#include <ext/standard/html.h>
#include "ext/standard/html.h"
#include "ext/json/php_json.h"

static char *fpm_status_uri = NULL;
static char *fpm_status_ping_uri = NULL;
Expand Down Expand Up @@ -140,7 +141,8 @@ int fpm_status_handle_request(void) /* {{{ */
struct fpm_scoreboard_proc_s *proc;
char *buffer, *time_format, time_buffer[64];
time_t now_epoch;
int full, encode, has_start_time;
int full, has_start_time;
bool encode_html, encode_json;
char *short_syntax, *short_post;
char *full_pre, *full_syntax, *full_post, *full_separator;
zend_string *_GET_str;
Expand Down Expand Up @@ -175,7 +177,8 @@ int fpm_status_handle_request(void) /* {{{ */
full = (fpm_php_get_string_from_table(_GET_str, "full") != NULL);
short_syntax = short_post = NULL;
full_separator = full_pre = full_syntax = full_post = NULL;
encode = 0;
encode_html = false;
encode_json = false;
has_start_time = 1;

scoreboard_p = fpm_scoreboard_get();
Expand Down Expand Up @@ -218,7 +221,7 @@ int fpm_status_handle_request(void) /* {{{ */
if (fpm_php_get_string_from_table(_GET_str, "html")) {
sapi_add_header_ex(ZEND_STRL("Content-Type: text/html"), 1, 1);
time_format = "%d/%b/%Y:%H:%M:%S %z";
encode = 1;
encode_html = true;

short_syntax =
"<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.0 Strict//EN\" \"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd\">\n"
Expand Down Expand Up @@ -287,7 +290,7 @@ int fpm_status_handle_request(void) /* {{{ */
} else if (fpm_php_get_string_from_table(_GET_str, "xml")) {
sapi_add_header_ex(ZEND_STRL("Content-Type: text/xml"), 1, 1);
time_format = "%s";
encode = 1;
encode_html = true;

short_syntax =
"<?xml version=\"1.0\" ?>\n"
Expand Down Expand Up @@ -336,6 +339,8 @@ int fpm_status_handle_request(void) /* {{{ */
sapi_add_header_ex(ZEND_STRL("Content-Type: application/json"), 1, 1);
time_format = "%s";

encode_json = true;

short_syntax =
"{"
"\"pool\":\"%s\","
Expand Down Expand Up @@ -549,11 +554,24 @@ int fpm_status_handle_request(void) /* {{{ */
query_string = NULL;
tmp_query_string = NULL;
if (proc->query_string[0] != '\0') {
if (!encode) {
query_string = proc->query_string;
if (encode_html) {
tmp_query_string = php_escape_html_entities_ex(
(const unsigned char *) proc->query_string,
strlen(proc->query_string), 1, ENT_HTML_IGNORE_ERRORS & ENT_COMPAT,
NULL, /* double_encode */ 1, /* quiet */ 0);
} else if (encode_json) {
tmp_query_string = php_json_encode_string(proc->query_string,
strlen(proc->query_string), PHP_JSON_INVALID_UTF8_IGNORE);
} else {
tmp_query_string = php_escape_html_entities_ex((const unsigned char *) proc->query_string, strlen(proc->query_string), 1, ENT_HTML_IGNORE_ERRORS & ENT_COMPAT, NULL, /* double_encode */ 1, /* quiet */ 0);
query_string = proc->query_string;
}
if (tmp_query_string) {
query_string = ZSTR_VAL(tmp_query_string);
/* remove quotes around the string */
if (encode_json && ZSTR_LEN(tmp_query_string) >= 2) {
query_string[ZSTR_LEN(tmp_query_string) - 1] = '\0';
++query_string;
}
}
}

Expand Down
50 changes: 50 additions & 0 deletions sapi/fpm/tests/bug64539-status-json-encoding.phpt
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
--TEST--
FPM: bug64539 - status json format escaping
--SKIPIF--
<?php
include "skipif.inc"; ?>
--FILE--
<?php

require_once "tester.inc";

$cfg = <<<EOT
[global]
error_log = {{FILE:LOG}}
[unconfined]
listen = {{ADDR}}
pm = static
pm.max_children = 2
pm.status_path = /status
catch_workers_output = yes
EOT;

$code = <<<EOT
<?php
usleep(200000);
EOT;

$tester = new FPM\Tester($cfg, $code);
$tester->start();
$tester->expectLogStartNotices();
$responses = $tester
->multiRequest([
['query' => 'a=b"c'],
['uri' => '/status', 'query' => 'full&json', 'delay' => 100000],
]);
$data = json_decode($responses[1]->getBody('application/json'), true);
var_dump(explode('?', $data['processes'][0]['request uri'])[1]);
$tester->terminate();
$tester->expectLogTerminatingNotices();
$tester->close();

?>
Done
--EXPECT--
string(5) "a=b"c"
Done
--CLEAN--
<?php
require_once "tester.inc";
FPM\Tester::clean();
?>
12 changes: 8 additions & 4 deletions sapi/fpm/tests/response.inc
Original file line number Diff line number Diff line change
Expand Up @@ -192,18 +192,22 @@ class Response

/**
* Print raw body.
*
* @param string $contentType Expect body to have specified content type.
*/
public function dumpBody()
public function dumpBody(string $contentType = 'text/html')
{
var_dump($this->getBody());
var_dump($this->getBody($contentType));
}

/**
* Print raw body.
*
* @param string $contentType Expect body to have specified content type.
*/
public function printBody()
public function printBody(string $contentType = 'text/html')
{
echo $this->getBody() . "\n";
echo $this->getBody($contentType) . "\n";
}

/**
Expand Down
4 changes: 4 additions & 0 deletions sapi/fpm/tests/tester.inc
Original file line number Diff line number Diff line change
Expand Up @@ -795,6 +795,10 @@ class Tester
$requestData['uri'] ?? null
);

if (isset($requestData['delay'])) {
usleep($requestData['delay']);
}

return [
'client' => $client,
'requestId' => $client->async_request($params, false),
Expand Down