From c420f28df5358553aa1220888886ad5905e0eaa4 Mon Sep 17 00:00:00 2001 From: Javier Santacruz Date: Fri, 24 Mar 2023 17:49:31 +0100 Subject: [PATCH] Escape all string values in broken json from php-fpm status Should fix #258 and #291 --- phpfpm/phpfpm.go | 25 +++++++++++++------------ phpfpm/phpfpm_test.go | 4 +++- 2 files changed, 16 insertions(+), 13 deletions(-) diff --git a/phpfpm/phpfpm.go b/phpfpm/phpfpm.go index 400c2330..4ba16942 100644 --- a/phpfpm/phpfpm.go +++ b/phpfpm/phpfpm.go @@ -202,21 +202,22 @@ func (p *Pool) error(err error) error { return err } -// JSONResponseFixer resolves encoding issues with PHP-FPMs JSON response func JSONResponseFixer(content []byte) []byte { - c := string(content) - re := regexp.MustCompile(`(,"request uri":)"(.*?)"(,"content length":)`) - matches := re.FindAllStringSubmatch(c, -1) - - for _, match := range matches { - requestURI, _ := json.Marshal(match[2]) + reValue := regexp.MustCompile(`^"(.*)"(,)?$`) + reKey := regexp.MustCompile(`"[^"]+":`) - sold := match[0] - snew := match[1] + string(requestURI) + match[3] - - c = strings.ReplaceAll(c, sold, snew) + c := string(content) + values := reKey.Split(c, -1) + for _, value := range values { + matches := reValue.FindAllSubmatch([]byte(value), 1) + if len(matches) == 1 { + escaped, _ := json.Marshal(string(matches[0][1])) + if(len(matches[0]) > 2) { + escaped = append(escaped, matches[0][2]...) + } + c = strings.ReplaceAll(c, string(matches[0][0]), string(escaped)) + } } - return []byte(c) } diff --git a/phpfpm/phpfpm_test.go b/phpfpm/phpfpm_test.go index dde01b7a..7e5770be 100644 --- a/phpfpm/phpfpm_test.go +++ b/phpfpm/phpfpm_test.go @@ -103,7 +103,7 @@ func TestInvalidCharacterIssue24(t *testing.T) { func TestJsonResponseFixer(t *testing.T) { pool := Pool{} - content := []byte(`{"pool":"www","process manager":"dynamic","start time":1528367006,"start since":15073840,"accepted conn":1577112,"listen queue":0,"max listen queue":0,"listen queue len":0,"idle processes":16,"active processes":1,"total processes":17,"max active processes":15,"max children reached":0,"slow requests":0, "processes":[{"pid":15873,"state":"Idle","start time":1543354120,"start since":86726,"requests":853,"request duration":5721,"request method":"GET","request uri":"/vbseo.php?ALTERNATE_TEMPLATES=|%20echo%20"Content-Type:%20text%2Fhtml"%3Becho%20""%20%3B%20id%00","content length":0,"user":"-","script":"/www/forum.example.com/vbseo.php","last request cpu":349.59,"last request memory":786432},{"pid":123,"state":"Idle","start time":1543354120,"start since":86726,"requests":853,"request duration":5721,"request method":"GET","request uri":"123/vbseo.php?ALTERNATE_TEMPLATES=|%20echo%20"Content-Type:%20text%2Fhtml"%3Becho%20""%20%3B%20id%00","content length":0,"user":"-","script":"/www/forum.example.com/vbseo.php","last request cpu":349.59,"last request memory":786432}]}`) + content := []byte(`{"pool":"www","process manager":"dynamic","start time":1528367006,"start since":15073840,"accepted conn":1577112,"listen queue":0,"max listen queue":0,"listen queue len":0,"idle processes":16,"active processes":1,"total processes":17,"max active processes":15,"max children reached":0,"slow requests":0, "processes":[{"pid":15873,"state":"Idle","start time":1543354120,"start since":86726,"requests":853,"request duration":5721,"request method":"GET","request uri":"/vbseo.php?ALTERNATE_TEMPLATES=|%20echo%20"Content-Type:%20text%2Fhtml"%3Becho%20""%20%3B%20id%00","content length":0,"user":"my\windows\program","script":"/www/forum.example.com/vbseo.php","last request cpu":349.59,"last request memory":786432},{"pid":123,"state":"Idle","start time":1543354120,"start since":86726,"requests":853,"request duration":5721,"request method":"GET","request uri":"123/vbseo.php?ALTERNATE_TEMPLATES=|%20echo%20"Content-Type:%20text%2Fhtml"%3Becho%20""%20%3B%20id%00","content length":0,"user":"eol\n","script":"/www/forum.example.com/vbseo.php","last request cpu":349.59,"last request memory":786432}]}`) content = JSONResponseFixer(content) @@ -111,7 +111,9 @@ func TestJsonResponseFixer(t *testing.T) { assert.Nil(t, err, "successfully unmarshal on invalid 'request uri'") assert.Equal(t, pool.Processes[0].RequestURI, `/vbseo.php?ALTERNATE_TEMPLATES=|%20echo%20"Content-Type:%20text%2Fhtml"%3Becho%20""%20%3B%20id%00`, "request uri couldn't be deserialized") + assert.Equal(t, pool.Processes[0].User, `my\windows\program`, "user couldn't be deserialized") assert.Equal(t, pool.Processes[1].RequestURI, `123/vbseo.php?ALTERNATE_TEMPLATES=|%20echo%20"Content-Type:%20text%2Fhtml"%3Becho%20""%20%3B%20id%00`, "request uri couldn't be deserialized") + assert.Equal(t, pool.Processes[1].User, `eol\n`, "user couldn't be deserialized") } func TestParseURL(t *testing.T) {