Merge pull request #36418 from zeertzjq/backport

fix(socket): avoid stack-use-after-return after timeout (#36405)
This commit is contained in:
zeertzjq
2025-11-01 09:00:47 +08:00
committed by GitHub
3 changed files with 39 additions and 8 deletions

View File

@@ -192,8 +192,9 @@ static void connect_cb(uv_connect_t *req, int status)
{
int *ret_status = req->data;
*ret_status = status;
if (status != 0) {
uv_close((uv_handle_t *)req->handle, NULL);
uv_handle_t *handle = (uv_handle_t *)req->handle;
if (status != 0 && !uv_is_closing(handle)) {
uv_close(handle, NULL);
}
}
@@ -247,11 +248,23 @@ tcp_retry:
if (status == 0) {
stream_init(NULL, &stream->s, -1, uv_stream);
success = true;
} else if (is_tcp && addrinfo->ai_next) {
addrinfo = addrinfo->ai_next;
goto tcp_retry;
} else {
*error = _("connection refused");
if (!uv_is_closing((uv_handle_t *)uv_stream)) {
uv_close((uv_handle_t *)uv_stream, NULL);
if (status == 1) {
// The uv_close() above will make libuv call connect_cb() with UV_ECANCELED.
// Make sure connect_cb() has been called here, as if it's called after this
// function ends it will cause a stack-use-after-scope.
LOOP_PROCESS_EVENTS_UNTIL(&main_loop, NULL, -1, status != 1);
}
}
if (is_tcp && addrinfo->ai_next) {
addrinfo = addrinfo->ai_next;
goto tcp_retry;
} else {
*error = _("connection refused");
}
}
cleanup:

View File

@@ -144,10 +144,12 @@ void stream_close_handle(Stream *stream)
static void close_cb(uv_handle_t *handle)
{
Stream *stream = handle->data;
if (stream->close_cb) {
// Need to check if handle->data is NULL here as this callback may be called between
// the handle's initialization and stream_init() (e.g. in socket_connect()).
if (stream && stream->close_cb) {
stream->close_cb(stream, stream->close_cb_data);
}
if (stream->internal_close_cb) {
if (stream && stream->internal_close_cb) {
stream->internal_close_cb(stream, stream->internal_data);
}
}

View File

@@ -465,6 +465,22 @@ describe('channels', function()
eq(true, exec_lua('return _G.result'))
end)
end)
describe('sockconnect() reports error when connection fails', function()
it('in "pipe" mode', function()
eq(
'Vim:connection failed: connection refused',
pcall_err(fn.sockconnect, 'pipe', n.new_pipename())
)
end)
it('in "tcp" mode', function()
eq(
'Vim:connection failed: connection refused',
pcall_err(fn.sockconnect, 'pipe', '127.0.0.1:0')
)
end)
end)
end)
describe('loopback', function()