From 323f818a6ce33d021bc0a6d34064598917e68c91 Mon Sep 17 00:00:00 2001 From: Ben Fuhrmannek Date: Sat, 5 Feb 2022 12:22:13 +0100 Subject: introduced sp_regexp / store original regex --- src/sp_config.c | 23 ++++++++++------------- src/sp_config.h | 16 ++++++++-------- src/sp_disabled_functions.c | 15 ++++++--------- src/sp_ini.c | 2 +- src/sp_pcre_compat.c | 14 +++----------- src/sp_pcre_compat.h | 38 +++++++++++++++++++++++++++++++------- src/sp_utils.c | 26 ++++++++------------------ src/sp_utils.h | 15 ++++++--------- src/sp_var_parser.c | 4 ++-- 9 files changed, 75 insertions(+), 78 deletions(-) (limited to 'src') diff --git a/src/sp_config.c b/src/sp_config.c index bc9aa0d..7294b0e 100644 --- a/src/sp_config.c +++ b/src/sp_config.c @@ -228,20 +228,17 @@ SP_PARSEKW_FN(parse_cidr) { } SP_PARSEKW_FN(parse_regexp) { - /* TODO: Do we want to use pcre_study? - * (http://www.pcre.org/original/doc/html/pcre_study.html) - * maybe not: http://sljit.sourceforge.net/pcre.html*/ CHECK_DUPLICATE_KEYWORD(retval); SP_PARSE_ARG(value); - sp_pcre *compiled_re = sp_pcre_compile(ZSTR_VAL(value)); + sp_regexp *compiled_re = sp_regexp_compile(value); if (!compiled_re) { sp_log_err("config", "Invalid regexp '%s' for '.%s()' on line %zu", ZSTR_VAL(value), token, kw->lineno); zend_string_release_ex(value, 1); return SP_PARSER_ERROR; } - *(sp_pcre **)retval = compiled_re; + *(sp_regexp **)retval = compiled_re; return SP_PARSER_SUCCESS; } @@ -252,24 +249,24 @@ void sp_free_disabled_function(void *data) { sp_free_zstr(df->textual_representation); sp_free_zstr(df->filename); - sp_pcre_free(df->r_filename); + sp_regexp_free(df->r_filename); sp_free_zstr(df->function); - sp_pcre_free(df->r_function); + sp_regexp_free(df->r_function); sp_list_free(df->functions_list, free); sp_free_zstr(df->hash); sp_tree_free(df->param); - sp_pcre_free(df->r_param); + sp_regexp_free(df->r_param); - sp_pcre_free(df->r_ret); + sp_regexp_free(df->r_ret); sp_free_zstr(df->ret); - sp_pcre_free(df->r_value); + sp_regexp_free(df->r_value); sp_free_zstr(df->value); - sp_pcre_free(df->r_key); + sp_regexp_free(df->r_key); sp_free_zstr(df->key); sp_free_zstr(df->dump); @@ -287,7 +284,7 @@ void sp_free_cookie(void *data) { sp_cookie *c = data; if (c->name) zend_string_release_ex(c->name, 1); - sp_pcre_free(c->name_r); + sp_regexp_free(c->name_r); } void sp_free_zstr(void *data) { @@ -302,7 +299,7 @@ void sp_free_ini_entry(void *data) { sp_free_zstr(entry->key); sp_free_zstr(entry->min); sp_free_zstr(entry->max); - sp_pcre_free(entry->regexp); + sp_regexp_free(entry->regexp); sp_free_zstr(entry->msg); sp_free_zstr(entry->set); } diff --git a/src/sp_config.h b/src/sp_config.h index 1a891c1..6d48240 100644 --- a/src/sp_config.h +++ b/src/sp_config.h @@ -63,7 +63,7 @@ typedef struct { enum samesite_type { strict = 1, lax = 2 } samesite; bool encrypt; zend_string *name; - sp_pcre *name_r; + sp_regexp *name_r; bool simulation; } sp_cookie; @@ -91,29 +91,29 @@ typedef struct { zend_string *textual_representation; zend_string *filename; - sp_pcre *r_filename; + sp_regexp *r_filename; zend_string *function; - sp_pcre *r_function; + sp_regexp *r_function; sp_list_node *functions_list; zend_string *hash; int simulation; sp_tree *param; - sp_pcre *r_param; + sp_regexp *r_param; sp_php_type param_type; int pos; unsigned int line; - sp_pcre *r_ret; + sp_regexp *r_ret; zend_string *ret; sp_php_type ret_type; - sp_pcre *r_value; + sp_regexp *r_value; zend_string *value; - sp_pcre *r_key; + sp_regexp *r_key; zend_string *key; zend_string *dump; @@ -157,7 +157,7 @@ typedef struct { sp_ini_permission access; zend_string *min; zend_string *max; - sp_pcre *regexp; + sp_regexp *regexp; zend_string *msg; zend_string *set; bool allow_null; diff --git a/src/sp_disabled_functions.c b/src/sp_disabled_functions.c index 0ff859c..95e19ad 100644 --- a/src/sp_disabled_functions.c +++ b/src/sp_disabled_functions.c @@ -210,17 +210,15 @@ static zend_execute_data* is_file_matching( return ex; // LCOV_EXCL_LINE } ITERATE(ex); - if (zend_string_equals(ex->func->op_array.filename, - config_node->filename)) { + if (zend_string_equals(ex->func->op_array.filename, config_node->filename)) { return ex; // LCOV_EXCL_LINE } } else if (config_node->r_filename) { - if (sp_is_regexp_matching_zend(config_node->r_filename, current_filename)) { + if (sp_is_regexp_matching_zstr(config_node->r_filename, current_filename)) { return ex; } ITERATE(ex); - if (sp_is_regexp_matching_zend(config_node->r_filename, - ex->func->op_array.filename)) { + if (sp_is_regexp_matching_zstr(config_node->r_filename, ex->func->op_array.filename)) { return ex; } } @@ -481,10 +479,9 @@ ZEND_FUNCTION(check_disabled_function) { static int hook_functions_regexp(const sp_list_node* config) { while (config && config->data) { - const zend_string* function_name = - ((sp_disabled_function*)config->data)->function; - const sp_pcre* function_name_regexp = - ((sp_disabled_function*)config->data)->r_function; + const zend_string* function_name = ((sp_disabled_function*)config->data)->function; + sp_regexp *function_name_sp_regexp = ((sp_disabled_function*)config->data)->r_function; + const sp_pcre* function_name_regexp = function_name_sp_regexp ? function_name_sp_regexp->re : NULL; assert(function_name || function_name_regexp); diff --git a/src/sp_ini.c b/src/sp_ini.c index 62bd181..7fec297 100644 --- a/src/sp_ini.c +++ b/src/sp_ini.c @@ -66,7 +66,7 @@ static bool /* success */ sp_ini_check(zend_string *varname, zend_string *new_va } if (entry->regexp) { - if (!sp_is_regexp_matching_len(entry->regexp, ZSTR_VAL(new_value), ZSTR_LEN(new_value))) { + if (!sp_is_regexp_matching_zstr(entry->regexp, new_value)) { sp_log_ini_check_violation("%s", (entry->msg ? ZSTR_VAL(entry->msg) : "INI value does not match regex")); return simulation; } diff --git a/src/sp_pcre_compat.c b/src/sp_pcre_compat.c index 375a708..81c51fd 100644 --- a/src/sp_pcre_compat.c +++ b/src/sp_pcre_compat.c @@ -1,10 +1,5 @@ #include "php_snuffleupagus.h" -inline void sp_pcre_free(sp_pcre* regexp) { -#ifdef SP_HAS_PCRE2 - pcre2_code_free(regexp); -#endif -} sp_pcre* sp_pcre_compile(const char* const pattern) { assert(NULL != pattern); @@ -14,8 +9,7 @@ sp_pcre* sp_pcre_compile(const char* const pattern) { unsigned char pcre_error[128] = {0}; int errornumber; PCRE2_SIZE erroroffset; - ret = pcre2_compile((PCRE2_SPTR)pattern, PCRE2_ZERO_TERMINATED, - PCRE2_CASELESS, &errornumber, &erroroffset, NULL); + ret = pcre2_compile((PCRE2_SPTR)pattern, PCRE2_ZERO_TERMINATED, PCRE2_CASELESS, &errornumber, &erroroffset, NULL); pcre2_get_error_message(errornumber, pcre_error, sizeof(pcre_error)-1); #else const char* pcre_error = NULL; @@ -29,16 +23,14 @@ sp_pcre* sp_pcre_compile(const char* const pattern) { return ret; } -bool ZEND_HOT sp_is_regexp_matching_len(const sp_pcre* regexp, const char* str, - size_t len) { +bool ZEND_HOT sp_is_regexp_matching_len(const sp_pcre* regexp, const char* str, size_t len) { int ret = 0; assert(NULL != regexp); assert(NULL != str); #ifdef SP_HAS_PCRE2 - pcre2_match_data* match_data = - pcre2_match_data_create_from_pattern(regexp, NULL); + pcre2_match_data* match_data = pcre2_match_data_create_from_pattern(regexp, NULL); if (NULL == match_data) { sp_log_err("regexp", "Unable to get memory for a regxp."); } diff --git a/src/sp_pcre_compat.h b/src/sp_pcre_compat.h index 725004d..6e9d91a 100644 --- a/src/sp_pcre_compat.h +++ b/src/sp_pcre_compat.h @@ -17,12 +17,36 @@ #endif sp_pcre* sp_pcre_compile(const char* str); -void sp_pcre_free(sp_pcre* regexp); -#define sp_is_regexp_matching_zend(regexp, zstr) \ - sp_is_regexp_matching_len(regexp, ZSTR_VAL(zstr), ZSTR_LEN(zstr)) -#define sp_is_regexp_matching(regexp, str) \ - sp_is_regexp_matching_len(regexp, str, strlen(str)) -bool sp_is_regexp_matching_len(const sp_pcre* regexp, const char* str, - size_t len); +static inline void sp_pcre_free(sp_pcre* regexp) { +#ifdef SP_HAS_PCRE2 + pcre2_code_free(regexp); +#endif +} +bool sp_is_regexp_matching_len(const sp_pcre* regexp, const char* str, size_t len); + + +typedef struct { + sp_pcre *re; + zend_string *pattern; +} sp_regexp; + +#define sp_is_regexp_matching_zstr(regexp, zstr) sp_is_regexp_matching_len(regexp->re, ZSTR_VAL(zstr), ZSTR_LEN(zstr)) +#define sp_is_regexp_matching(regexp, str) sp_is_regexp_matching_len(regexp->re, str, strlen(str)) +static inline sp_regexp* sp_regexp_compile(zend_string *zstr) { + sp_pcre *re = sp_pcre_compile(ZSTR_VAL(zstr)); + if (!re) { return NULL; } + sp_regexp *ret = pecalloc(sizeof(sp_regexp), 1, 1); + ret->re = re; + ret->pattern = zstr; + return ret; +} +static inline void sp_regexp_free(sp_regexp *regexp) { + if (regexp) { + if (regexp->re) { sp_pcre_free(regexp->re); } + if (regexp->pattern) { zend_string_release(regexp->pattern); } + pefree(regexp, 1); + } +} + #endif // SP_PCRE_COMPAT_H diff --git a/src/sp_utils.c b/src/sp_utils.c index 034aaf4..6161859 100644 --- a/src/sp_utils.c +++ b/src/sp_utils.c @@ -253,15 +253,11 @@ const zend_string* sp_zval_to_zend_string(const zval* zv) { } } -bool sp_match_value(const zend_string* value, const zend_string* to_match, - const sp_pcre* rx) { +bool sp_match_value(const zend_string* value, const zend_string* to_match, const sp_regexp* rx) { if (to_match) { return (sp_zend_string_equals(to_match, value)); } else if (rx) { - char* tmp = zend_string_to_char(value); - bool ret = sp_is_regexp_matching(rx, tmp); - efree(tmp); - return ret; + return sp_is_regexp_matching_zstr(rx, value); } return true; } @@ -338,8 +334,7 @@ void sp_log_disable_ret(const char* restrict path, efree(char_repr); } -bool sp_match_array_key(const zval* zv, const zend_string* to_match, - const sp_pcre* rx) { +bool sp_match_array_key(const zval* zv, const zend_string* to_match, const sp_regexp* rx) { zend_string* key; zend_ulong idx; @@ -363,8 +358,7 @@ bool sp_match_array_key(const zval* zv, const zend_string* to_match, return false; } -bool sp_match_array_value(const zval* arr, const zend_string* to_match, - const sp_pcre* rx) { +bool sp_match_array_value(const zval* arr, const zend_string* to_match, const sp_regexp* rx) { zval* value; ZEND_HASH_FOREACH_VAL(Z_ARRVAL_P(arr), value) { @@ -380,8 +374,7 @@ bool sp_match_array_value(const zval* arr, const zend_string* to_match, return false; } -bool /* success */ _hook_function(const char* original_name, HashTable* hook_table, - zif_handler new_function) { +bool /* success */ _hook_function(const char* original_name, HashTable* hook_table, zif_handler new_function) { zend_function* func; if ((func = zend_hash_str_find_ptr(CG(function_table), VAR_AND_LEN(original_name)))) { if (func->type != ZEND_INTERNAL_FUNCTION) { @@ -393,8 +386,7 @@ bool /* success */ _hook_function(const char* original_name, HashTable* hook_tab if (zend_hash_str_add_new_ptr((hook_table), VAR_AND_LEN(original_name), func->internal_function.handler) == NULL) { // LCOV_EXCL_START - sp_log_err("function_pointer_saving", - "Could not save function pointer for %s", original_name); + sp_log_err("function_pointer_saving", "Could not save function pointer for %s", original_name); return false; // LCOV_EXCL_STOP } @@ -404,8 +396,7 @@ bool /* success */ _hook_function(const char* original_name, HashTable* hook_tab return false; } -bool hook_function(const char* original_name, HashTable* hook_table, - zif_handler new_function) { +bool hook_function(const char* original_name, HashTable* hook_table, zif_handler new_function) { bool ret = _hook_function(original_name, hook_table, new_function); #if PHP_VERSION_ID < 80000 @@ -433,8 +424,7 @@ bool hook_function(const char* original_name, HashTable* hook_table, return ret; } -int hook_regexp(const sp_pcre* regexp, HashTable* hook_table, - zif_handler new_function) { +int hook_regexp(const sp_pcre* regexp, HashTable* hook_table, zif_handler new_function) { zend_string* key; ZEND_HASH_FOREACH_STR_KEY(CG(function_table), key) diff --git a/src/sp_utils.h b/src/sp_utils.h index 0581363..0e595d8 100644 --- a/src/sp_utils.h +++ b/src/sp_utils.h @@ -71,17 +71,14 @@ extern int sp_debug_stderr; #define GET_SUFFIX(x) (x == 1) ? "st" : ((x == 2) ? "nd" : "th") const char *get_ipaddr(void); -void sp_log_msgf(char const *restrict feature, int level, int type, - const char *restrict fmt, ...); +void sp_log_msgf(char const *restrict feature, int level, int type, const char *restrict fmt, ...); int compute_hash(const char *const restrict filename, char *restrict file_hash); const zend_string *sp_zval_to_zend_string(const zval *); -bool sp_match_value(const zend_string *, const zend_string *, const sp_pcre *); -bool sp_match_array_key(const zval *, const zend_string *, const sp_pcre *); -bool sp_match_array_value(const zval *, const zend_string *, const sp_pcre *); -void sp_log_disable(const char *restrict, const char *restrict, - const zend_string *restrict, const sp_disabled_function *); -void sp_log_disable_ret(const char *restrict, const zend_string *restrict, - const sp_disabled_function *); +bool sp_match_value(const zend_string* value, const zend_string* to_match, const sp_regexp* rx); +bool sp_match_array_key(const zval *, const zend_string *, const sp_regexp *); +bool sp_match_array_value(const zval *, const zend_string *, const sp_regexp *); +void sp_log_disable(const char *restrict, const char *restrict, const zend_string *restrict, const sp_disabled_function *); +void sp_log_disable_ret(const char *restrict, const zend_string *restrict, const sp_disabled_function *); bool hook_function(const char *, HashTable *, zif_handler); void unhook_functions(HashTable *ht); int hook_regexp(const sp_pcre *, HashTable *, zif_handler); diff --git a/src/sp_var_parser.c b/src/sp_var_parser.c index cc75d83..2639991 100644 --- a/src/sp_var_parser.c +++ b/src/sp_var_parser.c @@ -33,8 +33,8 @@ static bool is_var_name_valid(const char *const name) { if (NULL == regexp_var || NULL == regexp_const) { return false; // LCOV_EXCL_LINE } - if ((false == sp_is_regexp_matching(regexp_var, name)) && - (false == sp_is_regexp_matching(regexp_const, name))) { + if ((false == sp_is_regexp_matching_len(regexp_var, VAR_AND_LEN(name))) && + (false == sp_is_regexp_matching_len(regexp_const, VAR_AND_LEN(name)))) { return false; } return true; -- cgit v1.3