Skip to content

multi: notification queue is permanently disabled (and its chunks leak) after a dispatch spans two chunks #22963

Description

@Fengxiaoxx

Summary

With CURLMOPT_NOTIFYFUNCTION + curl_multi_notify_enable(CURLMNOTIFY_EASY_DONE),
a perform round that queues 129 or more notifications silently stops delivering
notifications for the remaining lifetime of the multi handle, and the queued
chunks are leaked. curl_multi_cleanup() cannot reclaim them.

Root cause

mnfty_chunk_reset() (lib/multi_ntfy.c) does memset(chunk, 0, sizeof(*chunk)),
which clears chunk->next after the head chunk is drained. The parent loop in
Curl_mntfy_dispatch_all() then reads the already-cleared pointer:

multi->ntfy.head = chunk->next;   /* NULL instead of the live second chunk */

head becomes NULL while tail still points at the queued second chunk, so the
dispatch loop never runs again and Curl_mntfy_cleanup() (which walks from
head) never frees the orphaned chunks.

Reproduction

Build curl from master (cdbe4eb) with AddressSanitizer and run:

./poc            # n = 200 concurrent completions, leak detection on
./poc 128        # control: exactly one chunk, no leak

with ASAN_OPTIONS=detect_leaks=1.

Observed (n = 200):

completions=200 notifications_delivered=129
Direct leak of 1048 byte(s) in 1 object(s) allocated from:
    #1 mnfty_chunk_create lib/multi_ntfy.c:54

Control (n = 128): 129 notifications delivered, no leak report.

Impact

The notification facility stops working silently for that handle (the
application never learns about it) and the orphaned chunk plus any later
appended chunks are never freed.

Suggested fix

Only reset the cursors, not the link pointer:

static void mnfty_chunk_reset(struct mntfy_chunk *chunk)
{
-  memset(chunk, 0, sizeof(*chunk));
+  chunk->r_offset = 0;
+  chunk->w_offset = 0;
}

(Equivalently, capture chunk->next before resetting it.)

Materials

poc.c (harness), reproduce.sh (clones and builds master with ASan) and
build.md are attached as curl_04_ntfy_chunk_leak_lsan_poc.zip.

Version

Affected release: curl 8.22.0 (2026-09-02, tag curl-8_22_0) - reproduced
on a fresh ASan build of the release tag. Also verified on current master
cdbe4eb (2026-09-15). lib/multi_ntfy.c is unchanged since 8.22.0.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions