From ae4ac9f69de3120004557824e0d766fe8140b27d Mon Sep 17 00:00:00 2001 From: Ben Fuhrmannek Date: Mon, 2 Aug 2021 19:19:23 +0200 Subject: properly free memory on shutdown --- src/snuffleupagus.c | 77 ++++++++++++++++++++++++++++------------------------- src/sp_config.c | 74 ++++++++++++++++++++++++++++++-------------------- src/sp_config.h | 10 ++++--- src/sp_list.c | 16 ++++++++++- src/sp_list.h | 3 ++- src/sp_var_parser.c | 2 +- 6 files changed, 110 insertions(+), 72 deletions(-) (limited to 'src') 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 = { NULL, /* op_array_dtor_func_t */ STANDARD_ZEND_EXTENSION_PROPERTIES}; -PHP_GINIT_FUNCTION(snuffleupagus) { +static PHP_GINIT_FUNCTION(snuffleupagus) { snuffleupagus_globals->is_config_valid = SP_CONFIG_NONE; snuffleupagus_globals->in_eval = 0; @@ -88,21 +88,21 @@ PHP_GINIT_FUNCTION(snuffleupagus) { #define SP_INIT(F) \ snuffleupagus_globals->config.F = \ pecalloc(sizeof(*(snuffleupagus_globals->config.F)), 1, 1); - SP_INIT(config_unserialize); SP_INIT(config_random); SP_INIT(config_sloppy); + SP_INIT(config_unserialize); SP_INIT(config_readonly_exec); - SP_INIT(config_global_strict); - SP_INIT(config_auto_cookie_secure); - SP_INIT(config_snuffleupagus); - SP_INIT(config_disable_xxe); SP_INIT(config_upload_validation); - SP_INIT(config_disabled_functions_reg); - SP_INIT(config_disabled_functions_reg_ret); SP_INIT(config_cookie); - SP_INIT(config_session); + SP_INIT(config_snuffleupagus); + SP_INIT(config_auto_cookie_secure); + SP_INIT(config_global_strict); + SP_INIT(config_disable_xxe); SP_INIT(config_eval); SP_INIT(config_wrapper); + SP_INIT(config_session); + SP_INIT(config_disabled_functions_reg); + SP_INIT(config_disabled_functions_reg_ret); #undef SP_INIT #define SP_INIT_NULL(F) snuffleupagus_globals->config.F = NULL; @@ -121,21 +121,27 @@ PHP_MINIT_FUNCTION(snuffleupagus) { return SUCCESS; } -static void free_disabled_functions_hashtable(HashTable *const ht) { +PHP_MSHUTDOWN_FUNCTION(snuffleupagus) { + UNREGISTER_INI_ENTRIES(); + + return SUCCESS; +} + +static inline void free_disabled_functions_hashtable(HashTable *const ht) { void *ptr = NULL; - ZEND_HASH_FOREACH_PTR(ht, ptr) { sp_list_free(ptr); } + ZEND_HASH_FOREACH_PTR(ht, ptr) { sp_list_free(ptr, sp_free_disabled_function); } ZEND_HASH_FOREACH_END(); } -PHP_MSHUTDOWN_FUNCTION(snuffleupagus) { +static PHP_GSHUTDOWN_FUNCTION(snuffleupagus) { #define FREE_HT(F) \ - zend_hash_destroy(SNUFFLEUPAGUS_G(F)); \ - pefree(SNUFFLEUPAGUS_G(F), 1); + zend_hash_destroy(snuffleupagus_globals->F); \ + pefree(snuffleupagus_globals->F, 1); FREE_HT(disabled_functions_hook); FREE_HT(sp_eval_blacklist_functions_hook); #define FREE_HT_LIST(F) \ - free_disabled_functions_hashtable(SNUFFLEUPAGUS_G(config).F); \ + free_disabled_functions_hashtable(snuffleupagus_globals->config.F); \ FREE_HT(config.F); FREE_HT_LIST(config_disabled_functions); FREE_HT_LIST(config_disabled_functions_hooked); @@ -145,44 +151,43 @@ PHP_MSHUTDOWN_FUNCTION(snuffleupagus) { #undef FREE_HT #define FREE_LST_DISABLE(L) \ - do { \ - sp_list_node *_n = SNUFFLEUPAGUS_G(config).L; \ - sp_disabled_function_list_free(_n); \ - sp_list_free(_n); \ - } while (0) + sp_list_free(snuffleupagus_globals->config.L, sp_free_disabled_function); FREE_LST_DISABLE(config_disabled_functions_reg->disabled_functions); FREE_LST_DISABLE(config_disabled_functions_reg_ret->disabled_functions); #undef FREE_LST_DISABLE - sp_list_node *_n = SNUFFLEUPAGUS_G(config).config_cookie->cookies; - sp_cookie_list_free(_n); - sp_list_free(_n); + sp_list_free(snuffleupagus_globals->config.config_cookie->cookies, sp_free_cookie); -#define FREE_LST(L) sp_list_free(SNUFFLEUPAGUS_G(config).L); +#define FREE_LST(L) sp_list_free(snuffleupagus_globals->config.L, sp_free_zstr); FREE_LST(config_eval->blacklist); FREE_LST(config_eval->whitelist); FREE_LST(config_wrapper->whitelist); #undef FREE_LST -#define FREE_CFG(C) pefree(SNUFFLEUPAGUS_G(config).C, 1); - FREE_CFG(config_unserialize); +#define FREE_CFG(C) pefree(snuffleupagus_globals->config.C, 1); +#define FREE_CFG_ZSTR(C) sp_free_zstr(snuffleupagus_globals->config.C); FREE_CFG(config_random); + FREE_CFG(config_sloppy); + FREE_CFG_ZSTR(config_unserialize->dump); + FREE_CFG_ZSTR(config_unserialize->textual_representation); + FREE_CFG(config_unserialize); FREE_CFG(config_readonly_exec); - FREE_CFG(config_global_strict); - FREE_CFG(config_auto_cookie_secure); + FREE_CFG_ZSTR(config_upload_validation->script); + FREE_CFG(config_upload_validation); + FREE_CFG(config_cookie); FREE_CFG(config_snuffleupagus); + FREE_CFG(config_auto_cookie_secure); + FREE_CFG(config_global_strict); FREE_CFG(config_disable_xxe); - FREE_CFG(config_upload_validation); + FREE_CFG_ZSTR(config_eval->dump); + FREE_CFG_ZSTR(config_eval->textual_representation); + FREE_CFG(config_eval); + FREE_CFG(config_wrapper); FREE_CFG(config_session); FREE_CFG(config_disabled_functions_reg); FREE_CFG(config_disabled_functions_reg_ret); - FREE_CFG(config_cookie); - FREE_CFG(config_wrapper); #undef FREE_CFG - - UNREGISTER_INI_ENTRIES(); - - return SUCCESS; +#undef FREE_CFG_ZSTR } PHP_RINIT_FUNCTION(snuffleupagus) { @@ -358,7 +363,7 @@ zend_module_entry snuffleupagus_module_entry = { PHP_SNUFFLEUPAGUS_VERSION, PHP_MODULE_GLOBALS(snuffleupagus), PHP_GINIT(snuffleupagus), - NULL, + PHP_GSHUTDOWN(snuffleupagus), NULL, STANDARD_MODULE_PROPERTIES_EX}; 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) { return SUCCESS; } -void sp_disabled_function_list_free(sp_list_node *list) { - sp_list_node *cursor = list; - while (cursor) { - sp_disabled_function *df = cursor->data; - if (df) { - sp_list_free(df->functions_list); - sp_list_free(df->param_array_keys); - sp_list_free(df->var_array_keys); - - sp_pcre_free(df->r_filename); - sp_pcre_free(df->r_function); - sp_pcre_free(df->r_param); - sp_pcre_free(df->r_ret); - sp_pcre_free(df->r_value); - sp_pcre_free(df->r_key); - - sp_tree_free(df->param); - sp_tree_free(df->var); - } - cursor = cursor->next; - } +void sp_free_disabled_function(void *data) { + sp_disabled_function *df = data; + + sp_free_zstr(df->textual_representation); + + sp_free_zstr(df->filename); + sp_pcre_free(df->r_filename); + + sp_free_zstr(df->function); + sp_pcre_free(df->r_function); + sp_list_free(df->functions_list, free); + + sp_free_zstr(df->hash); + + sp_tree_free(df->param); + sp_pcre_free(df->r_param); + + sp_pcre_free(df->r_ret); + sp_free_zstr(df->ret); + + sp_pcre_free(df->r_value); + sp_free_zstr(df->value); + + sp_pcre_free(df->r_key); + sp_free_zstr(df->key); + + sp_free_zstr(df->dump); + sp_free_zstr(df->alias); + + // sp_list_free(df->param_array_keys); + // sp_list_free(df->var_array_keys); + + sp_tree_free(df->var); + + pefree(df->cidr, 1); } -void sp_cookie_list_free(sp_list_node *list) { - sp_list_node *cursor = list; - while (cursor) { - sp_cookie *c = cursor->data; - if (c) { - sp_pcre_free(c->name_r); - } - cursor = cursor->next; +void sp_free_cookie(void *data) { + sp_cookie *c = data; + if (c->name) + zend_string_release_ex(c->name, 1); + sp_pcre_free(c->name_r); +} + +void sp_free_zstr(void *data) { + if (data) { + zend_string_release_ex((zend_string*)data, 1); } } 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 { zend_string *alias; bool param_is_array; bool var_is_array; - sp_list_node *param_array_keys; - sp_list_node *var_array_keys; + // sp_list_node *param_array_keys; + // sp_list_node *var_array_keys; bool allow; @@ -281,7 +281,9 @@ int parse_php_type(char *restrict, char *restrict, void *); int parse_list(char *restrict, char *restrict, void *); // cleanup -void sp_disabled_function_list_free(sp_list_node *); -void sp_cookie_list_free(sp_list_node *); +void sp_free_disabled_function(void *data); +void sp_free_cookie(void *data); +void sp_free_zstr(void *data); + #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 @@ #include "php_snuffleupagus.h" -void sp_list_free(sp_list_node *node) { +void sp_list_free(sp_list_node *node, void (*free_data_func)(void *data)) { while (node) { sp_list_node *tmp = node->next; + if (free_data_func && node->data) { + free_data_func(node->data); + } + pefree(node, 1); + node = tmp; + } +} + +void sp_list_free2(sp_list_node *node) { + while (node) { + sp_list_node *tmp = node->next; + if (node->data) { + pefree(node->data, 1); + } pefree(node, 1); node = tmp; } 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, sp_list_node const *const)); sp_list_node *sp_list_insert(sp_list_node *, void *); sp_list_node *sp_list_prepend(sp_list_node *, void *); -void sp_list_free(sp_list_node *); +void sp_list_free(sp_list_node *, void (*free_data_func)(void *data)); +void sp_list_free2(sp_list_node *node); #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) { } tokens_list = sp_list_sort(tokens_list, cmp_tokens); tree = parse_tokens(line, tokens_list); - sp_list_free(tokens_list); + sp_list_free2(tokens_list); // Check if tree is empty. if (tree && tree->next == NULL && tree->type == UNDEFINED) { tree->type = CONSTANT; -- cgit v1.3