From 4cb758019e374fa7c022fe79d28444e13441717b Mon Sep 17 00:00:00 2001
From: Carlos Garnacho <carlosg@gnome.org>
Date: Fri, 14 Jun 2019 17:54:47 +0200
Subject: [PATCH] Prepare for _XIOError() possibly returning
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

Ensure current state is cut short on _XIOError(), possible reentrancy
should be skipped through the XlibDisplayIOError flag checks.

Signed-off-by: Carlos Garnacho <carlosg@gnome.org>
Reviewed-by: Michel Dänzer <mdaenzer@redhat.com>
---
 src/XlibInt.c |  2 ++
 src/xcb_io.c  | 62 ++++++++++++++++++++++++++++++++++++++++++-----------------
 2 files changed, 46 insertions(+), 18 deletions(-)

Index: libX11-1.6.5/src/XlibInt.c
===================================================================
--- libX11-1.6.5.orig/src/XlibInt.c
+++ libX11-1.6.5/src/XlibInt.c
@@ -656,6 +656,7 @@ _XStoreEventCookie(Display *dpy, XEvent
     if (!add) {
         ESET(ENOMEM);
         _XIOError(dpy);
+        return;
     }
     add->ev = *cookie;
     DL_APPEND(*head, add);
@@ -730,6 +731,7 @@ void _XEnq(
 		/* Malloc call failed! */
 		ESET(ENOMEM);
 		_XIOError(dpy);
+		return;
 	}
 	qelt->next = NULL;
 
Index: libX11-1.6.5/src/xcb_io.c
===================================================================
--- libX11-1.6.5.orig/src/xcb_io.c
+++ libX11-1.6.5/src/xcb_io.c
@@ -55,7 +55,7 @@ static void return_socket(void *closure)
 	UnlockDisplay(dpy);
 }
 
-static void require_socket(Display *dpy)
+static Bool require_socket(Display *dpy)
 {
 	if(dpy->bufmax == dpy->buffer)
 	{
@@ -66,12 +66,15 @@ static void require_socket(Display *dpy)
 		if(dpy->xcb->event_owner != XlibOwnsEventQueue)
 			flags = XCB_REQUEST_CHECKED;
 		if(!xcb_take_socket(dpy->xcb->connection, return_socket, dpy,
-		                    flags, &sent))
+		                    flags, &sent)) {
 			_XIOError(dpy);
+			return False;
+		}
 		dpy->xcb->last_flushed = sent;
 		X_DPY_SET_REQUEST(dpy, sent);
 		dpy->bufmax = dpy->xcb->real_bufmax;
 	}
+	return True;
 }
 
 /* Call internal connection callbacks for any fds that are currently
@@ -91,7 +94,7 @@ static void require_socket(Display *dpy)
  *  _XEatData
  * _XReadPad
  */
-static void check_internal_connections(Display *dpy)
+static Bool check_internal_connections(Display *dpy)
 {
 	struct _XConnectionInfo *ilist;
 	fd_set r_mask;
@@ -100,7 +103,7 @@ static void check_internal_connections(D
 	int highest_fd = -1;
 
 	if(dpy->flags & XlibDisplayProcConni || !dpy->im_fd_info)
-		return;
+		return True;
 
 	FD_ZERO(&r_mask);
 	for(ilist = dpy->im_fd_info; ilist; ilist = ilist->next)
@@ -118,9 +121,12 @@ static void check_internal_connections(D
 
 	if(result == -1)
 	{
-		if(errno == EINTR)
-			return;
-		_XIOError(dpy);
+		if(errno != EINTR) {
+			_XIOError(dpy);
+			return False;
+		}
+
+		return True;
 	}
 
 	for(ilist = dpy->im_fd_info; result && ilist; ilist = ilist->next)
@@ -129,6 +135,8 @@ static void check_internal_connections(D
 			_XProcessInternalConnection(dpy, ilist);
 			--result;
 		}
+
+	return True;
 }
 
 static PendingRequest *append_pending_request(Display *dpy, uint64_t sequence)
@@ -233,7 +241,8 @@ static void widen(uint64_t *wide, unsign
 static xcb_generic_reply_t *poll_for_event(Display *dpy, Bool queued_only)
 {
 	/* Make sure the Display's sequence numbers are valid */
-	require_socket(dpy);
+	if (!require_socket(dpy))
+		return NULL;
 
 	/* Precondition: This thread can safely get events from XCB. */
 	assert(dpy->xcb->event_owner == XlibOwnsEventQueue && !dpy->xcb->event_waiter);
@@ -351,8 +360,8 @@ int _XEventsQueued(Display *dpy, int mod
 
 	if(mode == QueuedAfterFlush)
 		_XSend(dpy, NULL, 0);
-	else
-		check_internal_connections(dpy);
+	else if (!check_internal_connections(dpy))
+		return 0;
 
 	/* If another thread is blocked waiting for events, then we must
 	 * let that thread pick up the next event. Since it blocked, we
@@ -361,8 +370,10 @@ int _XEventsQueued(Display *dpy, int mod
 	{
 		while((response = poll_for_response(dpy)))
 			handle_response(dpy, response, False);
-		if(xcb_connection_has_error(dpy->xcb->connection))
+		if(xcb_connection_has_error(dpy->xcb->connection)) {
 			_XIOError(dpy);
+			return 0;
+		}
 	}
 	return dpy->qlen;
 }
@@ -380,7 +391,8 @@ void _XReadEvents(Display *dpy)
 	_XSend(dpy, NULL, 0);
 	if(dpy->xcb->event_owner != XlibOwnsEventQueue)
 		return;
-	check_internal_connections(dpy);
+	if (!check_internal_connections(dpy))
+		return;
 
 	serial = dpy->next_event_serial_num;
 	while(serial == dpy->next_event_serial_num || dpy->qlen == 0)
@@ -410,7 +422,10 @@ void _XReadEvents(Display *dpy)
 			dpy->xcb->event_waiter = 0;
 			ConditionBroadcast(dpy, dpy->xcb->event_notify);
 			if(!event)
+			{
 				_XIOError(dpy);
+				return;
+			}
 			dpy->xcb->next_event = event;
 		}
 
@@ -428,7 +443,10 @@ void _XReadEvents(Display *dpy)
 			ConditionWait(dpy, dpy->xcb->reply_notify);
 		}
 		else
-			_XIOError(dpy);
+		{
+		        _XIOError(dpy);
+		        return;
+		}
 	}
 
 	/* The preceding loop established that there is no
@@ -496,12 +514,15 @@ void _XSend(Display *dpy, const char *da
 				ext->before_flush(dpy, &ext->codes, vec[i].iov_base, vec[i].iov_len);
 	}
 
-	if(xcb_writev(c, vec, 3, requests) < 0)
+	if(xcb_writev(c, vec, 3, requests) < 0) {
 		_XIOError(dpy);
+		return;
+	}
 	dpy->bufptr = dpy->buffer;
 	dpy->last_req = (char *) &dummy_request;
 
-	check_internal_connections(dpy);
+	if (!check_internal_connections(dpy))
+		return;
 
 	_XSetSeqSyncFunction(dpy);
 }
@@ -512,7 +533,9 @@ void _XSend(Display *dpy, const char *da
  */
 void _XFlush(Display *dpy)
 {
-	require_socket(dpy);
+	if (!require_socket(dpy))
+		return;
+
 	_XSend(dpy, NULL, 0);
 
 	_XEventsQueued(dpy, QueuedAfterReading);
@@ -657,7 +680,8 @@ Status _XReply(Display *dpy, xReply *rep
 		else if(response)
 			handle_response(dpy, response, True);
 	}
-	check_internal_connections(dpy);
+	if (!check_internal_connections(dpy))
+		return 0;
 
 	if(dpy->xcb->next_event && dpy->xcb->next_event->response_type == X_Error)
 	{
@@ -712,8 +736,10 @@ Status _XReply(Display *dpy, xReply *rep
 
 	/* it's not an error, but we don't have a reply, so it's an I/O
 	 * error. */
-	if(!reply)
+	if(!reply) {
 		_XIOError(dpy);
+		return 0;
+	}
 
 	/* there's no error and we have a reply. */
 	dpy->xcb->reply_data = reply;
