diff options
Diffstat (limited to 'src/sp_disabled_functions.c')
| -rw-r--r-- | src/sp_disabled_functions.c | 334 |
1 files changed, 141 insertions, 193 deletions
diff --git a/src/sp_disabled_functions.c b/src/sp_disabled_functions.c index c47b5cb..95e19ad 100644 --- a/src/sp_disabled_functions.c +++ b/src/sp_disabled_functions.c | |||
| @@ -13,26 +13,26 @@ static void should_drop_on_ret(const zval* return_value, | |||
| 13 | zend_execute_data* execute_data); | 13 | zend_execute_data* execute_data); |
| 14 | 14 | ||
| 15 | char* get_complete_function_path(zend_execute_data const* const execute_data) { | 15 | char* get_complete_function_path(zend_execute_data const* const execute_data) { |
| 16 | if (zend_is_executing() && !EG(current_execute_data)->func) { | 16 | if (!execute_data) { |
| 17 | return NULL; // LCOV_EXCL_LINE | 17 | return NULL; // LCOV_EXCL_LINE |
| 18 | } | 18 | } |
| 19 | if (!(execute_data->func->common.function_name)) { | 19 | zend_function *func = execute_data->func; |
| 20 | if (!(func->common.function_name)) { | ||
| 20 | return NULL; | 21 | return NULL; |
| 21 | } | 22 | } |
| 22 | 23 | ||
| 23 | char const* class_name; | 24 | char const* const function_name = ZSTR_VAL(func->common.function_name); |
| 24 | char const* const function_name = | ||
| 25 | ZSTR_VAL(execute_data->func->common.function_name); | ||
| 26 | char* complete_path_function = NULL; | 25 | char* complete_path_function = NULL; |
| 27 | 26 | ||
| 28 | class_name = get_active_class_name(NULL); | 27 | if ((func->type == ZEND_USER_FUNCTION || func->type == ZEND_INTERNAL_FUNCTION) && func->common.scope) { |
| 29 | if (*class_name) { | 28 | char const* class_name = ZSTR_VAL(func->common.scope->name); |
| 30 | const size_t len = strlen(class_name) + 2 + strlen(function_name) + 1; | 29 | const size_t len = strlen(class_name) + 2 + strlen(function_name) + 1; |
| 31 | complete_path_function = emalloc(len); | 30 | complete_path_function = emalloc(len); |
| 32 | snprintf(complete_path_function, len, "%s::%s", class_name, function_name); | 31 | snprintf(complete_path_function, len, "%s::%s", class_name, function_name); |
| 33 | } else { | 32 | } else { |
| 34 | complete_path_function = estrdup(function_name); | 33 | complete_path_function = estrdup(function_name); |
| 35 | } | 34 | } |
| 35 | |||
| 36 | return complete_path_function; | 36 | return complete_path_function; |
| 37 | } | 37 | } |
| 38 | 38 | ||
| @@ -67,28 +67,22 @@ static bool is_functions_list_matching(zend_execute_data* execute_data, | |||
| 67 | return false; | 67 | return false; |
| 68 | } | 68 | } |
| 69 | 69 | ||
| 70 | static bool is_local_var_matching( | 70 | static bool is_local_var_matching(zend_execute_data* execute_data, const sp_disabled_function* const config_node) { |
| 71 | zend_execute_data* execute_data, | ||
| 72 | const sp_disabled_function* const config_node) { | ||
| 73 | zval* var_value = {0}; | 71 | zval* var_value = {0}; |
| 74 | 72 | ||
| 75 | var_value = sp_get_var_value(execute_data, config_node->var, false); | 73 | var_value = sp_get_var_value(execute_data, config_node->var, false); |
| 76 | if (var_value) { | 74 | if (var_value) { |
| 77 | if (Z_TYPE_P(var_value) == IS_ARRAY) { | 75 | if (Z_TYPE_P(var_value) == IS_ARRAY) { |
| 78 | if (config_node->key || config_node->r_key) { | 76 | if (config_node->key || config_node->r_key) { |
| 79 | if (sp_match_array_key(var_value, config_node->key, | 77 | if (sp_match_array_key(var_value, config_node->key, config_node->r_key)) { |
| 80 | config_node->r_key)) { | ||
| 81 | return true; | 78 | return true; |
| 82 | } | 79 | } |
| 83 | } else if (sp_match_array_value(var_value, config_node->value, | 80 | } else if (sp_match_array_value(var_value, config_node->value, config_node->r_value)) { |
| 84 | config_node->r_value)) { | ||
| 85 | return true; | 81 | return true; |
| 86 | } | 82 | } |
| 87 | } else { | 83 | } else { |
| 88 | zend_string const* const var_value_str = | 84 | zend_string const* const var_value_str = sp_zval_to_zend_string(var_value); |
| 89 | sp_zval_to_zend_string(var_value); | 85 | bool match = sp_match_value(var_value_str, config_node->value, config_node->r_value); |
| 90 | bool match = sp_match_value(var_value_str, config_node->value, | ||
| 91 | config_node->r_value); | ||
| 92 | 86 | ||
| 93 | if (true == match) { | 87 | if (true == match) { |
| 94 | return true; | 88 | return true; |
| @@ -98,107 +92,105 @@ static bool is_local_var_matching( | |||
| 98 | return false; | 92 | return false; |
| 99 | } | 93 | } |
| 100 | 94 | ||
| 95 | static inline const char* get_fn_arg_name(zend_function *fn, uint32_t i) { | ||
| 96 | if (fn->type == ZEND_USER_FUNCTION || (fn->common.fn_flags & ZEND_ACC_USER_ARG_INFO)) { | ||
| 97 | return ZSTR_VAL(fn->op_array.arg_info[i].name); | ||
| 98 | } else { | ||
| 99 | return fn->internal_function.arg_info[i].name; | ||
| 100 | } | ||
| 101 | } | ||
| 102 | |||
| 101 | static bool is_param_matching(zend_execute_data* execute_data, | 103 | static bool is_param_matching(zend_execute_data* execute_data, |
| 102 | sp_disabled_function const* const config_node, | 104 | sp_disabled_function const* const config_node, |
| 103 | const zend_string* builtin_param, | 105 | const zend_string* builtin_param, |
| 104 | const char* builtin_param_name, | 106 | const char* builtin_param_name, |
| 105 | const char** arg_name, | 107 | const char** arg_name, |
| 106 | const zend_string** arg_value_str) { | 108 | const zend_string** arg_value_str) { |
| 107 | int nb_param = ZEND_CALL_NUM_ARGS(execute_data); | 109 | // builtin functions |
| 108 | int i = 0; | ||
| 109 | zval* arg_value; | ||
| 110 | |||
| 111 | if (config_node->pos != -1) { | ||
| 112 | if (config_node->pos > nb_param - 1) { | ||
| 113 | char* complete_function_path = get_complete_function_path(execute_data); | ||
| 114 | sp_log_warn("config", | ||
| 115 | "It seems that you wrote a rule filtering on the " | ||
| 116 | "%d%s argument of the function '%s', but it takes only %d " | ||
| 117 | "arguments. " | ||
| 118 | "Matching on _all_ arguments instead.", | ||
| 119 | config_node->pos, GET_SUFFIX(config_node->pos), | ||
| 120 | complete_function_path, nb_param); | ||
| 121 | efree(complete_function_path); | ||
| 122 | } else { | ||
| 123 | i = config_node->pos; | ||
| 124 | nb_param = (config_node->pos) + 1; | ||
| 125 | } | ||
| 126 | } | ||
| 127 | |||
| 128 | if (builtin_param) { | 110 | if (builtin_param) { |
| 129 | /* We're matching on a language construct (here named "builtin"), | 111 | /* We're matching on a language construct (here named "builtin"), |
| 130 | * and they can only take a single argument, but PHP considers them | 112 | * and they can only take a single argument, but PHP considers them |
| 131 | * differently than functions arguments. */ | 113 | * differently than functions arguments. */ |
| 132 | *arg_name = builtin_param_name; | 114 | *arg_name = builtin_param_name; |
| 133 | *arg_value_str = builtin_param; | 115 | *arg_value_str = builtin_param; |
| 134 | return sp_match_value(builtin_param, config_node->value, | 116 | return sp_match_value(builtin_param, config_node->value, |
| 135 | config_node->r_value); | 117 | config_node->r_value); |
| 136 | } else if (config_node->r_param || config_node->pos != -1) { | 118 | } |
| 137 | // We're matching on a function (and not a language construct) | ||
| 138 | for (; i < nb_param; i++) { | ||
| 139 | if (ZEND_USER_CODE(execute_data->func->type)) { // yay consistency | ||
| 140 | *arg_name = ZSTR_VAL(execute_data->func->common.arg_info[i].name); | ||
| 141 | } else { | ||
| 142 | *arg_name = execute_data->func->internal_function.arg_info[i].name; | ||
| 143 | } | ||
| 144 | const bool pcre_matching = | ||
| 145 | config_node->r_param && | ||
| 146 | (true == sp_is_regexp_matching(config_node->r_param, *arg_name)); | ||
| 147 | 119 | ||
| 148 | /* This is the parameter name we're looking for. */ | 120 | // safeguards |
| 149 | if (true == pcre_matching || config_node->pos != -1) { | 121 | if (!execute_data || !execute_data->func) { |
| 150 | arg_value = ZEND_CALL_ARG(execute_data, i + 1); | 122 | sp_log_debug("no execute data -> silently ignore parameter matching"); |
| 123 | return false; | ||
| 124 | } | ||
| 151 | 125 | ||
| 152 | if (config_node->param_type) { // Are we matching on the `type`? | 126 | *arg_name = NULL; |
| 153 | if (config_node->param_type == Z_TYPE_P(arg_value)) { | 127 | int call_num_args = EX_NUM_ARGS(); |
| 154 | return true; | 128 | zend_function *fn = execute_data->func; |
| 155 | } | 129 | int fn_num_args = fn->common.num_args; |
| 156 | } else if (Z_TYPE_P(arg_value) == IS_ARRAY) { | 130 | |
| 157 | *arg_value_str = sp_zval_to_zend_string(arg_value); | 131 | if (!call_num_args) { |
| 158 | if (config_node->key || config_node->r_key) { | 132 | sp_log_debug("no call arguments -> return"); |
| 159 | if (sp_match_array_key(arg_value, config_node->key, | 133 | return false; // no arguments to check |
| 160 | config_node->r_key)) { | 134 | } |
| 161 | return true; | 135 | |
| 162 | } | 136 | if (config_node->pos > call_num_args - 1 || config_node->pos > fn_num_args) { |
| 163 | } else if (sp_match_array_value(arg_value, config_node->value, | 137 | // trying to match argument beyond last given argument OR beyond last declared argument. |
| 164 | config_node->r_value)) { | 138 | // this is perfectly normal for functions with |
| 165 | return true; | 139 | // (a) optional arguments |
| 166 | } | 140 | // (b) excess arguments |
| 167 | } else { | 141 | // (c) variadic arguments which are not supported |
| 168 | *arg_value_str = sp_zval_to_zend_string(arg_value); | 142 | return false; |
| 169 | if (sp_match_value(*arg_value_str, config_node->value, | 143 | } |
| 170 | config_node->r_value)) { | 144 | |
| 171 | return true; | 145 | zval* arg_value = NULL; |
| 172 | } | 146 | |
| 173 | } | 147 | if (config_node->pos > -1) { |
| 174 | } | 148 | if (config_node->pos < fn_num_args) { |
| 149 | *arg_name = get_fn_arg_name(fn, config_node->pos); | ||
| 175 | } | 150 | } |
| 151 | arg_value = ZEND_CALL_ARG(execute_data, config_node->pos + 1); | ||
| 176 | } else if (config_node->param) { | 152 | } else if (config_node->param) { |
| 177 | *arg_name = config_node->param->value; | 153 | *arg_name = config_node->param->value; |
| 178 | arg_value = sp_get_var_value(execute_data, config_node->param, true); | 154 | arg_value = sp_get_var_value(execute_data, config_node->param, true); |
| 155 | } else if (config_node->r_param) { | ||
| 156 | for (int i = 0; i < call_num_args; i++) { | ||
| 157 | *arg_name = get_fn_arg_name(fn, i); | ||
| 158 | if (true == sp_is_regexp_matching(config_node->r_param, *arg_name)) { | ||
| 159 | arg_value = ZEND_CALL_ARG(execute_data, i + 1); | ||
| 160 | } | ||
| 161 | } | ||
| 162 | } | ||
| 163 | |||
| 164 | if (!arg_value) { | ||
| 165 | sp_log_debug("no argument match -> return"); | ||
| 166 | return false; | ||
| 167 | } | ||
| 179 | 168 | ||
| 180 | if (arg_value) { | 169 | if (config_node->param_type) { |
| 181 | *arg_value_str = sp_zval_to_zend_string(arg_value); | 170 | if (config_node->param_type == Z_TYPE_P(arg_value)) { |
| 182 | if (config_node->param_type) { // Are we matching on the `type`? | 171 | if (!(config_node->key || config_node->r_key || config_node->value || config_node->r_value)) { // Are we matching on the `type` only? |
| 183 | if (config_node->param_type == Z_TYPE_P(arg_value)) { | 172 | sp_log_debug("arg type match only."); |
| 184 | return true; | ||
| 185 | } | ||
| 186 | } else if (Z_TYPE_P(arg_value) == IS_ARRAY) { | ||
| 187 | if (config_node->key || config_node->r_key) { | ||
| 188 | if (sp_match_array_key(arg_value, config_node->key, | ||
| 189 | config_node->r_key)) { | ||
| 190 | return true; | ||
| 191 | } | ||
| 192 | } else if (sp_match_array_value(arg_value, config_node->value, | ||
| 193 | config_node->r_value)) { | ||
| 194 | return true; | ||
| 195 | } | ||
| 196 | } else if (sp_match_value(*arg_value_str, config_node->value, | ||
| 197 | config_node->r_value)) { | ||
| 198 | return true; | 173 | return true; |
| 199 | } | 174 | } |
| 175 | } else { | ||
| 176 | sp_log_debug("arg type mismatch -> return"); | ||
| 177 | return false; | ||
| 200 | } | 178 | } |
| 201 | } | 179 | } |
| 180 | |||
| 181 | *arg_value_str = sp_zval_to_zend_string(arg_value); | ||
| 182 | if (Z_TYPE_P(arg_value) == IS_ARRAY) { | ||
| 183 | if (config_node->key || config_node->r_key) { | ||
| 184 | if (sp_match_array_key(arg_value, config_node->key, config_node->r_key)) { | ||
| 185 | return true; | ||
| 186 | } | ||
| 187 | } else if (sp_match_array_value(arg_value, config_node->value, config_node->r_value)) { | ||
| 188 | return true; | ||
| 189 | } | ||
| 190 | } else if (sp_match_value(*arg_value_str, config_node->value, config_node->r_value)) { | ||
| 191 | return true; | ||
| 192 | } | ||
| 193 | |||
| 202 | return false; | 194 | return false; |
| 203 | } | 195 | } |
| 204 | 196 | ||
| @@ -218,17 +210,15 @@ static zend_execute_data* is_file_matching( | |||
| 218 | return ex; // LCOV_EXCL_LINE | 210 | return ex; // LCOV_EXCL_LINE |
| 219 | } | 211 | } |
| 220 | ITERATE(ex); | 212 | ITERATE(ex); |
| 221 | if (zend_string_equals(ex->func->op_array.filename, | 213 | if (zend_string_equals(ex->func->op_array.filename, config_node->filename)) { |
| 222 | config_node->filename)) { | ||
| 223 | return ex; // LCOV_EXCL_LINE | 214 | return ex; // LCOV_EXCL_LINE |
| 224 | } | 215 | } |
| 225 | } else if (config_node->r_filename) { | 216 | } else if (config_node->r_filename) { |
| 226 | if (sp_is_regexp_matching_zend(config_node->r_filename, current_filename)) { | 217 | if (sp_is_regexp_matching_zstr(config_node->r_filename, current_filename)) { |
| 227 | return ex; | 218 | return ex; |
| 228 | } | 219 | } |
| 229 | ITERATE(ex); | 220 | ITERATE(ex); |
| 230 | if (sp_is_regexp_matching_zend(config_node->r_filename, | 221 | if (sp_is_regexp_matching_zstr(config_node->r_filename, ex->func->op_array.filename)) { |
| 231 | ex->func->op_array.filename)) { | ||
| 232 | return ex; | 222 | return ex; |
| 233 | } | 223 | } |
| 234 | } | 224 | } |
| @@ -267,7 +257,7 @@ void should_disable_ht(zend_execute_data* execute_data, | |||
| 267 | current_filename = zend_string_init(tmp, strlen(tmp), 0); | 257 | current_filename = zend_string_init(tmp, strlen(tmp), 0); |
| 268 | } | 258 | } |
| 269 | 259 | ||
| 270 | ht_entry = zend_hash_str_find_ptr(ht, function_name, strlen(function_name)); | 260 | ht_entry = zend_hash_str_find_ptr(ht, VAR_AND_LEN(function_name)); |
| 271 | 261 | ||
| 272 | if (ht_entry) { | 262 | if (ht_entry) { |
| 273 | should_disable(execute_data, function_name, builtin_param, | 263 | should_disable(execute_data, function_name, builtin_param, |
| @@ -289,26 +279,22 @@ static void should_disable(zend_execute_data* execute_data, | |||
| 289 | char current_file_hash[SHA256_SIZE * 2 + 1] = {0}; | 279 | char current_file_hash[SHA256_SIZE * 2 + 1] = {0}; |
| 290 | 280 | ||
| 291 | while (config) { | 281 | while (config) { |
| 292 | sp_disabled_function const* const config_node = | 282 | sp_disabled_function const* const config_node = (sp_disabled_function*)(config->data); |
| 293 | (sp_disabled_function*)(config->data); | ||
| 294 | const char* arg_name = NULL; | 283 | const char* arg_name = NULL; |
| 295 | const zend_string* arg_value_str = NULL; | 284 | const zend_string* arg_value_str = NULL; |
| 296 | 285 | ||
| 297 | /* The order matters, since when we have `config_node->functions_list`, | 286 | /* The order matters, since when we have `config_node->functions_list`, |
| 298 | we also do have `config_node->function` */ | 287 | we also do have `config_node->function` */ |
| 299 | if (config_node->functions_list) { | 288 | if (config_node->functions_list) { |
| 300 | if (false == is_functions_list_matching(execute_data, | 289 | if (false == is_functions_list_matching(execute_data, config_node->functions_list)) { |
| 301 | config_node->functions_list)) { | ||
| 302 | goto next; | 290 | goto next; |
| 303 | } | 291 | } |
| 304 | } else if (config_node->function) { | 292 | } else if (config_node->function) { |
| 305 | if (0 != | 293 | if (0 != strcmp(ZSTR_VAL(config_node->function), complete_function_path)) { |
| 306 | strcmp(ZSTR_VAL(config_node->function), complete_function_path)) { | ||
| 307 | goto next; // LCOV_EXCL_LINE | 294 | goto next; // LCOV_EXCL_LINE |
| 308 | } | 295 | } |
| 309 | } else if (config_node->r_function) { | 296 | } else if (config_node->r_function) { |
| 310 | if (false == sp_is_regexp_matching(config_node->r_function, | 297 | if (false == sp_is_regexp_matching(config_node->r_function, complete_function_path)) { |
| 311 | complete_function_path)) { | ||
| 312 | goto next; | 298 | goto next; |
| 313 | } | 299 | } |
| 314 | } | 300 | } |
| @@ -320,8 +306,7 @@ static void should_disable(zend_execute_data* execute_data, | |||
| 320 | } | 306 | } |
| 321 | 307 | ||
| 322 | if (config_node->filename || config_node->r_filename) { | 308 | if (config_node->filename || config_node->r_filename) { |
| 323 | zend_execute_data* ex = | 309 | zend_execute_data* ex = is_file_matching(execute_data, config_node, current_filename); |
| 324 | is_file_matching(execute_data, config_node, current_filename); | ||
| 325 | if (!ex) { | 310 | if (!ex) { |
| 326 | goto next; | 311 | goto next; |
| 327 | } | 312 | } |
| @@ -344,8 +329,7 @@ static void should_disable(zend_execute_data* execute_data, | |||
| 344 | if ('\0' == current_file_hash[0]) { | 329 | if ('\0' == current_file_hash[0]) { |
| 345 | compute_hash(ZSTR_VAL(current_filename), current_file_hash); | 330 | compute_hash(ZSTR_VAL(current_filename), current_file_hash); |
| 346 | } | 331 | } |
| 347 | if (0 != strncmp(current_file_hash, ZSTR_VAL(config_node->hash), | 332 | if (0 != strncmp(current_file_hash, ZSTR_VAL(config_node->hash), SHA256_SIZE)) { |
| 348 | SHA256_SIZE)) { | ||
| 349 | goto next; | 333 | goto next; |
| 350 | } | 334 | } |
| 351 | } | 335 | } |
| @@ -366,9 +350,7 @@ static void should_disable(zend_execute_data* execute_data, | |||
| 366 | "Snuffleupagus doesn't support variadic functions yet, sorry. " | 350 | "Snuffleupagus doesn't support variadic functions yet, sorry. " |
| 367 | "Check https://github.com/jvoisin/snuffleupagus/issues/164 for " | 351 | "Check https://github.com/jvoisin/snuffleupagus/issues/164 for " |
| 368 | "details."); | 352 | "details."); |
| 369 | } else if (false == is_param_matching( | 353 | } else if (false == is_param_matching(execute_data, config_node, builtin_param, builtin_param_name, &arg_name, &arg_value_str)) { |
| 370 | execute_data, config_node, builtin_param, builtin_param_name, | ||
| 371 | &arg_name, &arg_value_str)) { | ||
| 372 | goto next; | 354 | goto next; |
| 373 | } | 355 | } |
| 374 | } | 356 | } |
| @@ -379,11 +361,9 @@ static void should_disable(zend_execute_data* execute_data, | |||
| 379 | } | 361 | } |
| 380 | 362 | ||
| 381 | if (config_node->functions_list) { | 363 | if (config_node->functions_list) { |
| 382 | sp_log_disable(ZSTR_VAL(config_node->function), arg_name, arg_value_str, | 364 | sp_log_disable(ZSTR_VAL(config_node->function), arg_name, arg_value_str, config_node); |
| 383 | config_node); | ||
| 384 | } else { | 365 | } else { |
| 385 | sp_log_disable(complete_function_path, arg_name, arg_value_str, | 366 | sp_log_disable(complete_function_path, arg_name, arg_value_str, config_node); |
| 386 | config_node); | ||
| 387 | } | 367 | } |
| 388 | 368 | ||
| 389 | next: | 369 | next: |
| @@ -418,7 +398,6 @@ static void should_drop_on_ret(const zval* return_value, | |||
| 418 | bool match_type = false, match_value = false; | 398 | bool match_type = false, match_value = false; |
| 419 | 399 | ||
| 420 | while (config) { | 400 | while (config) { |
| 421 | const zend_string* ret_value_str = NULL; | ||
| 422 | sp_disabled_function const* const config_node = | 401 | sp_disabled_function const* const config_node = |
| 423 | (sp_disabled_function*)(config->data); | 402 | (sp_disabled_function*)(config->data); |
| 424 | 403 | ||
| @@ -462,13 +441,18 @@ static void should_drop_on_ret(const zval* return_value, | |||
| 462 | } | 441 | } |
| 463 | } | 442 | } |
| 464 | 443 | ||
| 465 | ret_value_str = sp_zval_to_zend_string(return_value); | 444 | const zend_string* ret_value_str = NULL; |
| 445 | sp_php_type ret_type = SP_PHP_TYPE_NULL; | ||
| 446 | |||
| 447 | if (return_value) { | ||
| 448 | ret_value_str = sp_zval_to_zend_string(return_value); | ||
| 449 | ret_type = Z_TYPE_P(return_value); | ||
| 450 | } | ||
| 466 | 451 | ||
| 467 | match_type = (config_node->ret_type) && | 452 | match_type = (config_node->ret_type) && |
| 468 | (config_node->ret_type == Z_TYPE_P(return_value)); | 453 | (config_node->ret_type == ret_type); |
| 469 | match_value = (config_node->ret || config_node->r_ret) && | 454 | match_value = return_value && (config_node->ret || config_node->r_ret) && |
| 470 | (true == sp_match_value(ret_value_str, config_node->ret, | 455 | (true == sp_match_value(ret_value_str, config_node->ret, config_node->r_ret)); |
| 471 | config_node->r_ret)); | ||
| 472 | 456 | ||
| 473 | if (true == match_type || true == match_value) { | 457 | if (true == match_type || true == match_value) { |
| 474 | if (true == config_node->allow) { | 458 | if (true == config_node->allow) { |
| @@ -483,40 +467,28 @@ static void should_drop_on_ret(const zval* return_value, | |||
| 483 | 467 | ||
| 484 | ZEND_FUNCTION(check_disabled_function) { | 468 | ZEND_FUNCTION(check_disabled_function) { |
| 485 | zif_handler orig_handler; | 469 | zif_handler orig_handler; |
| 486 | const char* current_function_name = get_active_function_name(TSRMLS_C); | 470 | const char* current_function_name = get_active_function_name(); |
| 487 | 471 | ||
| 488 | should_disable_ht( | 472 | should_disable_ht(execute_data, current_function_name, NULL, NULL, SPCFG(disabled_functions_reg).disabled_functions, SPCFG(disabled_functions_hooked)); |
| 489 | execute_data, current_function_name, NULL, NULL, | ||
| 490 | SNUFFLEUPAGUS_G(config).config_disabled_functions_reg->disabled_functions, | ||
| 491 | SNUFFLEUPAGUS_G(config).config_disabled_functions_hooked); | ||
| 492 | 473 | ||
| 493 | orig_handler = zend_hash_str_find_ptr( | 474 | orig_handler = zend_hash_str_find_ptr(SPG(disabled_functions_hook), VAR_AND_LEN(current_function_name)); |
| 494 | SNUFFLEUPAGUS_G(disabled_functions_hook), current_function_name, | ||
| 495 | strlen(current_function_name)); | ||
| 496 | orig_handler(INTERNAL_FUNCTION_PARAM_PASSTHRU); | 475 | orig_handler(INTERNAL_FUNCTION_PARAM_PASSTHRU); |
| 497 | should_drop_on_ret_ht( | 476 | |
| 498 | return_value, current_function_name, | 477 | should_drop_on_ret_ht(return_value, current_function_name, SPCFG(disabled_functions_reg_ret).disabled_functions, SPCFG(disabled_functions_ret_hooked), execute_data); |
| 499 | SNUFFLEUPAGUS_G(config) | ||
| 500 | .config_disabled_functions_reg_ret->disabled_functions, | ||
| 501 | SNUFFLEUPAGUS_G(config).config_disabled_functions_ret_hooked, | ||
| 502 | execute_data); | ||
| 503 | } | 478 | } |
| 504 | 479 | ||
| 505 | static int hook_functions_regexp(const sp_list_node* config) { | 480 | static int hook_functions_regexp(const sp_list_node* config) { |
| 506 | while (config && config->data) { | 481 | while (config && config->data) { |
| 507 | const zend_string* function_name = | 482 | const zend_string* function_name = ((sp_disabled_function*)config->data)->function; |
| 508 | ((sp_disabled_function*)config->data)->function; | 483 | sp_regexp *function_name_sp_regexp = ((sp_disabled_function*)config->data)->r_function; |
| 509 | const sp_pcre* function_name_regexp = | 484 | const sp_pcre* function_name_regexp = function_name_sp_regexp ? function_name_sp_regexp->re : NULL; |
| 510 | ((sp_disabled_function*)config->data)->r_function; | ||
| 511 | 485 | ||
| 512 | assert(function_name || function_name_regexp); | 486 | assert(function_name || function_name_regexp); |
| 513 | 487 | ||
| 514 | if (function_name) { | 488 | if (function_name) { |
| 515 | HOOK_FUNCTION(ZSTR_VAL(function_name), disabled_functions_hook, | 489 | HOOK_FUNCTION(ZSTR_VAL(function_name), disabled_functions_hook, PHP_FN(check_disabled_function)); |
| 516 | PHP_FN(check_disabled_function)); | ||
| 517 | } else { | 490 | } else { |
| 518 | HOOK_FUNCTION_BY_REGEXP(function_name_regexp, disabled_functions_hook, | 491 | HOOK_FUNCTION_BY_REGEXP(function_name_regexp, disabled_functions_hook, PHP_FN(check_disabled_function)); |
| 519 | PHP_FN(check_disabled_function)); | ||
| 520 | } | 492 | } |
| 521 | 493 | ||
| 522 | config = config->next; | 494 | config = config->next; |
| @@ -529,10 +501,8 @@ static void hook_functions(HashTable* to_hook_ht, HashTable* hooked_ht) { | |||
| 529 | zval* value; | 501 | zval* value; |
| 530 | 502 | ||
| 531 | ZEND_HASH_FOREACH_STR_KEY_VAL(to_hook_ht, key, value) { | 503 | ZEND_HASH_FOREACH_STR_KEY_VAL(to_hook_ht, key, value) { |
| 532 | bool hooked = HOOK_FUNCTION(ZSTR_VAL(key), disabled_functions_hook, | 504 | bool hooked = HOOK_FUNCTION(ZSTR_VAL(key), disabled_functions_hook, PHP_FN(check_disabled_function)); |
| 533 | PHP_FN(check_disabled_function)); | 505 | bool is_builtin = check_is_builtin_name(((sp_list_node*)Z_PTR_P(value))->data); |
| 534 | bool is_builtin = | ||
| 535 | check_is_builtin_name(((sp_list_node*)Z_PTR_P(value))->data); | ||
| 536 | if (hooked || is_builtin) { | 506 | if (hooked || is_builtin) { |
| 537 | zend_symtable_add_new(hooked_ht, key, value); | 507 | zend_symtable_add_new(hooked_ht, key, value); |
| 538 | zend_hash_del(to_hook_ht, key); | 508 | zend_hash_del(to_hook_ht, key); |
| @@ -543,41 +513,29 @@ static void hook_functions(HashTable* to_hook_ht, HashTable* hooked_ht) { | |||
| 543 | 513 | ||
| 544 | ZEND_FUNCTION(eval_blacklist_callback) { | 514 | ZEND_FUNCTION(eval_blacklist_callback) { |
| 545 | zif_handler orig_handler; | 515 | zif_handler orig_handler; |
| 546 | const char* current_function_name = get_active_function_name(TSRMLS_C); | 516 | char* current_function_name = get_complete_function_path(EG(current_execute_data)); |
| 547 | zend_string* tmp = | ||
| 548 | zend_string_init(current_function_name, strlen(current_function_name), 0); | ||
| 549 | 517 | ||
| 550 | if (true == check_is_in_eval_whitelist(tmp)) { | 518 | if (!current_function_name || true == check_is_in_eval_whitelist(current_function_name)) { |
| 551 | zend_string_release(tmp); | ||
| 552 | goto whitelisted; | 519 | goto whitelisted; |
| 553 | } | 520 | } |
| 554 | zend_string_release(tmp); | ||
| 555 | 521 | ||
| 556 | if (SNUFFLEUPAGUS_G(in_eval) > 0) { | 522 | if (SPG(in_eval) > 0) { |
| 557 | zend_string* filename = get_eval_filename(zend_get_executed_filename()); | 523 | const sp_config_eval* config_eval = &(SPCFG(eval)); |
| 558 | const int line_number = zend_get_executed_lineno(TSRMLS_C); | ||
| 559 | const sp_config_eval* config_eval = SNUFFLEUPAGUS_G(config).config_eval; | ||
| 560 | 524 | ||
| 561 | if (config_eval->dump) { | 525 | if (config_eval->dump) { |
| 562 | sp_log_request(config_eval->dump, config_eval->textual_representation, | 526 | sp_log_request(config_eval->dump, config_eval->textual_representation); |
| 563 | SP_TOKEN_EVAL_BLACKLIST); | ||
| 564 | } | 527 | } |
| 565 | if (config_eval->simulation) { | 528 | if (config_eval->simulation) { |
| 566 | sp_log_simulation("eval", | 529 | sp_log_simulation("eval", "A call to '%s' was tried in eval. logging it.", current_function_name); |
| 567 | "A call to %s was tried in eval, in %s:%d, logging it.", | ||
| 568 | current_function_name, ZSTR_VAL(filename), line_number); | ||
| 569 | } else { | 530 | } else { |
| 570 | sp_log_drop("eval", | 531 | sp_log_drop("eval", "A call to '%s' was tried in eval. dropping it.", current_function_name); |
| 571 | "A call to %s was tried in eval, in %s:%d, dropping it.", | ||
| 572 | current_function_name, ZSTR_VAL(filename), line_number); | ||
| 573 | } | 532 | } |
| 574 | efree(filename); | ||
| 575 | } | 533 | } |
| 576 | 534 | ||
| 577 | whitelisted: | 535 | whitelisted: |
| 578 | orig_handler = zend_hash_str_find_ptr( | 536 | |
| 579 | SNUFFLEUPAGUS_G(sp_eval_blacklist_functions_hook), current_function_name, | 537 | orig_handler = zend_hash_str_find_ptr(SPG(sp_eval_blacklist_functions_hook), current_function_name, strlen(current_function_name)); |
| 580 | strlen(current_function_name)); | 538 | efree(current_function_name); |
| 581 | orig_handler(INTERNAL_FUNCTION_PARAM_PASSTHRU); | 539 | orig_handler(INTERNAL_FUNCTION_PARAM_PASSTHRU); |
| 582 | } | 540 | } |
| 583 | 541 | ||
| @@ -586,26 +544,19 @@ int hook_disabled_functions(void) { | |||
| 586 | 544 | ||
| 587 | int ret = SUCCESS; | 545 | int ret = SUCCESS; |
| 588 | 546 | ||
| 589 | hook_functions(SNUFFLEUPAGUS_G(config).config_disabled_functions, | 547 | hook_functions(SPCFG(disabled_functions), SPCFG(disabled_functions_hooked)); |
| 590 | SNUFFLEUPAGUS_G(config).config_disabled_functions_hooked); | 548 | hook_functions(SPCFG(disabled_functions_ret), SPCFG(disabled_functions_ret_hooked)); |
| 591 | |||
| 592 | hook_functions(SNUFFLEUPAGUS_G(config).config_disabled_functions_ret, | ||
| 593 | SNUFFLEUPAGUS_G(config).config_disabled_functions_ret_hooked); | ||
| 594 | 549 | ||
| 595 | ret |= hook_functions_regexp( | 550 | ret |= hook_functions_regexp(SPCFG(disabled_functions_reg).disabled_functions); |
| 596 | SNUFFLEUPAGUS_G(config) | ||
| 597 | .config_disabled_functions_reg->disabled_functions); | ||
| 598 | 551 | ||
| 599 | ret |= hook_functions_regexp( | 552 | ret |= hook_functions_regexp(SPCFG(disabled_functions_reg_ret).disabled_functions); |
| 600 | SNUFFLEUPAGUS_G(config) | ||
| 601 | .config_disabled_functions_reg_ret->disabled_functions); | ||
| 602 | 553 | ||
| 603 | if (NULL != SNUFFLEUPAGUS_G(config).config_eval->blacklist) { | 554 | if (NULL != SPCFG(eval).blacklist) { |
| 604 | sp_list_node* it = SNUFFLEUPAGUS_G(config).config_eval->blacklist; | 555 | sp_list_node* it = SPCFG(eval).blacklist; |
| 605 | 556 | ||
| 606 | while (it) { | 557 | while (it) { |
| 607 | hook_function(ZSTR_VAL((zend_string*)it->data), | 558 | hook_function(ZSTR_VAL((zend_string*)it->data), |
| 608 | SNUFFLEUPAGUS_G(sp_eval_blacklist_functions_hook), | 559 | SPG(sp_eval_blacklist_functions_hook), |
| 609 | PHP_FN(eval_blacklist_callback)); | 560 | PHP_FN(eval_blacklist_callback)); |
| 610 | it = it->next; | 561 | it = it->next; |
| 611 | } | 562 | } |
| @@ -622,10 +573,7 @@ int hook_echo(const char* str, size_t str_length) { | |||
| 622 | #endif | 573 | #endif |
| 623 | zend_string* zs = zend_string_init(str, str_length, 0); | 574 | zend_string* zs = zend_string_init(str, str_length, 0); |
| 624 | 575 | ||
| 625 | should_disable_ht( | 576 | should_disable_ht(EG(current_execute_data), "echo", zs, NULL, SPCFG(disabled_functions_reg).disabled_functions, SPCFG(disabled_functions_hooked)); |
| 626 | EG(current_execute_data), "echo", zs, NULL, | ||
| 627 | SNUFFLEUPAGUS_G(config).config_disabled_functions_reg->disabled_functions, | ||
| 628 | SNUFFLEUPAGUS_G(config).config_disabled_functions_hooked); | ||
| 629 | 577 | ||
| 630 | zend_string_release(zs); | 578 | zend_string_release(zs); |
| 631 | 579 | ||
