diff options
Diffstat (limited to 'src/sp_utils.c')
| -rw-r--r-- | src/sp_utils.c | 71 |
1 files changed, 42 insertions, 29 deletions
diff --git a/src/sp_utils.c b/src/sp_utils.c index 5483618..af78d20 100644 --- a/src/sp_utils.c +++ b/src/sp_utils.c | |||
| @@ -391,41 +391,43 @@ bool sp_match_array_value(const zval* arr, const zend_string* to_match, | |||
| 391 | return false; | 391 | return false; |
| 392 | } | 392 | } |
| 393 | 393 | ||
| 394 | bool /* success */ _hook_function(const char* original_name, HashTable* hook_table, | ||
| 395 | zif_handler new_function) { | ||
| 396 | zend_function* func; | ||
| 397 | if ((func = zend_hash_str_find_ptr(CG(function_table), VAR_AND_LEN(original_name)))) { | ||
| 398 | if (func->type != ZEND_INTERNAL_FUNCTION) { | ||
| 399 | return false; | ||
| 400 | } | ||
| 401 | if (zend_hash_str_add_new_ptr((hook_table), VAR_AND_LEN(original_name), | ||
| 402 | func->internal_function.handler) == NULL) { | ||
| 403 | // LCOV_EXCL_START | ||
| 404 | sp_log_err("function_pointer_saving", | ||
| 405 | "Could not save function pointer for %s", original_name); | ||
| 406 | return false; | ||
| 407 | // LCOV_EXCL_STOP | ||
| 408 | } | ||
| 409 | func->internal_function.handler = new_function; | ||
| 410 | return true; | ||
| 411 | } | ||
| 412 | return false; | ||
| 413 | } | ||
| 414 | |||
| 394 | bool hook_function(const char* original_name, HashTable* hook_table, | 415 | bool hook_function(const char* original_name, HashTable* hook_table, |
| 395 | zif_handler new_function) { | 416 | zif_handler new_function) { |
| 396 | zend_internal_function* func; | 417 | zend_function* func; |
| 397 | bool ret = false; | ||
| 398 | 418 | ||
| 399 | /* The `mb` module likes to hook functions, like strlen->mb_strlen, | ||
| 400 | * so we have to hook both of them. */ | ||
| 401 | 419 | ||
| 402 | if ((func = zend_hash_str_find_ptr(CG(function_table), | 420 | bool ret = _hook_function(original_name, hook_table, new_function); |
| 403 | VAR_AND_LEN(original_name)))) { | ||
| 404 | if (func->handler == new_function) { | ||
| 405 | return SUCCESS; // the function is already hooked | ||
| 406 | } else { | ||
| 407 | if (zend_hash_str_add_new_ptr((hook_table), VAR_AND_LEN(original_name), | ||
| 408 | func->handler) == NULL) { | ||
| 409 | // LCOV_EXCL_START | ||
| 410 | sp_log_err("function_pointer_saving", | ||
| 411 | "Could not save function pointer for %s", original_name); | ||
| 412 | return FAILURE; | ||
| 413 | // LCOV_EXCL_STOP | ||
| 414 | } | ||
| 415 | func->handler = new_function; | ||
| 416 | ret = true; | ||
| 417 | } | ||
| 418 | } | ||
| 419 | 421 | ||
| 420 | #if PHP_VERSION_ID < 80000 | 422 | #if PHP_VERSION_ID < 80000 |
| 421 | CG(compiler_options) |= ZEND_COMPILE_NO_BUILTIN_STRLEN; | 423 | CG(compiler_options) |= ZEND_COMPILE_NO_BUILTIN_STRLEN; |
| 422 | #endif | 424 | #endif |
| 423 | 425 | ||
| 424 | if (0 == strncmp(original_name, "mb_", 3) && !CG(multibyte)) { | 426 | /* The `mb` module likes to hook functions, like strlen->mb_strlen, |
| 425 | if (zend_hash_str_find(CG(function_table), | 427 | * so we have to hook both of them. */ |
| 426 | VAR_AND_LEN(original_name + 3))) { | 428 | |
| 427 | return hook_function(original_name + 3, hook_table, new_function); | 429 | if (!CG(multibyte) && 0 == strncmp(original_name, "mb_", 3)) { |
| 428 | } | 430 | _hook_function(original_name + 3, hook_table, new_function); |
| 429 | } else if (CG(multibyte)) { | 431 | } else if (CG(multibyte)) { |
| 430 | // LCOV_EXCL_START | 432 | // LCOV_EXCL_START |
| 431 | char* mb_name = ecalloc(strlen(original_name) + 3 + 1, 1); | 433 | char* mb_name = ecalloc(strlen(original_name) + 3 + 1, 1); |
| @@ -434,9 +436,7 @@ bool hook_function(const char* original_name, HashTable* hook_table, | |||
| 434 | } | 436 | } |
| 435 | memcpy(mb_name, "mb_", sizeof("mb_") - 1); | 437 | memcpy(mb_name, "mb_", sizeof("mb_") - 1); |
| 436 | memcpy(mb_name + 3, VAR_AND_LEN(original_name)); | 438 | memcpy(mb_name + 3, VAR_AND_LEN(original_name)); |
| 437 | if (zend_hash_str_find(CG(function_table), VAR_AND_LEN(mb_name))) { | 439 | _hook_function(mb_name, hook_table, new_function); |
| 438 | return hook_function(mb_name, hook_table, new_function); | ||
| 439 | } | ||
| 440 | efree(mb_name); | 440 | efree(mb_name); |
| 441 | // LCOV_EXCL_STOP | 441 | // LCOV_EXCL_STOP |
| 442 | } | 442 | } |
| @@ -459,6 +459,19 @@ int hook_regexp(const sp_pcre* regexp, HashTable* hook_table, | |||
| 459 | return SUCCESS; | 459 | return SUCCESS; |
| 460 | } | 460 | } |
| 461 | 461 | ||
| 462 | void unhook_functions(HashTable *ht) { | ||
| 463 | zend_string *fname; | ||
| 464 | zif_handler orig_handler; | ||
| 465 | zend_ulong idx; | ||
| 466 | |||
| 467 | ZEND_HASH_REVERSE_FOREACH_KEY_PTR(ht, idx, fname, orig_handler) | ||
| 468 | zend_function *func = zend_hash_find_ptr(CG(function_table), fname); | ||
| 469 | if (func && func->type == ZEND_INTERNAL_FUNCTION && orig_handler) { | ||
| 470 | func->internal_function.handler = orig_handler; | ||
| 471 | } | ||
| 472 | ZEND_HASH_FOREACH_END_DEL(); | ||
| 473 | } | ||
| 474 | |||
| 462 | bool check_is_in_eval_whitelist(const zend_string* const function_name) { | 475 | bool check_is_in_eval_whitelist(const zend_string* const function_name) { |
| 463 | const sp_list_node* it = SNUFFLEUPAGUS_G(config).config_eval->whitelist; | 476 | const sp_list_node* it = SNUFFLEUPAGUS_G(config).config_eval->whitelist; |
| 464 | 477 | ||
