summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBen Fuhrmannek2022-01-06 21:22:50 +0100
committerBen Fuhrmannek2022-01-06 21:22:50 +0100
commit4b5afd0148cef6c845a37aff68e1fbac8f5653d7 (patch)
treead4a4832d3ddaa33e336216a3363107acf02c2ed
parent94d3124c3972ee950a40dad72fe1b4bcf16db2c4 (diff)
prevent double checks and fixed segfault on return value access
-rw-r--r--src/snuffleupagus.c3
-rw-r--r--src/sp_disabled_functions.c16
-rw-r--r--src/sp_execute.c19
3 files changed, 24 insertions, 14 deletions
diff --git a/src/snuffleupagus.c b/src/snuffleupagus.c
index 1ccc412..53db721 100644
--- a/src/snuffleupagus.c
+++ b/src/snuffleupagus.c
@@ -334,7 +334,6 @@ static PHP_INI_MH(OnUpdateConfiguration) {
334 } 334 }
335 } 335 }
336 336
337 hook_disabled_functions();
338 hook_execute(); 337 hook_execute();
339 hook_cookies(); 338 hook_cookies();
340 339
@@ -353,6 +352,8 @@ static PHP_INI_MH(OnUpdateConfiguration) {
353 CG(compiler_options) |= ZEND_COMPILE_HANDLE_OP_ARRAY; 352 CG(compiler_options) |= ZEND_COMPILE_HANDLE_OP_ARRAY;
354 } 353 }
355 354
355 hook_disabled_functions();
356
356 // If `zend_write_default` is not NULL it is already hooked. 357 // If `zend_write_default` is not NULL it is already hooked.
357 if ((zend_hash_str_find(SPCFG(disabled_functions_hooked), ZEND_STRL("echo")) || 358 if ((zend_hash_str_find(SPCFG(disabled_functions_hooked), ZEND_STRL("echo")) ||
358 zend_hash_str_find(SPCFG(disabled_functions_ret_hooked), ZEND_STRL("echo"))) && 359 zend_hash_str_find(SPCFG(disabled_functions_ret_hooked), ZEND_STRL("echo"))) &&
diff --git a/src/sp_disabled_functions.c b/src/sp_disabled_functions.c
index 1d9c6c7..c0c642b 100644
--- a/src/sp_disabled_functions.c
+++ b/src/sp_disabled_functions.c
@@ -400,7 +400,6 @@ static void should_drop_on_ret(const zval* return_value,
400 bool match_type = false, match_value = false; 400 bool match_type = false, match_value = false;
401 401
402 while (config) { 402 while (config) {
403 const zend_string* ret_value_str = NULL;
404 sp_disabled_function const* const config_node = 403 sp_disabled_function const* const config_node =
405 (sp_disabled_function*)(config->data); 404 (sp_disabled_function*)(config->data);
406 405
@@ -444,13 +443,18 @@ static void should_drop_on_ret(const zval* return_value,
444 } 443 }
445 } 444 }
446 445
447 ret_value_str = sp_zval_to_zend_string(return_value); 446 const zend_string* ret_value_str = NULL;
447 sp_php_type ret_type = SP_PHP_TYPE_NULL;
448
449 if (return_value) {
450 ret_value_str = sp_zval_to_zend_string(return_value);
451 ret_type = Z_TYPE_P(return_value);
452 }
448 453
449 match_type = (config_node->ret_type) && 454 match_type = (config_node->ret_type) &&
450 (config_node->ret_type == Z_TYPE_P(return_value)); 455 (config_node->ret_type == ret_type);
451 match_value = (config_node->ret || config_node->r_ret) && 456 match_value = return_value && (config_node->ret || config_node->r_ret) &&
452 (true == sp_match_value(ret_value_str, config_node->ret, 457 (true == sp_match_value(ret_value_str, config_node->ret, config_node->r_ret));
453 config_node->r_ret));
454 458
455 if (true == match_type || true == match_value) { 459 if (true == match_type || true == match_value) {
456 if (true == config_node->allow) { 460 if (true == config_node->allow) {
diff --git a/src/sp_execute.c b/src/sp_execute.c
index 21a68dd..aadd145 100644
--- a/src/sp_execute.c
+++ b/src/sp_execute.c
@@ -161,14 +161,18 @@ static inline void sp_execute_handler(INTERNAL_FUNCTION_PARAMETERS, bool interna
161 return; 161 return;
162 } 162 }
163 163
164 const sp_list_node *config_disabled_functions_reg = SPCFG(disabled_functions_reg).disabled_functions; 164 bool is_hooked = (zend_hash_str_find(SPG(disabled_functions_hook), VAR_AND_LEN(function_name)) || zend_hash_str_find(SPG(disabled_functions_hook), VAR_AND_LEN(function_name)));
165 if (is_hooked) {
166 sp_call_orig_execute(INTERNAL_FUNCTION_PARAM_PASSTHRU, internal);
167 return;
168 }
165 169
166 // If we're at an internal function 170 // If we're at an internal function
167 if (!execute_data->prev_execute_data || 171 if (!execute_data->prev_execute_data ||
168 !execute_data->prev_execute_data->func || 172 !execute_data->prev_execute_data->func ||
169 !ZEND_USER_CODE(execute_data->prev_execute_data->func->type) || 173 !ZEND_USER_CODE(execute_data->prev_execute_data->func->type) ||
170 !execute_data->prev_execute_data->opline) { 174 !execute_data->prev_execute_data->opline) {
171 should_disable_ht(execute_data, function_name, NULL, NULL, config_disabled_functions_reg, SPCFG(disabled_functions)); 175 should_disable_ht(execute_data, function_name, NULL, NULL, SPCFG(disabled_functions_reg).disabled_functions, SPCFG(disabled_functions));
172 } else { // If we're at a userland function call 176 } else { // If we're at a userland function call
173 switch (execute_data->prev_execute_data->opline->opcode) { 177 switch (execute_data->prev_execute_data->opline->opcode) {
174 case ZEND_DO_FCALL: 178 case ZEND_DO_FCALL:
@@ -176,7 +180,7 @@ static inline void sp_execute_handler(INTERNAL_FUNCTION_PARAMETERS, bool interna
176 case ZEND_DO_ICALL: 180 case ZEND_DO_ICALL:
177 case ZEND_DO_UCALL: 181 case ZEND_DO_UCALL:
178 case ZEND_TICKS: 182 case ZEND_TICKS:
179 should_disable_ht(execute_data, function_name, NULL, NULL, config_disabled_functions_reg, SPCFG(disabled_functions)); 183 should_disable_ht(execute_data, function_name, NULL, NULL, SPCFG(disabled_functions_reg).disabled_functions, SPCFG(disabled_functions));
180 default: 184 default:
181 break; 185 break;
182 } 186 }
@@ -188,23 +192,24 @@ static inline void sp_execute_handler(INTERNAL_FUNCTION_PARAMETERS, bool interna
188 zval ret_val; 192 zval ret_val;
189 if (EX(return_value) == NULL) { 193 if (EX(return_value) == NULL) {
190 memset(&ret_val, 0, sizeof(ret_val)); 194 memset(&ret_val, 0, sizeof(ret_val));
191 EX(return_value) = &ret_val; 195 return_value = EX(return_value) = &ret_val;
192 } 196 }
193 197
194 sp_call_orig_execute(INTERNAL_FUNCTION_PARAM_PASSTHRU, internal); 198 sp_call_orig_execute(INTERNAL_FUNCTION_PARAM_PASSTHRU, internal);
195 199
196 should_drop_on_ret_ht(EX(return_value), function_name, SPCFG(disabled_functions_reg_ret).disabled_functions, SPCFG(disabled_functions_ret), execute_data); 200 should_drop_on_ret_ht(return_value, function_name, SPCFG(disabled_functions_reg_ret).disabled_functions, SPCFG(disabled_functions_ret), execute_data);
201
197 efree(function_name); 202 efree(function_name);
198 203
199 if (EX(return_value) == &ret_val) { 204 if (EX(return_value) == &ret_val) {
200 EX(return_value) = NULL; 205 return_value = EX(return_value) = NULL;
201 } 206 }
202 207
203} 208}
204 209
205 210
206static void sp_execute_ex(zend_execute_data *execute_data) { 211static void sp_execute_ex(zend_execute_data *execute_data) {
207 sp_execute_handler(execute_data, NULL, false); 212 sp_execute_handler(execute_data, execute_data ? EX(return_value) : NULL, false);
208} 213}
209 214
210static void sp_zend_execute_internal(INTERNAL_FUNCTION_PARAMETERS) { 215static void sp_zend_execute_internal(INTERNAL_FUNCTION_PARAMETERS) {