diff options
| author | Ben Fuhrmannek | 2021-08-02 19:19:23 +0200 |
|---|---|---|
| committer | Ben Fuhrmannek | 2021-08-02 19:19:23 +0200 |
| commit | ae4ac9f69de3120004557824e0d766fe8140b27d (patch) | |
| tree | ef97751ab54357d5d74859b870ce84f4c6d044df /src | |
| parent | 4cda0120313dfd5d71236f6faf87416e93f5f89c (diff) | |
properly free memory on shutdown
Diffstat (limited to 'src')
| -rw-r--r-- | src/snuffleupagus.c | 77 | ||||
| -rw-r--r-- | src/sp_config.c | 70 | ||||
| -rw-r--r-- | src/sp_config.h | 10 | ||||
| -rw-r--r-- | src/sp_list.c | 16 | ||||
| -rw-r--r-- | src/sp_list.h | 3 | ||||
| -rw-r--r-- | src/sp_var_parser.c | 2 |
6 files changed, 108 insertions, 70 deletions
diff --git a/src/snuffleupagus.c b/src/snuffleupagus.c index 7bf3649..d8a86b5 100644 --- a/src/snuffleupagus.c +++ b/src/snuffleupagus.c | |||
| @@ -69,7 +69,7 @@ ZEND_DLEXPORT zend_extension zend_extension_entry = { | |||
| 69 | NULL, /* op_array_dtor_func_t */ | 69 | NULL, /* op_array_dtor_func_t */ |
| 70 | STANDARD_ZEND_EXTENSION_PROPERTIES}; | 70 | STANDARD_ZEND_EXTENSION_PROPERTIES}; |
| 71 | 71 | ||
| 72 | PHP_GINIT_FUNCTION(snuffleupagus) { | 72 | static PHP_GINIT_FUNCTION(snuffleupagus) { |
| 73 | snuffleupagus_globals->is_config_valid = SP_CONFIG_NONE; | 73 | snuffleupagus_globals->is_config_valid = SP_CONFIG_NONE; |
| 74 | snuffleupagus_globals->in_eval = 0; | 74 | snuffleupagus_globals->in_eval = 0; |
| 75 | 75 | ||
| @@ -88,21 +88,21 @@ PHP_GINIT_FUNCTION(snuffleupagus) { | |||
| 88 | #define SP_INIT(F) \ | 88 | #define SP_INIT(F) \ |
| 89 | snuffleupagus_globals->config.F = \ | 89 | snuffleupagus_globals->config.F = \ |
| 90 | pecalloc(sizeof(*(snuffleupagus_globals->config.F)), 1, 1); | 90 | pecalloc(sizeof(*(snuffleupagus_globals->config.F)), 1, 1); |
| 91 | SP_INIT(config_unserialize); | ||
| 92 | SP_INIT(config_random); | 91 | SP_INIT(config_random); |
| 93 | SP_INIT(config_sloppy); | 92 | SP_INIT(config_sloppy); |
| 93 | SP_INIT(config_unserialize); | ||
| 94 | SP_INIT(config_readonly_exec); | 94 | SP_INIT(config_readonly_exec); |
| 95 | SP_INIT(config_global_strict); | ||
| 96 | SP_INIT(config_auto_cookie_secure); | ||
| 97 | SP_INIT(config_snuffleupagus); | ||
| 98 | SP_INIT(config_disable_xxe); | ||
| 99 | SP_INIT(config_upload_validation); | 95 | SP_INIT(config_upload_validation); |
| 100 | SP_INIT(config_disabled_functions_reg); | ||
| 101 | SP_INIT(config_disabled_functions_reg_ret); | ||
| 102 | SP_INIT(config_cookie); | 96 | SP_INIT(config_cookie); |
| 103 | SP_INIT(config_session); | 97 | SP_INIT(config_snuffleupagus); |
| 98 | SP_INIT(config_auto_cookie_secure); | ||
| 99 | SP_INIT(config_global_strict); | ||
| 100 | SP_INIT(config_disable_xxe); | ||
| 104 | SP_INIT(config_eval); | 101 | SP_INIT(config_eval); |
| 105 | SP_INIT(config_wrapper); | 102 | SP_INIT(config_wrapper); |
| 103 | SP_INIT(config_session); | ||
| 104 | SP_INIT(config_disabled_functions_reg); | ||
| 105 | SP_INIT(config_disabled_functions_reg_ret); | ||
| 106 | #undef SP_INIT | 106 | #undef SP_INIT |
| 107 | 107 | ||
| 108 | #define SP_INIT_NULL(F) snuffleupagus_globals->config.F = NULL; | 108 | #define SP_INIT_NULL(F) snuffleupagus_globals->config.F = NULL; |
| @@ -121,21 +121,27 @@ PHP_MINIT_FUNCTION(snuffleupagus) { | |||
| 121 | return SUCCESS; | 121 | return SUCCESS; |
| 122 | } | 122 | } |
| 123 | 123 | ||
| 124 | static void free_disabled_functions_hashtable(HashTable *const ht) { | 124 | PHP_MSHUTDOWN_FUNCTION(snuffleupagus) { |
| 125 | UNREGISTER_INI_ENTRIES(); | ||
| 126 | |||
| 127 | return SUCCESS; | ||
| 128 | } | ||
| 129 | |||
| 130 | static inline void free_disabled_functions_hashtable(HashTable *const ht) { | ||
| 125 | void *ptr = NULL; | 131 | void *ptr = NULL; |
| 126 | ZEND_HASH_FOREACH_PTR(ht, ptr) { sp_list_free(ptr); } | 132 | ZEND_HASH_FOREACH_PTR(ht, ptr) { sp_list_free(ptr, sp_free_disabled_function); } |
| 127 | ZEND_HASH_FOREACH_END(); | 133 | ZEND_HASH_FOREACH_END(); |
| 128 | } | 134 | } |
| 129 | 135 | ||
| 130 | PHP_MSHUTDOWN_FUNCTION(snuffleupagus) { | 136 | static PHP_GSHUTDOWN_FUNCTION(snuffleupagus) { |
| 131 | #define FREE_HT(F) \ | 137 | #define FREE_HT(F) \ |
| 132 | zend_hash_destroy(SNUFFLEUPAGUS_G(F)); \ | 138 | zend_hash_destroy(snuffleupagus_globals->F); \ |
| 133 | pefree(SNUFFLEUPAGUS_G(F), 1); | 139 | pefree(snuffleupagus_globals->F, 1); |
| 134 | FREE_HT(disabled_functions_hook); | 140 | FREE_HT(disabled_functions_hook); |
| 135 | FREE_HT(sp_eval_blacklist_functions_hook); | 141 | FREE_HT(sp_eval_blacklist_functions_hook); |
| 136 | 142 | ||
| 137 | #define FREE_HT_LIST(F) \ | 143 | #define FREE_HT_LIST(F) \ |
| 138 | free_disabled_functions_hashtable(SNUFFLEUPAGUS_G(config).F); \ | 144 | free_disabled_functions_hashtable(snuffleupagus_globals->config.F); \ |
| 139 | FREE_HT(config.F); | 145 | FREE_HT(config.F); |
| 140 | FREE_HT_LIST(config_disabled_functions); | 146 | FREE_HT_LIST(config_disabled_functions); |
| 141 | FREE_HT_LIST(config_disabled_functions_hooked); | 147 | FREE_HT_LIST(config_disabled_functions_hooked); |
| @@ -145,44 +151,43 @@ PHP_MSHUTDOWN_FUNCTION(snuffleupagus) { | |||
| 145 | #undef FREE_HT | 151 | #undef FREE_HT |
| 146 | 152 | ||
| 147 | #define FREE_LST_DISABLE(L) \ | 153 | #define FREE_LST_DISABLE(L) \ |
| 148 | do { \ | 154 | sp_list_free(snuffleupagus_globals->config.L, sp_free_disabled_function); |
| 149 | sp_list_node *_n = SNUFFLEUPAGUS_G(config).L; \ | ||
| 150 | sp_disabled_function_list_free(_n); \ | ||
| 151 | sp_list_free(_n); \ | ||
| 152 | } while (0) | ||
| 153 | FREE_LST_DISABLE(config_disabled_functions_reg->disabled_functions); | 155 | FREE_LST_DISABLE(config_disabled_functions_reg->disabled_functions); |
| 154 | FREE_LST_DISABLE(config_disabled_functions_reg_ret->disabled_functions); | 156 | FREE_LST_DISABLE(config_disabled_functions_reg_ret->disabled_functions); |
| 155 | #undef FREE_LST_DISABLE | 157 | #undef FREE_LST_DISABLE |
| 156 | 158 | ||
| 157 | sp_list_node *_n = SNUFFLEUPAGUS_G(config).config_cookie->cookies; | 159 | sp_list_free(snuffleupagus_globals->config.config_cookie->cookies, sp_free_cookie); |
| 158 | sp_cookie_list_free(_n); | ||
| 159 | sp_list_free(_n); | ||
| 160 | 160 | ||
| 161 | #define FREE_LST(L) sp_list_free(SNUFFLEUPAGUS_G(config).L); | 161 | #define FREE_LST(L) sp_list_free(snuffleupagus_globals->config.L, sp_free_zstr); |
| 162 | FREE_LST(config_eval->blacklist); | 162 | FREE_LST(config_eval->blacklist); |
| 163 | FREE_LST(config_eval->whitelist); | 163 | FREE_LST(config_eval->whitelist); |
| 164 | FREE_LST(config_wrapper->whitelist); | 164 | FREE_LST(config_wrapper->whitelist); |
| 165 | #undef FREE_LST | 165 | #undef FREE_LST |
| 166 | 166 | ||
| 167 | #define FREE_CFG(C) pefree(SNUFFLEUPAGUS_G(config).C, 1); | 167 | #define FREE_CFG(C) pefree(snuffleupagus_globals->config.C, 1); |
| 168 | FREE_CFG(config_unserialize); | 168 | #define FREE_CFG_ZSTR(C) sp_free_zstr(snuffleupagus_globals->config.C); |
| 169 | FREE_CFG(config_random); | 169 | FREE_CFG(config_random); |
| 170 | FREE_CFG(config_sloppy); | ||
| 171 | FREE_CFG_ZSTR(config_unserialize->dump); | ||
| 172 | FREE_CFG_ZSTR(config_unserialize->textual_representation); | ||
| 173 | FREE_CFG(config_unserialize); | ||
| 170 | FREE_CFG(config_readonly_exec); | 174 | FREE_CFG(config_readonly_exec); |
| 171 | FREE_CFG(config_global_strict); | 175 | FREE_CFG_ZSTR(config_upload_validation->script); |
| 172 | FREE_CFG(config_auto_cookie_secure); | 176 | FREE_CFG(config_upload_validation); |
| 177 | FREE_CFG(config_cookie); | ||
| 173 | FREE_CFG(config_snuffleupagus); | 178 | FREE_CFG(config_snuffleupagus); |
| 179 | FREE_CFG(config_auto_cookie_secure); | ||
| 180 | FREE_CFG(config_global_strict); | ||
| 174 | FREE_CFG(config_disable_xxe); | 181 | FREE_CFG(config_disable_xxe); |
| 175 | FREE_CFG(config_upload_validation); | 182 | FREE_CFG_ZSTR(config_eval->dump); |
| 183 | FREE_CFG_ZSTR(config_eval->textual_representation); | ||
| 184 | FREE_CFG(config_eval); | ||
| 185 | FREE_CFG(config_wrapper); | ||
| 176 | FREE_CFG(config_session); | 186 | FREE_CFG(config_session); |
| 177 | FREE_CFG(config_disabled_functions_reg); | 187 | FREE_CFG(config_disabled_functions_reg); |
| 178 | FREE_CFG(config_disabled_functions_reg_ret); | 188 | FREE_CFG(config_disabled_functions_reg_ret); |
| 179 | FREE_CFG(config_cookie); | ||
| 180 | FREE_CFG(config_wrapper); | ||
| 181 | #undef FREE_CFG | 189 | #undef FREE_CFG |
| 182 | 190 | #undef FREE_CFG_ZSTR | |
| 183 | UNREGISTER_INI_ENTRIES(); | ||
| 184 | |||
| 185 | return SUCCESS; | ||
| 186 | } | 191 | } |
| 187 | 192 | ||
| 188 | PHP_RINIT_FUNCTION(snuffleupagus) { | 193 | PHP_RINIT_FUNCTION(snuffleupagus) { |
| @@ -358,7 +363,7 @@ zend_module_entry snuffleupagus_module_entry = { | |||
| 358 | PHP_SNUFFLEUPAGUS_VERSION, | 363 | PHP_SNUFFLEUPAGUS_VERSION, |
| 359 | PHP_MODULE_GLOBALS(snuffleupagus), | 364 | PHP_MODULE_GLOBALS(snuffleupagus), |
| 360 | PHP_GINIT(snuffleupagus), | 365 | PHP_GINIT(snuffleupagus), |
| 361 | NULL, | 366 | PHP_GSHUTDOWN(snuffleupagus), |
| 362 | NULL, | 367 | NULL, |
| 363 | STANDARD_MODULE_PROPERTIES_EX}; | 368 | STANDARD_MODULE_PROPERTIES_EX}; |
| 364 | 369 | ||
diff --git a/src/sp_config.c b/src/sp_config.c index c12b435..72781c6 100644 --- a/src/sp_config.c +++ b/src/sp_config.c | |||
| @@ -216,36 +216,52 @@ int sp_parse_config(const char *conf_file) { | |||
| 216 | return SUCCESS; | 216 | return SUCCESS; |
| 217 | } | 217 | } |
| 218 | 218 | ||
| 219 | void sp_disabled_function_list_free(sp_list_node *list) { | 219 | void sp_free_disabled_function(void *data) { |
| 220 | sp_list_node *cursor = list; | 220 | sp_disabled_function *df = data; |
| 221 | while (cursor) { | ||
| 222 | sp_disabled_function *df = cursor->data; | ||
| 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 | 221 | ||
| 228 | sp_pcre_free(df->r_filename); | 222 | sp_free_zstr(df->textual_representation); |
| 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 | 223 | ||
| 235 | sp_tree_free(df->param); | 224 | sp_free_zstr(df->filename); |
| 236 | sp_tree_free(df->var); | 225 | sp_pcre_free(df->r_filename); |
| 237 | } | 226 | |
| 238 | cursor = cursor->next; | 227 | sp_free_zstr(df->function); |
| 239 | } | 228 | sp_pcre_free(df->r_function); |
| 229 | sp_list_free(df->functions_list, free); | ||
| 230 | |||
| 231 | sp_free_zstr(df->hash); | ||
| 232 | |||
| 233 | sp_tree_free(df->param); | ||
| 234 | sp_pcre_free(df->r_param); | ||
| 235 | |||
| 236 | sp_pcre_free(df->r_ret); | ||
| 237 | sp_free_zstr(df->ret); | ||
| 238 | |||
| 239 | sp_pcre_free(df->r_value); | ||
| 240 | sp_free_zstr(df->value); | ||
| 241 | |||
| 242 | sp_pcre_free(df->r_key); | ||
| 243 | sp_free_zstr(df->key); | ||
| 244 | |||
| 245 | sp_free_zstr(df->dump); | ||
| 246 | sp_free_zstr(df->alias); | ||
| 247 | |||
| 248 | // sp_list_free(df->param_array_keys); | ||
| 249 | // sp_list_free(df->var_array_keys); | ||
| 250 | |||
| 251 | sp_tree_free(df->var); | ||
| 252 | |||
| 253 | pefree(df->cidr, 1); | ||
| 240 | } | 254 | } |
| 241 | 255 | ||
| 242 | void sp_cookie_list_free(sp_list_node *list) { | 256 | void sp_free_cookie(void *data) { |
| 243 | sp_list_node *cursor = list; | 257 | sp_cookie *c = data; |
| 244 | while (cursor) { | 258 | if (c->name) |
| 245 | sp_cookie *c = cursor->data; | 259 | zend_string_release_ex(c->name, 1); |
| 246 | if (c) { | 260 | sp_pcre_free(c->name_r); |
| 247 | sp_pcre_free(c->name_r); | 261 | } |
| 248 | } | 262 | |
| 249 | cursor = cursor->next; | 263 | void sp_free_zstr(void *data) { |
| 264 | if (data) { | ||
| 265 | zend_string_release_ex((zend_string*)data, 1); | ||
| 250 | } | 266 | } |
| 251 | } | 267 | } |
diff --git a/src/sp_config.h b/src/sp_config.h index e7b1473..f3b64a6 100644 --- a/src/sp_config.h +++ b/src/sp_config.h | |||
| @@ -130,8 +130,8 @@ typedef struct { | |||
| 130 | zend_string *alias; | 130 | zend_string *alias; |
| 131 | bool param_is_array; | 131 | bool param_is_array; |
| 132 | bool var_is_array; | 132 | bool var_is_array; |
| 133 | sp_list_node *param_array_keys; | 133 | // sp_list_node *param_array_keys; |
| 134 | sp_list_node *var_array_keys; | 134 | // sp_list_node *var_array_keys; |
| 135 | 135 | ||
| 136 | bool allow; | 136 | bool allow; |
| 137 | 137 | ||
| @@ -281,7 +281,9 @@ int parse_php_type(char *restrict, char *restrict, void *); | |||
| 281 | int parse_list(char *restrict, char *restrict, void *); | 281 | int parse_list(char *restrict, char *restrict, void *); |
| 282 | 282 | ||
| 283 | // cleanup | 283 | // cleanup |
| 284 | void sp_disabled_function_list_free(sp_list_node *); | 284 | void sp_free_disabled_function(void *data); |
| 285 | void sp_cookie_list_free(sp_list_node *); | 285 | void sp_free_cookie(void *data); |
| 286 | void sp_free_zstr(void *data); | ||
| 287 | |||
| 286 | 288 | ||
| 287 | #endif /* SP_CONFIG_H */ | 289 | #endif /* SP_CONFIG_H */ |
diff --git a/src/sp_list.c b/src/sp_list.c index 0f00371..92e628d 100644 --- a/src/sp_list.c +++ b/src/sp_list.c | |||
| @@ -1,8 +1,22 @@ | |||
| 1 | #include "php_snuffleupagus.h" | 1 | #include "php_snuffleupagus.h" |
| 2 | 2 | ||
| 3 | void sp_list_free(sp_list_node *node) { | 3 | void sp_list_free(sp_list_node *node, void (*free_data_func)(void *data)) { |
| 4 | while (node) { | 4 | while (node) { |
| 5 | sp_list_node *tmp = node->next; | 5 | sp_list_node *tmp = node->next; |
| 6 | if (free_data_func && node->data) { | ||
| 7 | free_data_func(node->data); | ||
| 8 | } | ||
| 9 | pefree(node, 1); | ||
| 10 | node = tmp; | ||
| 11 | } | ||
| 12 | } | ||
| 13 | |||
| 14 | void sp_list_free2(sp_list_node *node) { | ||
| 15 | while (node) { | ||
| 16 | sp_list_node *tmp = node->next; | ||
| 17 | if (node->data) { | ||
| 18 | pefree(node->data, 1); | ||
| 19 | } | ||
| 6 | pefree(node, 1); | 20 | pefree(node, 1); |
| 7 | node = tmp; | 21 | node = tmp; |
| 8 | } | 22 | } |
diff --git a/src/sp_list.h b/src/sp_list.h index 2c91995..7ceee50 100644 --- a/src/sp_list.h +++ b/src/sp_list.h | |||
| @@ -11,6 +11,7 @@ sp_list_node *sp_list_sort(sp_list_node *, int (*)(sp_list_node const *const, | |||
| 11 | sp_list_node const *const)); | 11 | sp_list_node const *const)); |
| 12 | sp_list_node *sp_list_insert(sp_list_node *, void *); | 12 | sp_list_node *sp_list_insert(sp_list_node *, void *); |
| 13 | sp_list_node *sp_list_prepend(sp_list_node *, void *); | 13 | sp_list_node *sp_list_prepend(sp_list_node *, void *); |
| 14 | void sp_list_free(sp_list_node *); | 14 | void sp_list_free(sp_list_node *, void (*free_data_func)(void *data)); |
| 15 | void sp_list_free2(sp_list_node *node); | ||
| 15 | 16 | ||
| 16 | #endif | 17 | #endif |
diff --git a/src/sp_var_parser.c b/src/sp_var_parser.c index bb5a5c0..eb57f70 100644 --- a/src/sp_var_parser.c +++ b/src/sp_var_parser.c | |||
| @@ -249,7 +249,7 @@ sp_tree *sp_parse_var(const char *line) { | |||
| 249 | } | 249 | } |
| 250 | tokens_list = sp_list_sort(tokens_list, cmp_tokens); | 250 | tokens_list = sp_list_sort(tokens_list, cmp_tokens); |
| 251 | tree = parse_tokens(line, tokens_list); | 251 | tree = parse_tokens(line, tokens_list); |
| 252 | sp_list_free(tokens_list); | 252 | sp_list_free2(tokens_list); |
| 253 | // Check if tree is empty. | 253 | // Check if tree is empty. |
| 254 | if (tree && tree->next == NULL && tree->type == UNDEFINED) { | 254 | if (tree && tree->next == NULL && tree->type == UNDEFINED) { |
| 255 | tree->type = CONSTANT; | 255 | tree->type = CONSTANT; |
