From: Yuxuan Shui <yshui(a)codeweavers.com> In this call chain: GetBestInterface -> GetBestInterfaceEx -> GetBestRoute2, we cast a socketaddr_in * (16 bytes) is to SOCKETADDR_INET * (28 bytes) before passing it to GetBestRoute2, but GetBestRoute2 will access all of the 28 bytes, leading to out-of-bound access. So we create a local SOCKETADDR_INET in GetBestInterfaceEx. Found by ASan. --- dlls/iphlpapi/iphlpapi_main.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/dlls/iphlpapi/iphlpapi_main.c b/dlls/iphlpapi/iphlpapi_main.c index 83c6e8b53b8..849ab0b0dbc 100644 --- a/dlls/iphlpapi/iphlpapi_main.c +++ b/dlls/iphlpapi/iphlpapi_main.c @@ -1392,14 +1392,20 @@ DWORD WINAPI GetBestInterface(IPAddr dwDestAddr, PDWORD pdwBestIfIndex) DWORD WINAPI GetBestInterfaceEx( struct sockaddr *dst, DWORD *best_index ) { SOCKADDR_INET best_address; + SOCKADDR_INET dst_address; MIB_IPFORWARD_ROW2 row; DWORD ret; TRACE( "dst %p, best_index %p\n", dst, best_index ); if (!dst || !best_index) return ERROR_INVALID_PARAMETER; + if (dst->sa_family != AF_INET && dst->sa_family != AF_INET6) return ERROR_INVALID_PARAMETER; - ret = GetBestRoute2( NULL, 0, NULL, (const SOCKADDR_INET *)dst, 0, &row, &best_address ); + dst_address.si_family = dst->sa_family; + if (dst->sa_family == AF_INET6) dst_address.Ipv6 = *(struct sockaddr_in6 *)dst; + else dst_address.Ipv4 = *(struct sockaddr_in *)dst; + + ret = GetBestRoute2( NULL, 0, NULL, &dst_address, 0, &row, &best_address ); if (!ret) *best_index = row.InterfaceIndex; TRACE( "returning %ld\n", ret ); -- GitLab https://gitlab.winehq.org/wine/wine/-/merge_requests/9085