From 9287c73df9f5310b821ec66fd6a35f5660ef6006 Mon Sep 17 00:00:00 2001 From: zeertzjq Date: Fri, 27 Mar 2026 22:32:06 +0800 Subject: [PATCH] fix(:connect): don't use freed memory (#38512) Changing REUSE_MAX from 4 to 0 produces the following ASAN error: ================================================================= ==924403==ERROR: AddressSanitizer: heap-use-after-free on address 0x7d33333ed128 at pc 0x55f165a47a86 bp 0x7fff40e71690 sp 0x7fff40e71688 READ of size 1 at 0x7d33333ed128 thread T0 #0 0x55f165a47a85 in socket_address_tcp_host_end **/src/nvim/event/socket.c:37:30 #1 0x55f1667d6349 in channel_connect_event **/src/nvim/ui_client.c:296:17 #2 0x55f165a35af6 in multiqueue_process_events **/src/nvim/event/multiqueue.c:159:7 #3 0x55f165a308f6 in loop_poll_events **/src/nvim/event/loop.c:81:3 #4 0x55f1667d3fbc in ui_client_run **/src/nvim/ui_client.c:172:5 #5 0x55f165e1f2e1 in main **/src/nvim/main.c:367:5 #6 0x7f23340bc6c0 in __libc_start_call_main /usr/src/debug/glibc/glibc/csu/../sysdeps/nptl/libc_start_call_main.h:59:16 #7 0x7f23340bc7f8 in __libc_start_main /usr/src/debug/glibc/glibc/csu/../csu/libc-start.c:360:3 #8 0x55f16521d044 in _start (**/build/bin/nvim+0xcb9044) (BuildId: 6c8517919bbcd317c6bb5675d1eb3f2c7c319e2c) 0x7d33333ed128 is located 40 bytes inside of 4096-byte region [0x7d33333ed100,0x7d33333ee100) freed by thread T0 here: #0 0x55f16532547d in free.part.0 asan_malloc_linux.cpp.o #1 0x55f165fc2380 in xfree **/src/nvim/memory.c:159:3 #2 0x55f165fc5b6d in free_block **/src/nvim/memory.c:786:5 #3 0x55f165fc5c38 in arena_mem_free **/src/nvim/memory.c:798:5 #4 0x55f166082dd2 in parse_msgpack **/src/nvim/msgpack_rpc/channel.c:258:7 #5 0x55f166078ade in receive_msgpack **/src/nvim/msgpack_rpc/channel.c:217:5 #6 0x55f165a4683b in read_event **/src/nvim/event/rstream.c:234:23 #7 0x55f165a462d8 in invoke_read_cb **/src/nvim/event/rstream.c:287:3 #8 0x55f165a42e11 in read_cb **/src/nvim/event/rstream.c:149:3 #9 0x55f166bdc28b in uv__read **/.deps/build/src/libuv/src/unix/stream.c:1145:7 #10 0x55f166bdba97 in uv__stream_io **/.deps/build/src/libuv/src/unix/stream.c:1208:5 #11 0x55f166bca7fe in uv__io_cb **/.deps/build/src/libuv/src/unix/core.c:930:5 #12 0x55f166be6251 in uv__io_poll **/.deps/build/src/libuv/src/unix/linux.c:1546:11 #13 0x55f166bc9c57 in uv_run **/.deps/build/src/libuv/src/unix/core.c:460:5 #14 0x55f165a30be7 in loop_uv_run **/src/nvim/event/loop.c:59:3 #15 0x55f165a30864 in loop_poll_events **/src/nvim/event/loop.c:80:26 #16 0x55f1667d3fbc in ui_client_run **/src/nvim/ui_client.c:172:5 #17 0x55f165e1f2e1 in main **/src/nvim/main.c:367:5 #18 0x7f23340bc6c0 in __libc_start_call_main /usr/src/debug/glibc/glibc/csu/../sysdeps/nptl/libc_start_call_main.h:59:16 #19 0x7f23340bc7f8 in __libc_start_main /usr/src/debug/glibc/glibc/csu/../csu/libc-start.c:360:3 #20 0x55f16521d044 in _start (**/build/bin/nvim+0xcb9044) (BuildId: 6c8517919bbcd317c6bb5675d1eb3f2c7c319e2c) previously allocated by thread T0 here: #0 0x55f1653263e5 in malloc (**/build/bin/nvim+0xdc23e5) (BuildId: 6c8517919bbcd317c6bb5675d1eb3f2c7c319e2c) #1 0x55f165fc2054 in try_malloc **/src/nvim/memory.c:113:15 #2 0x55f165fc22b4 in xmalloc **/src/nvim/memory.c:147:15 #3 0x55f165fc4d5d in alloc_block **/src/nvim/memory.c:717:12 #4 0x55f165fc4e09 in arena_alloc_block **/src/nvim/memory.c:724:20 #5 0x55f165fc5113 in arena_alloc **/src/nvim/memory.c:746:5 #6 0x55f166096d98 in api_parse_enter **/src/nvim/msgpack_rpc/unpacker.c:161:5 #7 0x55f166aa290e in mpack_parse_tok **/src/mpack/object.c:56:29 #8 0x55f166aa4fa9 in mpack_parse **/src/mpack/object.c:82:16 #9 0x55f166099de9 in unpacker_advance **/src/nvim/msgpack_rpc/unpacker.c:343:12 #10 0x55f1660825c9 in parse_msgpack **/src/nvim/msgpack_rpc/channel.c:248:10 #11 0x55f166078ade in receive_msgpack **/src/nvim/msgpack_rpc/channel.c:217:5 #12 0x55f165a4683b in read_event **/src/nvim/event/rstream.c:234:23 #13 0x55f165a462d8 in invoke_read_cb **/src/nvim/event/rstream.c:287:3 #14 0x55f165a42e11 in read_cb **/src/nvim/event/rstream.c:149:3 #15 0x55f166bdc28b in uv__read **/.deps/build/src/libuv/src/unix/stream.c:1145:7 #16 0x55f166bdba97 in uv__stream_io **/.deps/build/src/libuv/src/unix/stream.c:1208:5 #17 0x55f166bca7fe in uv__io_cb **/.deps/build/src/libuv/src/unix/core.c:930:5 #18 0x55f166be6251 in uv__io_poll **/.deps/build/src/libuv/src/unix/linux.c:1546:11 #19 0x55f166bc9c57 in uv_run **/.deps/build/src/libuv/src/unix/core.c:460:5 #20 0x55f165a30be7 in loop_uv_run **/src/nvim/event/loop.c:59:3 #21 0x55f165a30864 in loop_poll_events **/src/nvim/event/loop.c:80:26 #22 0x55f1667d3fbc in ui_client_run **/src/nvim/ui_client.c:172:5 #23 0x55f165e1f2e1 in main **/src/nvim/main.c:367:5 #24 0x7f23340bc6c0 in __libc_start_call_main /usr/src/debug/glibc/glibc/csu/../sysdeps/nptl/libc_start_call_main.h:59:16 #25 0x7f23340bc7f8 in __libc_start_main /usr/src/debug/glibc/glibc/csu/../csu/libc-start.c:360:3 #26 0x55f16521d044 in _start (**/build/bin/nvim+0xcb9044) (BuildId: 6c8517919bbcd317c6bb5675d1eb3f2c7c319e2c) SUMMARY: AddressSanitizer: heap-use-after-free **/src/nvim/event/socket.c:37:30 in socket_address_tcp_host_end Shadow bytes around the buggy address: 0x7d33333ece80: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa 0x7d33333ecf00: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa 0x7d33333ecf80: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa 0x7d33333ed000: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa 0x7d33333ed080: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa =>0x7d33333ed100: fd fd fd fd fd[fd]fd fd fd fd fd fd fd fd fd fd 0x7d33333ed180: fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd 0x7d33333ed200: fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd 0x7d33333ed280: fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd 0x7d33333ed300: fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd 0x7d33333ed380: fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd Shadow byte legend (one shadow byte represents 8 application bytes): Addressable: 00 Partially addressable: 01 02 03 04 05 06 07 Heap left redzone: fa Freed heap region: fd Stack left redzone: f1 Stack mid redzone: f2 Stack right redzone: f3 Stack after return: f5 Stack use after scope: f8 Global redzone: f9 Global init order: f6 Poisoned by user: f7 Container overflow: fc Array cookie: ac Intra object redzone: bb ASan internal: fe Left alloca redzone: ca Right alloca redzone: cb ==924403==ABORTING --- src/nvim/ui_client.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/nvim/ui_client.c b/src/nvim/ui_client.c index 0e3a5b3fff..bb2bc39ebd 100644 --- a/src/nvim/ui_client.c +++ b/src/nvim/ui_client.c @@ -282,7 +282,8 @@ void ui_client_event_connect(Array args) return; } - char *server_addr = args.items[0].data.string.data; + String s = args.items[0].data.string; + char *server_addr = xmemdupz(s.data, s.size); multiqueue_put(main_loop.fast_events, channel_connect_event, server_addr); // Set a dummy channel ID to prevent client exit when server detaches. ui_client_channel_id = UINT64_MAX; @@ -299,6 +300,7 @@ static void channel_connect_event(void **argv) if (!strequal(err, "")) { ELOG("Cannot connect to server %s: %s", server_addr, err); + xfree(server_addr); ui_client_exit_status = 1; os_exit(1); } @@ -308,6 +310,7 @@ static void channel_connect_event(void **argv) ui_client_attach(tui_width, tui_height, tui_term, tui_rgb); ILOG("Connected to server %s on channel %" PRId64, server_addr, chan); + xfree(server_addr); } /// When a "restart" UI event is received, its arguments are saved here when