summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBen Fuhrmannek2021-08-06 20:17:38 +0200
committerBen Fuhrmannek2021-08-06 20:17:38 +0200
commit260f17f112e2d081783c6dc102f81666ac2435d9 (patch)
tree959d5e83c91b77b52017d809656a8655fd017fa4
parent2b6086486be69533d0077585c7726b3efa175fe6 (diff)
restructured function hooks, implemented unhook
-rw-r--r--src/sp_utils.c71
-rw-r--r--src/sp_utils.h1
2 files changed, 43 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
394bool /* 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
394bool hook_function(const char* original_name, HashTable* hook_table, 415bool 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
462void 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
462bool check_is_in_eval_whitelist(const zend_string* const function_name) { 475bool 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
diff --git a/src/sp_utils.h b/src/sp_utils.h
index 5537a34..ec79e8b 100644
--- a/src/sp_utils.h
+++ b/src/sp_utils.h
@@ -82,6 +82,7 @@ void sp_log_disable(const char *restrict, const char *restrict,
82void sp_log_disable_ret(const char *restrict, const zend_string *restrict, 82void sp_log_disable_ret(const char *restrict, const zend_string *restrict,
83 const sp_disabled_function *); 83 const sp_disabled_function *);
84bool hook_function(const char *, HashTable *, zif_handler); 84bool hook_function(const char *, HashTable *, zif_handler);
85void unhook_functions(HashTable *ht);
85int hook_regexp(const sp_pcre *, HashTable *, zif_handler); 86int hook_regexp(const sp_pcre *, HashTable *, zif_handler);
86bool check_is_in_eval_whitelist(const zend_string *const function_name); 87bool check_is_in_eval_whitelist(const zend_string *const function_name);
87int sp_log_request(const zend_string *restrict folder, 88int sp_log_request(const zend_string *restrict folder,