From: Stephan Bosch Date: Fri, 7 Dec 2018 21:38:19 +0000 (+0100) Subject: lib-http: client: Fix panic occurring at connection failure. X-Git-Tag: 2.3.6~105 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=b922e51d2d1fd32c5934ac8a1bb0e5eb4017a6ee;p=thirdparty%2Fdovecot%2Fcore.git lib-http: client: Fix panic occurring at connection failure. In http_client_peer_connection_failed_pool(), all linked queues are notified about the connection failure through http_client_queue_connection_failure(). That function can internally link and unlink peers to the queue, including the calling one. This means that the peer->queues array can be modified while it is iterated in the array_foreach() loop. The problem is fixed by making a local copy of the peer->queues array. --- diff --git a/src/lib-http/http-client-peer.c b/src/lib-http/http-client-peer.c index aaf098fe1d..5a668f074d 100644 --- a/src/lib-http/http-client-peer.c +++ b/src/lib-http/http-client-peer.c @@ -1270,7 +1270,8 @@ static void http_client_peer_connection_failed_pool(struct http_client_peer *peer, const char *reason) { - struct http_client_queue *const *queue; + struct http_client_queue *const *queuep; + ARRAY_TYPE(http_client_queue) queues; e_debug(peer->event, "Failed to establish any connection within our peer pool: %s " @@ -1279,11 +1280,17 @@ http_client_peer_connection_failed_pool(struct http_client_peer *peer, peer->connect_failed = TRUE; + /* make a copy of the queue array; queues get linked/unlinged while the + connection failure is handled */ + t_array_init(&queues, array_count(&peer->queues)); + array_copy(&queues.arr, 0, &peer->queues.arr, 0, + array_count(&peer->queues)); + /* failed to make any connection. a second connect will probably also fail, so just try another IP for the hosts(s) or abort all requests if this was the only/last option. */ - array_foreach(&peer->queues, queue) - http_client_queue_connection_failure(*queue, peer, reason); + array_foreach(&queues, queuep) + http_client_queue_connection_failure(*queuep, peer, reason); } void http_client_peer_connection_lost(struct http_client_peer *peer,