diff options
| -rw-r--r-- | src/snuffleupagus.c | 7 | ||||
| -rw-r--r-- | src/sp_disabled_functions.c | 42 | ||||
| -rw-r--r-- | src/sp_disabled_functions.h | 3 | ||||
| -rw-r--r-- | src/tests/config/disabled_function_echo.ini | 2 | ||||
| -rw-r--r-- | src/tests/disabled_function_echo.phpt | 18 | ||||
| -rw-r--r-- | src/tests/disabled_function_echo_2.phpt | 14 | ||||
| -rw-r--r-- | src/tests/disabled_function_echo_local_var.phpt | 20 |
7 files changed, 101 insertions, 5 deletions
diff --git a/src/snuffleupagus.c b/src/snuffleupagus.c index edca185..ad1d0a9 100644 --- a/src/snuffleupagus.c +++ b/src/snuffleupagus.c | |||
| @@ -261,6 +261,13 @@ static PHP_INI_MH(OnUpdateConfiguration) { | |||
| 261 | // This is needed to implement the global strict mode | 261 | // This is needed to implement the global strict mode |
| 262 | CG(compiler_options) |= ZEND_COMPILE_HANDLE_OP_ARRAY; | 262 | CG(compiler_options) |= ZEND_COMPILE_HANDLE_OP_ARRAY; |
| 263 | } | 263 | } |
| 264 | if (zend_hash_str_find(SNUFFLEUPAGUS_G(config).config_disabled_functions_hooked, | ||
| 265 | "echo", strlen("echo")) || | ||
| 266 | zend_hash_str_find(SNUFFLEUPAGUS_G(config).config_disabled_functions_ret_hooked, | ||
| 267 | "echo", strlen("echo"))) { | ||
| 268 | zend_write_default = zend_write; | ||
| 269 | zend_write = hook_echo; | ||
| 270 | } | ||
| 264 | 271 | ||
| 265 | SNUFFLEUPAGUS_G(config).hook_execute = | 272 | SNUFFLEUPAGUS_G(config).hook_execute = |
| 266 | SNUFFLEUPAGUS_G(config).config_disabled_functions_reg->disabled_functions || | 273 | SNUFFLEUPAGUS_G(config).config_disabled_functions_reg->disabled_functions || |
diff --git a/src/sp_disabled_functions.c b/src/sp_disabled_functions.c index 14783f6..f266951 100644 --- a/src/sp_disabled_functions.c +++ b/src/sp_disabled_functions.c | |||
| @@ -236,13 +236,15 @@ static bool check_is_builtin_name( | |||
| 236 | return (zend_string_equals_literal(config_node->function, "include") || | 236 | return (zend_string_equals_literal(config_node->function, "include") || |
| 237 | zend_string_equals_literal(config_node->function, "include_once") || | 237 | zend_string_equals_literal(config_node->function, "include_once") || |
| 238 | zend_string_equals_literal(config_node->function, "require") || | 238 | zend_string_equals_literal(config_node->function, "require") || |
| 239 | zend_string_equals_literal(config_node->function, "require_once")); | 239 | zend_string_equals_literal(config_node->function, "require_once") || |
| 240 | zend_string_equals_literal(config_node->function, "echo")); | ||
| 240 | } | 241 | } |
| 241 | if (config_node->r_function) { | 242 | if (config_node->r_function) { |
| 242 | return (sp_is_regexp_matching(config_node->r_function, "include") || | 243 | return (sp_is_regexp_matching(config_node->r_function, "include") || |
| 243 | sp_is_regexp_matching(config_node->r_function, "include_once") || | 244 | sp_is_regexp_matching(config_node->r_function, "include_once") || |
| 244 | sp_is_regexp_matching(config_node->r_function, "require") || | 245 | sp_is_regexp_matching(config_node->r_function, "require") || |
| 245 | sp_is_regexp_matching(config_node->r_function, "require_once")); | 246 | sp_is_regexp_matching(config_node->r_function, "require_once") || |
| 247 | sp_is_regexp_matching(config_node->r_function, "echo")); | ||
| 246 | } | 248 | } |
| 247 | return false; | 249 | return false; |
| 248 | } | 250 | } |
| @@ -383,7 +385,12 @@ bool should_disable(zend_execute_data* execute_data, | |||
| 383 | } | 385 | } |
| 384 | 386 | ||
| 385 | if (config_node->r_value || config_node->value) { | 387 | if (config_node->r_value || config_node->value) { |
| 386 | if (check_is_builtin_name(config_node)) { | 388 | if (check_is_builtin_name(config_node) && |
| 389 | !config_node->var && | ||
| 390 | !config_node->param && | ||
| 391 | !config_node->r_param && | ||
| 392 | !config_node->key && | ||
| 393 | !config_node->r_key) { | ||
| 387 | if (false == is_param_matching(execute_data, config_node, builtin_param, | 394 | if (false == is_param_matching(execute_data, config_node, builtin_param, |
| 388 | &arg_name, builtin_param_name, | 395 | &arg_name, builtin_param_name, |
| 389 | &arg_value_str)) { | 396 | &arg_value_str)) { |
| @@ -566,8 +573,14 @@ static int hook_functions(HashTable* to_hook_ht, HashTable* hooked_ht) { | |||
| 566 | if (!HOOK_FUNCTION(ZSTR_VAL(key), disabled_functions_hook, | 573 | if (!HOOK_FUNCTION(ZSTR_VAL(key), disabled_functions_hook, |
| 567 | PHP_FN(check_disabled_function)) || | 574 | PHP_FN(check_disabled_function)) || |
| 568 | check_is_builtin_name(((sp_list_node*)Z_PTR_P(value))->data)) { | 575 | check_is_builtin_name(((sp_list_node*)Z_PTR_P(value))->data)) { |
| 569 | zend_symtable_add_new(hooked_ht, key, value); | 576 | if (zend_string_equals_literal(key, "echo") || |
| 570 | zend_hash_del(to_hook_ht, key); | 577 | zend_string_equals_literal(key, "print")) { |
| 578 | zend_hash_str_add_new(hooked_ht, "echo", strlen("echo"), value); | ||
| 579 | zend_hash_del(to_hook_ht, key); | ||
| 580 | } else { | ||
| 581 | zend_symtable_add_new(hooked_ht, key, value); | ||
| 582 | zend_hash_del(to_hook_ht, key); | ||
| 583 | } | ||
| 571 | } | 584 | } |
| 572 | } | 585 | } |
| 573 | ZEND_HASH_FOREACH_END(); | 586 | ZEND_HASH_FOREACH_END(); |
| @@ -648,3 +661,22 @@ int hook_disabled_functions(void) { | |||
| 648 | } | 661 | } |
| 649 | return ret; | 662 | return ret; |
| 650 | } | 663 | } |
| 664 | |||
| 665 | zend_write_func_t zend_write_default = NULL; | ||
| 666 | |||
| 667 | int hook_echo(const char* str, size_t str_length) { | ||
| 668 | zend_string* zs = zend_string_init(str, str_length, 0); | ||
| 669 | |||
| 670 | bool ret = should_disable_ht( | ||
| 671 | EG(current_execute_data), "echo", zs, NULL, | ||
| 672 | SNUFFLEUPAGUS_G(config).config_disabled_functions_reg->disabled_functions, | ||
| 673 | SNUFFLEUPAGUS_G(config).config_disabled_functions_hooked); | ||
| 674 | |||
| 675 | zend_string_release(zs); | ||
| 676 | |||
| 677 | if (ret) { | ||
| 678 | sp_terminate(); | ||
| 679 | } | ||
| 680 | |||
| 681 | return zend_write_default(str, str_length); | ||
| 682 | } | ||
diff --git a/src/sp_disabled_functions.h b/src/sp_disabled_functions.h index 4e795a1..83b1551 100644 --- a/src/sp_disabled_functions.h +++ b/src/sp_disabled_functions.h | |||
| @@ -1,7 +1,10 @@ | |||
| 1 | #ifndef __SP_DISABLE_FUNCTIONS_H | 1 | #ifndef __SP_DISABLE_FUNCTIONS_H |
| 2 | #define __SP_DISABLE_FUNCTIONS_H | 2 | #define __SP_DISABLE_FUNCTIONS_H |
| 3 | 3 | ||
| 4 | extern zend_write_func_t zend_write_default; | ||
| 5 | |||
| 4 | int hook_disabled_functions(); | 6 | int hook_disabled_functions(); |
| 7 | int hook_echo(const char*, size_t); | ||
| 5 | bool should_disable(zend_execute_data *, const char *, const zend_string *, | 8 | bool should_disable(zend_execute_data *, const char *, const zend_string *, |
| 6 | const char *, const sp_list_node *, const zend_string *); | 9 | const char *, const sp_list_node *, const zend_string *); |
| 7 | 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 *, |
diff --git a/src/tests/config/disabled_function_echo.ini b/src/tests/config/disabled_function_echo.ini new file mode 100644 index 0000000..39bc5e3 --- /dev/null +++ b/src/tests/config/disabled_function_echo.ini | |||
| @@ -0,0 +1,2 @@ | |||
| 1 | sp.disable_function.function("echo").var("$abc").value("123").drop(); | ||
| 2 | sp.disable_function.function("echo").value("oops").drop(); | ||
diff --git a/src/tests/disabled_function_echo.phpt b/src/tests/disabled_function_echo.phpt new file mode 100644 index 0000000..a884e4a --- /dev/null +++ b/src/tests/disabled_function_echo.phpt | |||
| @@ -0,0 +1,18 @@ | |||
| 1 | --TEST-- | ||
| 2 | Echo hooking | ||
| 3 | --SKIPIF-- | ||
| 4 | <?php if (!extension_loaded("snuffleupagus")) die "skip"; ?> | ||
| 5 | --INI-- | ||
| 6 | sp.configuration_file={PWD}/config/disabled_function_echo.ini | ||
| 7 | --FILE-- | ||
| 8 | <?php | ||
| 9 | function test($a) { | ||
| 10 | print "$a"; | ||
| 11 | } | ||
| 12 | echo "qwe"; | ||
| 13 | test("rty"); | ||
| 14 | test("oops"); | ||
| 15 | ?> | ||
| 16 | --CLEAN-- | ||
| 17 | --EXPECTF-- | ||
| 18 | qwerty[snuffleupagus][0.0.0.0][disabled_function][drop] Aborted execution on call of the function 'echo' in %a/tests/disabled_function_echo.php:3. | ||
diff --git a/src/tests/disabled_function_echo_2.phpt b/src/tests/disabled_function_echo_2.phpt new file mode 100644 index 0000000..20dbee4 --- /dev/null +++ b/src/tests/disabled_function_echo_2.phpt | |||
| @@ -0,0 +1,14 @@ | |||
| 1 | --TEST-- | ||
| 2 | Echo hooking | ||
| 3 | --SKIPIF-- | ||
| 4 | <?php if (!extension_loaded("snuffleupagus")) die "skip"; ?> | ||
| 5 | --INI-- | ||
| 6 | sp.configuration_file={PWD}/config/disabled_function_echo.ini | ||
| 7 | --FILE-- | ||
| 8 | <?php | ||
| 9 | echo "qwe"; | ||
| 10 | echo "1", "oops"; | ||
| 11 | ?> | ||
| 12 | --CLEAN-- | ||
| 13 | --EXPECTF-- | ||
| 14 | qwe1[snuffleupagus][0.0.0.0][disabled_function][drop] Aborted execution on call of the function 'echo' in %a/tests/disabled_function_echo_2.php:3. | ||
diff --git a/src/tests/disabled_function_echo_local_var.phpt b/src/tests/disabled_function_echo_local_var.phpt new file mode 100644 index 0000000..bfa3c8c --- /dev/null +++ b/src/tests/disabled_function_echo_local_var.phpt | |||
| @@ -0,0 +1,20 @@ | |||
| 1 | --TEST-- | ||
| 2 | Echo hooking | ||
| 3 | --SKIPIF-- | ||
| 4 | <?php if (!extension_loaded("snuffleupagus")) die "skip"; ?> | ||
| 5 | --INI-- | ||
| 6 | sp.configuration_file={PWD}/config/disabled_function_echo.ini | ||
| 7 | --FILE-- | ||
| 8 | <?php | ||
| 9 | function test() { | ||
| 10 | print "3\n"; | ||
| 11 | } | ||
| 12 | $abc = 1; | ||
| 13 | test(); | ||
| 14 | $abc = 123; | ||
| 15 | test(); | ||
| 16 | ?> | ||
| 17 | --CLEAN-- | ||
| 18 | --EXPECTF-- | ||
| 19 | 3 | ||
| 20 | [snuffleupagus][0.0.0.0][disabled_function][drop] Aborted execution on call of the function 'echo' in %a/tests/disabled_function_echo_local_var.php:3. | ||
