diff options
Diffstat (limited to 'src/snuffleupagus.c')
| -rw-r--r-- | src/snuffleupagus.c | 109 |
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 | ||
| 24 | static inline void sp_op_array_handler(zend_op_array *op) { | 24 | static 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) { | |||
| 47 | PHP_INI_BEGIN() | 47 | PHP_INI_BEGIN() |
| 48 | PHP_INI_ENTRY("sp.configuration_file", "", PHP_INI_SYSTEM, | 48 | PHP_INI_ENTRY("sp.configuration_file", "", PHP_INI_SYSTEM, |
| 49 | OnUpdateConfiguration) | 49 | OnUpdateConfiguration) |
| 50 | PHP_INI_ENTRY("sp.allow_broken_configuration", "0", PHP_INI_SYSTEM, | 50 | PHP_INI_ENTRY("sp.allow_broken_configuration", "0", PHP_INI_SYSTEM, StrictMode) |
| 51 | StrictMode) | ||
| 52 | PHP_INI_END() | 51 | PHP_INI_END() |
| 53 | 52 | ||
| 54 | ZEND_DLEXPORT zend_extension zend_extension_entry = { | 53 | ZEND_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 | ||
| 73 | PHP_GINIT_FUNCTION(snuffleupagus) { | 72 | PHP_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 | ||
| 124 | static void free_disabled_functions_hashtable(HashTable *ht) { | 124 | static 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 | ||
| 130 | PHP_MSHUTDOWN_FUNCTION(snuffleupagus) { | 130 | PHP_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 | ||
| 186 | PHP_RINIT_FUNCTION(snuffleupagus) { | 188 | PHP_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 | ||
| 219 | PHP_MINFO_FUNCTION(snuffleupagus) { | 223 | PHP_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 | } |
