BUG/MINOR: h2: fix reverse if no timeout defined

h2c.task is not allocated in h2_init() if timeout client/server is not
defined depending on the connection side. This caused crash on
connection reverse due to systematic requeuing of h2c.task in
h2_conn_reverse().

To fix this, check h2c.task in h2_conn_reverse(). If old timeout was
undefined but new one is, h2c.task must be allocated as it was not in
h2_init(). On the opposite situation, if old timeout was defined and new
one is not, h2c.task is freed. In this case, or if neither timeout are
defined, skip the task requeuing.

This bug is easily reproduced by using reverse bind or server with
undefined timeout client/server depending on the connection reverse
direction.

This bug has been introduced by reverse connect support.
No need to backport it.
This commit is contained in:
Amaury Denoyelle 2023-08-24 17:32:50 +02:00
parent 36d936dd15
commit 6bd994d5d7

View File

@ -3294,8 +3294,27 @@ static int h2_conn_reverse(struct h2c *h2c)
h2c->flags |= H2_CF_DEM_TOOMANY;
}
h2c->task->expire = tick_add(now_ms, h2c->timeout);
task_queue(h2c->task);
/* If only the new side has a defined timeout, task must be allocated.
* On the contrary, if only old side has a timeout, it must be freed.
*/
if (!h2c->task && tick_isset(h2c->timeout)) {
h2c->task = task_new_here();
if (!h2c->task)
goto err;
h2c->task->process = h2_timeout_task;
h2c->task->context = h2c;
}
else if (!tick_isset(h2c->timeout)) {
task_destroy(h2c->task);
h2c->task = NULL;
}
/* Requeue task if instantiated with the new timeout value. */
if (h2c->task) {
h2c->task->expire = tick_add(now_ms, h2c->timeout);
task_queue(h2c->task);
}
TRACE_LEAVE(H2_EV_H2C_WAKE, h2c->conn);
return 1;