From eb1e776a56df0557682ab9185f398f7e15396b24 Mon Sep 17 00:00:00 2001 From: Alexander Medvednikov Date: Wed, 15 Apr 2026 05:51:17 +0300 Subject: [PATCH] net: fix socket bug (fixes #15026) --- vlib/net/aasocket.c.v | 4 ++++ vlib/net/address.c.v | 25 ++++++++++++++++++------- vlib/net/utils_test.v | 16 ++++++++++++++++ 3 files changed, 38 insertions(+), 7 deletions(-) diff --git a/vlib/net/aasocket.c.v b/vlib/net/aasocket.c.v index b0bc8924d..f78f98b0c 100644 --- a/vlib/net/aasocket.c.v +++ b/vlib/net/aasocket.c.v @@ -67,6 +67,10 @@ fn C.getaddrinfo(node &char, service &char, hints &C.addrinfo, res &&C.addrinfo) fn C.freeaddrinfo(info &C.addrinfo) +$if !windows { + fn C.gai_strerror(code i32) &char +} + // fn C.connect(sockfd int, addr &C.sockaddr, addrlen C.socklen_t) int fn C.connect(sockfd i32, addr &Addr, addrlen u32) i32 diff --git a/vlib/net/address.c.v b/vlib/net/address.c.v index 5eb11192b..d49a08127 100644 --- a/vlib/net/address.c.v +++ b/vlib/net/address.c.v @@ -183,6 +183,23 @@ pub fn resolve_addrs_fuzzy(addr string, typ SocketType) ![]Addr { return resolve_addrs(addr, .unix, typ) } +fn wrap_getaddrinfo_error(code int) ! { + if code == 0 { + return + } + $if windows { + socket_error(0 - code)! + } $else { + if code == C.EAI_SYSTEM { + err_code := error_code() + return error_with_code('net: getaddrinfo failed: ${os.posix_get_error_msg(err_code)}', + err_code) + } + return error_with_code('net: getaddrinfo failed: ${unsafe { cstring_to_vstring(C.gai_strerror(code)) }}', + code) + } +} + // resolve_ipaddrs converts the given `addr`, `family` and `typ` to a list of addresses pub fn resolve_ipaddrs(addr string, family AddrFamily, typ SocketType) ![]Addr { address, port := split_address(addr)! @@ -213,13 +230,7 @@ pub fn resolve_ipaddrs(addr string, family AddrFamily, typ SocketType) ![]Addr { sport := '${port}' - // This might look silly but is recommended by MSDN - $if windows { - socket_error(0 - C.getaddrinfo(&char(address.str), &char(sport.str), &hints, &results))! - } $else { - x := C.getaddrinfo(&char(address.str), &char(sport.str), &hints, &results) - wrap_error(x)! - } + wrap_getaddrinfo_error(C.getaddrinfo(&char(address.str), &char(sport.str), &hints, &results))! defer { C.freeaddrinfo(results) diff --git a/vlib/net/utils_test.v b/vlib/net/utils_test.v index 4e9f1c64a..2cb9e3ff2 100644 --- a/vlib/net/utils_test.v +++ b/vlib/net/utils_test.v @@ -29,3 +29,19 @@ fn test_resolve_port_without_brackets() { assert x.len > 0 assert x[0].port()! == 48872 } + +fn test_resolve_invalid_host_reports_getaddrinfo_error() { + if _ := net.resolve_addrs_fuzzy('definitely-not-a-real-hostname-for-v-tests.invalid:12345', + .tcp) + { + assert false + } else { + msg := err.msg() + $if windows { + assert msg.len > 0 + } $else { + assert msg.starts_with('net: getaddrinfo failed:') + assert !msg.contains('socket error') + } + } +} -- 2.39.5