]> git.ipfire.org Git - thirdparty/bind9.git/commitdiff
DoH: Fix missing send callback calls
authorArtem Boldariev <artem@boldariev.com>
Wed, 12 Feb 2025 20:58:42 +0000 (22:58 +0200)
committerArtem Boldariev <artem@boldariev.com>
Wed, 19 Feb 2025 17:42:15 +0000 (19:42 +0200)
When handling outgoing data, there were a couple of rarely executed
code paths that would not take into account that the callback MUST be
called.

It could lead to potential memory leaks and consequent shutdown hangs.

(cherry picked from commit 8b8f4d500d9c1d41d95d34a79c8935823978114c)

lib/isc/netmgr/http.c

index 1006581d485fb9c520abbc6771164f0b96dab248..2df182edbc1e71afdd7a9e22a9807d9e41227790 100644 (file)
@@ -1361,6 +1361,23 @@ move_pending_send_callbacks(isc_nm_http_session_t *session,
        ISC_LIST_INIT(session->pending_write_callbacks);
 }
 
+static inline void
+http_append_pending_send_request(isc_nm_http_session_t *session,
+                                isc_nmhandle_t *httphandle, isc_nm_cb_t cb,
+                                void *cbarg) {
+       REQUIRE(VALID_HTTP2_SESSION(session));
+       REQUIRE(VALID_NMHANDLE(httphandle));
+       REQUIRE(cb != NULL);
+
+       isc__nm_uvreq_t *newcb = isc__nm_uvreq_get(httphandle->sock->mgr,
+                                                  httphandle->sock);
+
+       newcb->cb.send = cb;
+       newcb->cbarg = cbarg;
+       isc_nmhandle_attach(httphandle, &newcb->handle);
+       ISC_LIST_APPEND(session->pending_write_callbacks, newcb, link);
+}
+
 static bool
 http_send_outgoing(isc_nm_http_session_t *session, isc_nmhandle_t *httphandle,
                   isc_nm_cb_t cb, void *cbarg) {
@@ -1372,10 +1389,25 @@ http_send_outgoing(isc_nm_http_session_t *session, isc_nmhandle_t *httphandle,
        size_t max_total_write_size = 0;
 #endif /* ENABLE_HTTP_WRITE_BUFFERING */
 
-       if (!http_session_active(session) ||
-           (!nghttp2_session_want_write(session->ngsession) &&
-            session->pending_write_data == NULL))
+       if (!http_session_active(session)) {
+               if (cb != NULL) {
+                       isc__nm_uvreq_t *req = isc__nm_uvreq_get(
+                               httphandle->sock->mgr, httphandle->sock);
+
+                       req->cb.send = cb;
+                       req->cbarg = cbarg;
+                       isc_nmhandle_attach(httphandle, &req->handle);
+                       isc__nm_sendcb(httphandle->sock, req, ISC_R_CANCELED,
+                                      true);
+               }
+               return false;
+       } else if (!nghttp2_session_want_write(session->ngsession) &&
+                  session->pending_write_data == NULL)
        {
+               if (cb != NULL) {
+                       http_append_pending_send_request(session, httphandle,
+                                                        cb, cbarg);
+               }
                return false;
        }
 
@@ -1435,15 +1467,8 @@ http_send_outgoing(isc_nm_http_session_t *session, isc_nmhandle_t *httphandle,
                 * FLUSH_HTTP_WRITE_BUFFER_AFTER bytes in the write buffer, we
                 * will flush the buffer. */
                if (cb != NULL) {
-                       isc__nm_uvreq_t *newcb = isc__nm_uvreq_get(
-                               httphandle->sock->mgr, httphandle->sock);
-
-                       INSIST(VALID_NMHANDLE(httphandle));
-                       newcb->cb.send = cb;
-                       newcb->cbarg = cbarg;
-                       isc_nmhandle_attach(httphandle, &newcb->handle);
-                       ISC_LIST_APPEND(session->pending_write_callbacks, newcb,
-                                       link);
+                       http_append_pending_send_request(session, httphandle,
+                                                        cb, cbarg);
                }
                goto nothing_to_send;
        } else if (session->sending == 0 && total == 0 &&
@@ -1480,6 +1505,10 @@ http_send_outgoing(isc_nm_http_session_t *session, isc_nmhandle_t *httphandle,
 
        if (total == 0) {
                /* No data returned */
+               if (cb != NULL) {
+                       http_append_pending_send_request(session, httphandle,
+                                                        cb, cbarg);
+               }
                goto nothing_to_send;
        }