win32: add some sanity checks to avoid infinite loops or large memory allocations when retrieving NLA responses release-2.x.y

Thu, 20 Oct 2016 18:20:44 -0400

author
Daniel Atallah <datallah@pidgin.im>
date
Thu, 20 Oct 2016 18:20:44 -0400
branch
release-2.x.y
changeset 38166
3094e049f882
parent 38165
b3ad11cab64e
child 38167
65df1e5e7ff0

win32: add some sanity checks to avoid infinite loops or large memory allocations when retrieving NLA responses

libpurple/network.c file | annotate | diff | comparison | revisions
--- a/libpurple/network.c	Wed Oct 19 13:01:43 2016 -0400
+++ b/libpurple/network.c	Thu Oct 20 18:20:44 2016 -0400
@@ -639,7 +639,8 @@
 		gchar *buf = NULL;
 		WSAQUERYSET *res = (LPWSAQUERYSET) buf;
 		DWORD current_size = 0;
-		while (TRUE) {
+		int iteration_count = 0;
+		while (iteration_count++ < 100) {
 			DWORD size = current_size;
 			retval = WSALookupServiceNextA(h, 0, &size, res);
 			if (retval == ERROR_SUCCESS) {
@@ -649,6 +650,10 @@
 			} else {
 				errorid = WSAGetLastError();
 				if (errorid == WSAEFAULT) {
+					if (size == 0 || size > 102400) {
+						purple_debug_warning("network", "Got unexpected NLA buffer size %" G_GUINT32_FORMAT ".\n", (guint32) size);
+						break;
+					}
 					buf = g_realloc(buf, size);
 					res = (LPWSAQUERYSET) buf;
 					current_size = size;
@@ -729,6 +734,7 @@
 
 	while (TRUE) {
 		int retval;
+		int iteration_count;
 		DWORD retLen = 0;
 		WSACOMPLETION completion;
 		WSAOVERLAPPED overlapped;
@@ -806,7 +812,8 @@
 			return NULL;
 		}
 
-		while (TRUE) {
+		iteration_count = 0;
+		while (iteration_count++ < 100) {
 			DWORD size = current_size;
 			retval = WSALookupServiceNextA(network_change_handle, 0, &size, res);
 			if (retval == ERROR_SUCCESS) {
@@ -816,6 +823,11 @@
 			} else {
 				int errorid = WSAGetLastError();
 				if (errorid == WSAEFAULT) {
+					if (size == 0 || size > 102400) {
+						purple_timeout_add(0, _print_debug_msg,
+							   g_strdup_printf("Thread got unexpected NLA buffer size %" G_GUINT32_FORMAT ".\n", (guint32) size));
+						break;
+					}
 					buf = g_realloc(buf, size);
 					res = (LPWSAQUERYSET) buf;
 					current_size = size;

mercurial