From 39929ce509361ee72746a9b971bdc531fbf0b843 Mon Sep 17 00:00:00 2001 From: kkadosh Date: Mon, 19 Mar 2018 16:39:47 +0000 Subject: The filename filter is now matching on callsite instead of implemsite (#167) * Add match on the file where the function is called * Add the test * Constify some params * Fix potentiel null deref * Return more before if execute_data is NULL --- src/sp_disabled_functions.c | 59 ++++++++++++++++++---- src/sp_utils.c | 21 ++++---- src/sp_utils.h | 3 +- .../config_disabled_functions_called_file_r.ini | 1 + src/tests/disabled_functions_called_file_r.phpt | 34 +++++++++++++ 5 files changed, 97 insertions(+), 21 deletions(-) create mode 100644 src/tests/config/config_disabled_functions_called_file_r.ini create mode 100644 src/tests/disabled_functions_called_file_r.phpt (limited to 'src') diff --git a/src/sp_disabled_functions.c b/src/sp_disabled_functions.c index 0e05f4e..eeee007 100644 --- a/src/sp_disabled_functions.c +++ b/src/sp_disabled_functions.c @@ -213,12 +213,53 @@ static bool is_param_matching(zend_execute_data* execute_data, return false; } +static zend_execute_data* is_file_matching( + zend_execute_data* const execute_data, + sp_disabled_function const* const config_node, + char const* const current_filename) { +#define ITERATE(ex) \ + ex = ex->prev_execute_data; \ + while (ex && (!ex->func || !ZEND_USER_CODE(ex->func->type))) \ + ex = ex->prev_execute_data; \ + if (!ex) return NULL; + + zend_execute_data* ex = execute_data; + if (config_node->filename) { + if (0 == strcmp(current_filename, config_node->filename)) { + return ex; + } + ITERATE(ex); + if (0 == + strcmp(ZSTR_VAL(ex->func->op_array.filename), config_node->filename)) { + return ex; + } + } else if (config_node->r_filename) { + if (true == + sp_is_regexp_matching(config_node->r_filename, current_filename)) { + return ex; + } + ITERATE(ex); + if (true == sp_is_regexp_matching(config_node->r_filename, + ZSTR_VAL(ex->func->op_array.filename))) { + return ex; + } + } + return NULL; +#undef ITERATE +} + bool should_disable(zend_execute_data* execute_data, const char* builtin_name, const char* builtin_param, const char* builtin_param_name) { char current_file_hash[SHA256_SIZE * 2 + 1] = {0}; const sp_list_node* config = get_config_node(builtin_name); char* complete_path_function = NULL; const char* current_filename = NULL; + unsigned int line = 0; + char* filename = NULL; + + if (!execute_data) { + return false; + } if (!config || !config->data) { return false; @@ -269,14 +310,14 @@ bool should_disable(zend_execute_data* execute_data, const char* builtin_name, } } - if (config_node->filename) { /* Check the current file name. */ - if (0 != strcmp(current_filename, config_node->filename)) { - goto next; - } - } else if (config_node->r_filename) { - if (false == - sp_is_regexp_matching(config_node->r_filename, current_filename)) { + if (config_node->filename || config_node->r_filename) { + zend_execute_data* ex = + is_file_matching(execute_data, config_node, current_filename); + if (!ex) { goto next; + } else if (ex != execute_data) { + line = ex->opline->lineno; + filename = ZSTR_VAL(ex->func->op_array.filename); } } @@ -327,10 +368,10 @@ bool should_disable(zend_execute_data* execute_data, const char* builtin_name, if (config_node->functions_list) { sp_log_disable(config_node->function, arg_name, arg_value_str, - config_node); + config_node, line, filename); } else { sp_log_disable(complete_path_function, arg_name, arg_value_str, - config_node); + config_node, line, filename); } if (true == config_node->simulation) { goto next; diff --git a/src/sp_utils.c b/src/sp_utils.c index 54a8e1b..5f34ccc 100644 --- a/src/sp_utils.c +++ b/src/sp_utils.c @@ -189,39 +189,38 @@ bool sp_match_value(const char* value, const char* to_match, void sp_log_disable(const char* restrict path, const char* restrict arg_name, const char* restrict arg_value, - const sp_disabled_function* config_node) { + const sp_disabled_function* config_node, unsigned int line, + const char* restrict filename) { const char* dump = config_node->dump; const char* alias = config_node->alias; const int sim = config_node->simulation; + + filename = filename ? filename : zend_get_executed_filename(TSRMLS_C); + line = line ? line : zend_get_executed_lineno(TSRMLS_C); + if (arg_name) { if (alias) { sp_log_msg( "disabled_function", sim ? SP_LOG_SIMULATION : SP_LOG_DROP, "The call to the function '%s' in %s:%d has been disabled, " "because its argument '%s' content (%s) matched the rule '%s'.", - path, zend_get_executed_filename(TSRMLS_C), - zend_get_executed_lineno(TSRMLS_C), arg_name, - arg_value ? arg_value : "?", alias); + path, filename, line, arg_name, arg_value ? arg_value : "?", alias); } else { sp_log_msg("disabled_function", sim ? SP_LOG_SIMULATION : SP_LOG_DROP, "The call to the function '%s' in %s:%d has been disabled, " "because its argument '%s' content (%s) matched a rule.", - path, zend_get_executed_filename(TSRMLS_C), - zend_get_executed_lineno(TSRMLS_C), arg_name, - arg_value ? arg_value : "?"); + path, filename, line, arg_name, arg_value ? arg_value : "?"); } } else { if (alias) { sp_log_msg("disabled_function", sim ? SP_LOG_SIMULATION : SP_LOG_DROP, "The call to the function '%s' in %s:%d has been disabled, " "because of the the rule '%s'.", - path, zend_get_executed_filename(TSRMLS_C), - zend_get_executed_lineno(TSRMLS_C), alias); + path, filename, line, alias); } else { sp_log_msg("disabled_function", sim ? SP_LOG_SIMULATION : SP_LOG_DROP, "The call to the function '%s' in %s:%d has been disabled.", - path, zend_get_executed_filename(TSRMLS_C), - zend_get_executed_lineno(TSRMLS_C)); + path, filename, line); } } if (dump) { diff --git a/src/sp_utils.h b/src/sp_utils.h index b92f16d..61a23f9 100644 --- a/src/sp_utils.h +++ b/src/sp_utils.h @@ -49,7 +49,8 @@ bool sp_match_value(const char *, const char *, const sp_pcre *); bool sp_match_array_key(const zval *, const char *, const sp_pcre *); bool sp_match_array_value(const zval *, const char *, const sp_pcre *); void sp_log_disable(const char *restrict, const char *restrict, - const char *restrict, const sp_disabled_function *); + const char *restrict, const sp_disabled_function *, + unsigned int, const char*restrict); void sp_log_disable_ret(const char *restrict, const char *restrict, const sp_disabled_function *); int hook_function(const char *, HashTable *, diff --git a/src/tests/config/config_disabled_functions_called_file_r.ini b/src/tests/config/config_disabled_functions_called_file_r.ini new file mode 100644 index 0000000..17b019a --- /dev/null +++ b/src/tests/config/config_disabled_functions_called_file_r.ini @@ -0,0 +1 @@ +sp.disable_function.function_r("test").filename_r("file_r\\.php$").drop(); \ No newline at end of file diff --git a/src/tests/disabled_functions_called_file_r.phpt b/src/tests/disabled_functions_called_file_r.phpt new file mode 100644 index 0000000..45e57a9 --- /dev/null +++ b/src/tests/disabled_functions_called_file_r.phpt @@ -0,0 +1,34 @@ +--TEST-- +Disable functions by matching on the filename_r where the function is called, and not defined +--SKIPIF-- + +--INI-- +sp.configuration_file={PWD}/config/config_disabled_functions_called_file_r.ini +--FILE-- + +EOD; + +file_put_contents("$dir/myfunc.php", $mycode); + +include "$dir/myfunc.php"; + +test(); + +?> +--EXPECTF-- +[snuffleupagus][0.0.0.0][disabled_function][drop] The call to the function 'test' in %a/disabled_functions_called_file_r.php:18 has been disabled. +--CLEAN-- + -- cgit v1.3