Skip to content

Commit

Permalink
properly free memory on shutdown
Browse files Browse the repository at this point in the history
  • Loading branch information
bef committed Aug 2, 2021
1 parent 4cda012 commit ae4ac9f
Show file tree
Hide file tree
Showing 6 changed files with 110 additions and 72 deletions.
77 changes: 41 additions & 36 deletions src/snuffleupagus.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;

Expand All @@ -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;
Expand All @@ -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);
Expand All @@ -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) {
Expand Down Expand Up @@ -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};

Expand Down
74 changes: 45 additions & 29 deletions src/sp_config.c
Original file line number Diff line number Diff line change
Expand Up @@ -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);
}
}
10 changes: 6 additions & 4 deletions src/sp_config.h
Original file line number Diff line number Diff line change
Expand Up @@ -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;

Expand Down Expand Up @@ -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 */
16 changes: 15 additions & 1 deletion src/sp_list.c
Original file line number Diff line number Diff line change
@@ -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;
}
Expand Down
3 changes: 2 additions & 1 deletion src/sp_list.h
Original file line number Diff line number Diff line change
Expand Up @@ -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
2 changes: 1 addition & 1 deletion src/sp_var_parser.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down

0 comments on commit ae4ac9f

Please sign in to comment.