summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorxXx-caillou-xXx2018-08-30 14:43:58 +0200
committerjvoisin2018-08-30 12:43:58 +0000
commitf61a4772bfc33e08e7b06250e2f0f640bcae875f (patch)
tree2c26573cdd6ffa9eed1a46291660d82611154eb0 /src
parentdcc64e0f1530fbe5d528873977199ceeb715305d (diff)
Match on ret improvements
This commit does two things: - Implement matching on calltraces for ret - Implement matching on ret of user functions if the return value is not used.
Diffstat (limited to 'src')
-rw-r--r--src/sp_disabled_functions.c25
-rw-r--r--src/sp_disabled_functions.h7
-rw-r--r--src/sp_execute.c32
-rw-r--r--src/sp_utils.c2
-rw-r--r--src/sp_utils.h2
-rw-r--r--src/tests/disabled_functions_chain_call_user_func_ret.phpt13
-rw-r--r--src/tests/disabled_functions_ret_user.phpt4
7 files changed, 58 insertions, 27 deletions
diff --git a/src/sp_disabled_functions.c b/src/sp_disabled_functions.c
index 842b15c..379ed75 100644
--- a/src/sp_disabled_functions.c
+++ b/src/sp_disabled_functions.c
@@ -403,8 +403,9 @@ allow:
403 return false; 403 return false;
404} 404}
405 405
406bool should_drop_on_ret_ht(zval* return_value, const char* function_name, 406bool should_drop_on_ret_ht(const zval* return_value, const char* function_name,
407 const sp_list_node* config, const HashTable* ht) { 407 const sp_list_node* config, const HashTable* ht,
408 zend_execute_data* execute_data) {
408 const sp_list_node* ht_entry = NULL; 409 const sp_list_node* ht_entry = NULL;
409 bool ret = false; 410 bool ret = false;
410 411
@@ -414,17 +415,19 @@ bool should_drop_on_ret_ht(zval* return_value, const char* function_name,
414 415
415 ht_entry = zend_hash_str_find_ptr(ht, function_name, strlen(function_name)); 416 ht_entry = zend_hash_str_find_ptr(ht, function_name, strlen(function_name));
416 417
417 if (ht_entry && should_drop_on_ret(return_value, ht_entry, function_name)) { 418 if (ht_entry && should_drop_on_ret(return_value, ht_entry, function_name,
419 execute_data)) {
418 ret = true; 420 ret = true;
419 } else if (config && config->data) { 421 } else if (config && config->data) {
420 ret = should_drop_on_ret(return_value, config, function_name); 422 ret = should_drop_on_ret(return_value, config, function_name, execute_data);
421 } 423 }
422 424
423 return ret; 425 return ret;
424} 426}
425 427
426bool should_drop_on_ret(zval* return_value, const sp_list_node* config, 428bool should_drop_on_ret(const zval* return_value, const sp_list_node* config,
427 const char* complete_function_path) { 429 const char* complete_function_path,
430 zend_execute_data* execute_data) {
428 const char* current_filename = zend_get_executed_filename(TSRMLS_C); 431 const char* current_filename = zend_get_executed_filename(TSRMLS_C);
429 char current_file_hash[SHA256_SIZE * 2 + 1] = {0}; 432 char current_file_hash[SHA256_SIZE * 2 + 1] = {0};
430 bool match_type = false, match_value = false; 433 bool match_type = false, match_value = false;
@@ -436,7 +439,12 @@ bool should_drop_on_ret(zval* return_value, const sp_list_node* config,
436 439
437 assert(config_node->function || config_node->r_function); 440 assert(config_node->function || config_node->r_function);
438 441
439 if (config_node->function) { 442 if (config_node->functions_list) {
443 if (false == is_functions_list_matching(execute_data,
444 config_node->functions_list)) {
445 goto next;
446 }
447 } else if (config_node->function) {
440 if (0 != 448 if (0 !=
441 strcmp(ZSTR_VAL(config_node->function), complete_function_path)) { 449 strcmp(ZSTR_VAL(config_node->function), complete_function_path)) {
442 goto next; 450 goto next;
@@ -513,7 +521,8 @@ ZEND_FUNCTION(check_disabled_function) {
513 return_value, current_function_name, 521 return_value, current_function_name,
514 SNUFFLEUPAGUS_G(config) 522 SNUFFLEUPAGUS_G(config)
515 .config_disabled_functions_reg_ret->disabled_functions, 523 .config_disabled_functions_reg_ret->disabled_functions,
516 SNUFFLEUPAGUS_G(config).config_disabled_functions_ret_hooked)) { 524 SNUFFLEUPAGUS_G(config).config_disabled_functions_ret_hooked,
525 execute_data)) {
517 sp_terminate(); 526 sp_terminate();
518 } 527 }
519} 528}
diff --git a/src/sp_disabled_functions.h b/src/sp_disabled_functions.h
index 258e2e6..ae1500a 100644
--- a/src/sp_disabled_functions.h
+++ b/src/sp_disabled_functions.h
@@ -9,9 +9,10 @@ bool should_disable(zend_execute_data *, const char *, const zend_string *,
9 const char *, const sp_list_node *, const zend_string *); 9 const char *, const sp_list_node *, const zend_string *);
10bool should_disable_ht(zend_execute_data *, const char *, const zend_string *, 10bool should_disable_ht(zend_execute_data *, const char *, const zend_string *,
11 const char *, const sp_list_node *, const HashTable *); 11 const char *, const sp_list_node *, const HashTable *);
12bool should_drop_on_ret_ht(zval *, const char *, const sp_list_node *config, 12bool should_drop_on_ret_ht(const zval *, const char *, const sp_list_node *config,
13 const HashTable *); 13 const HashTable *, zend_execute_data *);
14bool should_drop_on_ret(zval *, const sp_list_node *config, const char *); 14bool should_drop_on_ret(const zval *, const sp_list_node *config, const char *,
15 zend_execute_data *);
15char *get_complete_function_path(zend_execute_data const *const); 16char *get_complete_function_path(zend_execute_data const *const);
16 17
17#endif /* __SP_DISABLE_FUNCTIONS_H */ 18#endif /* __SP_DISABLE_FUNCTIONS_H */
diff --git a/src/sp_execute.c b/src/sp_execute.c
index 844647e..5447ea1 100644
--- a/src/sp_execute.c
+++ b/src/sp_execute.c
@@ -151,6 +151,7 @@ static void sp_execute_ex(zend_execute_data *execute_data) {
151 151
152 if (SNUFFLEUPAGUS_G(config).hook_execute) { 152 if (SNUFFLEUPAGUS_G(config).hook_execute) {
153 char *function_name = get_complete_function_path(execute_data); 153 char *function_name = get_complete_function_path(execute_data);
154 zval ret_val;
154 155
155 if (!function_name) { 156 if (!function_name) {
156 orig_execute_ex(execute_data); 157 orig_execute_ex(execute_data);
@@ -185,23 +186,34 @@ static void sp_execute_ex(zend_execute_data *execute_data) {
185 } 186 }
186 } 187 }
187 188
189 // When a function's return value isn't used, php doesn't store it in the execute_data,
190 // so we need to use a local variable to be able to match on it later.
191 if (EX(return_value) == NULL) {
192 memset(&ret_val, 0, sizeof(ret_val));
193 EX(return_value) = &ret_val;
194 }
195
188 orig_execute_ex(execute_data); 196 orig_execute_ex(execute_data);
189 197
190 if (EX(return_value) != NULL) { 198 if (UNEXPECTED(
191 if (UNEXPECTED( 199 true ==
192 true == 200 should_drop_on_ret_ht(
193 should_drop_on_ret_ht( 201 EX(return_value), function_name,
194 EX(return_value), function_name, 202 SNUFFLEUPAGUS_G(config)
195 SNUFFLEUPAGUS_G(config) 203 .config_disabled_functions_reg_ret->disabled_functions,
196 .config_disabled_functions_reg_ret->disabled_functions, 204 SNUFFLEUPAGUS_G(config).config_disabled_functions_ret,
197 SNUFFLEUPAGUS_G(config).config_disabled_functions_ret))) { 205 execute_data))) {
198 sp_terminate(); 206 sp_terminate();
199 }
200 } 207 }
201 efree(function_name); 208 efree(function_name);
209
210 if (EX(return_value) == &ret_val) {
211 EX(return_value) = NULL;
212 }
202 } else { 213 } else {
203 orig_execute_ex(execute_data); 214 orig_execute_ex(execute_data);
204 } 215 }
216
205} 217}
206 218
207static void sp_zend_execute_internal(INTERNAL_FUNCTION_PARAMETERS) { 219static void sp_zend_execute_internal(INTERNAL_FUNCTION_PARAMETERS) {
diff --git a/src/sp_utils.c b/src/sp_utils.c
index 41d817e..e872abd 100644
--- a/src/sp_utils.c
+++ b/src/sp_utils.c
@@ -151,7 +151,7 @@ static char* zend_string_to_char(const zend_string* zs) {
151 return copy; 151 return copy;
152} 152}
153 153
154const zend_string* sp_zval_to_zend_string(zval* zv) { 154const zend_string* sp_zval_to_zend_string(const zval* zv) {
155 switch (Z_TYPE_P(zv)) { 155 switch (Z_TYPE_P(zv)) {
156 case IS_LONG: { 156 case IS_LONG: {
157 char* msg; 157 char* msg;
diff --git a/src/sp_utils.h b/src/sp_utils.h
index 97c97fd..c094fac 100644
--- a/src/sp_utils.h
+++ b/src/sp_utils.h
@@ -46,7 +46,7 @@
46 46
47void sp_log_msg(char const *feature, int type, const char *fmt, ...); 47void sp_log_msg(char const *feature, int type, const char *fmt, ...);
48int compute_hash(const char *const filename, char *file_hash); 48int compute_hash(const char *const filename, char *file_hash);
49const zend_string *sp_zval_to_zend_string(zval *); 49const zend_string *sp_zval_to_zend_string(const zval *);
50bool sp_match_value(const zend_string *, const zend_string *, const sp_pcre *); 50bool sp_match_value(const zend_string *, const zend_string *, const sp_pcre *);
51bool sp_match_array_key(const zval *, const zend_string *, const sp_pcre *); 51bool sp_match_array_key(const zval *, const zend_string *, const sp_pcre *);
52bool sp_match_array_value(const zval *, const zend_string *, const sp_pcre *); 52bool sp_match_array_value(const zval *, const zend_string *, const sp_pcre *);
diff --git a/src/tests/disabled_functions_chain_call_user_func_ret.phpt b/src/tests/disabled_functions_chain_call_user_func_ret.phpt
index 44c9b24..d0ee389 100644
--- a/src/tests/disabled_functions_chain_call_user_func_ret.phpt
+++ b/src/tests/disabled_functions_chain_call_user_func_ret.phpt
@@ -21,6 +21,15 @@ echo one('matching') . "\n";
21echo one('still not matching') . "\n"; 21echo one('still not matching') . "\n";
22 22
23?> 23?>
24--XFAIL--
25--EXPECTF-- 24--EXPECTF--
26Match on ret is broken :/ 25one
26two
27not matching_one
28one
29two
30
31Warning: [snuffleupagus][disabled_function] Aborted execution on return of the function 'two', because the function returned 'matching_two', which matched a rule in %a/tests/disabled_functions_chain_call_user_func_ret.php on line %d
32matching_one
33one
34two
35still not matching_one
diff --git a/src/tests/disabled_functions_ret_user.phpt b/src/tests/disabled_functions_ret_user.phpt
index 597a6b8..89c1bce 100644
--- a/src/tests/disabled_functions_ret_user.phpt
+++ b/src/tests/disabled_functions_ret_user.phpt
@@ -12,5 +12,5 @@ function qwe() {
12qwe(); 12qwe();
13echo 1; 13echo 1;
14?> 14?>
15--EXPECT-- 15--EXPECTF--
161 16Fatal error: [snuffleupagus][disabled_function] Aborted execution on return of the function 'qwe', because the function returned 'asd', which matched a rule in %a/tests/disabled_functions_ret_user.php on line %d