From 59ed934b055229ff2da96f96c772a060dc0f4092 Mon Sep 17 00:00:00 2001 From: Dan Winship Date: Sun, 2 Jun 2013 18:32:21 -0300 Subject: [PATCH] ginetaddress: fix addr/string conversions on windows When parsing an address, we need to re-set "len" between IPv4 and IPv6, since WSAStringToAddress() might set it to sizeof(struct sin_addr) when trying to parse the string as IPv4, even if it fails. Also, we need to make sure to not pass strings to WSAStringToAddress() that it will accept but that we don't want it to. When stringifying an address, we need to clear the sockaddr before filling it in, so we don't accidentally end up with an unwanted scope_id or the like. https://bugzilla.gnome.org/show_bug.cgi?id=701401 --- gio/ginetaddress.c | 29 +++++++++++++++++++++-------- 1 file changed, 21 insertions(+), 8 deletions(-) diff --git a/gio/ginetaddress.c b/gio/ginetaddress.c index de67272d3..e5357c86f 100644 --- a/gio/ginetaddress.c +++ b/gio/ginetaddress.c @@ -405,12 +405,26 @@ g_inet_address_new_from_string (const gchar *string) g_networking_init (); #ifdef G_OS_WIN32 - memset (&sa, 0, sizeof (sa)); - len = sizeof (sa); - if (WSAStringToAddress ((LPTSTR) string, AF_INET, NULL, (LPSOCKADDR) &sa, &len) == 0) - return g_inet_address_new_from_bytes ((guint8 *)&sin->sin_addr, AF_INET); - else if (WSAStringToAddress ((LPTSTR) string, AF_INET6, NULL, (LPSOCKADDR) &sa, &len) == 0) - return g_inet_address_new_from_bytes ((guint8 *)&sin6->sin6_addr, AF_INET6); + /* We need to make sure to not pass a string of the form + * "IPv4addr:port" or "[IPv6addr]:port" to WSAStringToAddress(), + * since it would accept them (returning both the address and the + * port), but we only want to accept standalone IP addresses. (In + * the IPv6 case, WINE actually only checks for the ']', not the + * '[', which is why we do the same here.) + */ + if (!strchr (string, ':')) + { + len = sizeof (sa); + if (WSAStringToAddress ((LPTSTR) string, AF_INET, NULL, (LPSOCKADDR) &sa, &len) == 0) + return g_inet_address_new_from_bytes ((guint8 *)&sin->sin_addr, AF_INET); + } + + if (!strchr (string, ']')) + { + len = sizeof (sa); + if (WSAStringToAddress ((LPTSTR) string, AF_INET6, NULL, (LPSOCKADDR) &sa, &len) == 0) + return g_inet_address_new_from_bytes ((guint8 *)&sin6->sin6_addr, AF_INET6); + } #else /* !G_OS_WIN32 */ @@ -529,20 +543,19 @@ g_inet_address_to_string (GInetAddress *address) g_return_val_if_fail (G_IS_INET_ADDRESS (address), NULL); #ifdef G_OS_WIN32 + memset (&sa, 0, sizeof (sa)); sa.ss_family = address->priv->family; if (address->priv->family == AF_INET) { addrlen = sizeof (*sin); memcpy (&sin->sin_addr, &address->priv->addr.ipv4, sizeof (sin->sin_addr)); - sin->sin_port = 0; } else { addrlen = sizeof (*sin6); memcpy (&sin6->sin6_addr, &address->priv->addr.ipv6, sizeof (sin6->sin6_addr)); - sin6->sin6_port = 0; } if (WSAAddressToString ((LPSOCKADDR) &sa, addrlen, NULL, buffer, &buflen) != 0) return NULL;