diff options
| -rw-r--r-- | src/sp_disabled_functions.c | 25 | ||||
| -rw-r--r-- | src/sp_disabled_functions.h | 7 | ||||
| -rw-r--r-- | src/sp_execute.c | 32 | ||||
| -rw-r--r-- | src/sp_utils.c | 2 | ||||
| -rw-r--r-- | src/sp_utils.h | 2 | ||||
| -rw-r--r-- | src/tests/disabled_functions_chain_call_user_func_ret.phpt | 13 | ||||
| -rw-r--r-- | src/tests/disabled_functions_ret_user.phpt | 4 |
7 files changed, 58 insertions, 27 deletions
diff --git a/src/sp_disabled_functions.c b/src/sp_disabled_functions.c index 842b15c..379ed75 100644 --- a/src/sp_disabled_functions.c +++ b/src/sp_disabled_functions.c | |||
| @@ -403,8 +403,9 @@ allow: | |||
| 403 | return false; | 403 | return false; |
| 404 | } | 404 | } |
| 405 | 405 | ||
| 406 | bool should_drop_on_ret_ht(zval* return_value, const char* function_name, | 406 | bool should_drop_on_ret_ht(const zval* return_value, const char* function_name, |
| 407 | const sp_list_node* config, const HashTable* ht) { | 407 | const sp_list_node* config, const HashTable* ht, |
| 408 | zend_execute_data* execute_data) { | ||
| 408 | const sp_list_node* ht_entry = NULL; | 409 | const sp_list_node* ht_entry = NULL; |
| 409 | bool ret = false; | 410 | bool ret = false; |
| 410 | 411 | ||
| @@ -414,17 +415,19 @@ bool should_drop_on_ret_ht(zval* return_value, const char* function_name, | |||
| 414 | 415 | ||
| 415 | ht_entry = zend_hash_str_find_ptr(ht, function_name, strlen(function_name)); | 416 | ht_entry = zend_hash_str_find_ptr(ht, function_name, strlen(function_name)); |
| 416 | 417 | ||
| 417 | if (ht_entry && should_drop_on_ret(return_value, ht_entry, function_name)) { | 418 | if (ht_entry && should_drop_on_ret(return_value, ht_entry, function_name, |
| 419 | execute_data)) { | ||
| 418 | ret = true; | 420 | ret = true; |
| 419 | } else if (config && config->data) { | 421 | } else if (config && config->data) { |
| 420 | ret = should_drop_on_ret(return_value, config, function_name); | 422 | ret = should_drop_on_ret(return_value, config, function_name, execute_data); |
| 421 | } | 423 | } |
| 422 | 424 | ||
| 423 | return ret; | 425 | return ret; |
| 424 | } | 426 | } |
| 425 | 427 | ||
| 426 | bool should_drop_on_ret(zval* return_value, const sp_list_node* config, | 428 | bool should_drop_on_ret(const zval* return_value, const sp_list_node* config, |
| 427 | const char* complete_function_path) { | 429 | const char* complete_function_path, |
| 430 | zend_execute_data* execute_data) { | ||
| 428 | const char* current_filename = zend_get_executed_filename(TSRMLS_C); | 431 | const char* current_filename = zend_get_executed_filename(TSRMLS_C); |
| 429 | char current_file_hash[SHA256_SIZE * 2 + 1] = {0}; | 432 | char current_file_hash[SHA256_SIZE * 2 + 1] = {0}; |
| 430 | bool match_type = false, match_value = false; | 433 | bool match_type = false, match_value = false; |
| @@ -436,7 +439,12 @@ bool should_drop_on_ret(zval* return_value, const sp_list_node* config, | |||
| 436 | 439 | ||
| 437 | assert(config_node->function || config_node->r_function); | 440 | assert(config_node->function || config_node->r_function); |
| 438 | 441 | ||
| 439 | if (config_node->function) { | 442 | if (config_node->functions_list) { |
| 443 | if (false == is_functions_list_matching(execute_data, | ||
| 444 | config_node->functions_list)) { | ||
| 445 | goto next; | ||
| 446 | } | ||
| 447 | } else if (config_node->function) { | ||
| 440 | if (0 != | 448 | if (0 != |
| 441 | strcmp(ZSTR_VAL(config_node->function), complete_function_path)) { | 449 | strcmp(ZSTR_VAL(config_node->function), complete_function_path)) { |
| 442 | goto next; | 450 | goto next; |
| @@ -513,7 +521,8 @@ ZEND_FUNCTION(check_disabled_function) { | |||
| 513 | return_value, current_function_name, | 521 | return_value, current_function_name, |
| 514 | SNUFFLEUPAGUS_G(config) | 522 | SNUFFLEUPAGUS_G(config) |
| 515 | .config_disabled_functions_reg_ret->disabled_functions, | 523 | .config_disabled_functions_reg_ret->disabled_functions, |
| 516 | SNUFFLEUPAGUS_G(config).config_disabled_functions_ret_hooked)) { | 524 | SNUFFLEUPAGUS_G(config).config_disabled_functions_ret_hooked, |
| 525 | execute_data)) { | ||
| 517 | sp_terminate(); | 526 | sp_terminate(); |
| 518 | } | 527 | } |
| 519 | } | 528 | } |
diff --git a/src/sp_disabled_functions.h b/src/sp_disabled_functions.h index 258e2e6..ae1500a 100644 --- a/src/sp_disabled_functions.h +++ b/src/sp_disabled_functions.h | |||
| @@ -9,9 +9,10 @@ bool should_disable(zend_execute_data *, const char *, const zend_string *, | |||
| 9 | const char *, const sp_list_node *, const zend_string *); | 9 | const char *, const sp_list_node *, const zend_string *); |
| 10 | bool should_disable_ht(zend_execute_data *, const char *, const zend_string *, | 10 | bool should_disable_ht(zend_execute_data *, const char *, const zend_string *, |
| 11 | const char *, const sp_list_node *, const HashTable *); | 11 | const char *, const sp_list_node *, const HashTable *); |
| 12 | bool should_drop_on_ret_ht(zval *, const char *, const sp_list_node *config, | 12 | bool should_drop_on_ret_ht(const zval *, const char *, const sp_list_node *config, |
| 13 | const HashTable *); | 13 | const HashTable *, zend_execute_data *); |
| 14 | bool should_drop_on_ret(zval *, const sp_list_node *config, const char *); | 14 | bool should_drop_on_ret(const zval *, const sp_list_node *config, const char *, |
| 15 | zend_execute_data *); | ||
| 15 | char *get_complete_function_path(zend_execute_data const *const); | 16 | char *get_complete_function_path(zend_execute_data const *const); |
| 16 | 17 | ||
| 17 | #endif /* __SP_DISABLE_FUNCTIONS_H */ | 18 | #endif /* __SP_DISABLE_FUNCTIONS_H */ |
diff --git a/src/sp_execute.c b/src/sp_execute.c index 844647e..5447ea1 100644 --- a/src/sp_execute.c +++ b/src/sp_execute.c | |||
| @@ -151,6 +151,7 @@ static void sp_execute_ex(zend_execute_data *execute_data) { | |||
| 151 | 151 | ||
| 152 | if (SNUFFLEUPAGUS_G(config).hook_execute) { | 152 | if (SNUFFLEUPAGUS_G(config).hook_execute) { |
| 153 | char *function_name = get_complete_function_path(execute_data); | 153 | char *function_name = get_complete_function_path(execute_data); |
| 154 | zval ret_val; | ||
| 154 | 155 | ||
| 155 | if (!function_name) { | 156 | if (!function_name) { |
| 156 | orig_execute_ex(execute_data); | 157 | orig_execute_ex(execute_data); |
| @@ -185,23 +186,34 @@ static void sp_execute_ex(zend_execute_data *execute_data) { | |||
| 185 | } | 186 | } |
| 186 | } | 187 | } |
| 187 | 188 | ||
| 189 | // When a function's return value isn't used, php doesn't store it in the execute_data, | ||
| 190 | // so we need to use a local variable to be able to match on it later. | ||
| 191 | if (EX(return_value) == NULL) { | ||
| 192 | memset(&ret_val, 0, sizeof(ret_val)); | ||
| 193 | EX(return_value) = &ret_val; | ||
| 194 | } | ||
| 195 | |||
| 188 | orig_execute_ex(execute_data); | 196 | orig_execute_ex(execute_data); |
| 189 | 197 | ||
| 190 | if (EX(return_value) != NULL) { | 198 | if (UNEXPECTED( |
| 191 | if (UNEXPECTED( | 199 | true == |
| 192 | true == | 200 | should_drop_on_ret_ht( |
| 193 | should_drop_on_ret_ht( | 201 | EX(return_value), function_name, |
| 194 | EX(return_value), function_name, | 202 | SNUFFLEUPAGUS_G(config) |
| 195 | SNUFFLEUPAGUS_G(config) | 203 | .config_disabled_functions_reg_ret->disabled_functions, |
| 196 | .config_disabled_functions_reg_ret->disabled_functions, | 204 | SNUFFLEUPAGUS_G(config).config_disabled_functions_ret, |
| 197 | SNUFFLEUPAGUS_G(config).config_disabled_functions_ret))) { | 205 | execute_data))) { |
| 198 | sp_terminate(); | 206 | sp_terminate(); |
| 199 | } | ||
| 200 | } | 207 | } |
| 201 | efree(function_name); | 208 | efree(function_name); |
| 209 | |||
| 210 | if (EX(return_value) == &ret_val) { | ||
| 211 | EX(return_value) = NULL; | ||
| 212 | } | ||
| 202 | } else { | 213 | } else { |
| 203 | orig_execute_ex(execute_data); | 214 | orig_execute_ex(execute_data); |
| 204 | } | 215 | } |
| 216 | |||
| 205 | } | 217 | } |
| 206 | 218 | ||
| 207 | static void sp_zend_execute_internal(INTERNAL_FUNCTION_PARAMETERS) { | 219 | static void sp_zend_execute_internal(INTERNAL_FUNCTION_PARAMETERS) { |
diff --git a/src/sp_utils.c b/src/sp_utils.c index 41d817e..e872abd 100644 --- a/src/sp_utils.c +++ b/src/sp_utils.c | |||
| @@ -151,7 +151,7 @@ static char* zend_string_to_char(const zend_string* zs) { | |||
| 151 | return copy; | 151 | return copy; |
| 152 | } | 152 | } |
| 153 | 153 | ||
| 154 | const zend_string* sp_zval_to_zend_string(zval* zv) { | 154 | const zend_string* sp_zval_to_zend_string(const zval* zv) { |
| 155 | switch (Z_TYPE_P(zv)) { | 155 | switch (Z_TYPE_P(zv)) { |
| 156 | case IS_LONG: { | 156 | case IS_LONG: { |
| 157 | char* msg; | 157 | char* msg; |
diff --git a/src/sp_utils.h b/src/sp_utils.h index 97c97fd..c094fac 100644 --- a/src/sp_utils.h +++ b/src/sp_utils.h | |||
| @@ -46,7 +46,7 @@ | |||
| 46 | 46 | ||
| 47 | void sp_log_msg(char const *feature, int type, const char *fmt, ...); | 47 | void sp_log_msg(char const *feature, int type, const char *fmt, ...); |
| 48 | int compute_hash(const char *const filename, char *file_hash); | 48 | int compute_hash(const char *const filename, char *file_hash); |
| 49 | const zend_string *sp_zval_to_zend_string(zval *); | 49 | const zend_string *sp_zval_to_zend_string(const zval *); |
| 50 | bool sp_match_value(const zend_string *, const zend_string *, const sp_pcre *); | 50 | bool sp_match_value(const zend_string *, const zend_string *, const sp_pcre *); |
| 51 | bool sp_match_array_key(const zval *, const zend_string *, const sp_pcre *); | 51 | bool sp_match_array_key(const zval *, const zend_string *, const sp_pcre *); |
| 52 | bool sp_match_array_value(const zval *, const zend_string *, const sp_pcre *); | 52 | bool sp_match_array_value(const zval *, const zend_string *, const sp_pcre *); |
diff --git a/src/tests/disabled_functions_chain_call_user_func_ret.phpt b/src/tests/disabled_functions_chain_call_user_func_ret.phpt index 44c9b24..d0ee389 100644 --- a/src/tests/disabled_functions_chain_call_user_func_ret.phpt +++ b/src/tests/disabled_functions_chain_call_user_func_ret.phpt | |||
| @@ -21,6 +21,15 @@ echo one('matching') . "\n"; | |||
| 21 | echo one('still not matching') . "\n"; | 21 | echo one('still not matching') . "\n"; |
| 22 | 22 | ||
| 23 | ?> | 23 | ?> |
| 24 | --XFAIL-- | ||
| 25 | --EXPECTF-- | 24 | --EXPECTF-- |
| 26 | Match on ret is broken :/ | 25 | one |
| 26 | two | ||
| 27 | not matching_one | ||
| 28 | one | ||
| 29 | two | ||
| 30 | |||
| 31 | Warning: [snuffleupagus][disabled_function] Aborted execution on return of the function 'two', because the function returned 'matching_two', which matched a rule in %a/tests/disabled_functions_chain_call_user_func_ret.php on line %d | ||
| 32 | matching_one | ||
| 33 | one | ||
| 34 | two | ||
| 35 | still not matching_one | ||
diff --git a/src/tests/disabled_functions_ret_user.phpt b/src/tests/disabled_functions_ret_user.phpt index 597a6b8..89c1bce 100644 --- a/src/tests/disabled_functions_ret_user.phpt +++ b/src/tests/disabled_functions_ret_user.phpt | |||
| @@ -12,5 +12,5 @@ function qwe() { | |||
| 12 | qwe(); | 12 | qwe(); |
| 13 | echo 1; | 13 | echo 1; |
| 14 | ?> | 14 | ?> |
| 15 | --EXPECT-- | 15 | --EXPECTF-- |
| 16 | 1 | 16 | Fatal error: [snuffleupagus][disabled_function] Aborted execution on return of the function 'qwe', because the function returned 'asd', which matched a rule in %a/tests/disabled_functions_ret_user.php on line %d |
