summaryrefslogtreecommitdiff
path: root/src/snuffleupagus.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/snuffleupagus.c')
-rw-r--r--src/snuffleupagus.c109
1 files changed, 58 insertions, 51 deletions
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 }