summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorBen Fuhrmannek2021-08-02 10:42:12 +0200
committerBen Fuhrmannek2021-08-02 10:42:12 +0200
commit4cda0120313dfd5d71236f6faf87416e93f5f89c (patch)
tree0c2c6d15e8ac5287fb3304f96de719547d9e847a /src
parent6c132e6a1d8d339a20282afb5a4af52eb6bce9db (diff)
parente62f226c3ed885808c832040872fc2d73ca46dac (diff)
Merge branch 'master' of https://github.com/jvoisin/snuffleupagus
Diffstat (limited to 'src')
-rw-r--r--src/php_snuffleupagus.h2
-rw-r--r--src/snuffleupagus.c109
-rw-r--r--src/sp_config.c31
-rw-r--r--src/sp_config.h1
-rw-r--r--src/sp_disable_xxe.c31
-rw-r--r--src/sp_execute.c24
-rw-r--r--src/sp_pcre_compat.c11
-rw-r--r--src/sp_pcre_compat.h1
-rw-r--r--src/sp_sloppy.c5
-rw-r--r--src/sp_upload_validation.c4
-rw-r--r--src/sp_utils.c18
-rw-r--r--src/sp_var_parser.c2
-rw-r--r--src/sp_var_value.c31
-rw-r--r--src/sp_wrapper.c4
-rw-r--r--src/tests/broken_configuration/broken_conf_config_invalid_param.phpt6
-rw-r--r--src/tests/broken_configuration_php8/broken_conf_session_encryption_without_encryption_key.phpt1
-rw-r--r--src/tests/broken_configuration_php8/broken_conf_session_encryption_without_env_var.phpt1
-rw-r--r--src/tests/deny_writable/deny_writable_execution_simulation.phpt2
-rw-r--r--src/tests/disable_function/config/disabled_functions.ini1
-rw-r--r--src/tests/disable_function/config/disabled_functions_chmod.ini4
-rw-r--r--src/tests/disable_function/disabled_functions_chmod.phpt14
-rw-r--r--src/tests/disable_function/disabled_functions_chmod_php8.phpt14
-rw-r--r--src/tests/disable_function/disabled_functions_shell_exec_wrong.phpt14
-rw-r--r--src/tests/session_encryption/crypt_session_corrupted_session.phpt2
-rw-r--r--src/tests/session_encryption/crypt_session_invalid.phpt2
-rw-r--r--src/tests/xxe/disable_xxe_dom_disabled.phpt5
26 files changed, 231 insertions, 109 deletions
diff --git a/src/php_snuffleupagus.h b/src/php_snuffleupagus.h
index 248045c..5b2b414 100644
--- a/src/php_snuffleupagus.h
+++ b/src/php_snuffleupagus.h
@@ -56,7 +56,7 @@ typedef void (*zif_handler)(INTERNAL_FUNCTION_PARAMETERS);
56#define TSRMLS_FETCH() 56#define TSRMLS_FETCH()
57#define TSRMLS_C 57#define TSRMLS_C
58#else 58#else
59#if ( !HAVE_PCRE && !HAVE_BUNDLED_PCRE ) 59#if (!HAVE_PCRE && !HAVE_BUNDLED_PCRE)
60#error Snuffleupagus requires PHP7+ with PCRE support 60#error Snuffleupagus requires PHP7+ with PCRE support
61#endif 61#endif
62#endif 62#endif
diff --git a/src/snuffleupagus.c b/src/snuffleupagus.c
index 9a5ac90..7bf3649 100644
--- a/src/snuffleupagus.c
+++ b/src/snuffleupagus.c
@@ -21,7 +21,7 @@ ZEND_DLEXPORT int sp_zend_startup(zend_extension *extension) {
21} 21}
22// LCOV_EXCL_END 22// LCOV_EXCL_END
23 23
24static inline void sp_op_array_handler(zend_op_array *op) { 24static inline void sp_op_array_handler(zend_op_array *const op) {
25 // We need a filename, and strict mode not already enabled on this op 25 // We need a filename, and strict mode not already enabled on this op
26 if (NULL == op->filename || op->fn_flags & ZEND_ACC_STRICT_TYPES) { 26 if (NULL == op->filename || op->fn_flags & ZEND_ACC_STRICT_TYPES) {
27 return; 27 return;
@@ -47,8 +47,7 @@ static PHP_INI_MH(StrictMode) {
47PHP_INI_BEGIN() 47PHP_INI_BEGIN()
48PHP_INI_ENTRY("sp.configuration_file", "", PHP_INI_SYSTEM, 48PHP_INI_ENTRY("sp.configuration_file", "", PHP_INI_SYSTEM,
49 OnUpdateConfiguration) 49 OnUpdateConfiguration)
50PHP_INI_ENTRY("sp.allow_broken_configuration", "0", PHP_INI_SYSTEM, 50PHP_INI_ENTRY("sp.allow_broken_configuration", "0", PHP_INI_SYSTEM, StrictMode)
51 StrictMode)
52PHP_INI_END() 51PHP_INI_END()
53 52
54ZEND_DLEXPORT zend_extension zend_extension_entry = { 53ZEND_DLEXPORT zend_extension zend_extension_entry = {
@@ -59,24 +58,24 @@ ZEND_DLEXPORT zend_extension zend_extension_entry = {
59 PHP_SNUFFLEUPAGUS_COPYRIGHT, 58 PHP_SNUFFLEUPAGUS_COPYRIGHT,
60 sp_zend_startup, 59 sp_zend_startup,
61 NULL, 60 NULL,
62 NULL, /* activate_func_t */ 61 NULL, /* activate_func_t */
63 NULL, /* deactivate_func_t */ 62 NULL, /* deactivate_func_t */
64 NULL, /* message_handler_func_t */ 63 NULL, /* message_handler_func_t */
65 sp_op_array_handler, /* op_array_handler_func_t */ 64 sp_op_array_handler, /* op_array_handler_func_t */
66 NULL, /* statement_handler_func_t */ 65 NULL, /* statement_handler_func_t */
67 NULL, /* fcall_begin_handler_func_t */ 66 NULL, /* fcall_begin_handler_func_t */
68 NULL, /* fcall_end_handler_func_t */ 67 NULL, /* fcall_end_handler_func_t */
69 NULL, /* op_array_ctor_func_t */ 68 NULL, /* op_array_ctor_func_t */
70 NULL, /* op_array_dtor_func_t */ 69 NULL, /* op_array_dtor_func_t */
71 STANDARD_ZEND_EXTENSION_PROPERTIES}; 70 STANDARD_ZEND_EXTENSION_PROPERTIES};
72 71
73PHP_GINIT_FUNCTION(snuffleupagus) { 72PHP_GINIT_FUNCTION(snuffleupagus) {
74 snuffleupagus_globals->is_config_valid = SP_CONFIG_NONE; 73 snuffleupagus_globals->is_config_valid = SP_CONFIG_NONE;
75 snuffleupagus_globals->in_eval = 0; 74 snuffleupagus_globals->in_eval = 0;
76 75
77#define SP_INIT_HT(F) snuffleupagus_globals->F = \ 76#define SP_INIT_HT(F) \
78 pemalloc(sizeof(*(snuffleupagus_globals->F)), 1); \ 77 snuffleupagus_globals->F = pemalloc(sizeof(*(snuffleupagus_globals->F)), 1); \
79 zend_hash_init(snuffleupagus_globals->F, 10, NULL, NULL, 1); 78 zend_hash_init(snuffleupagus_globals->F, 10, NULL, NULL, 1);
80 SP_INIT_HT(disabled_functions_hook); 79 SP_INIT_HT(disabled_functions_hook);
81 SP_INIT_HT(sp_internal_functions_hook); 80 SP_INIT_HT(sp_internal_functions_hook);
82 SP_INIT_HT(sp_eval_blacklist_functions_hook); 81 SP_INIT_HT(sp_eval_blacklist_functions_hook);
@@ -86,8 +85,9 @@ PHP_GINIT_FUNCTION(snuffleupagus) {
86 SP_INIT_HT(config.config_disabled_functions_ret_hooked); 85 SP_INIT_HT(config.config_disabled_functions_ret_hooked);
87#undef SP_INIT_HT 86#undef SP_INIT_HT
88 87
89#define SP_INIT(F) snuffleupagus_globals->config.F = \ 88#define SP_INIT(F) \
90 pecalloc(sizeof(*(snuffleupagus_globals->config.F)), 1, 1); 89 snuffleupagus_globals->config.F = \
90 pecalloc(sizeof(*(snuffleupagus_globals->config.F)), 1, 1);
91 SP_INIT(config_unserialize); 91 SP_INIT(config_unserialize);
92 SP_INIT(config_random); 92 SP_INIT(config_random);
93 SP_INIT(config_sloppy); 93 SP_INIT(config_sloppy);
@@ -121,23 +121,22 @@ PHP_MINIT_FUNCTION(snuffleupagus) {
121 return SUCCESS; 121 return SUCCESS;
122} 122}
123 123
124static void free_disabled_functions_hashtable(HashTable *ht) { 124static void free_disabled_functions_hashtable(HashTable *const ht) {
125 void *ptr = NULL; 125 void *ptr = NULL;
126 ZEND_HASH_FOREACH_PTR(ht, ptr) { sp_list_free(ptr); } 126 ZEND_HASH_FOREACH_PTR(ht, ptr) { sp_list_free(ptr); }
127 ZEND_HASH_FOREACH_END(); 127 ZEND_HASH_FOREACH_END();
128} 128}
129 129
130PHP_MSHUTDOWN_FUNCTION(snuffleupagus) { 130PHP_MSHUTDOWN_FUNCTION(snuffleupagus) {
131
132#define FREE_HT(F) \ 131#define FREE_HT(F) \
133 zend_hash_destroy(SNUFFLEUPAGUS_G(F)); \ 132 zend_hash_destroy(SNUFFLEUPAGUS_G(F)); \
134 pefree(SNUFFLEUPAGUS_G(F), 1); 133 pefree(SNUFFLEUPAGUS_G(F), 1);
135 FREE_HT(disabled_functions_hook); 134 FREE_HT(disabled_functions_hook);
136 FREE_HT(sp_eval_blacklist_functions_hook); 135 FREE_HT(sp_eval_blacklist_functions_hook);
137 136
138#define FREE_HT_LIST(F) \ 137#define FREE_HT_LIST(F) \
139 free_disabled_functions_hashtable(SNUFFLEUPAGUS_G(config).F); \ 138 free_disabled_functions_hashtable(SNUFFLEUPAGUS_G(config).F); \
140 FREE_HT(config.F); 139 FREE_HT(config.F);
141 FREE_HT_LIST(config_disabled_functions); 140 FREE_HT_LIST(config_disabled_functions);
142 FREE_HT_LIST(config_disabled_functions_hooked); 141 FREE_HT_LIST(config_disabled_functions_hooked);
143 FREE_HT_LIST(config_disabled_functions_ret); 142 FREE_HT_LIST(config_disabled_functions_ret);
@@ -145,18 +144,21 @@ PHP_MSHUTDOWN_FUNCTION(snuffleupagus) {
145#undef FREE_HT_LIST 144#undef FREE_HT_LIST
146#undef FREE_HT 145#undef FREE_HT
147 146
148#define FREE_LST_DISABLE(L) \ 147#define FREE_LST_DISABLE(L) \
149 do { \ 148 do { \
150 sp_list_node *_n = SNUFFLEUPAGUS_G(config).L; \ 149 sp_list_node *_n = SNUFFLEUPAGUS_G(config).L; \
151 sp_disabled_function_list_free(_n); \ 150 sp_disabled_function_list_free(_n); \
152 sp_list_free(_n); \ 151 sp_list_free(_n); \
153 } while (0) 152 } while (0)
154 FREE_LST_DISABLE(config_disabled_functions_reg->disabled_functions); 153 FREE_LST_DISABLE(config_disabled_functions_reg->disabled_functions);
155 FREE_LST_DISABLE(config_disabled_functions_reg_ret->disabled_functions); 154 FREE_LST_DISABLE(config_disabled_functions_reg_ret->disabled_functions);
156#undef FREE_LST_DISABLE 155#undef FREE_LST_DISABLE
157 156
157 sp_list_node *_n = SNUFFLEUPAGUS_G(config).config_cookie->cookies;
158 sp_cookie_list_free(_n);
159 sp_list_free(_n);
160
158#define FREE_LST(L) sp_list_free(SNUFFLEUPAGUS_G(config).L); 161#define FREE_LST(L) sp_list_free(SNUFFLEUPAGUS_G(config).L);
159 FREE_LST(config_cookie->cookies);
160 FREE_LST(config_eval->blacklist); 162 FREE_LST(config_eval->blacklist);
161 FREE_LST(config_eval->whitelist); 163 FREE_LST(config_eval->whitelist);
162 FREE_LST(config_wrapper->whitelist); 164 FREE_LST(config_wrapper->whitelist);
@@ -184,24 +186,26 @@ PHP_MSHUTDOWN_FUNCTION(snuffleupagus) {
184} 186}
185 187
186PHP_RINIT_FUNCTION(snuffleupagus) { 188PHP_RINIT_FUNCTION(snuffleupagus) {
187 const sp_config_wrapper* config_wrapper = 189 const sp_config_wrapper *const config_wrapper =
188 SNUFFLEUPAGUS_G(config).config_wrapper; 190 SNUFFLEUPAGUS_G(config).config_wrapper;
189#if defined(COMPILE_DL_SNUFFLEUPAGUS) && defined(ZTS) 191#if defined(COMPILE_DL_SNUFFLEUPAGUS) && defined(ZTS)
190 ZEND_TSRMLS_CACHE_UPDATE(); 192 ZEND_TSRMLS_CACHE_UPDATE();
191#endif 193#endif
192 194
193 if (!SNUFFLEUPAGUS_G(allow_broken_configuration)) { 195 if (!SNUFFLEUPAGUS_G(allow_broken_configuration)) {
194 if (SNUFFLEUPAGUS_G(is_config_valid) == SP_CONFIG_INVALID ) { 196 if (SNUFFLEUPAGUS_G(is_config_valid) == SP_CONFIG_INVALID) {
195 sp_log_err("config", "Invalid configuration file"); 197 sp_log_err("config", "Invalid configuration file");
196 } else if (SNUFFLEUPAGUS_G(is_config_valid) == SP_CONFIG_NONE) { 198 } else if (SNUFFLEUPAGUS_G(is_config_valid) == SP_CONFIG_NONE) {
197 sp_log_warn("config", "No configuration specificed via sp.configuration_file"); 199 sp_log_warn("config",
200 "No configuration specificed via sp.configuration_file");
198 } 201 }
199 } 202 }
200 203
201 // We need to disable wrappers loaded by extensions loaded after SNUFFLEUPAGUS. 204 // We need to disable wrappers loaded by extensions loaded after
205 // SNUFFLEUPAGUS.
202 if (config_wrapper->enabled && 206 if (config_wrapper->enabled &&
203 zend_hash_num_elements(php_stream_get_url_stream_wrappers_hash()) != 207 zend_hash_num_elements(php_stream_get_url_stream_wrappers_hash()) !=
204 config_wrapper->num_wrapper) { 208 config_wrapper->num_wrapper) {
205 sp_disable_wrapper(); 209 sp_disable_wrapper();
206 } 210 }
207 211
@@ -218,7 +222,7 @@ PHP_RSHUTDOWN_FUNCTION(snuffleupagus) { return SUCCESS; }
218 222
219PHP_MINFO_FUNCTION(snuffleupagus) { 223PHP_MINFO_FUNCTION(snuffleupagus) {
220 const char *valid_config; 224 const char *valid_config;
221 switch(SNUFFLEUPAGUS_G(is_config_valid)) { 225 switch (SNUFFLEUPAGUS_G(is_config_valid)) {
222 case SP_CONFIG_VALID: 226 case SP_CONFIG_VALID:
223 valid_config = "yes"; 227 valid_config = "yes";
224 break; 228 break;
@@ -230,10 +234,11 @@ PHP_MINFO_FUNCTION(snuffleupagus) {
230 valid_config = "no"; 234 valid_config = "no";
231 } 235 }
232 php_info_print_table_start(); 236 php_info_print_table_start();
233 php_info_print_table_row(2, "snuffleupagus support", 237 php_info_print_table_row(
234 SNUFFLEUPAGUS_G(is_config_valid)?"enabled":"disabled"); 238 2, "snuffleupagus support",
239 SNUFFLEUPAGUS_G(is_config_valid) ? "enabled" : "disabled");
235 php_info_print_table_row(2, "Version", PHP_SNUFFLEUPAGUS_VERSION); 240 php_info_print_table_row(2, "Version", PHP_SNUFFLEUPAGUS_VERSION);
236 php_info_print_table_row( 2, "Valid config", valid_config); 241 php_info_print_table_row(2, "Valid config", valid_config);
237 php_info_print_table_end(); 242 php_info_print_table_end();
238 DISPLAY_INI_ENTRIES(); 243 DISPLAY_INI_ENTRIES();
239} 244}
@@ -245,14 +250,15 @@ static PHP_INI_MH(OnUpdateConfiguration) {
245 return FAILURE; 250 return FAILURE;
246 } 251 }
247 252
248 glob_t globbuf; 253 char *str = new_value->val;
249 char *config_file;
250 char *rest = new_value->val;
251 254
252 while ((config_file = strtok_r(rest, ",", &rest))) { 255 while (1) {
253 int ret = glob(config_file, GLOB_NOCHECK, NULL, &globbuf); 256 // We don't care about overwriting new_value->val
257 const char *config_file = strsep(&str, ",");
258 if (config_file == NULL) break;
254 259
255 if (ret != 0) { 260 glob_t globbuf;
261 if (0 != glob(config_file, GLOB_NOCHECK, NULL, &globbuf)) {
256 SNUFFLEUPAGUS_G(is_config_valid) = SP_CONFIG_INVALID; 262 SNUFFLEUPAGUS_G(is_config_valid) = SP_CONFIG_INVALID;
257 globfree(&globbuf); 263 globfree(&globbuf);
258 return FAILURE; 264 return FAILURE;
@@ -315,11 +321,12 @@ static PHP_INI_MH(OnUpdateConfiguration) {
315 321
316 // If `zend_write_default` is not NULL it is already hooked. 322 // If `zend_write_default` is not NULL it is already hooked.
317 if ((zend_hash_str_find( 323 if ((zend_hash_str_find(
318 SNUFFLEUPAGUS_G(config).config_disabled_functions_hooked, "echo", 324 SNUFFLEUPAGUS_G(config).config_disabled_functions_hooked, "echo",
319 sizeof("echo") - 1) || 325 sizeof("echo") - 1) ||
320 zend_hash_str_find( 326 zend_hash_str_find(
321 SNUFFLEUPAGUS_G(config).config_disabled_functions_ret_hooked, "echo", 327 SNUFFLEUPAGUS_G(config).config_disabled_functions_ret_hooked, "echo",
322 sizeof("echo") - 1)) && NULL == zend_write_default) { 328 sizeof("echo") - 1)) &&
329 NULL == zend_write_default && zend_write != hook_echo) {
323 zend_write_default = zend_write; 330 zend_write_default = zend_write;
324 zend_write = hook_echo; 331 zend_write = hook_echo;
325 } 332 }
diff --git a/src/sp_config.c b/src/sp_config.c
index 69730e3..c12b435 100644
--- a/src/sp_config.c
+++ b/src/sp_config.c
@@ -6,7 +6,7 @@
6 6
7size_t sp_line_no; 7size_t sp_line_no;
8 8
9sp_config_tokens const sp_func[] = { 9static sp_config_tokens const sp_func[] = {
10 {.func = parse_unserialize, .token = SP_TOKEN_UNSERIALIZE_HMAC}, 10 {.func = parse_unserialize, .token = SP_TOKEN_UNSERIALIZE_HMAC},
11 {.func = parse_random, .token = SP_TOKEN_HARDEN_RANDOM}, 11 {.func = parse_random, .token = SP_TOKEN_HARDEN_RANDOM},
12 {.func = parse_log_media, .token = SP_TOKEN_LOG_MEDIA}, 12 {.func = parse_log_media, .token = SP_TOKEN_LOG_MEDIA},
@@ -73,7 +73,11 @@ int parse_list(char *restrict line, char *restrict keyword, void *list_ptr) {
73 } 73 }
74 74
75 tmp = ZSTR_VAL(value); 75 tmp = ZSTR_VAL(value);
76 while ((token = strtok_r(tmp, ",", &tmp))) { 76 while (1) {
77 token = strsep(&tmp, ",");
78 if (token == NULL) {
79 break;
80 }
77 *list = sp_list_insert(*list, zend_string_init(token, strlen(token), 1)); 81 *list = sp_list_insert(*list, zend_string_init(token, strlen(token), 1));
78 } 82 }
79 83
@@ -216,11 +220,32 @@ void sp_disabled_function_list_free(sp_list_node *list) {
216 sp_list_node *cursor = list; 220 sp_list_node *cursor = list;
217 while (cursor) { 221 while (cursor) {
218 sp_disabled_function *df = cursor->data; 222 sp_disabled_function *df = cursor->data;
219 if (df && df->functions_list) sp_list_free(df->functions_list);
220 if (df) { 223 if (df) {
224 sp_list_free(df->functions_list);
225 sp_list_free(df->param_array_keys);
226 sp_list_free(df->var_array_keys);
227
228 sp_pcre_free(df->r_filename);
229 sp_pcre_free(df->r_function);
230 sp_pcre_free(df->r_param);
231 sp_pcre_free(df->r_ret);
232 sp_pcre_free(df->r_value);
233 sp_pcre_free(df->r_key);
234
221 sp_tree_free(df->param); 235 sp_tree_free(df->param);
222 sp_tree_free(df->var); 236 sp_tree_free(df->var);
223 } 237 }
224 cursor = cursor->next; 238 cursor = cursor->next;
225 } 239 }
226} 240}
241
242void sp_cookie_list_free(sp_list_node *list) {
243 sp_list_node *cursor = list;
244 while (cursor) {
245 sp_cookie *c = cursor->data;
246 if (c) {
247 sp_pcre_free(c->name_r);
248 }
249 cursor = cursor->next;
250 }
251}
diff --git a/src/sp_config.h b/src/sp_config.h
index b06e8be..e7b1473 100644
--- a/src/sp_config.h
+++ b/src/sp_config.h
@@ -282,5 +282,6 @@ int parse_list(char *restrict, char *restrict, void *);
282 282
283// cleanup 283// cleanup
284void sp_disabled_function_list_free(sp_list_node *); 284void sp_disabled_function_list_free(sp_list_node *);
285void sp_cookie_list_free(sp_list_node *);
285 286
286#endif /* SP_CONFIG_H */ 287#endif /* SP_CONFIG_H */
diff --git a/src/sp_disable_xxe.c b/src/sp_disable_xxe.c
index 113d84b..f9712b5 100644
--- a/src/sp_disable_xxe.c
+++ b/src/sp_disable_xxe.c
@@ -1,26 +1,41 @@
1#include "php_snuffleupagus.h" 1#include "php_snuffleupagus.h"
2 2
3PHP_FUNCTION(sp_libxml_disable_entity_loader) { RETURN_TRUE; } 3PHP_FUNCTION(sp_libxml_disable_entity_loader) {
4 sp_log_warn("xxe",
5 "A call to libxml_disable_entity_loader was tried and nopped");
6 RETURN_TRUE;
7}
8
9PHP_FUNCTION(sp_libxml_set_external_entity_loader) {
10 sp_log_warn(
11 "xxe",
12 "A call to libxml_set_external_entity_loader was tried and nopped");
13 RETURN_TRUE;
14}
4 15
5int hook_libxml_disable_entity_loader() { 16int hook_libxml_disable_entity_loader() {
6 TSRMLS_FETCH(); 17 TSRMLS_FETCH();
7 18
8// External entities are disabled by default in PHP8+
9#if PHP_VERSION_ID < 80000
10 /* Call the php function here instead of re-implementing it is a bit
11 * ugly, but we do not want to introduce compile-time dependencies against
12 * libxml. */
13 zval func_name; 19 zval func_name;
14 zval hmac; 20 zval retval;
15 zval params[1]; 21 zval params[1];
16 22
23#if PHP_VERSION_ID < 80000
24 // This function is deprecated in PHP8, but better safe than sorry for php7.
17 ZVAL_STRING(&func_name, "libxml_disable_entity_loader"); 25 ZVAL_STRING(&func_name, "libxml_disable_entity_loader");
18 ZVAL_STRING(&params[0], "true"); 26 ZVAL_STRING(&params[0], "true");
19 call_user_function(CG(function_table), NULL, &func_name, &hmac, 1, params); 27 call_user_function(CG(function_table), NULL, &func_name, &retval, 1, params);
20#endif 28#endif
21 29
30 // This is now the recommended way to disable external entities
31 ZVAL_STRING(&func_name, "libxml_set_external_entity_loader");
32 ZVAL_NULL(&params[0]);
33 call_user_function(CG(function_table), NULL, &func_name, &retval, 1, params);
34
22 HOOK_FUNCTION("libxml_disable_entity_loader", sp_internal_functions_hook, 35 HOOK_FUNCTION("libxml_disable_entity_loader", sp_internal_functions_hook,
23 PHP_FN(sp_libxml_disable_entity_loader)); 36 PHP_FN(sp_libxml_disable_entity_loader));
37 HOOK_FUNCTION("libxml_set_external_entity_loader", sp_internal_functions_hook,
38 PHP_FN(sp_libxml_set_external_entity_loader));
24 39
25 return SUCCESS; 40 return SUCCESS;
26} 41}
diff --git a/src/sp_execute.c b/src/sp_execute.c
index de83a2a..7d078b0 100644
--- a/src/sp_execute.c
+++ b/src/sp_execute.c
@@ -274,17 +274,23 @@ int hook_execute(void) {
274 TSRMLS_FETCH(); 274 TSRMLS_FETCH();
275 275
276 if (NULL == orig_execute_ex && NULL == orig_zend_stream_open) { 276 if (NULL == orig_execute_ex && NULL == orig_zend_stream_open) {
277 /* zend_execute_ex is used for "user" function calls */ 277 if (zend_execute_ex != sp_execute_ex) {
278 orig_execute_ex = zend_execute_ex; 278 /* zend_execute_ex is used for "user" function calls */
279 zend_execute_ex = sp_execute_ex; 279 orig_execute_ex = zend_execute_ex;
280 zend_execute_ex = sp_execute_ex;
281 }
280 282
281 /* zend_execute_internal is used for "builtin" functions calls */ 283 if (zend_execute_internal != sp_zend_execute_internal) {
282 orig_zend_execute_internal = zend_execute_internal; 284 /* zend_execute_internal is used for "builtin" functions calls */
283 zend_execute_internal = sp_zend_execute_internal; 285 orig_zend_execute_internal = zend_execute_internal;
286 zend_execute_internal = sp_zend_execute_internal;
287 }
284 288
285 /* zend_stream_open_function is used for include-related stuff */ 289 if (zend_stream_open_function != sp_stream_open) {
286 orig_zend_stream_open = zend_stream_open_function; 290 /* zend_stream_open_function is used for include-related stuff */
287 zend_stream_open_function = sp_stream_open; 291 orig_zend_stream_open = zend_stream_open_function;
292 zend_stream_open_function = sp_stream_open;
293 }
288 } 294 }
289 295
290 return SUCCESS; 296 return SUCCESS;
diff --git a/src/sp_pcre_compat.c b/src/sp_pcre_compat.c
index 509a8ea..3bd00ca 100644
--- a/src/sp_pcre_compat.c
+++ b/src/sp_pcre_compat.c
@@ -1,5 +1,12 @@
1#include "php_snuffleupagus.h" 1#include "php_snuffleupagus.h"
2 2
3inline void sp_pcre_free(sp_pcre* regexp) {
4#ifdef SP_HAS_PCRE2
5 pcre2_code_free(regexp);
6#endif
7 regexp = NULL;
8}
9
3sp_pcre* sp_pcre_compile(const char* const pattern) { 10sp_pcre* sp_pcre_compile(const char* const pattern) {
4 assert(NULL != pattern); 11 assert(NULL != pattern);
5 12
@@ -34,7 +41,11 @@ bool ZEND_HOT sp_is_regexp_matching_len(const sp_pcre* regexp, const char* str,
34#ifdef SP_HAS_PCRE2 41#ifdef SP_HAS_PCRE2
35 pcre2_match_data* match_data = 42 pcre2_match_data* match_data =
36 pcre2_match_data_create_from_pattern(regexp, NULL); 43 pcre2_match_data_create_from_pattern(regexp, NULL);
44 if (NULL == match_data) {
45 sp_log_err("regexp", "Unable to get memory for a regxp.");
46 }
37 ret = pcre2_match(regexp, (PCRE2_SPTR)str, len, 0, 0, match_data, NULL); 47 ret = pcre2_match(regexp, (PCRE2_SPTR)str, len, 0, 0, match_data, NULL);
48 pcre2_match_data_free(match_data);
38#else 49#else
39 int vec[30]; 50 int vec[30];
40 ret = pcre_exec(regexp, NULL, str, len, 0, 0, vec, sizeof(vec) / sizeof(int)); 51 ret = pcre_exec(regexp, NULL, str, len, 0, 0, vec, sizeof(vec) / sizeof(int));
diff --git a/src/sp_pcre_compat.h b/src/sp_pcre_compat.h
index 14c33b2..725004d 100644
--- a/src/sp_pcre_compat.h
+++ b/src/sp_pcre_compat.h
@@ -17,6 +17,7 @@
17#endif 17#endif
18 18
19sp_pcre* sp_pcre_compile(const char* str); 19sp_pcre* sp_pcre_compile(const char* str);
20void sp_pcre_free(sp_pcre* regexp);
20#define sp_is_regexp_matching_zend(regexp, zstr) \ 21#define sp_is_regexp_matching_zend(regexp, zstr) \
21 sp_is_regexp_matching_len(regexp, ZSTR_VAL(zstr), ZSTR_LEN(zstr)) 22 sp_is_regexp_matching_len(regexp, ZSTR_VAL(zstr), ZSTR_LEN(zstr))
22#define sp_is_regexp_matching(regexp, str) \ 23#define sp_is_regexp_matching(regexp, str) \
diff --git a/src/sp_sloppy.c b/src/sp_sloppy.c
index f9ed718..ff2d644 100644
--- a/src/sp_sloppy.c
+++ b/src/sp_sloppy.c
@@ -99,12 +99,13 @@ PHP_FUNCTION(sp_array_keys) {
99void hook_sloppy() { 99void hook_sloppy() {
100 TSRMLS_FETCH(); 100 TSRMLS_FETCH();
101 101
102 if (NULL == orig_zend_compile_file) { 102 if (NULL == orig_zend_compile_file && zend_compile_file != sp_compile_file) {
103 orig_zend_compile_file = zend_compile_file; 103 orig_zend_compile_file = zend_compile_file;
104 zend_compile_file = sp_compile_file; 104 zend_compile_file = sp_compile_file;
105 } 105 }
106 106
107 if (NULL == orig_zend_compile_string) { 107 if (NULL == orig_zend_compile_string &&
108 zend_compile_string != sp_compile_string) {
108 orig_zend_compile_string = zend_compile_string; 109 orig_zend_compile_string = zend_compile_string;
109 zend_compile_string = sp_compile_string; 110 zend_compile_string = sp_compile_string;
110 } 111 }
diff --git a/src/sp_upload_validation.c b/src/sp_upload_validation.c
index f3ae311..cebab3e 100644
--- a/src/sp_upload_validation.c
+++ b/src/sp_upload_validation.c
@@ -103,6 +103,10 @@ int sp_rfc1867_callback(unsigned int event, void *event_data, void **extra) {
103#endif 103#endif
104 104
105void hook_upload() { 105void hook_upload() {
106 if (php_rfc1867_callback == sp_rfc1867_callback) {
107 return;
108 }
109
106 if (NULL == sp_rfc1867_orig_callback) { 110 if (NULL == sp_rfc1867_orig_callback) {
107 sp_rfc1867_orig_callback = php_rfc1867_callback; 111 sp_rfc1867_orig_callback = php_rfc1867_callback;
108 php_rfc1867_callback = sp_rfc1867_callback; 112 php_rfc1867_callback = sp_rfc1867_callback;
diff --git a/src/sp_utils.c b/src/sp_utils.c
index 73c0546..5f25920 100644
--- a/src/sp_utils.c
+++ b/src/sp_utils.c
@@ -19,24 +19,6 @@ const char* get_ipaddr() {
19 return fwd_ip; 19 return fwd_ip;
20 } 20 }
21 21
22 /* Some hosters (like heroku, see
23 * https://github.com/jvoisin/snuffleupagus/issues/336) are clearing the
24 * environment variables, so we don't have access to them, hence why we're
25 * resorting to $_SERVER['REMOTE_ADDR'].
26 */
27 if (!Z_ISUNDEF(PG(http_globals)[TRACK_VARS_SERVER])) {
28 const zval* const globals_client_ip =
29 zend_hash_str_find(Z_ARRVAL(PG(http_globals)[TRACK_VARS_SERVER]),
30 "REMOTE_ADDR", sizeof("REMOTE_ADDR") - 1);
31 if (globals_client_ip) {
32 if (Z_TYPE_P(globals_client_ip) == IS_STRING) {
33 if (Z_STRLEN_P(globals_client_ip) != 0) {
34 return estrdup(Z_STRVAL_P(globals_client_ip));
35 }
36 }
37 }
38 }
39
40 return default_ipaddr; 22 return default_ipaddr;
41} 23}
42 24
diff --git a/src/sp_var_parser.c b/src/sp_var_parser.c
index b066b84..bb5a5c0 100644
--- a/src/sp_var_parser.c
+++ b/src/sp_var_parser.c
@@ -20,7 +20,7 @@ static sp_list_node *parse_str_tokens(const char *str,
20 return tokens_list; 20 return tokens_list;
21} 21}
22 22
23static bool is_var_name_valid(const char *name) { 23static bool is_var_name_valid(const char *const name) {
24 static sp_pcre *regexp_const = NULL; 24 static sp_pcre *regexp_const = NULL;
25 static sp_pcre *regexp_var = NULL; 25 static sp_pcre *regexp_var = NULL;
26 26
diff --git a/src/sp_var_value.c b/src/sp_var_value.c
index b9ac357..fe37f99 100644
--- a/src/sp_var_value.c
+++ b/src/sp_var_value.c
@@ -1,6 +1,7 @@
1#include "php_snuffleupagus.h" 1#include "php_snuffleupagus.h"
2 2
3static zval *get_param_var(zend_execute_data *ed, const char *var_name) { 3static zval *get_param_var(const zend_execute_data *const ed,
4 const char *const var_name, bool print) {
4 unsigned int nb_param = ed->func->common.num_args; 5 unsigned int nb_param = ed->func->common.num_args;
5 6
6 for (unsigned int i = 0; i < nb_param; i++) { 7 for (unsigned int i = 0; i < nb_param; i++) {
@@ -13,11 +14,14 @@ static zval *get_param_var(zend_execute_data *ed, const char *var_name) {
13 if (0 == strcmp(arg_name, var_name)) { 14 if (0 == strcmp(arg_name, var_name)) {
14 return ZEND_CALL_VAR_NUM(ed, i); 15 return ZEND_CALL_VAR_NUM(ed, i);
15 } 16 }
17 if (print == true) {
18 sp_log_warn("config", " - %d parameter's name: '%s'", i, arg_name);
19 }
16 } 20 }
17 return NULL; 21 return NULL;
18} 22}
19 23
20static zval *get_local_var(zend_execute_data *ed, const char *var_name) { 24static zval *get_local_var(zend_execute_data *ed, const char *const var_name) {
21 zend_execute_data *orig_execute_data = ed; 25 zend_execute_data *orig_execute_data = ed;
22 zend_execute_data *current = ed; 26 zend_execute_data *current = ed;
23 27
@@ -48,7 +52,7 @@ static zval *get_local_var(zend_execute_data *ed, const char *var_name) {
48 return NULL; 52 return NULL;
49} 53}
50 54
51static zval *get_constant(const char *value) { 55static zval *get_constant(const char *const value) {
52 zend_string *name = zend_string_init(value, strlen(value), 0); 56 zend_string *name = zend_string_init(value, strlen(value), 0);
53 zval *zvalue = zend_get_constant_ex(name, NULL, ZEND_FETCH_CLASS_SILENT); 57 zval *zvalue = zend_get_constant_ex(name, NULL, ZEND_FETCH_CLASS_SILENT);
54 zend_string_release(name); 58 zend_string_release(name);
@@ -68,7 +72,7 @@ static zval *get_var_value(zend_execute_data *ed, const char *var_name,
68 } 72 }
69 73
70 if (is_param) { 74 if (is_param) {
71 zval *zvalue = get_param_var(ed, var_name); 75 zval *zvalue = get_param_var(ed, var_name, false);
72 if (!zvalue) { 76 if (!zvalue) {
73 char *complete_function_path = get_complete_function_path(ed); 77 char *complete_function_path = get_complete_function_path(ed);
74 sp_log_warn("config", 78 sp_log_warn("config",
@@ -76,6 +80,7 @@ static zval *get_var_value(zend_execute_data *ed, const char *var_name,
76 "'%s' of the function '%s', but the parameter does " 80 "'%s' of the function '%s', but the parameter does "
77 "not exists.", 81 "not exists.",
78 var_name, complete_function_path); 82 var_name, complete_function_path);
83 get_param_var(ed, var_name, true);
79 efree(complete_function_path); 84 efree(complete_function_path);
80 return NULL; 85 return NULL;
81 } 86 }
@@ -85,8 +90,8 @@ static zval *get_var_value(zend_execute_data *ed, const char *var_name,
85 } 90 }
86} 91}
87 92
88static void *get_entry_hashtable(const HashTable *ht, const char *entry, 93static void *get_entry_hashtable(const HashTable *const ht,
89 size_t entry_len) { 94 const char *const entry, size_t entry_len) {
90 zval *zvalue = zend_hash_str_find(ht, entry, entry_len); 95 zval *zvalue = zend_hash_str_find(ht, entry, entry_len);
91 96
92 if (!zvalue) { 97 if (!zvalue) {
@@ -104,8 +109,8 @@ static void *get_entry_hashtable(const HashTable *ht, const char *entry,
104 return zvalue; 109 return zvalue;
105} 110}
106 111
107static zval *get_array_value(zend_execute_data *ed, zval *zvalue, 112static zval *get_array_value(zend_execute_data *ed, const zval *const zvalue,
108 const sp_tree *tree) { 113 const sp_tree *const tree) {
109 zval *idx_value = sp_get_var_value(ed, tree->idx, false); 114 zval *idx_value = sp_get_var_value(ed, tree->idx, false);
110 115
111 if (!zvalue || !idx_value) { 116 if (!zvalue || !idx_value) {
@@ -113,7 +118,7 @@ static zval *get_array_value(zend_execute_data *ed, zval *zvalue,
113 } 118 }
114 119
115 if (Z_TYPE_P(zvalue) == IS_ARRAY) { 120 if (Z_TYPE_P(zvalue) == IS_ARRAY) {
116 const zend_string *idx = sp_zval_to_zend_string(idx_value); 121 const zend_string *const idx = sp_zval_to_zend_string(idx_value);
117 return get_entry_hashtable(Z_ARRVAL_P(zvalue), ZSTR_VAL(idx), 122 return get_entry_hashtable(Z_ARRVAL_P(zvalue), ZSTR_VAL(idx),
118 ZSTR_LEN(idx)); 123 ZSTR_LEN(idx));
119 } 124 }
@@ -123,10 +128,10 @@ static zval *get_array_value(zend_execute_data *ed, zval *zvalue,
123 128
124static zval *get_object_property(zend_execute_data *ed, zval *object, 129static zval *get_object_property(zend_execute_data *ed, zval *object,
125 const char *property, bool is_param) { 130 const char *property, bool is_param) {
126 char *class_name = object->value.obj->ce->name->val; 131 const char *const class_name = object->value.obj->ce->name->val;
127 HashTable *array = Z_OBJPROP_P(object); 132 HashTable *array = Z_OBJPROP_P(object);
128 zval *zvalue = NULL; 133 zval *zvalue = NULL;
129 zval *property_val = get_var_value(ed, property, is_param); 134 const zval *property_val = get_var_value(ed, property, is_param);
130 size_t len; 135 size_t len;
131 136
132 if (property_val) { 137 if (property_val) {
@@ -156,7 +161,7 @@ static zval *get_object_property(zend_execute_data *ed, zval *object,
156 return zvalue; 161 return zvalue;
157} 162}
158 163
159static zend_class_entry *get_class(const char *value) { 164static zend_class_entry *get_class(const char *const value) {
160 zend_string *name = zend_string_init(value, strlen(value), 0); 165 zend_string *name = zend_string_init(value, strlen(value), 0);
161 zend_class_entry *ce = zend_lookup_class(name); 166 zend_class_entry *ce = zend_lookup_class(name);
162 zend_string_release(name); 167 zend_string_release(name);
@@ -165,7 +170,7 @@ static zend_class_entry *get_class(const char *value) {
165 170
166static zval *get_unknown_type(const char *restrict value, zval *zvalue, 171static zval *get_unknown_type(const char *restrict value, zval *zvalue,
167 zend_class_entry *ce, zend_execute_data *ed, 172 zend_class_entry *ce, zend_execute_data *ed,
168 const sp_tree *tree, bool is_param) { 173 const sp_tree *const tree, bool is_param) {
169 if (ce) { 174 if (ce) {
170 zvalue = get_entry_hashtable(&ce->constants_table, value, strlen(value)); 175 zvalue = get_entry_hashtable(&ce->constants_table, value, strlen(value));
171 ce = NULL; 176 ce = NULL;
diff --git a/src/sp_wrapper.c b/src/sp_wrapper.c
index 277f23a..7610114 100644
--- a/src/sp_wrapper.c
+++ b/src/sp_wrapper.c
@@ -1,6 +1,6 @@
1#include "php_snuffleupagus.h" 1#include "php_snuffleupagus.h"
2 2
3static bool wrapper_is_whitelisted(const zend_string *zs) { 3static bool wrapper_is_whitelisted(const zend_string *const zs) {
4 const sp_list_node *list = SNUFFLEUPAGUS_G(config).config_wrapper->whitelist; 4 const sp_list_node *list = SNUFFLEUPAGUS_G(config).config_wrapper->whitelist;
5 5
6 if (!zs) { 6 if (!zs) {
@@ -18,7 +18,7 @@ static bool wrapper_is_whitelisted(const zend_string *zs) {
18 18
19void sp_disable_wrapper() { 19void sp_disable_wrapper() {
20 HashTable *orig = php_stream_get_url_stream_wrappers_hash(); 20 HashTable *orig = php_stream_get_url_stream_wrappers_hash();
21 HashTable *orig_complete = pemalloc(sizeof(*orig_complete), 1); 21 HashTable *orig_complete = pemalloc(sizeof(HashTable), 1);
22 zval *zv; 22 zval *zv;
23 zend_string *zs; 23 zend_string *zs;
24 24
diff --git a/src/tests/broken_configuration/broken_conf_config_invalid_param.phpt b/src/tests/broken_configuration/broken_conf_config_invalid_param.phpt
index ac85dea..45ccf24 100644
--- a/src/tests/broken_configuration/broken_conf_config_invalid_param.phpt
+++ b/src/tests/broken_configuration/broken_conf_config_invalid_param.phpt
@@ -13,4 +13,10 @@ function foo($blah, $x = null, $y = null) {
13foo("qwe"); 13foo("qwe");
14--EXPECTF-- 14--EXPECTF--
15Warning: [snuffleupagus][0.0.0.0][config][log] It seems that you are filtering on a parameter 'qwe' of the function 'foo', but the parameter does not exists. in %s/tests/broken_configuration/broken_conf_config_invalid_param.php on line %d 15Warning: [snuffleupagus][0.0.0.0][config][log] It seems that you are filtering on a parameter 'qwe' of the function 'foo', but the parameter does not exists. in %s/tests/broken_configuration/broken_conf_config_invalid_param.php on line %d
16
17Warning: [snuffleupagus][0.0.0.0][config][log] - 0 parameter's name: 'blah' in %s/tests/broken_configuration/broken_conf_config_invalid_param.php on line %d
18
19Warning: [snuffleupagus][0.0.0.0][config][log] - 1 parameter's name: 'x' in %s/tests/broken_configuration/broken_conf_config_invalid_param.php on line %d
20
21Warning: [snuffleupagus][0.0.0.0][config][log] - 2 parameter's name: 'y' in %s/tests/broken_configuration/broken_conf_config_invalid_param.php on line %d
16ok 22ok
diff --git a/src/tests/broken_configuration_php8/broken_conf_session_encryption_without_encryption_key.phpt b/src/tests/broken_configuration_php8/broken_conf_session_encryption_without_encryption_key.phpt
index 046dc7d..62ee41e 100644
--- a/src/tests/broken_configuration_php8/broken_conf_session_encryption_without_encryption_key.phpt
+++ b/src/tests/broken_configuration_php8/broken_conf_session_encryption_without_encryption_key.phpt
@@ -6,6 +6,7 @@ Broken configuration - encrypted session without encryption key
6--INI-- 6--INI--
7sp.configuration_file={PWD}/config/broken_conf_session_encryption_without_encryption_key.ini 7sp.configuration_file={PWD}/config/broken_conf_session_encryption_without_encryption_key.ini
8--FILE-- 8--FILE--
9--XFAIL--
9--EXPECT-- 10--EXPECT--
10 11
11Fatal error: [snuffleupagus][0.0.0.0][config][log] You're trying to use the session cookie encryption feature on line 2 without having set the `.secret_key` option in`sp.global`: please set it first in Unknown on line 0 12Fatal error: [snuffleupagus][0.0.0.0][config][log] You're trying to use the session cookie encryption feature on line 2 without having set the `.secret_key` option in`sp.global`: please set it first in Unknown on line 0
diff --git a/src/tests/broken_configuration_php8/broken_conf_session_encryption_without_env_var.phpt b/src/tests/broken_configuration_php8/broken_conf_session_encryption_without_env_var.phpt
index bb0f212..5acc1cd 100644
--- a/src/tests/broken_configuration_php8/broken_conf_session_encryption_without_env_var.phpt
+++ b/src/tests/broken_configuration_php8/broken_conf_session_encryption_without_env_var.phpt
@@ -6,6 +6,7 @@ Broken configuration - encrypted session without env var
6--INI-- 6--INI--
7sp.configuration_file={PWD}/config/broken_conf_session_encryption_without_env_var.ini 7sp.configuration_file={PWD}/config/broken_conf_session_encryption_without_env_var.ini
8--FILE-- 8--FILE--
9--XFAIL--
9--EXPECT-- 10--EXPECT--
10 11
11Fatal error: [snuffleupagus][0.0.0.0][config][log] You're trying to use the session cookie encryption feature on line 2 without having set the `.cookie_env_var` option in`sp.global`: please set it first in Unknown on line 0 12Fatal error: [snuffleupagus][0.0.0.0][config][log] You're trying to use the session cookie encryption feature on line 2 without having set the `.cookie_env_var` option in`sp.global`: please set it first in Unknown on line 0
diff --git a/src/tests/deny_writable/deny_writable_execution_simulation.phpt b/src/tests/deny_writable/deny_writable_execution_simulation.phpt
index 30f8cb1..d4b8efc 100644
--- a/src/tests/deny_writable/deny_writable_execution_simulation.phpt
+++ b/src/tests/deny_writable/deny_writable_execution_simulation.phpt
@@ -3,7 +3,7 @@ Readonly execution attempt (simulation mode)
3--SKIPIF-- 3--SKIPIF--
4<?php if (PHP_VERSION_ID >= 80000) print "skip"; ?> 4<?php if (PHP_VERSION_ID >= 80000) print "skip"; ?>
5<?php 5<?php
6if (!extension_loaded("snuffleupagus")) { print "skip" }; 6if (!extension_loaded("snuffleupagus")) { print "skip"; };
7 7
8// root has write privileges on any file 8// root has write privileges on any file
9if (TRUE == function_exists("posix_getuid")) { 9if (TRUE == function_exists("posix_getuid")) {
diff --git a/src/tests/disable_function/config/disabled_functions.ini b/src/tests/disable_function/config/disabled_functions.ini
index df7013f..0758c98 100644
--- a/src/tests/disable_function/config/disabled_functions.ini
+++ b/src/tests/disable_function/config/disabled_functions.ini
@@ -7,3 +7,4 @@ sp.disable_function.function_r("^var_dump$").drop();
7sp.disable_function.function("sprintf").filename("/wrong file name").drop(); 7sp.disable_function.function("sprintf").filename("/wrong file name").drop();
8sp.disable_function.function("sprintf").filename("/wrong file name").drop(); 8sp.disable_function.function("sprintf").filename("/wrong file name").drop();
9sp.disable_function.function("eval").drop(); 9sp.disable_function.function("eval").drop();
10sp.disable_function.function("shell_exec").param("foo").value("bar").drop();
diff --git a/src/tests/disable_function/config/disabled_functions_chmod.ini b/src/tests/disable_function/config/disabled_functions_chmod.ini
new file mode 100644
index 0000000..e601900
--- /dev/null
+++ b/src/tests/disable_function/config/disabled_functions_chmod.ini
@@ -0,0 +1,4 @@
1# PHP7 and below
2sp.disable_function.function("chmod").param("mode").value("511").drop();
3# PHP8
4sp.disable_function.function("chmod").param("permissions").value("511").drop();
diff --git a/src/tests/disable_function/disabled_functions_chmod.phpt b/src/tests/disable_function/disabled_functions_chmod.phpt
new file mode 100644
index 0000000..28f948d
--- /dev/null
+++ b/src/tests/disable_function/disabled_functions_chmod.phpt
@@ -0,0 +1,14 @@
1--TEST--
2Disable functions - chmod
3--SKIPIF--
4<?php if (!extension_loaded("snuffleupagus")) print "skip"; ?>
5<?php if (PHP_VERSION_ID >= 80000) print "skip"; ?>
6--INI--
7sp.configuration_file={PWD}/config/disabled_functions_chmod.ini
8--FILE--
9<?php
10chmod( 'foo', 0777 );
11?>
12--XFAIL--
13--EXPECTF--
14Fatal error: [snuffleupagus][0.0.0.0][disabled_function][drop] Aborted execution on call of the function 'chmod', because its argument '$mode' content (511) matched a rule in %a/disabled_function_chmod.php on line %d
diff --git a/src/tests/disable_function/disabled_functions_chmod_php8.phpt b/src/tests/disable_function/disabled_functions_chmod_php8.phpt
new file mode 100644
index 0000000..71bb034
--- /dev/null
+++ b/src/tests/disable_function/disabled_functions_chmod_php8.phpt
@@ -0,0 +1,14 @@
1--TEST--
2Disable functions - chmod, in php8
3--SKIPIF--
4<?php if (!extension_loaded("snuffleupagus")) print "skip"; ?>
5<?php if (PHP_VERSION_ID < 80000) print "skip"; ?>
6--INI--
7sp.configuration_file={PWD}/config/disabled_functions_chmod.ini
8--FILE--
9<?php
10chmod( 'foo', 0777 );
11?>
12--XFAIL--
13--EXPECTF--
14Fatal error: [snuffleupagus][0.0.0.0][disabled_function][drop] Aborted execution on call of the function 'chmod', because its argument '$permissions' content (511) matched a rule in %a/disabled_function_chmod_php8.php on line %d
diff --git a/src/tests/disable_function/disabled_functions_shell_exec_wrong.phpt b/src/tests/disable_function/disabled_functions_shell_exec_wrong.phpt
new file mode 100644
index 0000000..fe8e73a
--- /dev/null
+++ b/src/tests/disable_function/disabled_functions_shell_exec_wrong.phpt
@@ -0,0 +1,14 @@
1--TEST--
2Disable functions - shell_exec, with a non-existing command
3--SKIPIF--
4<?php if (!extension_loaded("snuffleupagus")) print "skip"; ?>
5--INI--
6sp.configuration_file={PWD}/config/disabled_functions.ini
7--FILE--
8<?php
9$gs = exec( 'foo' );
10echo "YES";
11?>
12--EXPECTF--
13%snot found
14YES
diff --git a/src/tests/session_encryption/crypt_session_corrupted_session.phpt b/src/tests/session_encryption/crypt_session_corrupted_session.phpt
index a89faf4..a97dbca 100644
--- a/src/tests/session_encryption/crypt_session_corrupted_session.phpt
+++ b/src/tests/session_encryption/crypt_session_corrupted_session.phpt
@@ -2,6 +2,8 @@
2Set a custom session handler 2Set a custom session handler
3--SKIPIF-- 3--SKIPIF--
4<?php if (!extension_loaded("snuffleupagus")) print "skip"; ?> 4<?php if (!extension_loaded("snuffleupagus")) print "skip"; ?>
5<?php if (PHP_VERSION_ID >= 80000) print "skip"; ?>
6<?php if (PHP_VERSION_ID >= 70400) print "skip"; ?>
5--INI-- 7--INI--
6sp.configuration_file={PWD}/config/config_crypt_session.ini 8sp.configuration_file={PWD}/config/config_crypt_session.ini
7session.save_path = "/tmp" 9session.save_path = "/tmp"
diff --git a/src/tests/session_encryption/crypt_session_invalid.phpt b/src/tests/session_encryption/crypt_session_invalid.phpt
index 9ec7c50..967d9d1 100644
--- a/src/tests/session_encryption/crypt_session_invalid.phpt
+++ b/src/tests/session_encryption/crypt_session_invalid.phpt
@@ -2,6 +2,8 @@
2SESSION crypt and bad decrypt 2SESSION crypt and bad decrypt
3--SKIPIF-- 3--SKIPIF--
4<?php if (!extension_loaded("snuffleupagus")) print "skip"; ?> 4<?php if (!extension_loaded("snuffleupagus")) print "skip"; ?>
5<?php if (PHP_VERSION_ID >= 80000) print "skip"; ?>
6<?php if (PHP_VERSION_ID >= 70400) print "skip"; ?>
5--INI-- 7--INI--
6sp.configuration_file={PWD}/config/config_crypt_session.ini 8sp.configuration_file={PWD}/config/config_crypt_session.ini
7--ENV-- 9--ENV--
diff --git a/src/tests/xxe/disable_xxe_dom_disabled.phpt b/src/tests/xxe/disable_xxe_dom_disabled.phpt
index 493f5a3..a49e094 100644
--- a/src/tests/xxe/disable_xxe_dom_disabled.phpt
+++ b/src/tests/xxe/disable_xxe_dom_disabled.phpt
@@ -44,8 +44,13 @@ printf("without xxe: %s", $dom->getElementsByTagName('testing')->item(0)->nodeVa
44 44
45?> 45?>
46--EXPECTF-- 46--EXPECTF--
47Warning: [snuffleupagus][0.0.0.0][xxe][log] A call to libxml_disable_entity_loader was tried and nopped in %s/tests/xxe/disable_xxe_dom_disabled.php on line %d
47libxml_disable_entity to true: WARNING, external entity loaded! 48libxml_disable_entity to true: WARNING, external entity loaded!
49
50Warning: [snuffleupagus][0.0.0.0][xxe][log] A call to libxml_disable_entity_loader was tried and nopped in %s/tests/xxe/disable_xxe_dom_disabled.php on line %d
48libxml_disable_entity to false: WARNING, external entity loaded! 51libxml_disable_entity to false: WARNING, external entity loaded!
52
53Warning: [snuffleupagus][0.0.0.0][xxe][log] A call to libxml_disable_entity_loader was tried and nopped in %s/tests/xxe/disable_xxe_dom_disabled.php on line %d
49without xxe: foo 54without xxe: foo
50--CLEAN-- 55--CLEAN--
51<?php 56<?php