diff --git a/include/common/uri_auth.h b/include/common/uri_auth.h index fbbe7df81..e52387c1d 100644 --- a/include/common/uri_auth.h +++ b/include/common/uri_auth.h @@ -42,6 +42,7 @@ struct uri_auth { int flags; /* some flags describing the statistics page */ struct user_auth *users; /* linked list of valid user:passwd couples */ struct stat_scope *scope; /* linked list of authorized proxies */ + struct uri_auth *next; /* Used at deinit() to build a list of unique elements */ }; /* This is the default statistics URI */ diff --git a/include/types/acl.h b/include/types/acl.h index ef5be58dc..53f9e708b 100644 --- a/include/types/acl.h +++ b/include/types/acl.h @@ -101,6 +101,7 @@ struct acl_pattern { char *str; /* any string */ regex_t *reg; /* a compiled regex */ } ptr; /* indirect values, allocated */ + void(*freeptrbuf)(void *ptr); /* a destructor able to free objects from the ptr */ int len; /* data length when required */ int flags; /* expr or pattern flags. */ }; diff --git a/src/acl.c b/src/acl.c index 96b21de42..02678f2d1 100644 --- a/src/acl.c +++ b/src/acl.c @@ -285,6 +285,12 @@ int acl_parse_str(const char **text, struct acl_pattern *pattern, int *opaque) return 1; } +/* Free data allocated by acl_parse_reg */ +static void acl_free_reg(void *ptr) { + + regfree((regex_t *)ptr); +} + /* Parse a regex. It is allocated. */ int acl_parse_reg(const char **text, struct acl_pattern *pattern, int *opaque) { @@ -303,6 +309,7 @@ int acl_parse_reg(const char **text, struct acl_pattern *pattern, int *opaque) } pattern->ptr.reg = preg; + pattern->freeptrbuf = &acl_free_reg; return 1; } @@ -452,8 +459,14 @@ struct acl_keyword *find_acl_kw(const char *kw) static void free_pattern(struct acl_pattern *pat) { - if (pat->ptr.ptr) + + if (pat->ptr.ptr) { + if (pat->freeptrbuf) + pat->freeptrbuf(pat->ptr.ptr); + free(pat->ptr.ptr); + } + free(pat); } diff --git a/src/haproxy.c b/src/haproxy.c index 4b6bdf899..d52524f6b 100644 --- a/src/haproxy.c +++ b/src/haproxy.c @@ -647,8 +647,11 @@ void deinit(void) struct acl_cond *cond, *condb; struct hdr_exp *exp, *expb; struct acl *acl, *aclb; + struct switching_rule *rule, *ruleb; + struct uri_auth *uap, *ua = NULL; + struct user_auth *user; int i; - + while (p) { if (p->id) free(p->id); @@ -699,8 +702,11 @@ void deinit(void) } for (exp = p->req_exp; exp != NULL; ) { - if (exp->preg) + if (exp->preg) { regfree((regex_t *)exp->preg); + free((regex_t *)exp->preg); + } + if (exp->replace && exp->action != ACT_SETBE) free((char *)exp->replace); expb = exp; @@ -709,8 +715,11 @@ void deinit(void) } for (exp = p->rsp_exp; exp != NULL; ) { - if (exp->preg) + if (exp->preg) { regfree((regex_t *)exp->preg); + free((regex_t *)exp->preg); + } + if (exp->replace && exp->action != ACT_SETBE) free((char *)exp->replace); expb = exp; @@ -718,9 +727,21 @@ void deinit(void) free(expb); } - /* FIXME: this must also be freed : - * - uri_auth (but it's shared) - */ + /* build a list of unique uri_auths */ + if (!ua) + ua = p->uri_auth; + else { + /* check if p->uri_auth is unique */ + for (uap = ua; uap; uap=uap->next) + if (uap == p->uri_auth) + break; + + if (!uap) { + /* add it, if it is */ + p->uri_auth->next = ua; + ua = p->uri_auth; + } + } list_for_each_entry_safe(acl, aclb, &p->acl, list) { LIST_DEL(&acl->list); @@ -728,6 +749,15 @@ void deinit(void) free(acl); } + list_for_each_entry_safe(rule, ruleb, &p->switching_rules, list) { + LIST_DEL(&rule->list); + + prune_acl_cond(rule->cond); + free(rule->cond); + + free(rule); + } + if (p->appsession_name) free(p->appsession_name); @@ -791,6 +821,27 @@ void deinit(void) free(p0); }/* end while(p) */ + while (ua) { + uap = ua; + ua = ua->next; + + if (uap->uri_prefix) + free(uap->uri_prefix); + + if (uap->auth_realm) + free(uap->auth_realm); + + while (uap->users) { + user = uap->users; + uap->users = uap->users->next; + + free(user->user_pwd); + free(user); + } + + free(uap); + } + protocol_unbind_all(); if (global.chroot) free(global.chroot); @@ -802,6 +853,9 @@ void deinit(void) if (fdtab) free(fdtab); fdtab = NULL; + if (oldpids) + free(oldpids); + pool_destroy2(pool2_session); pool_destroy2(pool2_buffer); pool_destroy2(pool2_requri);