summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/config.m42
-rw-r--r--src/php_snuffleupagus.h1
-rw-r--r--src/sp_config.c4
-rw-r--r--src/sp_config.h9
-rw-r--r--src/sp_config_keywords.c45
-rw-r--r--src/sp_config_utils.c44
-rw-r--r--src/sp_cookie_encryption.c4
-rw-r--r--src/sp_disabled_functions.c138
-rw-r--r--src/sp_list.c28
-rw-r--r--src/sp_list.h1
-rw-r--r--src/sp_tree.c20
-rw-r--r--src/sp_upload_validation.c4
-rw-r--r--src/sp_utils.c84
-rw-r--r--src/sp_utils.h6
-rw-r--r--src/sp_var_parser.c247
-rw-r--r--src/sp_var_parser.h51
-rw-r--r--src/sp_var_value.c226
-rw-r--r--src/tests/broken_conf_key_value.phpt9
-rw-r--r--src/tests/broken_conf_local_var_1.phpt10
-rw-r--r--src/tests/broken_conf_local_var_10.phpt10
-rw-r--r--src/tests/broken_conf_local_var_11.phpt10
-rw-r--r--src/tests/broken_conf_local_var_12.phpt9
-rw-r--r--src/tests/broken_conf_local_var_13.phpt10
-rw-r--r--src/tests/broken_conf_local_var_14.phpt10
-rw-r--r--src/tests/broken_conf_local_var_2.phpt10
-rw-r--r--src/tests/broken_conf_local_var_3.phpt10
-rw-r--r--src/tests/broken_conf_local_var_4.phpt10
-rw-r--r--src/tests/broken_conf_local_var_5.phpt10
-rw-r--r--src/tests/broken_conf_local_var_6.phpt10
-rw-r--r--src/tests/broken_conf_local_var_7.phpt10
-rw-r--r--src/tests/broken_conf_local_var_8.phpt10
-rw-r--r--src/tests/broken_conf_local_var_9.phpt10
-rw-r--r--src/tests/config/broken_conf_key_value.ini1
-rw-r--r--src/tests/config/broken_conf_local_var_1.ini1
-rw-r--r--src/tests/config/broken_conf_local_var_10.ini1
-rw-r--r--src/tests/config/broken_conf_local_var_11.ini1
-rw-r--r--src/tests/config/broken_conf_local_var_12.ini1
-rw-r--r--src/tests/config/broken_conf_local_var_13.ini1
-rw-r--r--src/tests/config/broken_conf_local_var_14.ini1
-rw-r--r--src/tests/config/broken_conf_local_var_2.ini1
-rw-r--r--src/tests/config/broken_conf_local_var_3.ini1
-rw-r--r--src/tests/config/broken_conf_local_var_4.ini1
-rw-r--r--src/tests/config/broken_conf_local_var_5.ini1
-rw-r--r--src/tests/config/broken_conf_local_var_6.ini1
-rw-r--r--src/tests/config/broken_conf_local_var_7.ini1
-rw-r--r--src/tests/config/broken_conf_local_var_8.ini1
-rw-r--r--src/tests/config/broken_conf_local_var_9.ini1
-rw-r--r--src/tests/config/config_disabled_functions_local_var_array.ini1
-rw-r--r--src/tests/config/config_disabled_functions_local_var_array_key.ini1
-rw-r--r--src/tests/config/config_disabled_functions_name_type.ini2
-rw-r--r--src/tests/config/config_disabled_functions_nul_byte.ini2
-rw-r--r--src/tests/config/config_disabled_functions_param.ini12
-rw-r--r--src/tests/config/config_disabled_functions_param_allow.ini4
-rw-r--r--src/tests/config/config_disabled_functions_param_array.ini11
-rw-r--r--src/tests/config/config_disabled_functions_param_int.ini4
-rw-r--r--src/tests/config/config_disabled_functions_param_r_array.ini2
-rw-r--r--src/tests/config/config_disabled_functions_param_runtime.ini2
-rw-r--r--src/tests/config/disabled_function_local_var.ini12
-rw-r--r--src/tests/config/disabled_function_local_var_2.ini1
-rw-r--r--src/tests/config/disabled_function_local_var_obj.ini3
-rw-r--r--src/tests/config/disabled_function_super_global_var.ini2
-rw-r--r--src/tests/config/disabled_functions_pos.ini1
-rw-r--r--src/tests/disabled_function_local_var_10.phpt44
-rw-r--r--src/tests/disabled_function_local_var_2.phpt46
-rw-r--r--src/tests/disabled_function_local_var_3.phpt45
-rw-r--r--src/tests/disabled_function_local_var_4.phpt56
-rw-r--r--src/tests/disabled_function_local_var_5.phpt33
-rw-r--r--src/tests/disabled_function_local_var_6.phpt31
-rw-r--r--src/tests/disabled_function_local_var_7.phpt31
-rw-r--r--src/tests/disabled_function_local_var_8.phpt20
-rw-r--r--src/tests/disabled_function_local_var_9.phpt20
-rw-r--r--src/tests/disabled_function_local_var_obj.phpt25
-rw-r--r--src/tests/disabled_functions_local_var_array.phpt20
-rw-r--r--src/tests/disabled_functions_local_var_array_key.phpt20
-rw-r--r--src/tests/disabled_functions_name_type.phpt2
-rw-r--r--src/tests/disabled_functions_nul_byte.phpt2
-rw-r--r--src/tests/disabled_functions_param.phpt2
-rw-r--r--src/tests/disabled_functions_param_array.phpt2
-rw-r--r--src/tests/disabled_functions_param_array_deref.phpt2
-rw-r--r--src/tests/disabled_functions_param_array_no_value.phpt2
-rw-r--r--src/tests/disabled_functions_param_array_r.phpt20
-rw-r--r--src/tests/disabled_functions_param_array_r_keys.phpt20
-rw-r--r--src/tests/disabled_functions_param_array_several_levels.phpt2
-rw-r--r--src/tests/disabled_functions_param_array_several_levels_int.phpt20
-rw-r--r--src/tests/disabled_functions_param_array_several_levels_keys.phpt20
-rw-r--r--src/tests/disabled_functions_param_array_several_levels_keys_int.phpt20
-rw-r--r--src/tests/disabled_functions_param_int.phpt2
-rw-r--r--src/tests/disabled_functions_pos_type.phpt14
-rw-r--r--src/tests/disabled_functions_runtime.phpt2
89 files changed, 1440 insertions, 220 deletions
diff --git a/src/config.m4 b/src/config.m4
index 8fa22c5..b2c6ed5 100644
--- a/src/config.m4
+++ b/src/config.m4
@@ -5,7 +5,7 @@ sources="snuffleupagus.c sp_config.c sp_config_utils.c sp_harden_rand.c"
5sources="$sources sp_unserialize.c sp_utils.c sp_disable_xxe.c sp_list.c" 5sources="$sources sp_unserialize.c sp_utils.c sp_disable_xxe.c sp_list.c"
6sources="$sources sp_disabled_functions.c sp_execute.c sp_upload_validation.c" 6sources="$sources sp_disabled_functions.c sp_execute.c sp_upload_validation.c"
7sources="$sources sp_cookie_encryption.c sp_network_utils.c tweetnacl.c" 7sources="$sources sp_cookie_encryption.c sp_network_utils.c tweetnacl.c"
8sources="$sources sp_config_keywords.c" 8sources="$sources sp_config_keywords.c sp_var_parser.c sp_var_value.c sp_tree.c"
9 9
10PHP_ARG_ENABLE(snuffleupagus, whether to enable snuffleupagus support, 10PHP_ARG_ENABLE(snuffleupagus, whether to enable snuffleupagus support,
11[ --enable-snuffleupagus Enable snuffleupagus support]) 11[ --enable-snuffleupagus Enable snuffleupagus support])
diff --git a/src/php_snuffleupagus.h b/src/php_snuffleupagus.h
index 2ad412d..bccf998 100644
--- a/src/php_snuffleupagus.h
+++ b/src/php_snuffleupagus.h
@@ -26,6 +26,7 @@
26#include "zend_extensions.h" 26#include "zend_extensions.h"
27 27
28#include "sp_list.h" 28#include "sp_list.h"
29#include "sp_var_parser.h"
29#include "sp_config.h" 30#include "sp_config.h"
30#include "sp_config_utils.h" 31#include "sp_config_utils.h"
31#include "sp_config_keywords.h" 32#include "sp_config_keywords.h"
diff --git a/src/sp_config.c b/src/sp_config.c
index 2432cc4..bed81bc 100644
--- a/src/sp_config.c
+++ b/src/sp_config.c
@@ -189,6 +189,10 @@ void sp_disabled_function_list_free(sp_node_t* list) {
189 sp_disabled_function* df = cursor->data; 189 sp_disabled_function* df = cursor->data;
190 if (df && df->functions_list) 190 if (df && df->functions_list)
191 sp_list_free(df->functions_list); 191 sp_list_free(df->functions_list);
192 if (df) {
193 sp_tree_free(df->param);
194 sp_tree_free(df->var);
195 }
192 cursor = cursor->next; 196 cursor = cursor->next;
193 } 197 }
194} 198}
diff --git a/src/sp_config.h b/src/sp_config.h
index 8ef62a2..127c557 100644
--- a/src/sp_config.h
+++ b/src/sp_config.h
@@ -78,7 +78,7 @@ typedef struct {
78 char *hash; 78 char *hash;
79 int simulation; 79 int simulation;
80 80
81 char *param; 81 sp_tree *param;
82 pcre *r_param; 82 pcre *r_param;
83 sp_php_type param_type; 83 sp_php_type param_type;
84 int pos; 84 int pos;
@@ -91,6 +91,9 @@ typedef struct {
91 pcre *value_r; 91 pcre *value_r;
92 char *value; 92 char *value;
93 93
94 pcre *r_key;
95 char *key;
96
94 char *dump; 97 char *dump;
95 char *alias; 98 char *alias;
96 bool param_is_array; 99 bool param_is_array;
@@ -100,7 +103,7 @@ typedef struct {
100 103
101 bool allow; 104 bool allow;
102 105
103 char *var; 106 sp_tree *var;
104 107
105 sp_cidr *cidr; 108 sp_cidr *cidr;
106} sp_disabled_function; 109} sp_disabled_function;
@@ -193,6 +196,8 @@ typedef struct {
193#define SP_TOKEN_RET_TYPE ".ret_type(" 196#define SP_TOKEN_RET_TYPE ".ret_type("
194#define SP_TOKEN_VALUE ".value(" 197#define SP_TOKEN_VALUE ".value("
195#define SP_TOKEN_VALUE_REGEXP ".value_r(" 198#define SP_TOKEN_VALUE_REGEXP ".value_r("
199#define SP_TOKEN_KEY ".key("
200#define SP_TOKEN_KEY_REGEXP ".key_r("
196#define SP_TOKEN_VALUE_ARG_POS ".pos(" 201#define SP_TOKEN_VALUE_ARG_POS ".pos("
197#define SP_TOKEN_LINE_NUMBER ".line(" 202#define SP_TOKEN_LINE_NUMBER ".line("
198 203
diff --git a/src/sp_config_keywords.c b/src/sp_config_keywords.c
index dd9a880..2d294ee 100644
--- a/src/sp_config_keywords.c
+++ b/src/sp_config_keywords.c
@@ -178,7 +178,7 @@ int parse_cookie(char *line) {
178int parse_disabled_functions(char *line) { 178int parse_disabled_functions(char *line) {
179 int ret = 0; 179 int ret = 0;
180 bool enable = true, disable = false, allow = false, drop = false; 180 bool enable = true, disable = false, allow = false, drop = false;
181 char *pos = NULL; 181 char *pos = NULL, *var = NULL, *param = NULL;
182 char *line_number = NULL; 182 char *line_number = NULL;
183 sp_disabled_function *df = pecalloc(sizeof(*df), 1, 1); 183 sp_disabled_function *df = pecalloc(sizeof(*df), 1, 1);
184 df->pos = -1; 184 df->pos = -1;
@@ -196,16 +196,18 @@ int parse_disabled_functions(char *line) {
196 {parse_empty, SP_TOKEN_ALLOW, &(allow)}, 196 {parse_empty, SP_TOKEN_ALLOW, &(allow)},
197 {parse_empty, SP_TOKEN_DROP, &(drop)}, 197 {parse_empty, SP_TOKEN_DROP, &(drop)},
198 {parse_str, SP_TOKEN_HASH, &(df->hash)}, 198 {parse_str, SP_TOKEN_HASH, &(df->hash)},
199 {parse_str, SP_TOKEN_PARAM, &(df->param)}, 199 {parse_str, SP_TOKEN_PARAM, &(param)},
200 {parse_regexp, SP_TOKEN_VALUE_REGEXP, &(df->value_r)}, 200 {parse_regexp, SP_TOKEN_VALUE_REGEXP, &(df->value_r)},
201 {parse_str, SP_TOKEN_VALUE, &(df->value)}, 201 {parse_str, SP_TOKEN_VALUE, &(df->value)},
202 {parse_str, SP_TOKEN_KEY, &(df->key)},
203 {parse_regexp, SP_TOKEN_KEY_REGEXP, &(df->r_key)},
202 {parse_regexp, SP_TOKEN_PARAM_REGEXP, &(df->r_param)}, 204 {parse_regexp, SP_TOKEN_PARAM_REGEXP, &(df->r_param)},
203 {parse_php_type, SP_TOKEN_PARAM_TYPE, &(df->param_type)}, 205 {parse_php_type, SP_TOKEN_PARAM_TYPE, &(df->param_type)},
204 {parse_str, SP_TOKEN_RET, &(df->ret)}, 206 {parse_str, SP_TOKEN_RET, &(df->ret)},
205 {parse_cidr, SP_TOKEN_CIDR, &(df->cidr)}, 207 {parse_cidr, SP_TOKEN_CIDR, &(df->cidr)},
206 {parse_regexp, SP_TOKEN_RET_REGEXP, &(df->r_ret)}, 208 {parse_regexp, SP_TOKEN_RET_REGEXP, &(df->r_ret)},
207 {parse_php_type, SP_TOKEN_RET_TYPE, &(df->ret_type)}, 209 {parse_php_type, SP_TOKEN_RET_TYPE, &(df->ret_type)},
208 {parse_str, SP_TOKEN_LOCAL_VAR, &(df->var)}, 210 {parse_str, SP_TOKEN_LOCAL_VAR, &(var)},
209 {parse_str, SP_TOKEN_VALUE_ARG_POS, &(pos)}, 211 {parse_str, SP_TOKEN_VALUE_ARG_POS, &(pos)},
210 {parse_str, SP_TOKEN_LINE_NUMBER, &(line_number)}, 212 {parse_str, SP_TOKEN_LINE_NUMBER, &(line_number)},
211 {0}}; 213 {0}};
@@ -229,9 +231,10 @@ int parse_disabled_functions(char *line) {
229 MUTUALLY_EXCLUSIVE(df->r_function, df->function, "r_function", "function"); 231 MUTUALLY_EXCLUSIVE(df->r_function, df->function, "r_function", "function");
230 MUTUALLY_EXCLUSIVE(df->filename, df->r_filename, "r_filename", "filename"); 232 MUTUALLY_EXCLUSIVE(df->filename, df->r_filename, "r_filename", "filename");
231 MUTUALLY_EXCLUSIVE(df->ret, df->r_ret, "r_ret", "ret"); 233 MUTUALLY_EXCLUSIVE(df->ret, df->r_ret, "r_ret", "ret");
234 MUTUALLY_EXCLUSIVE(df->key, df->r_key, "r_key", "key");
232#undef MUTUALLY_EXCLUSIVE 235#undef MUTUALLY_EXCLUSIVE
233 236
234 if (1 < ((df->r_param ? 1 : 0) + (df->param ? 1 : 0) + 237 if (1 < ((df->r_param ? 1 : 0) + (param ? 1 : 0) +
235 ((-1 != df->pos) ? 1 : 0))) { 238 ((-1 != df->pos) ? 1 : 0))) {
236 sp_log_err( 239 sp_log_err(
237 "config", 240 "config",
@@ -239,7 +242,13 @@ int parse_disabled_functions(char *line) {
239 "'.r_param', '.param' and '.pos' are mutually exclusive on line %zu.", 242 "'.r_param', '.param' and '.pos' are mutually exclusive on line %zu.",
240 line, sp_line_no); 243 line, sp_line_no);
241 return -1; 244 return -1;
242 } else if ((df->r_ret || df->ret) && (df->r_param || df->param)) { 245 } else if ((df->r_key || df->key) && (df->value_r || df->value)) {
246 sp_log_err("config",
247 "Invalid configuration line: 'sp.disabled_functions%s':"
248 "`key` and `value` are mutually exclusive on line %zu.",
249 line, sp_line_no);
250 return -1;
251 } else if ((df->r_ret || df->ret) && (df->r_param || param)) {
243 sp_log_err("config", 252 sp_log_err("config",
244 "Invalid configuration line: 'sp.disabled_functions%s':" 253 "Invalid configuration line: 'sp.disabled_functions%s':"
245 "`ret` and `param` are mutually exclusive on line %zu.", 254 "`ret` and `param` are mutually exclusive on line %zu.",
@@ -293,22 +302,28 @@ int parse_disabled_functions(char *line) {
293 df->functions_list = parse_functions_list(df->function); 302 df->functions_list = parse_functions_list(df->function);
294 } 303 }
295 304
296 if (df->param && strchr(df->param, '[')) { // assume that this is an array 305 if (param) {
297 df->param_array_keys = sp_list_new(); 306 df->param = parse_var(param);
298 if (0 != array_to_list(&df->param, &df->param_array_keys)) { 307 if (!df->param) {
299 pefree(df->param_array_keys, 1); 308 sp_log_err("config", "Invalid value '%s' for `param` on line %zu.",
309 param, sp_line_no);
300 return -1; 310 return -1;
301 } 311 }
302 df->param_is_array = 1;
303 } 312 }
304 313
305 if (df->var && strchr(df->var, '[')) { // assume that this is an array 314 if (var) {
306 df->var_array_keys = sp_list_new(); 315 if (*var) {
307 if (0 != array_to_list(&df->var, &df->var_array_keys)) { 316 df->var = parse_var(var);
308 pefree(df->var_array_keys, 1); 317 if (!df->var) {
318 sp_log_err("config", "Invalid value '%s' for `var` on line %zu.",
319 var, sp_line_no);
320 return -1;
321 }
322 } else {
323 sp_log_err("config", "Empty value in `var` on line %zu.",
324 sp_line_no);
309 return -1; 325 return -1;
310 } 326 }
311 df->var_is_array = 1;
312 } 327 }
313 328
314 switch (get_construct_type(df)) { 329 switch (get_construct_type(df)) {
diff --git a/src/sp_config_utils.c b/src/sp_config_utils.c
index 1a797e5..ddd2e05 100644
--- a/src/sp_config_utils.c
+++ b/src/sp_config_utils.c
@@ -133,50 +133,6 @@ char *get_param(size_t *consumed, char *restrict line, sp_type type,
133 return NULL; 133 return NULL;
134} 134}
135 135
136// FIXME this is leaking like hell @blotus
137int array_to_list(char **name_ptr, sp_node_t **keys) {
138 int in_key = 0;
139 size_t i = 0;
140 char *name = *name_ptr;
141 char *key_name = ecalloc(strlen(name) + 1, 1); // im way too lazy for
142 // now
143 char *tmp = ecalloc(strlen(name) + 1, 1);
144
145 for (i = 0; name[i] != '['; i++) {
146 tmp[i] = name[i];
147 }
148 tmp[i] = 0;
149
150 for (size_t j = 0; name[i]; i++) {
151 const char c = name[i];
152 if (c == '[') {
153 if (in_key == 0) {
154 in_key = 1;
155 } else {
156 efree(key_name);
157 return -1;
158 }
159 } else if (c == ']') {
160 if (in_key == 0) {
161 efree(key_name);
162 return -1;
163 } else {
164 in_key = 0;
165 j = 0;
166 sp_list_insert(*keys, pestrdup(key_name, 1));
167 memset(key_name, 0, strlen(name) + 1);
168 }
169 } else if (in_key == 1) {
170 key_name[j] = c;
171 j++;
172 }
173 }
174 efree(key_name);
175 *name_ptr = pestrdup(tmp, 1);
176 return in_key;
177}
178
179
180zend_always_inline sp_node_t *parse_functions_list(char *value) { 136zend_always_inline sp_node_t *parse_functions_list(char *value) {
181 const char *sep = ">"; 137 const char *sep = ">";
182 138
diff --git a/src/sp_cookie_encryption.c b/src/sp_cookie_encryption.c
index b7050da..c749040 100644
--- a/src/sp_cookie_encryption.c
+++ b/src/sp_cookie_encryption.c
@@ -8,9 +8,9 @@ static zend_long nonce_d = 0;
8 8
9static inline void generate_key(unsigned char *key) { 9static inline void generate_key(unsigned char *key) {
10 PHP_SHA256_CTX ctx; 10 PHP_SHA256_CTX ctx;
11 const char *user_agent = sp_getenv("HTTP_USER_AGENT"); 11 const char *user_agent = getenv("HTTP_USER_AGENT");
12 const char *env_var = 12 const char *env_var =
13 sp_getenv(SNUFFLEUPAGUS_G(config).config_snuffleupagus->cookies_env_var); 13 getenv(SNUFFLEUPAGUS_G(config).config_snuffleupagus->cookies_env_var);
14 const char *encryption_key = 14 const char *encryption_key =
15 SNUFFLEUPAGUS_G(config).config_snuffleupagus->encryption_key; 15 SNUFFLEUPAGUS_G(config).config_snuffleupagus->encryption_key;
16 16
diff --git a/src/sp_disabled_functions.c b/src/sp_disabled_functions.c
index 6c180aa..c7974ff 100644
--- a/src/sp_disabled_functions.c
+++ b/src/sp_disabled_functions.c
@@ -64,43 +64,30 @@ end:
64static bool is_local_var_matching( 64static bool is_local_var_matching(
65 zend_execute_data* execute_data, 65 zend_execute_data* execute_data,
66 const sp_disabled_function* const config_node) { 66 const sp_disabled_function* const config_node) {
67 zend_execute_data* orig_execute_data = execute_data; 67 zval *var_value;
68 68
69 /*because execute_data points to hooked function data, 69 var_value = get_value(execute_data, config_node->var, false);
70 which we dont care about */ 70 if (var_value) {
71 zend_execute_data* current = execute_data->prev_execute_data; 71 char *var_value_str = sp_convert_to_string(var_value);
72 zval* value = NULL; 72 if (Z_TYPE_P(var_value) == IS_ARRAY) {
73 73 if (config_node->key || config_node->r_key) {
74 while (current) { 74 if (sp_match_array_key(var_value, config_node->key,
75 zend_string* key = NULL; 75 config_node->r_key)) {
76 EG(current_execute_data) = current; 76 efree(var_value_str);
77 zend_array* symtable = zend_rebuild_symbol_table(); 77 return true;
78 ZEND_HASH_FOREACH_STR_KEY_VAL(symtable, key, value) { 78 }
79 if (0 == strcmp(config_node->var, key->val)) { // is the var name right? 79 } else if (sp_match_array_value(var_value, config_node->value,
80 if (Z_TYPE_P(value) == IS_INDIRECT) { 80 config_node->value_r)) {
81 value = Z_INDIRECT_P(value); 81 efree(var_value_str);
82 } 82 return true;
83 if (Z_TYPE_P(value) != IS_ARRAY) {
84 char* var_value_str = sp_convert_to_string(value);
85 if (true == sp_match_value(var_value_str, config_node->value,
86 config_node->value_r)) {
87 efree(var_value_str);
88 EG(current_execute_data) = orig_execute_data;
89 return true;
90 }
91 efree(var_value_str);
92 } else {
93 EG(current_execute_data) = orig_execute_data;
94 return sp_match_array_key_recurse(value, config_node->var_array_keys,
95 config_node->value, NULL);
96 }
97 } 83 }
84 } else if (sp_match_value(var_value_str, config_node->value,
85 config_node->value_r)) {
86 efree(var_value_str);
87 return true;
98 } 88 }
99 ZEND_HASH_FOREACH_END(); 89 efree(var_value_str);
100 current = current->prev_execute_data;
101 } 90 }
102
103 EG(current_execute_data) = orig_execute_data;
104 return false; 91 return false;
105} 92}
106 93
@@ -128,6 +115,7 @@ static bool is_param_matching(zend_execute_data* execute_data,
128 const char** arg_value_str) { 115 const char** arg_value_str) {
129 int nb_param = execute_data->func->common.num_args; 116 int nb_param = execute_data->func->common.num_args;
130 int i = 0; 117 int i = 0;
118 zval *arg_value;
131 119
132 if (config_node->pos != -1) { 120 if (config_node->pos != -1) {
133 if (config_node->pos <= nb_param) { 121 if (config_node->pos <= nb_param) {
@@ -154,7 +142,7 @@ static bool is_param_matching(zend_execute_data* execute_data,
154 *arg_value_str = builtin_param; 142 *arg_value_str = builtin_param;
155 return sp_match_value(builtin_param, config_node->value, 143 return sp_match_value(builtin_param, config_node->value,
156 config_node->value_r); 144 config_node->value_r);
157 } else { 145 } else if (config_node->r_param || config_node->pos != -1) {
158 // We're matching on a function (and not a language construct) 146 // We're matching on a function (and not a language construct)
159 for (; i < nb_param; i++) { 147 for (; i < nb_param; i++) {
160 if (ZEND_USER_CODE(execute_data->func->type)) { // yay consistency 148 if (ZEND_USER_CODE(execute_data->func->type)) { // yay consistency
@@ -162,49 +150,63 @@ static bool is_param_matching(zend_execute_data* execute_data,
162 } else { 150 } else {
163 *arg_name = execute_data->func->internal_function.arg_info[i].name; 151 *arg_name = execute_data->func->internal_function.arg_info[i].name;
164 } 152 }
165 153 const bool pcre_matching = config_node->r_param
166 const bool arg_matching = 154 && (true == is_regexp_matching(config_node->r_param, *arg_name));
167 config_node->param && (0 == strcmp(*arg_name, config_node->param));
168 const bool pcre_matching =
169 config_node->r_param &&
170 (true == is_regexp_matching(config_node->r_param, *arg_name));
171 155
172 /* This is the parameter name we're looking for. */ 156 /* This is the parameter name we're looking for. */
173 if (true == arg_matching || true == pcre_matching || 157 if (true == pcre_matching || config_node->pos != -1) {
174 (config_node->pos != -1)) { 158 arg_value = ZEND_CALL_VAR_NUM(execute_data, i);
175 zval* arg_value = ZEND_CALL_VAR_NUM(execute_data, i);
176 159
177 if (config_node->param_type) { // Are we matching on the `type`? 160 if (config_node->param_type) { // Are we matching on the `type`?
178 if (config_node->param_type == Z_TYPE_P(arg_value)) { 161 if (config_node->param_type == Z_TYPE_P(arg_value)) {
179 return true; 162 return true;
180 } 163 }
181 } else if (Z_TYPE_P(arg_value) == IS_ARRAY) { 164 } else if (Z_TYPE_P(arg_value) == IS_ARRAY) {
182 *arg_value_str = estrdup("Array"); 165 *arg_value_str = sp_convert_to_string(arg_value);
183 // match on arr -> match on all key content, if a key is an array, 166 if (config_node->key || config_node->r_key) {
184 // ignore it 167 if (sp_match_array_key(arg_value, config_node->key,
185 // match on arr[foo] -> match only on key foo, if the key is an 168 config_node->r_key)) {
186 // array, match on all keys content 169 return true;
187 if (config_node->param_is_array == true) { 170 }
188 if (true == sp_match_array_key_recurse( 171 } else if (sp_match_array_value(arg_value, config_node->value,
189 arg_value, config_node->param_array_keys, 172 config_node->value_r)) {
190 config_node->value, config_node->value_r)) { 173 return true;
191 return true; 174 }
192 } 175 } else {
193 } else { // match on all keys, but don't go into subarray 176 *arg_value_str = sp_convert_to_string(arg_value);
194 if (true == sp_match_array_key(arg_value, config_node->value, 177 if (sp_match_value(*arg_value_str, config_node->value,
195 config_node->value_r)) { 178 config_node->value_r)) {
196 return true;
197 }
198 }
199 } else {
200 *arg_value_str = sp_convert_to_string(arg_value);
201 if (true == sp_match_value(*arg_value_str, config_node->value,
202 config_node->value_r)) {
203 return true; 179 return true;
204 } 180 }
205 } 181 }
206 } 182 }
207 } 183 }
184 } else if (config_node->param) {
185 *arg_name = config_node->param->value;
186 arg_value = get_value(execute_data, config_node->param, true);
187
188 if (arg_value) {
189 *arg_value_str = sp_convert_to_string(arg_value);
190 if (config_node->param_type) { // Are we matching on the `type`?
191 if (config_node->param_type
192 && config_node->param_type == Z_TYPE_P(arg_value)) {
193 return true;
194 }
195 } else if (Z_TYPE_P(arg_value) == IS_ARRAY) {
196 if (config_node->key || config_node->r_key) {
197 if (sp_match_array_key(arg_value, config_node->key,
198 config_node->r_key)) {
199 return true;
200 }
201 } else if (sp_match_array_value(arg_value, config_node->value,
202 config_node->value_r)) {
203 return true;
204 }
205 } else if (sp_match_value(*arg_value_str, config_node->value,
206 config_node->value_r)) {
207 return true;
208 }
209 }
208 } 210 }
209 return false; 211 return false;
210} 212}
@@ -214,7 +216,7 @@ bool should_disable(zend_execute_data* execute_data, const char* builtin_name,
214 char current_file_hash[SHA256_SIZE * 2 + 1] = {0}; 216 char current_file_hash[SHA256_SIZE * 2 + 1] = {0};
215 const sp_node_t* config = get_config_node(builtin_name); 217 const sp_node_t* config = get_config_node(builtin_name);
216 char* complete_path_function = get_complete_function_path(execute_data); 218 char* complete_path_function = get_complete_function_path(execute_data);
217 char const* client_ip = sp_getenv("REMOTE_ADDR"); 219 char const* client_ip = getenv("REMOTE_ADDR");
218 const char* current_filename; 220 const char* current_filename;
219 221
220 if (!config || !config->data) { 222 if (!config || !config->data) {
diff --git a/src/sp_list.c b/src/sp_list.c
index c671f51..70d0ebe 100644
--- a/src/sp_list.c
+++ b/src/sp_list.c
@@ -17,6 +17,34 @@ sp_node_t *sp_list_new() {
17 return new; 17 return new;
18} 18}
19 19
20// Thanks to https://en.wikipedia.org/wiki/Insertion_sort :>
21sp_node_t *sp_list_sort(sp_node_t *pList, int (*cmp_func)(sp_node_t *, sp_node_t *)) {
22 sp_node_t *head = NULL;
23
24 if (pList == NULL || pList->next == NULL) {
25 return pList;
26 }
27 while (pList != NULL) {
28 sp_node_t *current = pList;
29 pList = pList->next;
30 if (head == NULL || 0 > cmp_func(current, head)) {
31 current->next = head;
32 head = current;
33 } else {
34 sp_node_t *p = head;
35 while (p != NULL) {
36 if (p->next == NULL || 0 > cmp_func(current, p->next)) {
37 current->next = p->next;
38 p->next = current;
39 break;
40 }
41 p = p->next;
42 }
43 }
44 }
45 return head;
46}
47
20void sp_list_insert(sp_node_t *list, void *data) { 48void sp_list_insert(sp_node_t *list, void *data) {
21 if (list->head == NULL) { 49 if (list->head == NULL) {
22 list->data = data; 50 list->data = data;
diff --git a/src/sp_list.h b/src/sp_list.h
index dda139f..7878f78 100644
--- a/src/sp_list.h
+++ b/src/sp_list.h
@@ -9,6 +9,7 @@ typedef struct sp_node_s {
9} sp_node_t; 9} sp_node_t;
10 10
11sp_node_t *sp_list_new(); 11sp_node_t *sp_list_new();
12sp_node_t *sp_list_sort(sp_node_t *, int (*)(sp_node_t *, sp_node_t *));
12void sp_list_insert(sp_node_t *, void *); 13void sp_list_insert(sp_node_t *, void *);
13void sp_list_free(sp_node_t *); 14void sp_list_free(sp_node_t *);
14void sp_list_prepend(sp_node_t *, void *); 15void sp_list_prepend(sp_node_t *, void *);
diff --git a/src/sp_tree.c b/src/sp_tree.c
new file mode 100644
index 0000000..328a919
--- /dev/null
+++ b/src/sp_tree.c
@@ -0,0 +1,20 @@
1#include "php_snuffleupagus.h"
2
3void sp_tree_free(sp_tree *tree) {
4 while (tree) {
5 sp_tree *tmp;
6 pefree(tree->value, 1);
7 sp_tree_free(tree->idx);
8 tmp = tree;
9 tree = tree->next;
10 pefree(tmp, 1);
11 }
12}
13
14sp_tree *sp_tree_new() {
15 sp_tree *new = pecalloc(sizeof(sp_tree), 1, 1);
16 new->next = new->idx = NULL;
17 new->value = NULL;
18 new->type = 0;
19 return new;
20}
diff --git a/src/sp_upload_validation.c b/src/sp_upload_validation.c
index 731a737..0010984 100644
--- a/src/sp_upload_validation.c
+++ b/src/sp_upload_validation.c
@@ -51,7 +51,7 @@ int sp_rfc1867_callback(unsigned int event, void *event_data, void **extra) {
51 cmd[2] = NULL; 51 cmd[2] = NULL;
52 52
53 spprintf(&env[0], 0, "SP_FILENAME=%s", filename); 53 spprintf(&env[0], 0, "SP_FILENAME=%s", filename);
54 spprintf(&env[1], 0, "SP_REMOTE_ADDR=%s", sp_getenv("REMOTE_ADDR")); 54 spprintf(&env[1], 0, "SP_REMOTE_ADDR=%s", getenv("REMOTE_ADDR"));
55 spprintf(&env[2], 0, "SP_CURRENT_FILE=%s", 55 spprintf(&env[2], 0, "SP_CURRENT_FILE=%s",
56 zend_get_executed_filename(TSRMLS_C)); 56 zend_get_executed_filename(TSRMLS_C));
57 spprintf(&env[3], 0, "SP_FILESIZE=%zu", filesize); 57 spprintf(&env[3], 0, "SP_FILESIZE=%zu", filesize);
@@ -77,7 +77,7 @@ int sp_rfc1867_callback(unsigned int event, void *event_data, void **extra) {
77 int waitstatus; 77 int waitstatus;
78 wait(&waitstatus); 78 wait(&waitstatus);
79 if (WEXITSTATUS(waitstatus) != 0) { // Nope 79 if (WEXITSTATUS(waitstatus) != 0) { // Nope
80 char *uri = sp_getenv("REQUEST_URI"); 80 char *uri = getenv("REQUEST_URI");
81 int sim = SNUFFLEUPAGUS_G(config).config_upload_validation->simulation; 81 int sim = SNUFFLEUPAGUS_G(config).config_upload_validation->simulation;
82 sp_log_msg("upload_validation", sim?SP_LOG_SIMULATION:SP_LOG_DROP, 82 sp_log_msg("upload_validation", sim?SP_LOG_SIMULATION:SP_LOG_DROP,
83 "The upload of %s on %s was rejected.", filename, uri?uri:"?"); 83 "The upload of %s on %s was rejected.", filename, uri?uri:"?");
diff --git a/src/sp_utils.c b/src/sp_utils.c
index 1ed770b..3fe2e44 100644
--- a/src/sp_utils.c
+++ b/src/sp_utils.c
@@ -25,20 +25,11 @@ void sp_log_msg(char const *feature, char const *level, const char* fmt, ...) {
25 vspprintf(&msg, 0, fmt, args); 25 vspprintf(&msg, 0, fmt, args);
26 va_end(args); 26 va_end(args);
27 27
28 char const * const client_ip = sp_getenv("REMOTE_ADDR"); 28 char const * const client_ip = getenv("REMOTE_ADDR");
29 _sp_log_err("[snuffleupagus][%s][%s][%s] %s", client_ip?client_ip:"0.0.0.0", 29 _sp_log_err("[snuffleupagus][%s][%s][%s] %s", client_ip?client_ip:"0.0.0.0",
30 feature, level, msg); 30 feature, level, msg);
31} 31}
32 32
33
34zend_always_inline char* sp_getenv(char* var) {
35 if (sapi_module.getenv) {
36 return sapi_module.getenv(ZEND_STRL(var));
37 } else {
38 return getenv(var);
39 }
40}
41
42zend_always_inline int is_regexp_matching(const pcre* regexp, const char* str) { 33zend_always_inline int is_regexp_matching(const pcre* regexp, const char* str) {
43 int vec[30]; 34 int vec[30];
44 int ret = 0; 35 int ret = 0;
@@ -278,63 +269,50 @@ void sp_log_disable_ret(const char* restrict path,
278 } 269 }
279} 270}
280 271
281int sp_match_array_key(const zval* zv, const char* to_match, const pcre* rx) { 272bool sp_match_array_key(const zval* zv, const char* to_match, const pcre* rx) {
282 zend_string* key; 273 zend_string* key;
283 zval* value; 274 zend_ulong idx;
284 char* arg_value_str;
285 275
286 ZEND_HASH_FOREACH_STR_KEY_VAL(Z_ARRVAL_P(zv), key, value) { 276 ZEND_HASH_FOREACH_KEY(Z_ARRVAL_P(zv), idx, key) {
287 if (Z_TYPE_P(value) == IS_ARRAY) { 277 if (key) {
288 continue; 278 if (sp_match_value(ZSTR_VAL(key), to_match, rx)) {
289 } 279 return true;
290 arg_value_str = sp_convert_to_string(value); 280 }
291 if (!sp_match_value(arg_value_str, to_match, rx)) {
292 efree(arg_value_str);
293 continue;
294 } else { 281 } else {
295 efree(arg_value_str); 282 char *idx_str = NULL;
296 return 1; 283
284 // Could use a log.
285 idx_str = emalloc(snprintf(NULL, 0, "%lu", idx));
286 sprintf(idx_str, "%lu", idx);
287 if (sp_match_value(idx_str, to_match, rx)) {
288 efree(idx_str);
289 return true;
290 }
291 efree(idx_str);
297 } 292 }
298 } 293 }
299 ZEND_HASH_FOREACH_END(); 294 ZEND_HASH_FOREACH_END();
300 295 return false;
301 (void)key; // silence a compiler warning
302
303 return 0;
304} 296}
305 297
306int sp_match_array_key_recurse(const zval* arr, sp_node_t* keys, 298bool sp_match_array_value(const zval* arr, const char* to_match, const pcre* rx) {
307 const char* to_match, const pcre* rx) {
308 zend_string* key;
309 zval* value; 299 zval* value;
310 sp_node_t* current = keys; 300
311 if (current == NULL) { 301 ZEND_HASH_FOREACH_VAL(Z_ARRVAL_P(arr), value) {
312 return 0; 302 if (Z_TYPE_P(value) != IS_ARRAY) {
313 } 303 char *value_str = sp_convert_to_string(value);
314 ZEND_HASH_FOREACH_STR_KEY_VAL(Z_ARRVAL_P(arr), key, value) { 304 if (sp_match_value(value_str, to_match, rx)) {
315 if (Z_TYPE_P(value) == IS_ARRAY && !strcmp(ZSTR_VAL(key), current->data)) { 305 efree(value_str);
316 return sp_match_array_key_recurse(value, current->next, to_match, rx); 306 return true;
317 }
318 if (!strcmp(ZSTR_VAL(key), current->data) && current->next == NULL) {
319 if (!to_match && !rx) {
320 return 1;
321 }
322 if (Z_TYPE_P(value) == IS_ARRAY) {
323 return sp_match_array_key(value, to_match, rx);
324 } else { 307 } else {
325 char *value_str = sp_convert_to_string(value); 308 efree (value_str);
326 if (sp_match_value(value_str, to_match, rx)) {
327 efree(value_str);
328 return 1;
329 } else {
330 efree (value_str);
331 return 0;
332 }
333 } 309 }
310 } else if (sp_match_array_value(value, to_match, rx)) {
311 return true;
334 } 312 }
335 } 313 }
336 ZEND_HASH_FOREACH_END(); 314 ZEND_HASH_FOREACH_END();
337 return 0; 315 return false;
338} 316}
339 317
340 318
diff --git a/src/sp_utils.h b/src/sp_utils.h
index a17ac4f..e54f307 100644
--- a/src/sp_utils.h
+++ b/src/sp_utils.h
@@ -57,14 +57,12 @@ void sp_log_msg(char const *feature, char const *level, const char* fmt, ...);
57int compute_hash(const char *const filename, char *file_hash); 57int compute_hash(const char *const filename, char *file_hash);
58char *sp_convert_to_string(zval *); 58char *sp_convert_to_string(zval *);
59bool sp_match_value(const char *, const char *, const pcre *); 59bool sp_match_value(const char *, const char *, const pcre *);
60int sp_match_array_key(const zval *, const char *, const pcre *); 60bool sp_match_array_key(const zval *, const char *, const pcre *);
61int sp_match_array_key_recurse(const zval *, sp_node_t *, const char *, 61bool sp_match_array_value(const zval *, const char *, const pcre *);
62 const pcre *);
63void sp_log_disable(const char *restrict, const char *restrict, 62void sp_log_disable(const char *restrict, const char *restrict,
64 const char *restrict, const sp_disabled_function *); 63 const char *restrict, const sp_disabled_function *);
65void sp_log_disable_ret(const char *restrict, const char *restrict, 64void sp_log_disable_ret(const char *restrict, const char *restrict,
66 const sp_disabled_function *); 65 const sp_disabled_function *);
67char *sp_getenv(char *);
68int is_regexp_matching(const pcre *, const char *); 66int is_regexp_matching(const pcre *, const char *);
69int hook_function(const char *, HashTable *, 67int hook_function(const char *, HashTable *,
70 void (*)(INTERNAL_FUNCTION_PARAMETERS), bool); 68 void (*)(INTERNAL_FUNCTION_PARAMETERS), bool);
diff --git a/src/sp_var_parser.c b/src/sp_var_parser.c
new file mode 100644
index 0000000..bc0a80e
--- /dev/null
+++ b/src/sp_var_parser.c
@@ -0,0 +1,247 @@
1#include "php_snuffleupagus.h"
2
3static int parse_str_tokens(const char *str, const sp_token_t token,
4 sp_node_t *tokens_list) {
5 const char *cur_str = str;
6
7 while ((cur_str = strchr(cur_str, token.token[0]))) {
8 if (0 == strncmp(cur_str, token.token, strlen(token.token))) {
9 sp_token_t *token_elm = pecalloc(sizeof(sp_token_t), 1, 1);
10 token_elm->pos = cur_str - str;
11 token_elm->token = token.token;
12 token_elm->type = token.type;
13 sp_list_insert(tokens_list, token_elm);
14 cur_str += strlen(token.token);
15 } else {
16 cur_str++;
17 }
18 }
19 return 0;
20}
21
22static bool is_var_name_valid(const char *name) {
23 static pcre *regexp_const = NULL;
24 static pcre *regexp_var = NULL;
25 const char *pcre_error;
26 int pcre_error_offset;
27
28 if (!name) {
29 return false;
30 }
31 if (NULL == regexp_var || NULL == regexp_const) {
32 regexp_var = sp_pcre_compile(REGEXP_VAR, PCRE_CASELESS, &pcre_error,
33 &pcre_error_offset, NULL);
34 regexp_const = sp_pcre_compile(REGEXP_CONST, PCRE_CASELESS, &pcre_error,
35 &pcre_error_offset, NULL);
36 }
37 if (NULL == regexp_var || NULL == regexp_const) {
38 sp_log_err("config", "Could not compile regexp.");
39 return false;
40 }
41 if (0 > sp_pcre_exec(regexp_var, NULL, name, strlen(name), 0, 0, NULL, 0)
42 && 0 > sp_pcre_exec(regexp_const, NULL, name, strlen(name), 0, 0, NULL, 0)) {
43 return false;
44 }
45 return true;
46}
47
48static int create_var(sp_tree *tree, const char *restrict value,
49 size_t value_len, elem_type _type, const char *restrict idx) {
50 sp_tree *var_node = NULL;
51
52 if (!tree) {
53 return -1;
54 }
55 if (tree->next == NULL && tree->type == 0) {
56 var_node = tree;
57 } else {
58 var_node = pecalloc(sizeof(sp_tree), 1, 1);
59 }
60
61 var_node->value = NULL;
62 var_node->next = NULL;
63 var_node->idx = NULL;
64 var_node->type = _type;
65 // Check if a constant is a variable
66 if (value && value[0] == VARIABLE_TOKEN && _type == CONSTANT) {
67 var_node->type = VAR;
68 }
69 if (!(var_node->value = pestrndup(value, value_len, 1))) {
70 sp_log_err("config", "Can't allocate a strndup");
71 return -1;
72 }
73 if (var_node->type != STRING_DELIMITER && !is_var_name_valid(var_node->value)) {
74 sp_log_err("config", "Invalid var name: %s.", var_node->value);
75 return -1;
76 }
77 var_node->idx = parse_var(idx);
78
79 if (tree != var_node) {
80 while (tree->next) {
81 tree = tree->next;
82 }
83 tree->next = var_node;
84 }
85 return 0;
86}
87
88int cmp_tokens(sp_node_t *list1, sp_node_t *list2) {
89 return (((sp_token_t *)list1->data)->pos
90 - ((sp_token_t *)list2->data)->pos);
91}
92
93static int is_next_token_empty(sp_token_t *token, sp_token_t *token_next,
94 const char * restrict str) {
95 if ((token_next && token_next->pos == token->pos + strlen(token->token))
96 || (!token_next && token->pos == strlen(str) - strlen(token->token))) {
97 return -1;
98 }
99 return 0;
100}
101
102static int is_token_valid(sp_node_t *tokens_list, elem_type ignore,
103 int array_count, const char * restrict str,
104 size_t pos) {
105 sp_token_t *token = (sp_token_t *)tokens_list->data;
106 sp_token_t *token_next = NULL;
107
108 if (tokens_list->next) {
109 token_next = (sp_token_t *)tokens_list->next->data;
110 }
111 switch (token->type) {
112 case ESC_STRING_DELIMITER:
113 case STRING_DELIMITER:
114 if (ignore == token->type) {
115 if (token_next) {
116 if (token_next->pos != token->pos + 1) {
117 return -1;
118 }
119 } else if (token->pos != strlen(str) - 1) {
120 return -1;
121 }
122 }
123 break;
124 case ARRAY_END:
125 if (!ignore) {
126 if (array_count < 1) {
127 return -1;
128 } else if (token_next) {
129 if (token_next->type == STRING_DELIMITER
130 || token_next->type == ESC_STRING_DELIMITER) {
131 return -1;
132 }
133 } else if (token->pos != strlen(str) - strlen(token->token)) {
134 return -1;
135 }
136 }
137 break;
138 case OBJECT:
139 if (!ignore && -1 == is_next_token_empty(token, token_next, str)) {
140 return -1;
141 }
142 if (pos == 0 && *str != VARIABLE_TOKEN) {
143 return -1;
144 }
145 break;
146 case CLASS:
147 if (!ignore && -1 == is_next_token_empty(token, token_next, str)) {
148 return -1;
149 }
150 break;
151 default:
152 break;
153 }
154 return 0;
155}
156
157static sp_tree *parse_tokens(const char * restrict str,
158 sp_node_t *tokens_list) {
159 size_t pos = 0;
160 int array_count = 0, pos_idx_start = -1;
161 elem_type ignore = 0;
162 sp_tree *tree = sp_tree_new();
163
164 for (; tokens_list && tokens_list->data; tokens_list = tokens_list->next) {
165 sp_token_t *token = (sp_token_t *)tokens_list->data;
166 size_t value_len;
167 char *idx = NULL;
168
169 if (-1 == is_token_valid(tokens_list, ignore, array_count, str, pos)) {
170 sp_log_err("config", "Invalid `%s` position.", token->token);
171 goto error;
172 }
173 if (token->type == STRING_DELIMITER || token->type == ESC_STRING_DELIMITER) {
174 pos = (!ignore && !array_count) ? pos + strlen(token->token) : pos;
175 ignore = (!ignore) ? token->type : (ignore == token->type) ? 0 : ignore;
176 token->type = STRING_DELIMITER;
177 }
178 if (ignore == 0) {
179 if (token->type == ARRAY) {
180 pos_idx_start = (array_count) ? pos_idx_start :
181 (int)(token->pos + strlen(token->token));
182 array_count++;
183 } else if (token->type == ARRAY_END) {
184 array_count--;
185 token->type = ARRAY;
186 }
187 if (array_count == 0) {
188 value_len = token->pos - pos;
189 if (token->type == ARRAY) {
190 value_len -= strlen(token->token);
191 }
192 if (pos_idx_start > 0) {
193 idx = estrndup(&(str[pos_idx_start]), token->pos - pos_idx_start);
194 value_len -= token->pos - pos_idx_start;
195 }
196 if (create_var(tree, &str[pos], value_len, token->type, idx)) {
197 goto error;
198 }
199 efree(idx);
200 pos = token->pos + strlen(token->token);
201 pos_idx_start = -1;
202 }
203 }
204 }
205
206 if (ignore != 0 || array_count != 0) {
207error:
208 sp_tree_free(tree);
209 return NULL;
210 }
211 if (pos != strlen(str)
212 && create_var(tree, &str[pos], strlen(str) - pos, CONSTANT, NULL)) {
213 goto error;
214 }
215 return tree;
216}
217
218sp_tree *parse_var(const char *line) {
219 sp_node_t *tokens_list = NULL;
220 sp_tree *tree = NULL;
221 const sp_token_t delimiter_list[] = {
222 {.type=OBJECT, .token=OBJECT_TOKEN},
223 {.type=ARRAY, .token=ARRAY_TOKEN},
224 {.type=ARRAY_END, .token=ARRAY_END_TOKEN},
225 {.type=STRING_DELIMITER, .token=STRING_TOKEN},
226 {.type=ESC_STRING_DELIMITER, .token=ESC_STRING_TOKEN},
227 {.type=CLASS, .token=CLASS_TOKEN}
228 };
229
230
231 if (!line) {
232 return NULL;
233 }
234 tokens_list = sp_list_new();
235 for (unsigned int i = 0; i < sizeof(delimiter_list) / sizeof(sp_token_t); i++) {
236 parse_str_tokens(line, delimiter_list[i], tokens_list);
237 }
238 tokens_list = sp_list_sort(tokens_list, cmp_tokens);
239 tree = parse_tokens(line, tokens_list);
240 sp_list_free(tokens_list);
241 // Check if tree is empty.
242 if (tree && tree->next == NULL && tree->type == 0) {
243 tree->type = CONSTANT;
244 tree->value = pestrdup("", 1);
245 }
246 return tree;
247}
diff --git a/src/sp_var_parser.h b/src/sp_var_parser.h
new file mode 100644
index 0000000..eec1d06
--- /dev/null
+++ b/src/sp_var_parser.h
@@ -0,0 +1,51 @@
1#ifndef SP_VAR_PARSER_H
2# define SP_VAR_PARSER_H
3# include "php_snuffleupagus.h"
4# include "sp_list.h"
5
6typedef enum {
7 OBJECT = 1,
8 ARRAY,
9 ARRAY_END,
10 STRING_DELIMITER,
11 CLASS,
12 VAR,
13 ESC_STRING_DELIMITER,
14 CONSTANT
15} elem_type;
16
17typedef struct sp_token_s {
18 elem_type type;
19 char *token;
20 unsigned int pos;
21} sp_token_t;
22
23typedef struct parser_s {
24 elem_type type;
25 char *value;
26 struct parser_s *idx;
27 struct parser_s *next;
28} sp_tree;
29
30zval *get_value(zend_execute_data *, const sp_tree *, bool);
31sp_tree *sp_tree_new();
32sp_tree *parse_var(const char *);
33void print_type_list(const char *, sp_tree*, int);
34void sp_tree_free(sp_tree *);
35
36# define OBJECT_TOKEN "->"
37# define ARRAY_TOKEN "["
38# define ARRAY_END_TOKEN "]"
39# define STRING_TOKEN "\""
40# define ESC_STRING_TOKEN "\'"
41# define CLASS_TOKEN "::"
42
43# define VARIABLE_TOKEN '$'
44
45# define PRIVATE_PROP_FMT "%c%s%c%s"
46# define PROTECTED_PROP_FMT "%c*%c%s"
47
48# define REGEXP_VAR "^\\$[a-z_][a-z0-9_]*$"
49# define REGEXP_CONST "^[a-z_0-9\\\\]*$"
50
51#endif
diff --git a/src/sp_var_value.c b/src/sp_var_value.c
new file mode 100644
index 0000000..304ece9
--- /dev/null
+++ b/src/sp_var_value.c
@@ -0,0 +1,226 @@
1#include "php_snuffleupagus.h"
2
3static zval *get_param_var(zend_execute_data *ed, const char *var_name) {
4 unsigned int nb_param = ed->func->common.num_args;
5
6 for (unsigned int i = 0; i < nb_param; i++) {
7 const char *arg_name;
8 if (ZEND_USER_CODE(ed->func->type)) {
9 arg_name = ZSTR_VAL(ed->func->common.arg_info[i].name);
10 } else {
11 arg_name = ed->func->internal_function.arg_info[i].name;
12 }
13 if (0 == strcmp(arg_name, var_name)) {
14 return ZEND_CALL_VAR_NUM(ed, i);
15 }
16 }
17 return NULL;
18}
19
20static zval *get_local_var(zend_execute_data *ed, const char *var_name) {
21 zend_execute_data *orig_execute_data = ed;
22 zend_execute_data *current = ed;
23 zval *value = NULL;
24
25 while (current) {
26 zend_string* key = NULL;
27 EG(current_execute_data) = current;
28 zend_array* symtable = zend_rebuild_symbol_table();
29 ZEND_HASH_FOREACH_STR_KEY_VAL(symtable, key, value) {
30 if (0 == strcmp(var_name, key->val)) {
31 if (Z_TYPE_P(value) == IS_INDIRECT) {
32 value = Z_INDIRECT_P(value);
33 }
34 EG(current_execute_data) = orig_execute_data;
35 return value;
36 }
37 }
38 ZEND_HASH_FOREACH_END();
39 current = current->prev_execute_data;
40 }
41 EG(current_execute_data) = orig_execute_data;
42 return NULL;
43}
44
45static zval *get_constant(const char *value) {
46 zend_string *name = zend_string_init(value, strlen(value), 0);
47 zval *zvalue = zend_get_constant_ex(name, NULL, 0);
48
49 zend_string_release(name);
50 return zvalue;
51}
52
53static zval *get_var_value(zend_execute_data *ed, const char *var_name,
54 bool is_param) {
55 zval *zvalue = NULL;
56
57 if (!var_name) {
58 return NULL;
59 }
60 if (*var_name != VARIABLE_TOKEN) {
61 return get_constant(var_name);
62 } else {
63 var_name++;
64 }
65 if (is_param) {
66 zvalue = get_param_var(ed, var_name);
67 if (!zvalue) {
68 return get_local_var(ed, var_name);
69 }
70 return zvalue;
71 }
72 return get_local_var(ed, var_name);
73}
74
75static void *get_entry_hashtable(const HashTable *ht, const char *entry,
76 size_t entry_len) {
77 zval *zvalue = zend_hash_str_find(ht, entry, entry_len);
78
79 if (!zvalue) {
80 zvalue = zend_hash_index_find(ht, atol(entry));
81 }
82 while (zvalue && (Z_TYPE_P(zvalue) == IS_INDIRECT
83 || Z_TYPE_P(zvalue) == IS_PTR)) {
84 if (Z_TYPE_P(zvalue) == IS_INDIRECT) {
85 zvalue = Z_INDIRECT_P(zvalue);
86 } else {
87 zvalue = Z_PTR_P(zvalue);
88 }
89 }
90 return zvalue;
91}
92
93static zval *get_array_value(zend_execute_data *ed, zval *zvalue,
94 const sp_tree *tree) {
95 zval *idx_value, *ret = NULL;
96 char *idx = NULL;
97
98 idx_value = get_value(ed, tree->idx, false);
99 if (!zvalue || !idx_value) {
100 return NULL;
101 }
102 if (Z_TYPE_P(zvalue) == IS_ARRAY) {
103 idx = sp_convert_to_string(idx_value);
104 ret = get_entry_hashtable(Z_ARRVAL_P(zvalue), idx, strlen(idx));
105 efree(idx);
106 }
107 return ret;
108}
109
110static zval *get_object_property(zend_execute_data *ed, zval *object,
111 const char *property, bool is_param) {
112 char *class_name = object->value.obj->ce->name->val;
113 HashTable *array = Z_OBJPROP_P(object);
114 zval *zvalue = NULL;
115 zval *property_val = get_var_value(ed, property, is_param);
116 size_t len;
117
118 if (property_val) {
119 if (Z_TYPE_P(property_val) != IS_STRING) {
120 return NULL;
121 } else {
122 property = Z_STRVAL_P(property_val);
123 }
124 }
125 zvalue = get_entry_hashtable(array, property, strlen(property));
126 if (!zvalue) {
127 char *protected_property = emalloc(strlen(property) + 4);
128 len = sprintf(protected_property, PROTECTED_PROP_FMT, 0, 0, property);
129 zvalue = get_entry_hashtable(array, protected_property, len);
130 efree(protected_property);
131 }
132 if (!zvalue) {
133 char *private_property = emalloc(strlen(class_name) + 3 + strlen(property));
134 len = sprintf(private_property, PRIVATE_PROP_FMT, 0, class_name, 0, property);
135 zvalue = get_entry_hashtable(array, private_property, len);
136 efree(private_property);
137 }
138 return zvalue;
139}
140
141static zend_class_entry *get_class(const char *value) {
142 zend_string *name;
143 zend_class_entry *ce;
144
145 name = zend_string_init(value, strlen(value), 0);
146 ce = zend_lookup_class(name);
147 zend_string_release(name);
148 return ce;
149}
150
151static zval *get_unknown_type(const char *restrict value, zval *zvalue,
152 zend_class_entry *ce, zend_execute_data *ed,
153 const sp_tree *tree, bool is_param) {
154 if (ce) {
155 zvalue = get_entry_hashtable(&ce->constants_table, value, strlen(value));
156 ce = NULL;
157 } else if (zvalue && Z_TYPE_P(zvalue) == IS_OBJECT && value[0]) {
158 zvalue = get_object_property(ed, zvalue, value, is_param);
159 } else if (!tree->next && !zvalue) {
160 if (tree->type == CONSTANT) {
161 zvalue = get_constant(value);
162 }
163 if (!zvalue) {
164 zvalue = emalloc(sizeof(zval));
165 zvalue->value.str = zend_string_init(value, strlen(value), 0);
166 zvalue->u1.v.type = IS_STRING;
167 }
168 } else {
169 return NULL;
170 }
171 return zvalue;
172}
173
174zval *get_value(zend_execute_data *ed, const sp_tree *tree,
175 bool is_param) {
176 zval *zvalue = NULL;
177 zend_class_entry *ce = NULL;
178
179 while (tree) {
180 switch (tree->type) {
181 case ARRAY:
182 if (ce) {
183 zvalue = get_entry_hashtable(&ce->constants_table, tree->value,
184 strlen(tree->value));
185 ce = NULL;
186 } else if (!zvalue) {
187 zvalue = get_var_value(ed, tree->value, is_param);
188 } else if (Z_TYPE_P(zvalue) == IS_OBJECT) {
189 zvalue = get_object_property(ed, zvalue, tree->value, is_param);
190 }
191 zvalue = get_array_value(ed, zvalue, tree);
192 break;
193 case VAR:
194 if (zvalue && Z_TYPE_P(zvalue) == IS_OBJECT) {
195 zvalue = get_object_property(ed, zvalue, tree->value, is_param);
196 } else {
197 zvalue = get_var_value(ed, tree->value, is_param);
198 }
199 break;
200 case OBJECT:
201 if (!zvalue) {
202 zvalue = get_var_value(ed, tree->value, is_param);
203 } else if (Z_TYPE_P(zvalue) == IS_OBJECT) {
204 if (0 != strlen(tree->value)) {
205 zvalue = get_object_property(ed, zvalue, tree->value, is_param);
206 }
207 } else {
208 return NULL;
209 }
210 break;
211 case CLASS:
212 ce = get_class(tree->value);
213 zvalue = NULL;
214 break;
215 default:
216 zvalue = get_unknown_type(tree->value, zvalue, ce, ed, tree, is_param);
217 ce = NULL;
218 break;
219 }
220 if (!zvalue && !ce) {
221 return NULL;
222 }
223 tree = tree->next;
224 }
225 return zvalue;
226}
diff --git a/src/tests/broken_conf_key_value.phpt b/src/tests/broken_conf_key_value.phpt
new file mode 100644
index 0000000..e9ee4a9
--- /dev/null
+++ b/src/tests/broken_conf_key_value.phpt
@@ -0,0 +1,9 @@
1--TEST--
2Broken configuration
3--SKIPIF--
4<?php if (!extension_loaded("snuffleupagus")) print "skip"; ?>
5--INI--
6sp.configuration_file={PWD}/config/broken_conf_key_value.ini
7--FILE--
8--EXPECT--
9[snuffleupagus][0.0.0.0][config][error] Invalid configuration line: 'sp.disabled_functions.function("system").var("").value("").key("").drop();':`key` and `value` are mutually exclusive on line 1.
diff --git a/src/tests/broken_conf_local_var_1.phpt b/src/tests/broken_conf_local_var_1.phpt
new file mode 100644
index 0000000..a91d275
--- /dev/null
+++ b/src/tests/broken_conf_local_var_1.phpt
@@ -0,0 +1,10 @@
1--TEST--
2Broken configuration
3--SKIPIF--
4<?php if (!extension_loaded("snuffleupagus")) print "skip"; ?>
5--INI--
6sp.configuration_file={PWD}/config/broken_conf_local_var_1.ini
7--FILE--
8--EXPECT--
9[snuffleupagus][0.0.0.0][config][error] Invalid `]` position.
10[snuffleupagus][0.0.0.0][config][error] Invalid value ']' for `var` on line 1.
diff --git a/src/tests/broken_conf_local_var_10.phpt b/src/tests/broken_conf_local_var_10.phpt
new file mode 100644
index 0000000..8a7d9b9
--- /dev/null
+++ b/src/tests/broken_conf_local_var_10.phpt
@@ -0,0 +1,10 @@
1--TEST--
2Broken configuration
3--SKIPIF--
4<?php if (!extension_loaded("snuffleupagus")) print "skip"; ?>
5--INI--
6sp.configuration_file={PWD}/config/broken_conf_local_var_10.ini
7--FILE--
8--EXPECT--
9[snuffleupagus][0.0.0.0][config][error] Invalid `]` position.
10[snuffleupagus][0.0.0.0][config][error] Invalid value 'asd[asd]asd' for `var` on line 1.
diff --git a/src/tests/broken_conf_local_var_11.phpt b/src/tests/broken_conf_local_var_11.phpt
new file mode 100644
index 0000000..1817a3f
--- /dev/null
+++ b/src/tests/broken_conf_local_var_11.phpt
@@ -0,0 +1,10 @@
1--TEST--
2Broken configuration
3--SKIPIF--
4<?php if (!extension_loaded("snuffleupagus")) print "skip"; ?>
5--INI--
6sp.configuration_file={PWD}/config/broken_conf_local_var_11.ini
7--FILE--
8--EXPECT--
9[snuffleupagus][0.0.0.0][config][error] Invalid `::` position.
10[snuffleupagus][0.0.0.0][config][error] Invalid value 'asd::' for `param` on line 1.
diff --git a/src/tests/broken_conf_local_var_12.phpt b/src/tests/broken_conf_local_var_12.phpt
new file mode 100644
index 0000000..0b52e2a
--- /dev/null
+++ b/src/tests/broken_conf_local_var_12.phpt
@@ -0,0 +1,9 @@
1--TEST--
2Broken configuration
3--SKIPIF--
4<?php if (!extension_loaded("snuffleupagus")) print "skip"; ?>
5--INI--
6sp.configuration_file={PWD}/config/broken_conf_local_var_12.ini
7--FILE--
8--EXPECT--
9[snuffleupagus][0.0.0.0][config][error] Empty value in `var` on line 1.
diff --git a/src/tests/broken_conf_local_var_13.phpt b/src/tests/broken_conf_local_var_13.phpt
new file mode 100644
index 0000000..ca6be6d
--- /dev/null
+++ b/src/tests/broken_conf_local_var_13.phpt
@@ -0,0 +1,10 @@
1--TEST--
2Broken configuration
3--SKIPIF--
4<?php if (!extension_loaded("snuffleupagus")) print "skip"; ?>
5--INI--
6sp.configuration_file={PWD}/config/broken_conf_local_var_13.ini
7--FILE--
8--EXPECT--
9[snuffleupagus][0.0.0.0][config][error] Invalid `->` position.
10[snuffleupagus][0.0.0.0][config][error] Invalid value 'asd->asd' for `var` on line 1.
diff --git a/src/tests/broken_conf_local_var_14.phpt b/src/tests/broken_conf_local_var_14.phpt
new file mode 100644
index 0000000..cb7e455
--- /dev/null
+++ b/src/tests/broken_conf_local_var_14.phpt
@@ -0,0 +1,10 @@
1--TEST--
2Broken configuration
3--SKIPIF--
4<?php if (!extension_loaded("snuffleupagus")) print "skip"; ?>
5--INI--
6sp.configuration_file={PWD}/config/broken_conf_local_var_14.ini
7--FILE--
8--EXPECT--
9[snuffleupagus][0.0.0.0][config][error] Invalid var name: $i+valid var name .
10[snuffleupagus][0.0.0.0][config][error] Invalid value '$i+valid var name ' for `var` on line 1.
diff --git a/src/tests/broken_conf_local_var_2.phpt b/src/tests/broken_conf_local_var_2.phpt
new file mode 100644
index 0000000..b67a492
--- /dev/null
+++ b/src/tests/broken_conf_local_var_2.phpt
@@ -0,0 +1,10 @@
1--TEST--
2Broken configuration
3--SKIPIF--
4<?php if (!extension_loaded("snuffleupagus")) print "skip"; ?>
5--INI--
6sp.configuration_file={PWD}/config/broken_conf_local_var_2.ini
7--FILE--
8--EXPECT--
9[snuffleupagus][0.0.0.0][config][error] Invalid `"` position.
10[snuffleupagus][0.0.0.0][config][error] Invalid value '""asd' for `var` on line 1.
diff --git a/src/tests/broken_conf_local_var_3.phpt b/src/tests/broken_conf_local_var_3.phpt
new file mode 100644
index 0000000..639d2ea
--- /dev/null
+++ b/src/tests/broken_conf_local_var_3.phpt
@@ -0,0 +1,10 @@
1--TEST--
2Broken configuration
3--SKIPIF--
4<?php if (!extension_loaded("snuffleupagus")) print "skip"; ?>
5--INI--
6sp.configuration_file={PWD}/config/broken_conf_local_var_3.ini
7--FILE--
8--EXPECT--
9[snuffleupagus][0.0.0.0][config][error] Invalid `->` position.
10[snuffleupagus][0.0.0.0][config][error] Invalid value '$qwe->::' for `var` on line 1.
diff --git a/src/tests/broken_conf_local_var_4.phpt b/src/tests/broken_conf_local_var_4.phpt
new file mode 100644
index 0000000..e50f9a6
--- /dev/null
+++ b/src/tests/broken_conf_local_var_4.phpt
@@ -0,0 +1,10 @@
1--TEST--
2Broken configuration
3--SKIPIF--
4<?php if (!extension_loaded("snuffleupagus")) print "skip"; ?>
5--INI--
6sp.configuration_file={PWD}/config/broken_conf_local_var_4.ini
7--FILE--
8--EXPECT--
9[snuffleupagus][0.0.0.0][config][error] Invalid `"` position.
10[snuffleupagus][0.0.0.0][config][error] Invalid value '"asd"asd[]' for `var` on line 1.
diff --git a/src/tests/broken_conf_local_var_5.phpt b/src/tests/broken_conf_local_var_5.phpt
new file mode 100644
index 0000000..0c0d59a
--- /dev/null
+++ b/src/tests/broken_conf_local_var_5.phpt
@@ -0,0 +1,10 @@
1--TEST--
2Broken configuration
3--SKIPIF--
4<?php if (!extension_loaded("snuffleupagus")) print "skip"; ?>
5--INI--
6sp.configuration_file={PWD}/config/broken_conf_local_var_5.ini
7--FILE--
8--EXPECT--
9[snuffleupagus][0.0.0.0][config][error] Invalid `'` position.
10[snuffleupagus][0.0.0.0][config][error] Invalid value ''asd'asd[]' for `var` on line 1.
diff --git a/src/tests/broken_conf_local_var_6.phpt b/src/tests/broken_conf_local_var_6.phpt
new file mode 100644
index 0000000..c51de24
--- /dev/null
+++ b/src/tests/broken_conf_local_var_6.phpt
@@ -0,0 +1,10 @@
1--TEST--
2Broken configuration
3--SKIPIF--
4<?php if (!extension_loaded("snuffleupagus")) print "skip"; ?>
5--INI--
6sp.configuration_file={PWD}/config/broken_conf_local_var_6.ini
7--FILE--
8--EXPECT--
9[snuffleupagus][0.0.0.0][config][error] Invalid `'` position.
10[snuffleupagus][0.0.0.0][config][error] Invalid value '''asd' for `var` on line 1.
diff --git a/src/tests/broken_conf_local_var_7.phpt b/src/tests/broken_conf_local_var_7.phpt
new file mode 100644
index 0000000..d3a0fa4
--- /dev/null
+++ b/src/tests/broken_conf_local_var_7.phpt
@@ -0,0 +1,10 @@
1--TEST--
2Broken configuration
3--SKIPIF--
4<?php if (!extension_loaded("snuffleupagus")) print "skip"; ?>
5--INI--
6sp.configuration_file={PWD}/config/broken_conf_local_var_7.ini
7--FILE--
8--EXPECT--
9[snuffleupagus][0.0.0.0][config][error] Invalid `->` position.
10[snuffleupagus][0.0.0.0][config][error] Invalid value 'asd-->' for `var` on line 1.
diff --git a/src/tests/broken_conf_local_var_8.phpt b/src/tests/broken_conf_local_var_8.phpt
new file mode 100644
index 0000000..749a1aa
--- /dev/null
+++ b/src/tests/broken_conf_local_var_8.phpt
@@ -0,0 +1,10 @@
1--TEST--
2Broken configuration
3--SKIPIF--
4<?php if (!extension_loaded("snuffleupagus")) print "skip"; ?>
5--INI--
6sp.configuration_file={PWD}/config/broken_conf_local_var_8.ini
7--FILE--
8--EXPECT--
9[snuffleupagus][0.0.0.0][config][error] Invalid `]` position.
10[snuffleupagus][0.0.0.0][config][error] Invalid value 'asd[asd]"asd"' for `var` on line 1.
diff --git a/src/tests/broken_conf_local_var_9.phpt b/src/tests/broken_conf_local_var_9.phpt
new file mode 100644
index 0000000..6f706db
--- /dev/null
+++ b/src/tests/broken_conf_local_var_9.phpt
@@ -0,0 +1,10 @@
1--TEST--
2Broken configuration
3--SKIPIF--
4<?php if (!extension_loaded("snuffleupagus")) print "skip"; ?>
5--INI--
6sp.configuration_file={PWD}/config/broken_conf_local_var_9.ini
7--FILE--
8--EXPECT--
9[snuffleupagus][0.0.0.0][config][error] Invalid `]` position.
10[snuffleupagus][0.0.0.0][config][error] Invalid value 'asd[asd]'asd'' for `var` on line 1.
diff --git a/src/tests/config/broken_conf_key_value.ini b/src/tests/config/broken_conf_key_value.ini
new file mode 100644
index 0000000..a0edaf2
--- /dev/null
+++ b/src/tests/config/broken_conf_key_value.ini
@@ -0,0 +1 @@
sp.disable_function.function("system").var("").value("").key("").drop();
diff --git a/src/tests/config/broken_conf_local_var_1.ini b/src/tests/config/broken_conf_local_var_1.ini
new file mode 100644
index 0000000..ae5165c
--- /dev/null
+++ b/src/tests/config/broken_conf_local_var_1.ini
@@ -0,0 +1 @@
sp.disable_function.function("system").var("]").drop();
diff --git a/src/tests/config/broken_conf_local_var_10.ini b/src/tests/config/broken_conf_local_var_10.ini
new file mode 100644
index 0000000..93dd07f
--- /dev/null
+++ b/src/tests/config/broken_conf_local_var_10.ini
@@ -0,0 +1 @@
sp.disable_function.function("system").var("asd[asd]asd").drop();
diff --git a/src/tests/config/broken_conf_local_var_11.ini b/src/tests/config/broken_conf_local_var_11.ini
new file mode 100644
index 0000000..028b1bd
--- /dev/null
+++ b/src/tests/config/broken_conf_local_var_11.ini
@@ -0,0 +1 @@
sp.disable_function.function("system").param("asd::").drop();
diff --git a/src/tests/config/broken_conf_local_var_12.ini b/src/tests/config/broken_conf_local_var_12.ini
new file mode 100644
index 0000000..a151960
--- /dev/null
+++ b/src/tests/config/broken_conf_local_var_12.ini
@@ -0,0 +1 @@
sp.disable_function.function("system").var("").drop();
diff --git a/src/tests/config/broken_conf_local_var_13.ini b/src/tests/config/broken_conf_local_var_13.ini
new file mode 100644
index 0000000..e7c9778
--- /dev/null
+++ b/src/tests/config/broken_conf_local_var_13.ini
@@ -0,0 +1 @@
sp.disable_function.function("system").var("asd->asd").drop();
diff --git a/src/tests/config/broken_conf_local_var_14.ini b/src/tests/config/broken_conf_local_var_14.ini
new file mode 100644
index 0000000..6c98ec3
--- /dev/null
+++ b/src/tests/config/broken_conf_local_var_14.ini
@@ -0,0 +1 @@
sp.disable_function.function("system").var("$i+valid var name ").drop();
diff --git a/src/tests/config/broken_conf_local_var_2.ini b/src/tests/config/broken_conf_local_var_2.ini
new file mode 100644
index 0000000..145a3b5
--- /dev/null
+++ b/src/tests/config/broken_conf_local_var_2.ini
@@ -0,0 +1 @@
sp.disable_function.function("system").var("\"\"asd").drop();
diff --git a/src/tests/config/broken_conf_local_var_3.ini b/src/tests/config/broken_conf_local_var_3.ini
new file mode 100644
index 0000000..5d89076
--- /dev/null
+++ b/src/tests/config/broken_conf_local_var_3.ini
@@ -0,0 +1 @@
sp.disable_function.function("system").var("\$qwe->::").drop();
diff --git a/src/tests/config/broken_conf_local_var_4.ini b/src/tests/config/broken_conf_local_var_4.ini
new file mode 100644
index 0000000..3ec073b
--- /dev/null
+++ b/src/tests/config/broken_conf_local_var_4.ini
@@ -0,0 +1 @@
sp.disable_function.function("system").var("\"asd\"asd[]").drop();
diff --git a/src/tests/config/broken_conf_local_var_5.ini b/src/tests/config/broken_conf_local_var_5.ini
new file mode 100644
index 0000000..cd350b6
--- /dev/null
+++ b/src/tests/config/broken_conf_local_var_5.ini
@@ -0,0 +1 @@
sp.disable_function.function("system").var("'asd'asd[]").drop();
diff --git a/src/tests/config/broken_conf_local_var_6.ini b/src/tests/config/broken_conf_local_var_6.ini
new file mode 100644
index 0000000..02f4f1a
--- /dev/null
+++ b/src/tests/config/broken_conf_local_var_6.ini
@@ -0,0 +1 @@
sp.disable_function.function("system").var("''asd").drop();
diff --git a/src/tests/config/broken_conf_local_var_7.ini b/src/tests/config/broken_conf_local_var_7.ini
new file mode 100644
index 0000000..abbd223
--- /dev/null
+++ b/src/tests/config/broken_conf_local_var_7.ini
@@ -0,0 +1 @@
sp.disable_function.function("system").var("asd-->").drop();
diff --git a/src/tests/config/broken_conf_local_var_8.ini b/src/tests/config/broken_conf_local_var_8.ini
new file mode 100644
index 0000000..fd18487
--- /dev/null
+++ b/src/tests/config/broken_conf_local_var_8.ini
@@ -0,0 +1 @@
sp.disable_function.function("system").var("asd[asd]\"asd\"").drop();
diff --git a/src/tests/config/broken_conf_local_var_9.ini b/src/tests/config/broken_conf_local_var_9.ini
new file mode 100644
index 0000000..a311b86
--- /dev/null
+++ b/src/tests/config/broken_conf_local_var_9.ini
@@ -0,0 +1 @@
sp.disable_function.function("system").var("asd[asd]\'asd\'").drop();
diff --git a/src/tests/config/config_disabled_functions_local_var_array.ini b/src/tests/config/config_disabled_functions_local_var_array.ini
new file mode 100644
index 0000000..15dd5a1
--- /dev/null
+++ b/src/tests/config/config_disabled_functions_local_var_array.ini
@@ -0,0 +1 @@
sp.disable_function.function("foo").var("$a[test2][foo]").value("aaa").drop();
diff --git a/src/tests/config/config_disabled_functions_local_var_array_key.ini b/src/tests/config/config_disabled_functions_local_var_array_key.ini
new file mode 100644
index 0000000..75c840d
--- /dev/null
+++ b/src/tests/config/config_disabled_functions_local_var_array_key.ini
@@ -0,0 +1 @@
sp.disable_function.function("foo").var("$a[test2][foo]").key("aaa").drop();
diff --git a/src/tests/config/config_disabled_functions_name_type.ini b/src/tests/config/config_disabled_functions_name_type.ini
index 25bdf98..c25b92c 100644
--- a/src/tests/config/config_disabled_functions_name_type.ini
+++ b/src/tests/config/config_disabled_functions_name_type.ini
@@ -1 +1 @@
sp.disable_function.function_r("^strcmp$").param("str1").param_type("array").drop(); sp.disable_function.function_r("^strcmp$").param("$str1").param_type("array").drop();
diff --git a/src/tests/config/config_disabled_functions_nul_byte.ini b/src/tests/config/config_disabled_functions_nul_byte.ini
index d5eb847..e664cba 100644
--- a/src/tests/config/config_disabled_functions_nul_byte.ini
+++ b/src/tests/config/config_disabled_functions_nul_byte.ini
@@ -1 +1 @@
sp.disable_function.function("system").param("command").value_r("id").drop(); \ No newline at end of file sp.disable_function.function("system").param("$command").value_r("id").drop();
diff --git a/src/tests/config/config_disabled_functions_param.ini b/src/tests/config/config_disabled_functions_param.ini
index 87f1b3c..dc1c949 100644
--- a/src/tests/config/config_disabled_functions_param.ini
+++ b/src/tests/config/config_disabled_functions_param.ini
@@ -1,6 +1,6 @@
1sp.disable_function.function("system").param("command").value_r("^id$").alias("1").drop(); 1sp.disable_function.function("system").param("$command").value_r("^id$").alias("1").drop();
2sp.disable_function.function("array_sum").param("array").value_r("^8$").alias("2").drop(); 2sp.disable_function.function("array_sum").param("$array").value_r("^8$").alias("2").drop();
3sp.disable_function.function("shell_exec").param("cmd").value("id").alias("3").drop(); 3sp.disable_function.function("shell_exec").param("$cmd").value("id").alias("3").drop();
4sp.disable_function.function("shell_exec").param("cmd").value("bla").alias("4").drop(); 4sp.disable_function.function("shell_exec").param("$cmd").value("bla").alias("4").drop();
5sp.disable_function.function("strcmp").param("str1").value("bla").alias("5").drop().simulation(); 5sp.disable_function.function("strcmp").param("$str1").value("bla").alias("5").drop().simulation();
6sp.disable_function.function("strncmp").param("str1").value("bla").drop().simulation(); 6sp.disable_function.function("strncmp").param("$str1").value("bla").drop().simulation();
diff --git a/src/tests/config/config_disabled_functions_param_allow.ini b/src/tests/config/config_disabled_functions_param_allow.ini
index 8e139e4..27d919a 100644
--- a/src/tests/config/config_disabled_functions_param_allow.ini
+++ b/src/tests/config/config_disabled_functions_param_allow.ini
@@ -1,3 +1,3 @@
1sp.disable_function.function("system").param("command").value("echo win").filename("/test.php").drop(); 1sp.disable_function.function("system").param("$command").value("echo win").filename("/test.php").drop();
2sp.disable_function.function("system").param("command").value("echo win").allow(); 2sp.disable_function.function("system").param("$command").value("echo win").allow();
3sp.disable_function.function("system").drop(); 3sp.disable_function.function("system").drop();
diff --git a/src/tests/config/config_disabled_functions_param_array.ini b/src/tests/config/config_disabled_functions_param_array.ini
index 0589ad8..6fe0615 100644
--- a/src/tests/config/config_disabled_functions_param_array.ini
+++ b/src/tests/config/config_disabled_functions_param_array.ini
@@ -1,4 +1,7 @@
1sp.disable_function.function("foo").param("arr").value("abcd").alias("1").drop(); 1sp.disable_function.function("foo").param("$arr[a]").value("abcd").alias("1").drop();
2sp.disable_function.function("foo").param("arr[bla]").value("abcdef").alias("2").drop(); 2sp.disable_function.function("foo").param("$arr[bla]").value("abcdef").alias("2").drop();
3sp.disable_function.function("foo").param("arr[test]").alias("3").drop(); 3sp.disable_function.function("foo").param("$arr[test]").alias("3").drop();
4sp.disable_function.function("foo").param("arr[test2][foo][lol]").value("aaa").alias("4").drop(); 4sp.disable_function.function("foo").param("$arr[test2][foo]").value("aaa").alias("4").drop();
5sp.disable_function.function("foo").param("$arr[test2][bar]").key("lol").alias("5").drop();
6sp.disable_function.function("foo").param("$arr[test2][bar]").key("123").alias("6").drop();
7sp.disable_function.function("foo").param("$qwe[a]").value("abcd").alias("7").drop();
diff --git a/src/tests/config/config_disabled_functions_param_int.ini b/src/tests/config/config_disabled_functions_param_int.ini
index 1c93c2f..2a7d962 100644
--- a/src/tests/config/config_disabled_functions_param_int.ini
+++ b/src/tests/config/config_disabled_functions_param_int.ini
@@ -1,2 +1,2 @@
1sp.disable_function.function("foobar").param("id").value("42").drop(); 1sp.disable_function.function("foobar").param("$id").value("42").drop();
2sp.disable_function.function("foobar").param("id").value_r("^1337").drop(); 2sp.disable_function.function("foobar").param("$id").value_r("^1337").drop();
diff --git a/src/tests/config/config_disabled_functions_param_r_array.ini b/src/tests/config/config_disabled_functions_param_r_array.ini
new file mode 100644
index 0000000..fcac71d
--- /dev/null
+++ b/src/tests/config/config_disabled_functions_param_r_array.ini
@@ -0,0 +1,2 @@
1sp.disable_function.function("foo").param_r("arr").value("abcd").alias("1").drop();
2sp.disable_function.function("foo").param_r("arr").key_r("abc").alias("2").drop();
diff --git a/src/tests/config/config_disabled_functions_param_runtime.ini b/src/tests/config/config_disabled_functions_param_runtime.ini
index e7a011f..e9d44a2 100644
--- a/src/tests/config/config_disabled_functions_param_runtime.ini
+++ b/src/tests/config/config_disabled_functions_param_runtime.ini
@@ -1 +1 @@
sp.disable_function.function("test").param("param").value_r("1337").drop(); sp.disable_function.function("test").param("$param").value_r("1337").drop();
diff --git a/src/tests/config/disabled_function_local_var.ini b/src/tests/config/disabled_function_local_var.ini
index cba2ae3..3d553c0 100644
--- a/src/tests/config/disabled_function_local_var.ini
+++ b/src/tests/config/disabled_function_local_var.ini
@@ -1,2 +1,10 @@
1sp.disable_function.function("phpinfo").var("b").value("1337").drop(); 1sp.disable_function.function("phpinfo").var("$b").value("1337").drop();
2sp.disable_function.function("strlen").var("a").value("1337").drop(); 2sp.disable_function.function("strlen").var("$a").value("1337").drop();
3sp.disable_function.function("strlen").var("$a['123']").value("block").drop();
4sp.disable_function.function("strlen").var("$a[$c]->prop").value("block").drop();
5sp.disable_function.function("strlen").var("$a->zxc").value("not a good value").drop();
6sp.disable_function.function("strlen").var("\\asd\\test_object::TEST_VALUE['constant']").value("no good").drop();
7sp.disable_function.function("strlen").var("\\asd\\test_object::TEST_VALUE").value("qwerty").drop();
8sp.disable_function.function("strlen").var("\\qwe\\ASD").value("qwerty").drop();
9sp.disable_function.function("strlen").var("\\qwe\\QWE['123']").value("asdfgh").drop();
10sp.disable_function.function("strlen").var("$qwe").value("block this").drop();
diff --git a/src/tests/config/disabled_function_local_var_2.ini b/src/tests/config/disabled_function_local_var_2.ini
new file mode 100644
index 0000000..e3e9ae6
--- /dev/null
+++ b/src/tests/config/disabled_function_local_var_2.ini
@@ -0,0 +1 @@
sp.disable_function.function("strlen").var("$b['_GET[obj->nop]'][$b[456][$d->$idk->qwe[\\qwe\\UNE_CONSTANTE]]][$a]->uio").value("valeur de apres").drop();
diff --git a/src/tests/config/disabled_function_local_var_obj.ini b/src/tests/config/disabled_function_local_var_obj.ini
new file mode 100644
index 0000000..df6b617
--- /dev/null
+++ b/src/tests/config/disabled_function_local_var_obj.ini
@@ -0,0 +1,3 @@
1sp.disable_function.function("strlen").var("$test->$test_array").value("value").drop();
2sp.disable_function.function("strlen").var("$arg->$test_array").value("value").drop();
3sp.disable_function.function("strlen").var("$test->$arg").value("nop_object").drop();
diff --git a/src/tests/config/disabled_function_super_global_var.ini b/src/tests/config/disabled_function_super_global_var.ini
index feac314..178a01a 100644
--- a/src/tests/config/disabled_function_super_global_var.ini
+++ b/src/tests/config/disabled_function_super_global_var.ini
@@ -1 +1 @@
sp.disable_function.function("strlen").var("_GET[bla]").value("test2").drop(); sp.disable_function.function("strlen").var("$_GET[bla]").value("test2").drop();
diff --git a/src/tests/config/disabled_functions_pos.ini b/src/tests/config/disabled_functions_pos.ini
index e7d12a9..2b4650d 100644
--- a/src/tests/config/disabled_functions_pos.ini
+++ b/src/tests/config/disabled_functions_pos.ini
@@ -1,2 +1,3 @@
1sp.disable_function.function("system").pos("1337").value("id").drop(); 1sp.disable_function.function("system").pos("1337").value("id").drop();
2sp.disable_function.function("system").pos("0").value("id").drop(); 2sp.disable_function.function("system").pos("0").value("id").drop();
3sp.disable_function.function("system").pos("1").param_type("ARRAY").alias("1").drop();
diff --git a/src/tests/disabled_function_local_var_10.phpt b/src/tests/disabled_function_local_var_10.phpt
new file mode 100644
index 0000000..538d693
--- /dev/null
+++ b/src/tests/disabled_function_local_var_10.phpt
@@ -0,0 +1,44 @@
1--TEST--
2Disable functions - match on a local variable
3--SKIPIF--
4<?php if (!extension_loaded("snuffleupagus")) die "skip"; ?>
5--INI--
6sp.configuration_file={PWD}/config/disabled_function_local_var.ini
7--FILE--
8<?php
9$qwe = Array('123' => Array('qwe'), '456' => Array('no block this'));
10var_dump($qwe);
11strlen("qwe");
12$qwe = Array('123' => Array('qwe'), '456' => Array(Array('block this')));
13var_dump($qwe);
14strlen("qwe");
15?>
16--EXPECTF--
17array(2) {
18 [123]=>
19 array(1) {
20 [0]=>
21 string(3) "qwe"
22 }
23 [456]=>
24 array(1) {
25 [0]=>
26 string(13) "no block this"
27 }
28}
29array(2) {
30 [123]=>
31 array(1) {
32 [0]=>
33 string(3) "qwe"
34 }
35 [456]=>
36 array(1) {
37 [0]=>
38 array(1) {
39 [0]=>
40 string(10) "block this"
41 }
42 }
43}
44[snuffleupagus][0.0.0.0][disabled_function][drop] The call to the function 'strlen' in %a/tests/disabled_function_local_var_10.php:%d has been disabled.
diff --git a/src/tests/disabled_function_local_var_2.phpt b/src/tests/disabled_function_local_var_2.phpt
new file mode 100644
index 0000000..da0a3d2
--- /dev/null
+++ b/src/tests/disabled_function_local_var_2.phpt
@@ -0,0 +1,46 @@
1--TEST--
2Disable functions - match on a local variable
3--SKIPIF--
4<?php if (!extension_loaded("snuffleupagus")) die "skip"; ?>
5--INI--
6sp.configuration_file={PWD}/config/disabled_function_local_var.ini
7--FILE--
8<?php
9$a = 1338;
10function test(){
11 echo strlen("id") . "\n";
12}
13echo "Value of a: $a\n";
14test();
15
16$a = Array();
17$a['qwe'] = 'block';
18$a['123'] = 'nop';
19echo "Value of a:\n";
20var_dump($a);
21test();
22
23$a['123'] = 'block';
24echo "Value of a:\n";
25var_dump($a);
26test();
27?>
28--EXPECTF--
29Value of a: 1338
302
31Value of a:
32array(2) {
33 ["qwe"]=>
34 string(5) "block"
35 [123]=>
36 string(3) "nop"
37}
382
39Value of a:
40array(2) {
41 ["qwe"]=>
42 string(5) "block"
43 [123]=>
44 string(5) "block"
45}
46[snuffleupagus][0.0.0.0][disabled_function][drop] The call to the function 'strlen' in %a/tests/disabled_function_local_var_2.php:%d has been disabled.
diff --git a/src/tests/disabled_function_local_var_3.phpt b/src/tests/disabled_function_local_var_3.phpt
new file mode 100644
index 0000000..d26b636
--- /dev/null
+++ b/src/tests/disabled_function_local_var_3.phpt
@@ -0,0 +1,45 @@
1--TEST--
2Disable functions - match on a local variable
3--SKIPIF--
4<?php if (!extension_loaded("snuffleupagus")) die "skip"; ?>
5--INI--
6sp.configuration_file={PWD}/config/disabled_function_local_var.ini
7--FILE--
8<?php
9function test(){
10 echo strlen("id") . "\n";
11}
12
13$a = Array();
14$c = '123';
15$a['qwe'] = 'qwe';
16$a['123'] = 'nop';
17echo "Value of a:\n";
18var_dump($a);
19test();
20
21$a[$c] = (Object)['prop' => 'block'];
22echo "Value of a:\n";
23var_dump($a);
24test();
25?>
26--EXPECTF--
27Value of a:
28array(2) {
29 ["qwe"]=>
30 string(3) "qwe"
31 [123]=>
32 string(3) "nop"
33}
342
35Value of a:
36array(2) {
37 ["qwe"]=>
38 string(3) "qwe"
39 [123]=>
40 object(stdClass)#1 (1) {
41 ["prop"]=>
42 string(5) "block"
43 }
44}
45[snuffleupagus][0.0.0.0][disabled_function][drop] The call to the function 'strlen' in %a/tests/disabled_function_local_var_3.php:%d has been disabled.
diff --git a/src/tests/disabled_function_local_var_4.phpt b/src/tests/disabled_function_local_var_4.phpt
new file mode 100644
index 0000000..ae8d713
--- /dev/null
+++ b/src/tests/disabled_function_local_var_4.phpt
@@ -0,0 +1,56 @@
1--TEST--
2Disable functions - match on a local variable
3--SKIPIF--
4<?php if (!extension_loaded("snuffleupagus")) die "skip"; ?>
5--INI--
6sp.configuration_file={PWD}/config/disabled_function_local_var_2.ini
7--FILE--
8<?php
9namespace qwe {
10 const UNE_CONSTANTE = 'constant';
11}
12namespace asd {
13$b = Array();
14$b['_GET[obj->nop]'] = Array();
15$b['_GET[obj->nop]']["qwe"] = Array();
16$b[456] = Array();
17$b[456]['zxc'] = "qwe";
18$b[456]['nop'] = "nop";
19$b['_GET[obj->nop]']["qwe"][321] = "Yeay";
20$b["123"] = "qwe";
21$b["123a"] = "foo";
22$b["asd"] = "zxc";
23$b['_GET[obj->nop]']["qwe"][1337] = (Object)(['uio' => "valeur de apres"]);
24$b['_GET[obj->nop]']["qwe"][1338] = (Object)(['uio' => "valeur de a"]);
25$c = (Object)(['qwe' => Array(\qwe\UNE_CONSTANTE => 'zxc')]);
26$idk = 'test_asd';
27$class_name = 'test_object';
28class test_object {
29 const TEST_VALUE = ['constant' => 'truc'];
30 private $asd = "qwe";
31 public $qwe = 'bar';
32 private $test_asd = '';
33 function __construct($asd) {
34 $this->test_asd = $asd;
35 }
36 function do_a_barell_roll() {
37 var_dump($this->test_asd);
38 }
39}
40$d = new test_object($c);
41$a = 1338;
42function test(){
43 strlen("qwe");
44}
45echo "Valeur: " . $b['_GET[obj->nop]']["qwe"][$a]->uio . "\n";
46test();
47
48$a = 1337;
49echo "Valeur: " . $b['_GET[obj->nop]']["qwe"][$a]->uio . "\n";
50test();
51}
52?>
53--EXPECTF--
54Valeur: valeur de a
55Valeur: valeur de apres
56[snuffleupagus][0.0.0.0][disabled_function][drop] The call to the function 'strlen' in %a/tests/disabled_function_local_var_4.php:%d has been disabled.
diff --git a/src/tests/disabled_function_local_var_5.phpt b/src/tests/disabled_function_local_var_5.phpt
new file mode 100644
index 0000000..d82574d
--- /dev/null
+++ b/src/tests/disabled_function_local_var_5.phpt
@@ -0,0 +1,33 @@
1--TEST--
2Disable functions - match on a local variable
3--SKIPIF--
4<?php if (!extension_loaded("snuffleupagus")) die "skip"; ?>
5--INI--
6sp.configuration_file={PWD}/config/disabled_function_local_var.ini
7--FILE--
8<?php
9function test(){
10 echo strlen("id") . "\n";
11}
12
13$a = Array();
14echo "Value of a:\n";
15var_dump($a);
16test();
17
18$a = (Object)['zxc' => 'not a good value'];
19echo "Value of a:\n";
20var_dump($a);
21test();
22?>
23--EXPECTF--
24Value of a:
25array(0) {
26}
272
28Value of a:
29object(stdClass)#1 (1) {
30 ["zxc"]=>
31 string(16) "not a good value"
32}
33[snuffleupagus][0.0.0.0][disabled_function][drop] The call to the function 'strlen' in %a/tests/disabled_function_local_var_5.php:%d has been disabled.
diff --git a/src/tests/disabled_function_local_var_6.phpt b/src/tests/disabled_function_local_var_6.phpt
new file mode 100644
index 0000000..90c1815
--- /dev/null
+++ b/src/tests/disabled_function_local_var_6.phpt
@@ -0,0 +1,31 @@
1--TEST--
2Disable functions - match on a local variable
3--SKIPIF--
4<?php if (!extension_loaded("snuffleupagus")) die "skip"; ?>
5--INI--
6sp.configuration_file={PWD}/config/disabled_function_local_var.ini
7--FILE--
8<?php
9namespace asd {
10function test(){
11 strlen("qwe");
12}
13echo "Valeur: " . \asd\test_object::TEST_VALUE['constant'] . "\n";
14test();
15class test_object {
16 const TEST_VALUE = ['constant' => 'no good'];
17 private $asd = "qwe";
18 public $qwe = 'bar';
19 private $test_asd = '';
20 function __construct($asd) {
21 $this->test_asd = $asd;
22 }
23 function do_a_barell_roll() {
24 var_dump($this->test_asd);
25 }
26}
27}
28?>
29--EXPECTF--
30Valeur: no good
31[snuffleupagus][0.0.0.0][disabled_function][drop] The call to the function 'strlen' in %a/tests/disabled_function_local_var_6.php:%d has been disabled.
diff --git a/src/tests/disabled_function_local_var_7.phpt b/src/tests/disabled_function_local_var_7.phpt
new file mode 100644
index 0000000..7ab249a
--- /dev/null
+++ b/src/tests/disabled_function_local_var_7.phpt
@@ -0,0 +1,31 @@
1--TEST--
2Disable functions - match on a local variable
3--SKIPIF--
4<?php if (!extension_loaded("snuffleupagus")) die "skip"; ?>
5--INI--
6sp.configuration_file={PWD}/config/disabled_function_local_var.ini
7--FILE--
8<?php
9namespace asd {
10function test(){
11 strlen("qwe");
12}
13echo "Valeur: " . \asd\test_object::TEST_VALUE . "\n";
14test();
15class test_object {
16 const TEST_VALUE = "qwerty";
17 private $asd = "qwe";
18 public $qwe = 'bar';
19 private $test_asd = '';
20 function __construct($asd) {
21 $this->test_asd = $asd;
22 }
23 function do_a_barell_roll() {
24 var_dump($this->test_asd);
25 }
26}
27}
28?>
29--EXPECTF--
30Valeur: qwerty
31[snuffleupagus][0.0.0.0][disabled_function][drop] The call to the function 'strlen' in %a/tests/disabled_function_local_var_7.php:%d has been disabled.
diff --git a/src/tests/disabled_function_local_var_8.phpt b/src/tests/disabled_function_local_var_8.phpt
new file mode 100644
index 0000000..475b472
--- /dev/null
+++ b/src/tests/disabled_function_local_var_8.phpt
@@ -0,0 +1,20 @@
1--TEST--
2Disable functions - match on a local variable
3--SKIPIF--
4<?php if (!extension_loaded("snuffleupagus")) die "skip"; ?>
5--INI--
6sp.configuration_file={PWD}/config/disabled_function_local_var.ini
7--FILE--
8<?php
9namespace qwe {
10 const ASD = 'qwerty';
11}
12namespace asd {
13 const asd = 'qwe';
14 echo "Valeur: " . \qwe\ASD . "\n";
15 strlen("qwe");
16}
17?>
18--EXPECTF--
19Valeur: qwerty
20[snuffleupagus][0.0.0.0][disabled_function][drop] The call to the function 'strlen' in %a/tests/disabled_function_local_var_8.php:%d has been disabled.
diff --git a/src/tests/disabled_function_local_var_9.phpt b/src/tests/disabled_function_local_var_9.phpt
new file mode 100644
index 0000000..fb65bc4
--- /dev/null
+++ b/src/tests/disabled_function_local_var_9.phpt
@@ -0,0 +1,20 @@
1--TEST--
2Disable functions - match on a local variable
3--SKIPIF--
4<?php if (!extension_loaded("snuffleupagus")) die "skip"; ?>
5--INI--
6sp.configuration_file={PWD}/config/disabled_function_local_var.ini
7--FILE--
8<?php
9namespace qwe {
10 const QWE = Array('123'=>'asdfgh');
11}
12namespace asd {
13 const asd = 'qwe';
14 echo "Valeur: " . \qwe\QWE[123]. "\n";
15 strlen("qwe");
16}
17?>
18--EXPECTF--
19Valeur: asdfgh
20[snuffleupagus][0.0.0.0][disabled_function][drop] The call to the function 'strlen' in %a/tests/disabled_function_local_var_9.php:%d has been disabled.
diff --git a/src/tests/disabled_function_local_var_obj.phpt b/src/tests/disabled_function_local_var_obj.phpt
new file mode 100644
index 0000000..868ea4c
--- /dev/null
+++ b/src/tests/disabled_function_local_var_obj.phpt
@@ -0,0 +1,25 @@
1--TEST--
2Disable functions - match on a local variable
3--SKIPIF--
4<?php if (!extension_loaded("snuffleupagus")) die "skip"; ?>
5--INI--
6sp.configuration_file={PWD}/config/disabled_function_local_var_obj.ini
7--FILE--
8<?php
9class test_class {
10 public $qwe = 'value';
11 function __construct($arg, $value) {
12 $this->$arg = $value;
13 }
14}
15
16$test_array = ['qwe'];
17$arg = 'qwe';
18$test = new test_class('qwe', 'qwe');
19echo strlen($test->$arg) . "\n";
20$test = new test_class('qwe', 'nop_object');
21echo strlen($test->$arg) . "\n";
22?>
23--EXPECTF--
243
25[snuffleupagus][0.0.0.0][disabled_function][drop] The call to the function 'strlen' in %a/tests/disabled_function_local_var_obj.php:%d has been disabled.
diff --git a/src/tests/disabled_functions_local_var_array.phpt b/src/tests/disabled_functions_local_var_array.phpt
new file mode 100644
index 0000000..2255cbf
--- /dev/null
+++ b/src/tests/disabled_functions_local_var_array.phpt
@@ -0,0 +1,20 @@
1--TEST--
2Disable functions - match on an array value buried in several levels
3--SKIPIF--
4<?php if (!extension_loaded("snuffleupagus")) die "skip"; ?>
5--INI--
6sp.configuration_file={PWD}/config/config_disabled_functions_local_var_array.ini
7--FILE--
8<?php
9function foo($arr) {
10 echo $arr["a"]."\n";
11}
12$a=Array("test2"=>Array("pof"=>"pif", "foo"=>Array("lol"=>"bbb")), "a"=>"cccc");
13foo($a);
14
15$a=Array("test2"=>Array("foo"=>Array("lol"=>"aaa")), "a"=>"dddd");
16foo($a);
17?>
18--EXPECTF--
19cccc
20[snuffleupagus][0.0.0.0][disabled_function][drop] The call to the function 'foo' in %a/tests/disabled_functions_local_var_array.php:3 has been disabled.
diff --git a/src/tests/disabled_functions_local_var_array_key.phpt b/src/tests/disabled_functions_local_var_array_key.phpt
new file mode 100644
index 0000000..4014c05
--- /dev/null
+++ b/src/tests/disabled_functions_local_var_array_key.phpt
@@ -0,0 +1,20 @@
1--TEST--
2Disable functions - match on an array value buried in several levels
3--SKIPIF--
4<?php if (!extension_loaded("snuffleupagus")) die "skip"; ?>
5--INI--
6sp.configuration_file={PWD}/config/config_disabled_functions_local_var_array_key.ini
7--FILE--
8<?php
9function foo($arr) {
10 echo $arr["a"]."\n";
11}
12$a=Array("test2"=>Array("pof"=>"pif", "foo"=>Array("lol"=>"bbb")), "a"=>"cccc");
13foo($a);
14
15$a=Array("test2"=>Array("foo"=>Array("aaa"=>"ccc")), "a"=>"dddd");
16foo($a);
17?>
18--EXPECTF--
19cccc
20[snuffleupagus][0.0.0.0][disabled_function][drop] The call to the function 'foo' in %a/tests/disabled_functions_local_var_array_key.php:3 has been disabled.
diff --git a/src/tests/disabled_functions_name_type.phpt b/src/tests/disabled_functions_name_type.phpt
index c5b24d6..1022238 100644
--- a/src/tests/disabled_functions_name_type.phpt
+++ b/src/tests/disabled_functions_name_type.phpt
@@ -11,4 +11,4 @@ echo strcmp([1,23], "pouet") . "\n";
11?> 11?>
12--EXPECTF-- 12--EXPECTF--
130 130
14[snuffleupagus][0.0.0.0][disabled_function][drop] The call to the function 'strcmp' in %a/disabled_functions_name_type.php:%d has been disabled, because its argument 'str1' content (?) matched a rule. 14[snuffleupagus][0.0.0.0][disabled_function][drop] The call to the function 'strcmp' in %a/disabled_functions_name_type.php:%d has been disabled, because its argument '$str1' content (ARRAY) matched a rule.
diff --git a/src/tests/disabled_functions_nul_byte.phpt b/src/tests/disabled_functions_nul_byte.phpt
index b4974a9..f03a8e4 100644
--- a/src/tests/disabled_functions_nul_byte.phpt
+++ b/src/tests/disabled_functions_nul_byte.phpt
@@ -11,4 +11,4 @@ system("id");
11 11
12?> 12?>
13--EXPECTF-- 13--EXPECTF--
14[snuffleupagus][0.0.0.0][disabled_function][drop] The call to the function 'system' in %a/tests/disabled_functions_nul_byte.php:2 has been disabled, because its argument 'command' content (0id) matched a rule. 14[snuffleupagus][0.0.0.0][disabled_function][drop] The call to the function 'system' in %a/tests/disabled_functions_nul_byte.php:2 has been disabled, because its argument '$command' content (0id) matched a rule.
diff --git a/src/tests/disabled_functions_param.phpt b/src/tests/disabled_functions_param.phpt
index d9f8767..fe0e244 100644
--- a/src/tests/disabled_functions_param.phpt
+++ b/src/tests/disabled_functions_param.phpt
@@ -15,4 +15,4 @@ strcmp("bla", "ble");
15strncmp("bla", "ble", 2); 15strncmp("bla", "ble", 2);
16?> 16?>
17--EXPECTF-- 17--EXPECTF--
18[snuffleupagus][0.0.0.0][disabled_function][drop] The call to the function 'system' in %a/disabled_functions_param.php:2 has been disabled, because its argument 'command' content (id) matched the rule '1'. 18[snuffleupagus][0.0.0.0][disabled_function][drop] The call to the function 'system' in %a/disabled_functions_param.php:2 has been disabled, because its argument '$command' content (id) matched the rule '1'.
diff --git a/src/tests/disabled_functions_param_array.phpt b/src/tests/disabled_functions_param_array.phpt
index 5ca13aa..f023cfc 100644
--- a/src/tests/disabled_functions_param_array.phpt
+++ b/src/tests/disabled_functions_param_array.phpt
@@ -21,4 +21,4 @@ foo($a);
21--EXPECTF-- 21--EXPECTF--
22test1 22test1
23abcde 23abcde
24[snuffleupagus][0.0.0.0][disabled_function][drop] The call to the function 'foo' in %a/disabled_functions_param_array.php:3 has been disabled, because its argument 'arr' content (Array) matched the rule '1'. 24[snuffleupagus][0.0.0.0][disabled_function][drop] The call to the function 'foo' in %a/disabled_functions_param_array.php:3 has been disabled, because its argument '$arr' content (abcd) matched the rule '1'.
diff --git a/src/tests/disabled_functions_param_array_deref.phpt b/src/tests/disabled_functions_param_array_deref.phpt
index 556cb06..1e8e31b 100644
--- a/src/tests/disabled_functions_param_array_deref.phpt
+++ b/src/tests/disabled_functions_param_array_deref.phpt
@@ -22,4 +22,4 @@ foo($a);
22--EXPECTF-- 22--EXPECTF--
23eee 23eee
24abcdef 24abcdef
25[snuffleupagus][0.0.0.0][disabled_function][drop] The call to the function 'foo' in %a/tests/disabled_functions_param_array_deref.php:3 has been disabled, because its argument 'arr' content (Array) matched the rule '2'. 25[snuffleupagus][0.0.0.0][disabled_function][drop] The call to the function 'foo' in %a/tests/disabled_functions_param_array_deref.php:3 has been disabled, because its argument '$arr' content (abcdef) matched the rule '2'.
diff --git a/src/tests/disabled_functions_param_array_no_value.phpt b/src/tests/disabled_functions_param_array_no_value.phpt
index 06b9839..ac1b5e0 100644
--- a/src/tests/disabled_functions_param_array_no_value.phpt
+++ b/src/tests/disabled_functions_param_array_no_value.phpt
@@ -19,4 +19,4 @@ foo($a);
19?> 19?>
20--EXPECTF-- 20--EXPECTF--
21cccc 21cccc
22[snuffleupagus][0.0.0.0][disabled_function][drop] The call to the function 'foo' in %a/tests/disabled_functions_param_array_no_value.php:3 has been disabled, because its argument 'arr' content (Array) matched the rule '3'. 22[snuffleupagus][0.0.0.0][disabled_function][drop] The call to the function 'foo' in %a/tests/disabled_functions_param_array_no_value.php:3 has been disabled, because its argument '$arr' content (aaa) matched the rule '3'.
diff --git a/src/tests/disabled_functions_param_array_r.phpt b/src/tests/disabled_functions_param_array_r.phpt
new file mode 100644
index 0000000..8bd85ce
--- /dev/null
+++ b/src/tests/disabled_functions_param_array_r.phpt
@@ -0,0 +1,20 @@
1--TEST--
2Disable functions - match on an array using regexp
3--SKIPIF--
4<?php if (!extension_loaded("snuffleupagus")) die "skip"; ?>
5--INI--
6sp.configuration_file={PWD}/config/config_disabled_functions_param_r_array.ini
7--FILE--
8<?php
9function foo($arr) {
10 echo $arr["a"]."\n";
11}
12$a=Array("test2"=>"pof", "pof"=>"pif", "a"=>Array("qwe"=>"bbb"), "a"=>"cccc");
13foo($a);
14
15$a=Array("a"=>"abcd", "pof"=>"pif", "bar"=>Array("qwe"=>"bbb"), "b"=>"cccc");
16foo($a);
17?>
18--EXPECTF--
19cccc
20[snuffleupagus][0.0.0.0][disabled_function][drop] The call to the function 'foo' in %a/tests/disabled_functions_param_array_r.php:3 has been disabled, because its argument 'arr' content (ARRAY) matched the rule '1'.
diff --git a/src/tests/disabled_functions_param_array_r_keys.phpt b/src/tests/disabled_functions_param_array_r_keys.phpt
new file mode 100644
index 0000000..e9ef50d
--- /dev/null
+++ b/src/tests/disabled_functions_param_array_r_keys.phpt
@@ -0,0 +1,20 @@
1--TEST--
2Disable functions - match on an array using regexp
3--SKIPIF--
4<?php if (!extension_loaded("snuffleupagus")) die "skip"; ?>
5--INI--
6sp.configuration_file={PWD}/config/config_disabled_functions_param_r_array.ini
7--FILE--
8<?php
9function foo($arr) {
10 echo $arr["a"]."\n";
11}
12$a=Array("test2"=>"pof", "pof"=>"pif", "qwe"=>Array("qwe"=>"bbb"), "a"=>"cccc");
13foo($a);
14
15$a=Array("a"=>"", "pof"=>"pif", "bar"=>Array("qwe"=>"bbb"), "qweabcqwe"=>"nop");
16foo($a);
17?>
18--EXPECTF--
19cccc
20[snuffleupagus][0.0.0.0][disabled_function][drop] The call to the function 'foo' in %a/tests/disabled_functions_param_array_r_keys.php:3 has been disabled, because its argument 'arr' content (ARRAY) matched the rule '2'.
diff --git a/src/tests/disabled_functions_param_array_several_levels.phpt b/src/tests/disabled_functions_param_array_several_levels.phpt
index cef6ded..f5665fb 100644
--- a/src/tests/disabled_functions_param_array_several_levels.phpt
+++ b/src/tests/disabled_functions_param_array_several_levels.phpt
@@ -17,4 +17,4 @@ foo($a);
17?> 17?>
18--EXPECTF-- 18--EXPECTF--
19cccc 19cccc
20[snuffleupagus][0.0.0.0][disabled_function][drop] The call to the function 'foo' in %a/tests/disabled_functions_param_array_several_levels.php:3 has been disabled, because its argument 'arr' content (Array) matched the rule '4'. 20[snuffleupagus][0.0.0.0][disabled_function][drop] The call to the function 'foo' in %a/tests/disabled_functions_param_array_several_levels.php:3 has been disabled, because its argument '$arr' content (ARRAY) matched the rule '4'.
diff --git a/src/tests/disabled_functions_param_array_several_levels_int.phpt b/src/tests/disabled_functions_param_array_several_levels_int.phpt
new file mode 100644
index 0000000..2e546f4
--- /dev/null
+++ b/src/tests/disabled_functions_param_array_several_levels_int.phpt
@@ -0,0 +1,20 @@
1--TEST--
2Disable functions - match on an array value buried in several levels
3--SKIPIF--
4<?php if (!extension_loaded("snuffleupagus")) die "skip"; ?>
5--INI--
6sp.configuration_file={PWD}/config/config_disabled_functions_param_array.ini
7--FILE--
8<?php
9function foo($arr) {
10 echo $arr["a"]."\n";
11}
12$a=Array("test2"=>Array("pof"=>"pif", "foo"=>Array("lol"=>"bbb")), "a"=>"cccc");
13foo($a);
14
15$a=Array("test2"=>Array("foo"=>Array("123"=>"aaa")), "a"=>"dddd");
16foo($a);
17?>
18--EXPECTF--
19cccc
20[snuffleupagus][0.0.0.0][disabled_function][drop] The call to the function 'foo' in %a/tests/disabled_functions_param_array_several_levels_int.php:3 has been disabled, because its argument '$arr' content (ARRAY) matched the rule '4'.
diff --git a/src/tests/disabled_functions_param_array_several_levels_keys.phpt b/src/tests/disabled_functions_param_array_several_levels_keys.phpt
new file mode 100644
index 0000000..1be59fc
--- /dev/null
+++ b/src/tests/disabled_functions_param_array_several_levels_keys.phpt
@@ -0,0 +1,20 @@
1--TEST--
2Disable functions - match on an array value buried in several levels
3--SKIPIF--
4<?php if (!extension_loaded("snuffleupagus")) die "skip"; ?>
5--INI--
6sp.configuration_file={PWD}/config/config_disabled_functions_param_array.ini
7--FILE--
8<?php
9function foo($arr) {
10 echo $arr["a"]."\n";
11}
12$a=Array("test2"=>Array("pof"=>"pif", "bar"=>Array("qwe"=>"bbb")), "a"=>"cccc");
13foo($a);
14
15$a=Array("test2"=>Array("bar"=>Array("lol"=>"aaa")), "a"=>"dddd");
16foo($a);
17?>
18--EXPECTF--
19cccc
20[snuffleupagus][0.0.0.0][disabled_function][drop] The call to the function 'foo' in %a/tests/disabled_functions_param_array_several_levels_keys.php:3 has been disabled, because its argument '$arr' content (ARRAY) matched the rule '5'.
diff --git a/src/tests/disabled_functions_param_array_several_levels_keys_int.phpt b/src/tests/disabled_functions_param_array_several_levels_keys_int.phpt
new file mode 100644
index 0000000..acb696f
--- /dev/null
+++ b/src/tests/disabled_functions_param_array_several_levels_keys_int.phpt
@@ -0,0 +1,20 @@
1--TEST--
2Disable functions - match on an array value buried in several levels
3--SKIPIF--
4<?php if (!extension_loaded("snuffleupagus")) die "skip"; ?>
5--INI--
6sp.configuration_file={PWD}/config/config_disabled_functions_param_array.ini
7--FILE--
8<?php
9function foo($arr) {
10 echo $arr["a"]."\n";
11}
12$a=Array("test2"=>Array("pof"=>"pif", "bar"=>Array("qwe"=>"bbb")), "a"=>"cccc");
13foo($a);
14
15$a=Array("test2"=>Array("bar"=>Array("123"=>"aaa")), "a"=>"dddd");
16foo($a);
17?>
18--EXPECTF--
19cccc
20[snuffleupagus][0.0.0.0][disabled_function][drop] The call to the function 'foo' in %a/tests/disabled_functions_param_array_several_levels_keys_int.php:3 has been disabled, because its argument '$arr' content (ARRAY) matched the rule '6'.
diff --git a/src/tests/disabled_functions_param_int.phpt b/src/tests/disabled_functions_param_int.phpt
index 0e6a62c..692009a 100644
--- a/src/tests/disabled_functions_param_int.phpt
+++ b/src/tests/disabled_functions_param_int.phpt
@@ -18,4 +18,4 @@ foobar("10");
18?> 18?>
19--EXPECTF-- 19--EXPECTF--
201 201
21[snuffleupagus][0.0.0.0][disabled_function][drop] The call to the function 'foobar' in %a/tests/disabled_functions_param_int.php:3 has been disabled, because its argument 'id' content (42) matched a rule. 21[snuffleupagus][0.0.0.0][disabled_function][drop] The call to the function 'foobar' in %a/tests/disabled_functions_param_int.php:3 has been disabled, because its argument '$id' content (42) matched a rule.
diff --git a/src/tests/disabled_functions_pos_type.phpt b/src/tests/disabled_functions_pos_type.phpt
new file mode 100644
index 0000000..7556440
--- /dev/null
+++ b/src/tests/disabled_functions_pos_type.phpt
@@ -0,0 +1,14 @@
1--TEST--
2Disable functions - match on argument's position
3--SKIPIF--
4<?php if (!extension_loaded("snuffleupagus")) die "skip"; ?>
5--INI--
6sp.configuration_file={PWD}/config/disabled_functions_pos.ini
7--FILE--
8<?php
9system([123, 456]);
10?>
11--EXPECTF--
12[snuffleupagus][0.0.0.0][config][error] It seems that you wrote a rule filtering on the 0th argument of the function 'system', but it takes only 2 arguments. Matching on _all_ arguments instead.
13[snuffleupagus][0.0.0.0][config][error] It seems that you wrote a rule filtering on the 1st argument of the function 'system', but it takes only 2 arguments. Matching on _all_ arguments instead.
14[snuffleupagus][0.0.0.0][disabled_function][drop] The call to the function 'system' in %a/disabled_functions_pos_type.php:2 has been disabled, because its argument 'command' content (?) matched the rule '1'.
diff --git a/src/tests/disabled_functions_runtime.phpt b/src/tests/disabled_functions_runtime.phpt
index 1c6a141..1508735 100644
--- a/src/tests/disabled_functions_runtime.phpt
+++ b/src/tests/disabled_functions_runtime.phpt
@@ -23,7 +23,7 @@ test('1338');test('1337');
23?> 23?>
24--EXPECTF-- 24--EXPECTF--
251338 251338
26[snuffleupagus][0.0.0.0][disabled_function][drop] The call to the function 'test' in %a has been disabled, because its argument 'param' content (1337) matched a rule. 26[snuffleupagus][0.0.0.0][disabled_function][drop] The call to the function 'test' in %a has been disabled, because its argument '$param' content (1337) matched a rule.
27--CLEAN-- 27--CLEAN--
28<?php 28<?php
29unlink("file_to_include1.php"); 29unlink("file_to_include1.php");