diff options
| author | Ben Fuhrmannek | 2021-09-23 12:23:40 +0200 |
|---|---|---|
| committer | Ben Fuhrmannek | 2021-09-23 12:23:40 +0200 |
| commit | 54c352c1b5aa08b187dd1e52e544709cad2b0fee (patch) | |
| tree | d15bf0f484c6baa1f2718e625e0d49f6fb488507 /src/sp_execute.c | |
| parent | 887e1c9d44fbcf5f23a928269034593b8521aaba (diff) | |
config is stack allocated now + some code improvements (see details)
* for easier memory manegement, the entire sp_config struct was merged into snuffleupagus_globals and allocated on stack where possible
* SNUFFLEUPAGUS_G() can be written as SPG(), which is faster to type and easier to read
* execution_depth is re-initialized to 0 for each request
* function calls with inline string and length parameters consistently use ZEND_STRL instead of sizeof()-1
* execution is actually hooked if recursion protection is enabled
* some line breaks were removed to make the code more readable
Diffstat (limited to 'src/sp_execute.c')
| -rw-r--r-- | src/sp_execute.c | 64 |
1 files changed, 23 insertions, 41 deletions
diff --git a/src/sp_execute.c b/src/sp_execute.c index 41257ad..ccb7508 100644 --- a/src/sp_execute.c +++ b/src/sp_execute.c | |||
| @@ -8,8 +8,7 @@ static int (*orig_zend_stream_open)(const char *filename, | |||
| 8 | 8 | ||
| 9 | // FIXME handle symlink | 9 | // FIXME handle symlink |
| 10 | ZEND_COLD static inline void terminate_if_writable(const char *filename) { | 10 | ZEND_COLD static inline void terminate_if_writable(const char *filename) { |
| 11 | const sp_config_readonly_exec *config_ro_exec = | 11 | const sp_config_readonly_exec *config_ro_exec = &(SPCFG(readonly_exec)); |
| 12 | SNUFFLEUPAGUS_G(config).config_readonly_exec; | ||
| 13 | 12 | ||
| 14 | if (0 == access(filename, W_OK)) { | 13 | if (0 == access(filename, W_OK)) { |
| 15 | if (config_ro_exec->dump) { | 14 | if (config_ro_exec->dump) { |
| @@ -43,21 +42,18 @@ inline static void is_builtin_matching( | |||
| 43 | return; | 42 | return; |
| 44 | } | 43 | } |
| 45 | 44 | ||
| 46 | should_disable_ht( | 45 | should_disable_ht(EG(current_execute_data), function_name, param_value, param_name, SPCFG(disabled_functions_reg).disabled_functions, ht); |
| 47 | EG(current_execute_data), function_name, param_value, param_name, | ||
| 48 | SNUFFLEUPAGUS_G(config).config_disabled_functions_reg->disabled_functions, | ||
| 49 | ht); | ||
| 50 | } | 46 | } |
| 51 | 47 | ||
| 52 | static void ZEND_HOT | 48 | static void ZEND_HOT |
| 53 | is_in_eval_and_whitelisted(const zend_execute_data *execute_data) { | 49 | is_in_eval_and_whitelisted(const zend_execute_data *execute_data) { |
| 54 | const sp_config_eval *config_eval = SNUFFLEUPAGUS_G(config).config_eval; | 50 | const sp_config_eval *config_eval = &(SPCFG(eval)); |
| 55 | 51 | ||
| 56 | if (EXPECTED(0 == SNUFFLEUPAGUS_G(in_eval))) { | 52 | if (EXPECTED(0 == SPG(in_eval))) { |
| 57 | return; | 53 | return; |
| 58 | } | 54 | } |
| 59 | 55 | ||
| 60 | if (EXPECTED(NULL == SNUFFLEUPAGUS_G(config).config_eval->whitelist)) { | 56 | if (EXPECTED(NULL == config_eval->whitelist)) { |
| 61 | return; | 57 | return; |
| 62 | } | 58 | } |
| 63 | 59 | ||
| @@ -113,50 +109,45 @@ zend_string *get_eval_filename(const char *const filename) { | |||
| 113 | } | 109 | } |
| 114 | 110 | ||
| 115 | static inline void sp_orig_execute(zend_execute_data *execute_data) { | 111 | static inline void sp_orig_execute(zend_execute_data *execute_data) { |
| 116 | SNUFFLEUPAGUS_G(execution_depth)++; | 112 | SPG(execution_depth)++; |
| 117 | if (SNUFFLEUPAGUS_G(execution_depth) > SNUFFLEUPAGUS_G(config).max_execution_depth && SNUFFLEUPAGUS_G(config).max_execution_depth > 0) { | 113 | if (SPCFG(max_execution_depth) > 0 && SPG(execution_depth) > SPCFG(max_execution_depth)) { |
| 118 | sp_log_drop("execute", "Maximum recursion limit reached. Script terminated."); | 114 | sp_log_drop("execute", "Maximum recursion limit reached. Script terminated."); |
| 119 | } | 115 | } |
| 120 | orig_execute_ex(execute_data); | 116 | orig_execute_ex(execute_data); |
| 121 | SNUFFLEUPAGUS_G(execution_depth)--; | 117 | SPG(execution_depth)--; |
| 122 | } | 118 | } |
| 123 | 119 | ||
| 124 | static void sp_execute_ex(zend_execute_data *execute_data) { | 120 | static void sp_execute_ex(zend_execute_data *execute_data) { |
| 125 | is_in_eval_and_whitelisted(execute_data); | 121 | is_in_eval_and_whitelisted(execute_data); |
| 126 | const HashTable *config_disabled_functions = | 122 | const HashTable *config_disabled_functions = SPCFG(disabled_functions); |
| 127 | SNUFFLEUPAGUS_G(config).config_disabled_functions; | ||
| 128 | 123 | ||
| 129 | if (!execute_data) { | 124 | if (!execute_data) { |
| 130 | return; // LCOV_EXCL_LINE | 125 | return; // LCOV_EXCL_LINE |
| 131 | } | 126 | } |
| 132 | 127 | ||
| 133 | if (UNEXPECTED(EX(func)->op_array.type == ZEND_EVAL_CODE)) { | 128 | if (UNEXPECTED(EX(func)->op_array.type == ZEND_EVAL_CODE)) { |
| 134 | const sp_list_node *config = zend_hash_str_find_ptr( | 129 | const sp_list_node *config = zend_hash_str_find_ptr(config_disabled_functions, ZEND_STRL("eval")); |
| 135 | config_disabled_functions, "eval", sizeof("eval") - 1); | ||
| 136 | 130 | ||
| 137 | zend_string *filename = get_eval_filename(zend_get_executed_filename()); | 131 | zend_string *filename = get_eval_filename(zend_get_executed_filename()); |
| 138 | is_builtin_matching(filename, "eval", NULL, config, | 132 | is_builtin_matching(filename, "eval", NULL, config, config_disabled_functions); |
| 139 | config_disabled_functions); | ||
| 140 | zend_string_release(filename); | 133 | zend_string_release(filename); |
| 141 | 134 | ||
| 142 | SNUFFLEUPAGUS_G(in_eval)++; | 135 | SPG(in_eval)++; |
| 143 | sp_orig_execute(execute_data); | 136 | sp_orig_execute(execute_data); |
| 144 | SNUFFLEUPAGUS_G(in_eval)--; | 137 | SPG(in_eval)--; |
| 145 | return; | 138 | return; |
| 146 | } | 139 | } |
| 147 | 140 | ||
| 148 | if (NULL != EX(func)->op_array.filename) { | 141 | if (NULL != EX(func)->op_array.filename) { |
| 149 | if (true == SNUFFLEUPAGUS_G(config).config_readonly_exec->enable) { | 142 | if (SPCFG(readonly_exec).enable) { |
| 150 | terminate_if_writable(ZSTR_VAL(EX(func)->op_array.filename)); | 143 | terminate_if_writable(ZSTR_VAL(EX(func)->op_array.filename)); |
| 151 | } | 144 | } |
| 152 | } | 145 | } |
| 153 | 146 | ||
| 154 | if (SNUFFLEUPAGUS_G(config).hook_execute) { | 147 | if (SPG(hook_execute)) { |
| 155 | char *function_name = get_complete_function_path(execute_data); | 148 | char *function_name = get_complete_function_path(execute_data); |
| 156 | zval ret_val; | 149 | zval ret_val; |
| 157 | const sp_list_node *config_disabled_functions_reg = | 150 | const sp_list_node *config_disabled_functions_reg = SPCFG(disabled_functions_reg).disabled_functions; |
| 158 | SNUFFLEUPAGUS_G(config) | ||
| 159 | .config_disabled_functions_reg->disabled_functions; | ||
| 160 | 151 | ||
| 161 | if (!function_name) { | 152 | if (!function_name) { |
| 162 | sp_orig_execute(execute_data); | 153 | sp_orig_execute(execute_data); |
| @@ -195,11 +186,7 @@ static void sp_execute_ex(zend_execute_data *execute_data) { | |||
| 195 | 186 | ||
| 196 | sp_orig_execute(execute_data); | 187 | sp_orig_execute(execute_data); |
| 197 | 188 | ||
| 198 | should_drop_on_ret_ht( | 189 | should_drop_on_ret_ht(EX(return_value), function_name, SPCFG(disabled_functions_reg_ret).disabled_functions, SPCFG(disabled_functions_ret), execute_data); |
| 199 | EX(return_value), function_name, | ||
| 200 | SNUFFLEUPAGUS_G(config) | ||
| 201 | .config_disabled_functions_reg_ret->disabled_functions, | ||
| 202 | SNUFFLEUPAGUS_G(config).config_disabled_functions_ret, execute_data); | ||
| 203 | efree(function_name); | 190 | efree(function_name); |
| 204 | 191 | ||
| 205 | if (EX(return_value) == &ret_val) { | 192 | if (EX(return_value) == &ret_val) { |
| @@ -231,41 +218,36 @@ static int sp_stream_open(const char *filename, zend_file_handle *handle) { | |||
| 231 | } | 218 | } |
| 232 | 219 | ||
| 233 | zend_string *zend_filename = zend_string_init(filename, strlen(filename), 0); | 220 | zend_string *zend_filename = zend_string_init(filename, strlen(filename), 0); |
| 234 | const HashTable *disabled_functions_hooked = | 221 | const HashTable *disabled_functions_hooked = SPCFG(disabled_functions_hooked); |
| 235 | SNUFFLEUPAGUS_G(config).config_disabled_functions_hooked; | ||
| 236 | 222 | ||
| 237 | switch (data->opline->opcode) { | 223 | switch (data->opline->opcode) { |
| 238 | case ZEND_INCLUDE_OR_EVAL: | 224 | case ZEND_INCLUDE_OR_EVAL: |
| 239 | if (true == SNUFFLEUPAGUS_G(config).config_readonly_exec->enable) { | 225 | if (SPCFG(readonly_exec).enable) { |
| 240 | terminate_if_writable(filename); | 226 | terminate_if_writable(filename); |
| 241 | } | 227 | } |
| 242 | switch (data->opline->extended_value) { | 228 | switch (data->opline->extended_value) { |
| 243 | case ZEND_INCLUDE: | 229 | case ZEND_INCLUDE: |
| 244 | is_builtin_matching( | 230 | is_builtin_matching( |
| 245 | zend_filename, "include", "inclusion path", | 231 | zend_filename, "include", "inclusion path", |
| 246 | zend_hash_str_find_ptr(disabled_functions_hooked, "include", | 232 | zend_hash_str_find_ptr(disabled_functions_hooked, ZEND_STRL("include")), |
| 247 | sizeof("include") - 1), | ||
| 248 | disabled_functions_hooked); | 233 | disabled_functions_hooked); |
| 249 | break; | 234 | break; |
| 250 | case ZEND_REQUIRE: | 235 | case ZEND_REQUIRE: |
| 251 | is_builtin_matching( | 236 | is_builtin_matching( |
| 252 | zend_filename, "require", "inclusion path", | 237 | zend_filename, "require", "inclusion path", |
| 253 | zend_hash_str_find_ptr(disabled_functions_hooked, "require", | 238 | zend_hash_str_find_ptr(disabled_functions_hooked, ZEND_STRL("require")), |
| 254 | sizeof("require") - 1), | ||
| 255 | disabled_functions_hooked); | 239 | disabled_functions_hooked); |
| 256 | break; | 240 | break; |
| 257 | case ZEND_REQUIRE_ONCE: | 241 | case ZEND_REQUIRE_ONCE: |
| 258 | is_builtin_matching( | 242 | is_builtin_matching( |
| 259 | zend_filename, "require_once", "inclusion path", | 243 | zend_filename, "require_once", "inclusion path", |
| 260 | zend_hash_str_find_ptr(disabled_functions_hooked, "require_once", | 244 | zend_hash_str_find_ptr(disabled_functions_hooked, ZEND_STRL("require_once")), |
| 261 | sizeof("require_once") - 1), | ||
| 262 | disabled_functions_hooked); | 245 | disabled_functions_hooked); |
| 263 | break; | 246 | break; |
| 264 | case ZEND_INCLUDE_ONCE: | 247 | case ZEND_INCLUDE_ONCE: |
| 265 | is_builtin_matching( | 248 | is_builtin_matching( |
| 266 | zend_filename, "include_once", "inclusion path", | 249 | zend_filename, "include_once", "inclusion path", |
| 267 | zend_hash_str_find_ptr(disabled_functions_hooked, "include_once", | 250 | zend_hash_str_find_ptr(disabled_functions_hooked, ZEND_STRL("include_once")), |
| 268 | sizeof("include_once") - 1), | ||
| 269 | disabled_functions_hooked); | 251 | disabled_functions_hooked); |
| 270 | break; | 252 | break; |
| 271 | EMPTY_SWITCH_DEFAULT_CASE(); // LCOV_EXCL_LINE | 253 | EMPTY_SWITCH_DEFAULT_CASE(); // LCOV_EXCL_LINE |
