diff options
Diffstat (limited to 'src/sp_config.c')
| -rw-r--r-- | src/sp_config.c | 440 |
1 files changed, 247 insertions, 193 deletions
diff --git a/src/sp_config.c b/src/sp_config.c index c12b435..7294b0e 100644 --- a/src/sp_config.c +++ b/src/sp_config.c | |||
| @@ -4,248 +4,302 @@ | |||
| 4 | 4 | ||
| 5 | #include "php_snuffleupagus.h" | 5 | #include "php_snuffleupagus.h" |
| 6 | 6 | ||
| 7 | size_t sp_line_no; | ||
| 8 | 7 | ||
| 9 | static sp_config_tokens const sp_func[] = { | 8 | static zend_result sp_process_config_root(sp_parsed_keyword *parsed_rule) { |
| 10 | {.func = parse_unserialize, .token = SP_TOKEN_UNSERIALIZE_HMAC}, | 9 | sp_config_keyword sp_func[] = { |
| 11 | {.func = parse_random, .token = SP_TOKEN_HARDEN_RANDOM}, | 10 | {parse_unserialize, SP_TOKEN_UNSERIALIZE_HMAC, &(SPCFG(unserialize))}, |
| 12 | {.func = parse_log_media, .token = SP_TOKEN_LOG_MEDIA}, | 11 | {parse_enable, SP_TOKEN_HARDEN_RANDOM, &(SPCFG(random).enable)}, |
| 13 | {.func = parse_disabled_functions, .token = SP_TOKEN_DISABLE_FUNC}, | 12 | {parse_log_media, SP_TOKEN_LOG_MEDIA, &(SPCFG(log_media))}, |
| 14 | {.func = parse_readonly_exec, .token = SP_TOKEN_READONLY_EXEC}, | 13 | {parse_disabled_functions, SP_TOKEN_DISABLE_FUNC, NULL}, |
| 15 | {.func = parse_global_strict, .token = SP_TOKEN_GLOBAL_STRICT}, | 14 | {parse_readonly_exec, SP_TOKEN_READONLY_EXEC, &(SPCFG(readonly_exec))}, |
| 16 | {.func = parse_upload_validation, .token = SP_TOKEN_UPLOAD_VALIDATION}, | 15 | {parse_enable, SP_TOKEN_GLOBAL_STRICT, &(SPCFG(global_strict).enable)}, |
| 17 | {.func = parse_cookie, .token = SP_TOKEN_COOKIE_ENCRYPTION}, | 16 | {parse_upload_validation, SP_TOKEN_UPLOAD_VALIDATION, &(SPCFG(upload_validation))}, |
| 18 | {.func = parse_global, .token = SP_TOKEN_GLOBAL}, | 17 | {parse_cookie, SP_TOKEN_COOKIE_ENCRYPTION, NULL}, |
| 19 | {.func = parse_auto_cookie_secure, .token = SP_TOKEN_AUTO_COOKIE_SECURE}, | 18 | {parse_global, SP_TOKEN_GLOBAL, NULL}, |
| 20 | {.func = parse_disable_xxe, .token = SP_TOKEN_DISABLE_XXE}, | 19 | {parse_enable, SP_TOKEN_AUTO_COOKIE_SECURE, &(SPCFG(auto_cookie_secure).enable)}, |
| 21 | {.func = parse_eval_blacklist, .token = SP_TOKEN_EVAL_BLACKLIST}, | 20 | {parse_enable, SP_TOKEN_XXE_PROTECTION, &(SPCFG(xxe_protection).enable)}, |
| 22 | {.func = parse_eval_whitelist, .token = SP_TOKEN_EVAL_WHITELIST}, | 21 | {parse_eval_filter_conf, SP_TOKEN_EVAL_BLACKLIST, &(SPCFG(eval).blacklist)}, |
| 23 | {.func = parse_session, .token = SP_TOKEN_SESSION_ENCRYPTION}, | 22 | {parse_eval_filter_conf, SP_TOKEN_EVAL_WHITELIST, &(SPCFG(eval).whitelist)}, |
| 24 | {.func = parse_sloppy_comparison, .token = SP_TOKEN_SLOPPY_COMPARISON}, | 23 | {parse_session, SP_TOKEN_SESSION_ENCRYPTION, &(SPCFG(session))}, |
| 25 | {.func = parse_wrapper_whitelist, .token = SP_TOKEN_ALLOW_WRAPPERS}, | 24 | {parse_enable, SP_TOKEN_SLOPPY_COMPARISON, &(SPCFG(sloppy).enable)}, |
| 26 | {NULL, NULL}}; | 25 | {parse_wrapper_whitelist, SP_TOKEN_ALLOW_WRAPPERS, &(SPCFG(wrapper))}, |
| 26 | {parse_ini_protection, SP_TOKEN_INI_PROTECTION, &(SPCFG(ini))}, | ||
| 27 | {parse_ini_entry, SP_TOKEN_INI, NULL}, | ||
| 28 | {NULL, NULL, NULL}}; | ||
| 29 | return sp_process_rule(parsed_rule, sp_func); | ||
| 30 | } | ||
| 27 | 31 | ||
| 28 | /* Top level keyword parsing */ | 32 | zend_result sp_parse_config(const char *filename) { |
| 33 | FILE *fd = fopen(filename, "rb"); | ||
| 34 | if (fd == NULL) { | ||
| 35 | sp_log_err("config", "Could not open configuration file %s : %s", filename, strerror(errno)); | ||
| 36 | return FAILURE; | ||
| 37 | } | ||
| 29 | 38 | ||
| 30 | static int parse_line(char *line) { | 39 | size_t step = 8192; |
| 31 | char *ptr = line; | 40 | size_t max_len = step, len = 0; |
| 41 | zend_string *data = zend_string_alloc(max_len, 0); | ||
| 42 | char *ptr = ZSTR_VAL(data); | ||
| 32 | 43 | ||
| 33 | while (*ptr == ' ' || *ptr == '\t') { | 44 | size_t bytes; |
| 34 | ++ptr; | 45 | while ((bytes = fread(ptr, 1, max_len - len, fd))) { |
| 46 | len += bytes; | ||
| 47 | if (max_len - len <= 0) { | ||
| 48 | max_len += step; | ||
| 49 | data = zend_string_extend(data, max_len, 0); | ||
| 50 | ptr = ZSTR_VAL(data) + len; | ||
| 51 | } else { | ||
| 52 | ptr += bytes; | ||
| 53 | } | ||
| 35 | } | 54 | } |
| 55 | fclose(fd); | ||
| 36 | 56 | ||
| 37 | if (!*ptr || *ptr == '#' || *ptr == ';') { | 57 | data = zend_string_truncate(data, len, 0); |
| 38 | return 0; | 58 | ZSTR_VAL(data)[len] = 0; |
| 39 | } | ||
| 40 | 59 | ||
| 41 | if (strncmp(ptr, SP_TOKEN_BASE, strlen(SP_TOKEN_BASE))) { | 60 | int ret = sp_config_scan(ZSTR_VAL(data), sp_process_config_root); |
| 42 | sp_log_err("config", "Invalid configuration prefix for '%s' on line %zu", | ||
| 43 | line, sp_line_no); | ||
| 44 | return -1; | ||
| 45 | } | ||
| 46 | ptr += strlen(SP_TOKEN_BASE); | ||
| 47 | 61 | ||
| 48 | for (size_t i = 0; sp_func[i].func; i++) { | 62 | zend_string_release_ex(data, 0); |
| 49 | if (!strncmp(sp_func[i].token, ptr, strlen(sp_func[i].token))) { | 63 | |
| 50 | return sp_func[i].func(ptr + strlen(sp_func[i].token)); | 64 | return ret; |
| 65 | } | ||
| 66 | |||
| 67 | |||
| 68 | zend_result sp_process_rule(sp_parsed_keyword *parsed_rule, sp_config_keyword *config_keywords) { | ||
| 69 | for (sp_parsed_keyword *kw = parsed_rule; kw->kw; kw++) { | ||
| 70 | bool found_kw = false; | ||
| 71 | for (sp_config_keyword *ckw = config_keywords; ckw->func; ckw++) { | ||
| 72 | if (kw->kwlen == strlen(ckw->token) && !strncmp(kw->kw, ckw->token, kw->kwlen)) { | ||
| 73 | if (ckw->func) { | ||
| 74 | int ret = ckw->func(ckw->token, kw, ckw->retval); | ||
| 75 | switch (ret) { | ||
| 76 | case SP_PARSER_SUCCESS: | ||
| 77 | break; | ||
| 78 | case SP_PARSER_ERROR: | ||
| 79 | return FAILURE; | ||
| 80 | case SP_PARSER_STOP: | ||
| 81 | return SUCCESS; | ||
| 82 | } | ||
| 83 | } | ||
| 84 | found_kw = true; | ||
| 85 | break; | ||
| 86 | } | ||
| 87 | } | ||
| 88 | |||
| 89 | if (!found_kw) { | ||
| 90 | zend_string *kwname = zend_string_init(kw->kw, kw->kwlen, 0); | ||
| 91 | sp_log_err("config", "Unexpected keyword '%s' on line %d", ZSTR_VAL(kwname), kw->lineno); | ||
| 92 | zend_string_release_ex(kwname, 0); | ||
| 93 | return FAILURE; | ||
| 51 | } | 94 | } |
| 52 | } | 95 | } |
| 53 | sp_log_err("config", "Invalid configuration section '%s' on line %zu", line, | 96 | return SUCCESS; |
| 54 | sp_line_no); | ||
| 55 | return -1; | ||
| 56 | } | 97 | } |
| 57 | 98 | ||
| 58 | /* keyword parsing */ | 99 | #define CHECK_DUPLICATE_KEYWORD(retval) \ |
| 59 | int parse_empty(char *restrict line, char *restrict keyword, void *retval) { | 100 | if (*(void**)(retval)) { \ |
| 101 | sp_log_err("config", "duplicate keyword '%s' on line %zu", token, kw->lineno); \ | ||
| 102 | return SP_PARSER_ERROR; } | ||
| 103 | |||
| 104 | |||
| 105 | SP_PARSEKW_FN(parse_empty) { | ||
| 106 | if (kw->arglen) { | ||
| 107 | sp_log_err("config", "Unexpected argument for keyword '%s' - it should be '%s()' on line %zu", token, token, kw->lineno); | ||
| 108 | return SP_PARSER_ERROR; | ||
| 109 | } | ||
| 110 | if (kw->argtype != SP_ARGTYPE_EMPTY) { | ||
| 111 | sp_log_err("config", "Missing paranthesis for keyword '%s' - it should be '%s()' on line %zu", token, token, kw->lineno); | ||
| 112 | return SP_PARSER_ERROR; | ||
| 113 | } | ||
| 60 | *(bool *)retval = true; | 114 | *(bool *)retval = true; |
| 61 | return 0; | 115 | return SP_PARSER_SUCCESS; |
| 62 | } | 116 | } |
| 63 | 117 | ||
| 64 | int parse_list(char *restrict line, char *restrict keyword, void *list_ptr) { | 118 | SP_PARSEKW_FN(parse_list) { |
| 65 | zend_string *value = NULL; | 119 | CHECK_DUPLICATE_KEYWORD(retval); |
| 66 | sp_list_node **list = list_ptr; | ||
| 67 | char *token, *tmp; | ||
| 68 | 120 | ||
| 69 | size_t consumed = 0; | 121 | sp_list_node **list = retval; |
| 70 | value = get_param(&consumed, line, SP_TYPE_STR, keyword); | 122 | char *tok, *tmp; |
| 71 | if (!value) { | 123 | |
| 72 | return -1; | 124 | SP_PARSE_ARG(value); |
| 73 | } | ||
| 74 | 125 | ||
| 75 | tmp = ZSTR_VAL(value); | 126 | tmp = ZSTR_VAL(value); |
| 76 | while (1) { | 127 | while (1) { |
| 77 | token = strsep(&tmp, ","); | 128 | tok = strsep(&tmp, ","); |
| 78 | if (token == NULL) { | 129 | if (tok == NULL) { |
| 79 | break; | 130 | break; |
| 80 | } | 131 | } |
| 81 | *list = sp_list_insert(*list, zend_string_init(token, strlen(token), 1)); | 132 | *list = sp_list_insert(*list, zend_string_init(tok, strlen(tok), 1)); |
| 82 | } | 133 | } |
| 134 | zend_string_release(value); | ||
| 83 | 135 | ||
| 84 | pefree(value, 1); | 136 | return SP_PARSER_SUCCESS; |
| 85 | return consumed; | ||
| 86 | } | 137 | } |
| 87 | 138 | ||
| 88 | int parse_php_type(char *restrict line, char *restrict keyword, void *retval) { | 139 | SP_PARSEKW_FN(parse_php_type) { |
| 89 | size_t consumed = 0; | 140 | SP_PARSE_ARG(value); |
| 90 | zend_string *value = get_param(&consumed, line, SP_TYPE_STR, keyword); | 141 | |
| 91 | if (value) { | 142 | if (zend_string_equals_literal_ci(value, "undef")) { |
| 92 | if (zend_string_equals_literal_ci(value, "undef")) { | 143 | *(sp_php_type *)retval = SP_PHP_TYPE_UNDEF; |
| 93 | *(sp_php_type *)retval = SP_PHP_TYPE_UNDEF; | 144 | } else if (zend_string_equals_literal_ci(value, "null")) { |
| 94 | } else if (zend_string_equals_literal_ci(value, "null")) { | 145 | *(sp_php_type *)retval = SP_PHP_TYPE_NULL; |
| 95 | *(sp_php_type *)retval = SP_PHP_TYPE_NULL; | 146 | } else if (zend_string_equals_literal_ci(value, "true")) { |
| 96 | } else if (zend_string_equals_literal_ci(value, "true")) { | 147 | *(sp_php_type *)retval = SP_PHP_TYPE_TRUE; |
| 97 | *(sp_php_type *)retval = SP_PHP_TYPE_TRUE; | 148 | } else if (zend_string_equals_literal_ci(value, "false")) { |
| 98 | } else if (zend_string_equals_literal_ci(value, "false")) { | 149 | *(sp_php_type *)retval = SP_PHP_TYPE_FALSE; |
| 99 | *(sp_php_type *)retval = SP_PHP_TYPE_FALSE; | 150 | } else if (zend_string_equals_literal_ci(value, "long")) { |
| 100 | } else if (zend_string_equals_literal_ci(value, "long")) { | 151 | *(sp_php_type *)retval = SP_PHP_TYPE_LONG; |
| 101 | *(sp_php_type *)retval = SP_PHP_TYPE_LONG; | 152 | } else if (zend_string_equals_literal_ci(value, "double")) { |
| 102 | } else if (zend_string_equals_literal_ci(value, "double")) { | 153 | *(sp_php_type *)retval = SP_PHP_TYPE_DOUBLE; |
| 103 | *(sp_php_type *)retval = SP_PHP_TYPE_DOUBLE; | 154 | } else if (zend_string_equals_literal_ci(value, "string")) { |
| 104 | } else if (zend_string_equals_literal_ci(value, "string")) { | 155 | *(sp_php_type *)retval = SP_PHP_TYPE_STRING; |
| 105 | *(sp_php_type *)retval = SP_PHP_TYPE_STRING; | 156 | } else if (zend_string_equals_literal_ci(value, "array")) { |
| 106 | } else if (zend_string_equals_literal_ci(value, "array")) { | 157 | *(sp_php_type *)retval = SP_PHP_TYPE_ARRAY; |
| 107 | *(sp_php_type *)retval = SP_PHP_TYPE_ARRAY; | 158 | } else if (zend_string_equals_literal_ci(value, "object")) { |
| 108 | } else if (zend_string_equals_literal_ci(value, "object")) { | 159 | *(sp_php_type *)retval = SP_PHP_TYPE_OBJECT; |
| 109 | *(sp_php_type *)retval = SP_PHP_TYPE_OBJECT; | 160 | } else if (zend_string_equals_literal_ci(value, "resource")) { |
| 110 | } else if (zend_string_equals_literal_ci(value, "resource")) { | 161 | *(sp_php_type *)retval = SP_PHP_TYPE_RESOURCE; |
| 111 | *(sp_php_type *)retval = SP_PHP_TYPE_RESOURCE; | 162 | } else if (zend_string_equals_literal_ci(value, "reference")) { |
| 112 | } else if (zend_string_equals_literal_ci(value, "reference")) { | 163 | *(sp_php_type *)retval = SP_PHP_TYPE_REFERENCE; |
| 113 | *(sp_php_type *)retval = SP_PHP_TYPE_REFERENCE; | ||
| 114 | } else { | ||
| 115 | pefree(value, 1); | ||
| 116 | sp_log_err("error", | ||
| 117 | "%s) is expecting a valid php type ('false', 'true'," | ||
| 118 | " 'array'. 'object', 'long', 'double', 'null', 'resource', " | ||
| 119 | "'reference', 'undef') on line %zu", | ||
| 120 | keyword, sp_line_no); | ||
| 121 | return -1; | ||
| 122 | } | ||
| 123 | pefree(value, 1); | ||
| 124 | return consumed; | ||
| 125 | } else { | 164 | } else { |
| 126 | return -1; | 165 | zend_string_release(value); |
| 166 | sp_log_err("error", ".%s() is expecting a valid php type ('false', 'true'," | ||
| 167 | " 'array'. 'object', 'long', 'double', 'null', 'resource', " | ||
| 168 | "'reference', 'undef') on line %zu", token, kw->lineno); | ||
| 169 | return SP_PARSER_ERROR; | ||
| 127 | } | 170 | } |
| 171 | zend_string_release(value); | ||
| 172 | return SP_PARSER_SUCCESS; | ||
| 128 | } | 173 | } |
| 129 | 174 | ||
| 130 | int parse_str(char *restrict line, char *restrict keyword, void *retval) { | ||
| 131 | zend_string *value = NULL; | ||
| 132 | 175 | ||
| 133 | size_t consumed = 0; | 176 | SP_PARSEKW_FN(parse_str) { |
| 134 | value = get_param(&consumed, line, SP_TYPE_STR, keyword); | 177 | CHECK_DUPLICATE_KEYWORD(retval); |
| 135 | if (value) { | 178 | SP_PARSE_ARG(value); |
| 136 | *(zend_string **)retval = value; | 179 | |
| 137 | return consumed; | 180 | *(zend_string **)retval = value; |
| 138 | } | 181 | |
| 139 | return -1; | 182 | return SP_PARSER_SUCCESS; |
| 140 | } | 183 | } |
| 141 | 184 | ||
| 142 | int parse_cidr(char *restrict line, char *restrict keyword, void *retval) { | 185 | SP_PARSEKW_FN(parse_int) { |
| 143 | size_t consumed = 0; | 186 | int ret = SP_PARSER_SUCCESS; |
| 144 | zend_string *value = get_param(&consumed, line, SP_TYPE_STR, keyword); | 187 | SP_PARSE_ARG(value); |
| 145 | sp_cidr *cidr = pecalloc(sizeof(sp_cidr), 1, 1); | ||
| 146 | 188 | ||
| 147 | if (value) { | 189 | char *endptr; |
| 148 | if (-1 == get_ip_and_cidr(ZSTR_VAL(value), cidr)) { | 190 | errno = 0; |
| 149 | return -1; | 191 | *(int*)retval = (int)strtoimax(ZSTR_VAL(value), &endptr, 10); |
| 150 | } | 192 | if (errno != 0 || !endptr || endptr == ZSTR_VAL(value)) { |
| 151 | *(sp_cidr **)retval = cidr; | 193 | sp_log_err("config", "Failed to parse arg '%s' of `%s` on line %zu", ZSTR_VAL(value), token, kw->lineno); |
| 152 | return consumed; | 194 | ret = SP_PARSER_ERROR; |
| 153 | } else { | ||
| 154 | sp_log_err("config", "%s doesn't contain a valid cidr on line %zu", line, | ||
| 155 | sp_line_no); | ||
| 156 | return -1; | ||
| 157 | } | 195 | } |
| 196 | zend_string_release(value); | ||
| 197 | return ret; | ||
| 158 | } | 198 | } |
| 159 | 199 | ||
| 160 | int parse_regexp(char *restrict line, char *restrict keyword, void *retval) { | 200 | SP_PARSEKW_FN(parse_ulong) { |
| 161 | /* TODO: Do we want to use pcre_study? | 201 | int ret = SP_PARSER_SUCCESS; |
| 162 | * (http://www.pcre.org/original/doc/html/pcre_study.html) | 202 | SP_PARSE_ARG(value); |
| 163 | * maybe not: http://sljit.sourceforge.net/pcre.html*/ | ||
| 164 | size_t consumed = 0; | ||
| 165 | zend_string *value = get_param(&consumed, line, SP_TYPE_STR, keyword); | ||
| 166 | 203 | ||
| 167 | if (value) { | 204 | char *endptr; |
| 168 | sp_pcre *compiled_re = sp_pcre_compile(ZSTR_VAL(value)); | 205 | errno = 0; |
| 169 | if (NULL != compiled_re) { | 206 | *(u_long*)retval = (u_long)strtoul(ZSTR_VAL(value), &endptr, 10); |
| 170 | *(sp_pcre **)retval = compiled_re; | 207 | if (errno != 0 || !endptr || endptr == ZSTR_VAL(value)) { |
| 171 | return consumed; | 208 | sp_log_err("config", "Failed to parse arg '%s' of `%s` on line %zu", ZSTR_VAL(value), token, kw->lineno); |
| 172 | } | 209 | ret = SP_PARSER_ERROR; |
| 173 | } | 210 | } |
| 174 | char *closing_paren = strchr(line, ')'); | 211 | zend_string_release(value); |
| 175 | if (NULL != closing_paren) { | 212 | return ret; |
| 176 | closing_paren[0] = '\0'; | ||
| 177 | } | ||
| 178 | sp_log_err("config", | ||
| 179 | "'%s)' is expecting a valid regexp, and not '%s' on line %zu", | ||
| 180 | keyword, line, sp_line_no); | ||
| 181 | return -1; | ||
| 182 | } | 213 | } |
| 183 | 214 | ||
| 184 | int sp_parse_config(const char *conf_file) { | 215 | SP_PARSEKW_FN(parse_cidr) { |
| 185 | FILE *fd = fopen(conf_file, "r"); | 216 | CHECK_DUPLICATE_KEYWORD(retval); |
| 186 | char *lineptr = NULL; | 217 | SP_PARSE_ARG(value); |
| 187 | size_t n = 0; | ||
| 188 | sp_line_no = 1; | ||
| 189 | 218 | ||
| 190 | if (fd == NULL) { | 219 | sp_cidr *cidr = pecalloc(sizeof(sp_cidr), 1, 1); |
| 191 | sp_log_err("config", "Could not open configuration file %s : %s", conf_file, | 220 | |
| 192 | strerror(errno)); | 221 | if (0 != get_ip_and_cidr(ZSTR_VAL(value), cidr)) { |
| 193 | return FAILURE; | 222 | pefree(cidr, 1); |
| 223 | cidr = NULL; | ||
| 194 | } | 224 | } |
| 195 | 225 | ||
| 196 | while (getline(&lineptr, &n, fd) > 0) { | 226 | *(sp_cidr **)retval = cidr; |
| 197 | /* We trash the terminal `\n`. This simplify the display of logs. */ | 227 | return cidr ? SP_PARSER_SUCCESS : SP_PARSER_ERROR; |
| 198 | if (lineptr[strlen(lineptr) - 1] == '\n') { | 228 | } |
| 199 | if (strlen(lineptr) >= 2 && lineptr[strlen(lineptr) - 2] == '\r') { | 229 | |
| 200 | lineptr[strlen(lineptr) - 2] = '\0'; | 230 | SP_PARSEKW_FN(parse_regexp) { |
| 201 | } else { | 231 | CHECK_DUPLICATE_KEYWORD(retval); |
| 202 | lineptr[strlen(lineptr) - 1] = '\0'; | 232 | SP_PARSE_ARG(value); |
| 203 | } | 233 | |
| 204 | } | 234 | sp_regexp *compiled_re = sp_regexp_compile(value); |
| 205 | if (parse_line(lineptr) == -1) { | 235 | if (!compiled_re) { |
| 206 | fclose(fd); | 236 | sp_log_err("config", "Invalid regexp '%s' for '.%s()' on line %zu", ZSTR_VAL(value), token, kw->lineno); |
| 207 | free(lineptr); | 237 | zend_string_release_ex(value, 1); |
| 208 | return FAILURE; | 238 | return SP_PARSER_ERROR; |
| 209 | } | ||
| 210 | free(lineptr); | ||
| 211 | lineptr = NULL; | ||
| 212 | n = 0; | ||
| 213 | sp_line_no++; | ||
| 214 | } | 239 | } |
| 215 | fclose(fd); | 240 | |
| 216 | return SUCCESS; | 241 | *(sp_regexp **)retval = compiled_re; |
| 242 | |||
| 243 | return SP_PARSER_SUCCESS; | ||
| 217 | } | 244 | } |
| 218 | 245 | ||
| 219 | void sp_disabled_function_list_free(sp_list_node *list) { | 246 | void sp_free_disabled_function(void *data) { |
| 220 | sp_list_node *cursor = list; | 247 | 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 | 248 | ||
| 228 | sp_pcre_free(df->r_filename); | 249 | 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 | 250 | ||
| 235 | sp_tree_free(df->param); | 251 | sp_free_zstr(df->filename); |
| 236 | sp_tree_free(df->var); | 252 | sp_regexp_free(df->r_filename); |
| 237 | } | 253 | |
| 238 | cursor = cursor->next; | 254 | sp_free_zstr(df->function); |
| 239 | } | 255 | sp_regexp_free(df->r_function); |
| 256 | sp_list_free(df->functions_list, free); | ||
| 257 | |||
| 258 | sp_free_zstr(df->hash); | ||
| 259 | |||
| 260 | sp_tree_free(df->param); | ||
| 261 | sp_regexp_free(df->r_param); | ||
| 262 | |||
| 263 | sp_regexp_free(df->r_ret); | ||
| 264 | sp_free_zstr(df->ret); | ||
| 265 | |||
| 266 | sp_regexp_free(df->r_value); | ||
| 267 | sp_free_zstr(df->value); | ||
| 268 | |||
| 269 | sp_regexp_free(df->r_key); | ||
| 270 | sp_free_zstr(df->key); | ||
| 271 | |||
| 272 | sp_free_zstr(df->dump); | ||
| 273 | sp_free_zstr(df->alias); | ||
| 274 | |||
| 275 | // sp_list_free(df->param_array_keys); | ||
| 276 | // sp_list_free(df->var_array_keys); | ||
| 277 | |||
| 278 | sp_tree_free(df->var); | ||
| 279 | |||
| 280 | pefree(df->cidr, 1); | ||
| 240 | } | 281 | } |
| 241 | 282 | ||
| 242 | void sp_cookie_list_free(sp_list_node *list) { | 283 | void sp_free_cookie(void *data) { |
| 243 | sp_list_node *cursor = list; | 284 | sp_cookie *c = data; |
| 244 | while (cursor) { | 285 | if (c->name) |
| 245 | sp_cookie *c = cursor->data; | 286 | zend_string_release_ex(c->name, 1); |
| 246 | if (c) { | 287 | sp_regexp_free(c->name_r); |
| 247 | sp_pcre_free(c->name_r); | 288 | } |
| 248 | } | 289 | |
| 249 | cursor = cursor->next; | 290 | void sp_free_zstr(void *data) { |
| 291 | if (data) { | ||
| 292 | zend_string_release_ex((zend_string*)data, 1); | ||
| 250 | } | 293 | } |
| 251 | } | 294 | } |
| 295 | |||
| 296 | void sp_free_ini_entry(void *data) { | ||
| 297 | sp_ini_entry *entry = data; | ||
| 298 | |||
| 299 | sp_free_zstr(entry->key); | ||
| 300 | sp_free_zstr(entry->min); | ||
| 301 | sp_free_zstr(entry->max); | ||
| 302 | sp_regexp_free(entry->regexp); | ||
| 303 | sp_free_zstr(entry->msg); | ||
| 304 | sp_free_zstr(entry->set); | ||
| 305 | } | ||
