From 9d2525152274f860162160291b48b26e162ec167 Mon Sep 17 00:00:00 2001 From: Robert Landers Date: Sun, 22 Jun 2025 10:17:52 +0200 Subject: [PATCH 1/6] add fast path --- ext/filter/filter.c | 50 +++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 48 insertions(+), 2 deletions(-) diff --git a/ext/filter/filter.c b/ext/filter/filter.c index 50eefb440d67a..dfad4575a5ba3 100644 --- a/ext/filter/filter.c +++ b/ext/filter/filter.c @@ -279,9 +279,11 @@ static void php_zval_filter(zval *value, zend_long filter, zend_long flags, zval static unsigned int php_sapi_filter(int arg, const char *var, char **val, size_t val_len, size_t *new_val_len) /* {{{ */ { - zval new_var, raw_var; + zval raw_var, new_var; zval *array_ptr = NULL, *orig_array_ptr = NULL; int retval = 0; + int is_raw = (IF_G(default_filter) == FILTER_UNSAFE_RAW); + size_t var_len = strlen(var); assert(*val != NULL); @@ -313,10 +315,54 @@ static unsigned int php_sapi_filter(int arg, const char *var, char **val, size_t * more specific cookies with the less specific ones. */ if (arg == PARSE_COOKIE && orig_array_ptr && - zend_symtable_str_exists(Z_ARRVAL_P(orig_array_ptr), var, strlen(var))) { + zend_symtable_str_exists(Z_ARRVAL_P(orig_array_ptr), var, var_len)) { return 0; } + /* + * Fast path: if the default filter is UNSAFE_RAW, we can build a single zval, register it twice, and be done + */ + if (is_raw) + { + if (array_ptr || orig_array_ptr) + { + if (val_len) + { + ZVAL_STRINGL(&raw_var, *val, val_len); + } else + { + ZVAL_EMPTY_STRING(&raw_var); + } + if (array_ptr) + { + php_register_variable_ex(var, &raw_var, array_ptr); + } + if (orig_array_ptr) + { + php_register_variable_ex(var, &raw_var, orig_array_ptr); + } + + if (retval) + { + if (new_val_len) + { + *new_val_len = Z_STRLEN_P(&raw_var); + } + efree(*val); + if (Z_STRLEN_P(&raw_var)) + { + *val = estrndup(Z_STRVAL_P(&raw_var), Z_STRLEN_P(&raw_var)); + } else + { + *val = strdup(""); + } + } + + zval_ptr_dtor(&raw_var); + } + return retval; + } + if (array_ptr) { /* Store the RAW variable internally */ ZVAL_STRINGL(&raw_var, *val, val_len); From e4e7535a14d6ec66efa28e4d4e35ee34161473c5 Mon Sep 17 00:00:00 2001 From: Robert Landers Date: Sun, 22 Jun 2025 10:28:07 +0200 Subject: [PATCH 2/6] fix typo --- ext/filter/filter.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ext/filter/filter.c b/ext/filter/filter.c index dfad4575a5ba3..9a6c3f06c143d 100644 --- a/ext/filter/filter.c +++ b/ext/filter/filter.c @@ -354,7 +354,7 @@ static unsigned int php_sapi_filter(int arg, const char *var, char **val, size_t *val = estrndup(Z_STRVAL_P(&raw_var), Z_STRLEN_P(&raw_var)); } else { - *val = strdup(""); + *val = estrdup(""); } } From 6628aaa8959abac16d7126aa2c654cfdbf8beecb Mon Sep 17 00:00:00 2001 From: Robert Landers Date: Sun, 22 Jun 2025 10:47:24 +0200 Subject: [PATCH 3/6] fix memory issue --- ext/filter/filter.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/ext/filter/filter.c b/ext/filter/filter.c index 9a6c3f06c143d..cd8b943689d30 100644 --- a/ext/filter/filter.c +++ b/ext/filter/filter.c @@ -335,10 +335,12 @@ static unsigned int php_sapi_filter(int arg, const char *var, char **val, size_t } if (array_ptr) { + Z_TRY_ADDREF_P(&raw_var); php_register_variable_ex(var, &raw_var, array_ptr); } if (orig_array_ptr) { + Z_TRY_ADDREF_P(&raw_var); php_register_variable_ex(var, &raw_var, orig_array_ptr); } From 3568c1b3940a1f02c21e93cd8ea555bd448da56e Mon Sep 17 00:00:00 2001 From: Robert Landers Date: Sun, 22 Jun 2025 11:35:49 +0200 Subject: [PATCH 4/6] fix typo --- ext/filter/filter.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/ext/filter/filter.c b/ext/filter/filter.c index cd8b943689d30..6c98bd52645ed 100644 --- a/ext/filter/filter.c +++ b/ext/filter/filter.c @@ -324,7 +324,7 @@ static unsigned int php_sapi_filter(int arg, const char *var, char **val, size_t */ if (is_raw) { - if (array_ptr || orig_array_ptr) + if (array_ptr || orig_array_ptr || retval) { if (val_len) { @@ -333,11 +333,13 @@ static unsigned int php_sapi_filter(int arg, const char *var, char **val, size_t { ZVAL_EMPTY_STRING(&raw_var); } + if (array_ptr) { Z_TRY_ADDREF_P(&raw_var); php_register_variable_ex(var, &raw_var, array_ptr); } + if (orig_array_ptr) { Z_TRY_ADDREF_P(&raw_var); From 09d1026f73c0c9b1539ae3953df32ecbb4c889e0 Mon Sep 17 00:00:00 2001 From: Rob Landers Date: Sun, 22 Jun 2025 12:30:38 +0200 Subject: [PATCH 5/6] Branch prediction hints. --- ext/filter/filter.c | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/ext/filter/filter.c b/ext/filter/filter.c index 6c98bd52645ed..38df08edc1809 100644 --- a/ext/filter/filter.c +++ b/ext/filter/filter.c @@ -283,7 +283,6 @@ static unsigned int php_sapi_filter(int arg, const char *var, char **val, size_t zval *array_ptr = NULL, *orig_array_ptr = NULL; int retval = 0; int is_raw = (IF_G(default_filter) == FILTER_UNSAFE_RAW); - size_t var_len = strlen(var); assert(*val != NULL); @@ -314,15 +313,15 @@ static unsigned int php_sapi_filter(int arg, const char *var, char **val, size_t * to have the same (plain text) cookie name for the same path and we should not overwrite * more specific cookies with the less specific ones. */ - if (arg == PARSE_COOKIE && orig_array_ptr && - zend_symtable_str_exists(Z_ARRVAL_P(orig_array_ptr), var, var_len)) { + if (UNEXPECTED(arg == PARSE_COOKIE && orig_array_ptr && + zend_symtable_str_exists(Z_ARRVAL_P(orig_array_ptr), var, str_len(var)))) { return 0; } /* * Fast path: if the default filter is UNSAFE_RAW, we can build a single zval, register it twice, and be done */ - if (is_raw) + if (EXPECTED(is_raw)) { if (array_ptr || orig_array_ptr || retval) { From 5f0b02d661a4463f0e5388c29e7fdb7c2110d659 Mon Sep 17 00:00:00 2001 From: Rob Landers Date: Sun, 22 Jun 2025 12:39:29 +0200 Subject: [PATCH 6/6] Fix typo --- ext/filter/filter.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ext/filter/filter.c b/ext/filter/filter.c index 38df08edc1809..2a663448be78d 100644 --- a/ext/filter/filter.c +++ b/ext/filter/filter.c @@ -314,7 +314,7 @@ static unsigned int php_sapi_filter(int arg, const char *var, char **val, size_t * more specific cookies with the less specific ones. */ if (UNEXPECTED(arg == PARSE_COOKIE && orig_array_ptr && - zend_symtable_str_exists(Z_ARRVAL_P(orig_array_ptr), var, str_len(var)))) { + zend_symtable_str_exists(Z_ARRVAL_P(orig_array_ptr), var, strlen(var)))) { return 0; }