mirror of
http://git.haproxy.org/git/haproxy.git/
synced 2025-02-01 11:01:46 +00:00
[BUG] http: fix for capture memory leak was incorrect
That patch was incorrect because under some circumstances, the capture memory could be freed by session_free() and then again by http_end_txn(), causing a double free and an eventual segfault. The pool use count was also reported wrong due to this bug. The cleanup code was removed from session_free() to remain only in http_end_txn().
This commit is contained in:
parent
6fe60182aa
commit
4602363f6a
@ -6310,19 +6310,11 @@ void http_init_txn(struct session *s)
|
||||
if (fe->options2 & PR_O2_REQBUG_OK)
|
||||
txn->req.err_pos = -1; /* let buggy requests pass */
|
||||
|
||||
if (txn->req.cap) {
|
||||
struct cap_hdr *h;
|
||||
for (h = fe->req_cap; h; h = h->next)
|
||||
pool_free2(h->pool, txn->req.cap[h->index]);
|
||||
if (txn->req.cap)
|
||||
memset(txn->req.cap, 0, fe->nb_req_cap * sizeof(void *));
|
||||
}
|
||||
|
||||
if (txn->rsp.cap) {
|
||||
struct cap_hdr *h;
|
||||
for (h = fe->rsp_cap; h; h = h->next)
|
||||
pool_free2(h->pool, txn->rsp.cap[h->index]);
|
||||
if (txn->rsp.cap)
|
||||
memset(txn->rsp.cap, 0, fe->nb_rsp_cap * sizeof(void *));
|
||||
}
|
||||
|
||||
if (txn->hdr_idx.v)
|
||||
hdr_idx_init(&txn->hdr_idx);
|
||||
@ -6340,6 +6332,21 @@ void http_end_txn(struct session *s)
|
||||
txn->uri = NULL;
|
||||
txn->srv_cookie = NULL;
|
||||
txn->cli_cookie = NULL;
|
||||
|
||||
if (txn->req.cap) {
|
||||
struct cap_hdr *h;
|
||||
for (h = s->fe->req_cap; h; h = h->next)
|
||||
pool_free2(h->pool, txn->req.cap[h->index]);
|
||||
memset(txn->req.cap, 0, s->fe->nb_req_cap * sizeof(void *));
|
||||
}
|
||||
|
||||
if (txn->rsp.cap) {
|
||||
struct cap_hdr *h;
|
||||
for (h = s->fe->rsp_cap; h; h = h->next)
|
||||
pool_free2(h->pool, txn->rsp.cap[h->index]);
|
||||
memset(txn->rsp.cap, 0, s->fe->nb_rsp_cap * sizeof(void *));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/* to be used at the end of a transaction to prepare a new one */
|
||||
|
@ -81,25 +81,14 @@ void session_free(struct session *s)
|
||||
if (s->sessid)
|
||||
pool_free2(apools.sessid, s->sessid);
|
||||
|
||||
http_end_txn(s);
|
||||
|
||||
if (fe) {
|
||||
pool_free2(fe->hdr_idx_pool, txn->hdr_idx.v);
|
||||
|
||||
if (txn->rsp.cap != NULL) {
|
||||
struct cap_hdr *h;
|
||||
for (h = fe->rsp_cap; h; h = h->next)
|
||||
pool_free2(h->pool, txn->rsp.cap[h->index]);
|
||||
pool_free2(fe->rsp_cap_pool, txn->rsp.cap);
|
||||
}
|
||||
if (txn->req.cap != NULL) {
|
||||
struct cap_hdr *h;
|
||||
for (h = fe->req_cap; h; h = h->next)
|
||||
pool_free2(h->pool, txn->req.cap[h->index]);
|
||||
pool_free2(fe->req_cap_pool, txn->req.cap);
|
||||
}
|
||||
pool_free2(fe->rsp_cap_pool, txn->rsp.cap);
|
||||
pool_free2(fe->req_cap_pool, txn->req.cap);
|
||||
}
|
||||
|
||||
http_end_txn(s);
|
||||
|
||||
list_for_each_entry_safe(bref, back, &s->back_refs, users) {
|
||||
/* we have to unlink all watchers. We must not relink them if
|
||||
* this session was the last one in the list.
|
||||
|
Loading…
Reference in New Issue
Block a user