You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
SecureTransport proxy error cleanup frees borrowed stream before TLS close #7432
I observed a crash in a macOS arm64 application using libgit2 1.9.7 with the SecureTransport HTTPS backend while resolving refs on an HTTPS remote through an HTTP CONNECT proxy (GIT_PROXY_AUTO). A connection attempt failed and entered http_client_connect's on_error cleanup. I do not yet have a standalone reproducer, and the original connection error is unknown because cleanup crashes before it can propagate.
The relevant lifetime relationship is visible in the source:
on_error:
if (error!=GIT_RETRY)
close_stream(&client->proxy);
close_stream(&client->server);
returnerror;
close_stream calls both git_stream_close and git_stream_free and sets the pointer to NULL. The subsequent TLS close calls SSLClose, which can call write_cb; that callback uses the borrowed st->io, which now refers to the freed proxy stream.
Expected behavior
Close/free the borrowing TLS child before its underlying proxy stream and return the original connection failure rather than crashing. The normal reconnect path already follows this order: httpclient.c:1085–1096 closes the server first, then the proxy.
Suggested minimal reorder (not locally built or verified yet):
The GIT_RETRY guard stays on the proxy close. This moves the unconditional child cleanup; it is not a swap of the two stream names under the existing guard. The helper already handles NULL, frees the stream, and clears its pointer.
Actual behavior
SIGSEGV / EXC_BAD_ACCESS, instruction pointer 0, with this stack (top first):
The crash report's library UUID (C737B73B-D177-3444-9997-890059719E64) matches the loaded libgit2 dylib. In one subsequent debugger diagnostic, stopped at stransport_close before SSLClose, the TLS stream was non-owning (owned = 0) and git_error_last()->klass was already 0. Thus no useful original error class remained at child cleanup. I did not observe the class before parent cleanup, so I cannot identify the original failure or attribute the class reset to a particular cleanup call. No conclusion about certificate validation or proxy authentication follows from this crash.
Related issues #7396 and #6417 discuss SecureTransport deprecation and intermittent transport failures, respectively; neither describes this borrowed-stream cleanup order.
May I take #7432 as a focused cleanup-order fix? I'd first add an offline stream regression that checks the TLS wrapper is closed and freed before its borrowed proxy, while preserving the GIT_RETRY proxy-retention behavior; I haven't reproduced the original SecureTransport crash locally yet.
Activity
Tiancheng-Xu commentedon Oct 17, 2026
May I take #7432 as a focused cleanup-order fix? I'd first add an offline stream regression that checks the TLS wrapper is closed and freed before its borrowed proxy, while preserving the GIT_RETRY proxy-retention behavior; I haven't reproduced the original SecureTransport crash locally yet.