[PATCH] libXinerama: Set number to 0 on error.

2017-01-22 Thread Tobias Stoeckmann
The documentation of XineramaQueryScreens states that number is always
set to the amount of screens in the returned array, but if the
communication with the X server fails, NULL is returned without
modifying number.

At least dwm relies on the fact that number is set to 0 on error, i.e.
when NULL is returned. As a NULL pointer contains 0 elements and the
documentation states that number contains the amount of elements of the
returned array, I think this should be fixed inside libXinerama.
---
 src/Xinerama.c | 1 +
 1 file changed, 1 insertion(+)

diff --git a/src/Xinerama.c b/src/Xinerama.c
index 8472ec5..ee1f630 100644
--- a/src/Xinerama.c
+++ b/src/Xinerama.c
@@ -286,6 +286,7 @@ XineramaQueryScreens(
 if (!_XReply (dpy, (xReply *) , 0, xFalse)) {
UnlockDisplay (dpy);
SyncHandle ();
+   *number = 0;
return NULL;
 }
 
-- 
2.11.0

___
xorg-devel@lists.x.org: X.Org development
Archives: http://lists.x.org/archives/xorg-devel
Info: https://lists.x.org/mailman/listinfo/xorg-devel

Re: [PATCH] libXinerama: Set number to 0 on error.

2017-01-23 Thread Tobias Stoeckmann
On Mon, Jan 23, 2017 at 11:52:13AM -0500, Adam Jackson wrote:
> Not that any caller has likely made this mistake, but you want an if
> (number) before this, otherwise you turn a protocol error into a
> segfault.

If a caller supplies NULL, a segfault would always occur because the
pointer is never checked for NULL.


Tobias
___
xorg-devel@lists.x.org: X.Org development
Archives: http://lists.x.org/archives/xorg-devel
Info: https://lists.x.org/mailman/listinfo/xorg-devel

[PATCH] xinit: check for correct fork error code

2017-01-30 Thread Tobias Stoeckmann
Even though this code is only active on __sun machines, the fork return
value should be checked for -1, not 1, to detect an error situation.
---
 xinit.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/xinit.c b/xinit.c
index 1b04911..f826b7a 100644
--- a/xinit.c
+++ b/xinit.c
@@ -638,7 +638,7 @@ shutdown(void)
 Fatal("Unable to run program \"%s\"", "kbd_mode");
 break;
 
-case 1:
+case -1:
 Error("fork failed");
 break;
 
-- 
2.11.0

___
xorg-devel@lists.x.org: X.Org development
Archives: http://lists.x.org/archives/xorg-devel
Info: https://lists.x.org/mailman/listinfo/xorg-devel

Re: [PATCH libXrandr] Avoid out of boundary accesses on illegal responses

2017-01-07 Thread Tobias Stoeckmann
Hi Julien,

On Sat, Jan 07, 2017 at 07:03:17PM +0100, Julien Cristau wrote:
> It looks like we're leaking 'attr' on these error paths?

confirmed. That is what I get for copying the error handling of the
attr == NULL case...


diff --git a/src/XrrCrtc.c b/src/XrrCrtc.c
index 6665092..8316b78 100644
--- a/src/XrrCrtc.c
+++ b/src/XrrCrtc.c
@@ -459,6 +459,7 @@ XRRGetCrtcTransform (Display*dpy,
 e = extra;
 
 if (e + rep.pendingNbytesFilter > end) {
+   XFree (attr);
XFree (extra);
return False;
 }
@@ -468,6 +469,7 @@ XRRGetCrtcTransform (Display*dpy,
 for (p = 0; p < rep.pendingNparamsFilter; p++) {
INT32   f;
if (e + 4 > end) {
+   XFree (attr);
XFree (extra);
return False;
}
@@ -478,6 +480,7 @@ XRRGetCrtcTransform (Display*dpy,
 attr->pendingNparams = rep.pendingNparamsFilter;
 
 if (e + rep.currentNbytesFilter > end) {
+   XFree (attr);
XFree (extra);
return False;
 }
@@ -487,6 +490,7 @@ XRRGetCrtcTransform (Display*dpy,
 for (p = 0; p < rep.currentNparamsFilter; p++) {
INT32   f;
if (e + 4 > end) {
+   XFree (attr);
XFree (extra);
return False;
}
___
xorg-devel@lists.x.org: X.Org development
Archives: http://lists.x.org/archives/xorg-devel
Info: https://lists.x.org/mailman/listinfo/xorg-devel

[PATCH xserver] Fix OOB access in ProcRecordUnregisterClients

2017-03-19 Thread Tobias Stoeckmann
If a client sends a RecordUnregisterClients request with an nClients
field larger than INT_MAX / 4, an integer overflow leads to an
out of boundary access in RecordSanityCheckClientSpecifiers.

An example line with libXtst would be:
XRecordUnregisterClients(dpy, rc, clients, 0x4001);
---
 record/record.c | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/record/record.c b/record/record.c
index 3e8b497e7..fdcee7e00 100644
--- a/record/record.c
+++ b/record/record.c
@@ -1910,7 +1910,8 @@ ProcRecordUnregisterClients(ClientPtr client)
 int i;
 
 REQUEST_AT_LEAST_SIZE(xRecordUnregisterClientsReq);
-if ((client->req_len << 2) - SIZEOF(xRecordUnregisterClientsReq) !=
+if (INT_MAX / 4 < stuff->nClients ||
+(client->req_len << 2) - SIZEOF(xRecordUnregisterClientsReq) !=
 4 * stuff->nClients)
 return BadLength;
 VERIFY_CONTEXT(pContext, stuff->context, client);
-- 
2.12.0

___
xorg-devel@lists.x.org: X.Org development
Archives: http://lists.x.org/archives/xorg-devel
Info: https://lists.x.org/mailman/listinfo/xorg-devel

[PATCH] dmx: Fix null pointer dereference

2017-03-12 Thread Tobias Stoeckmann
A null pointer dereference can occur in dmxSync, because TimerForce
does not handle a null pointer.

dmxSyncTimer is set to NULL a few lines above on a certain condition,
which happened on my machine. The explicit NULL check allowed me to
start Xdmx again without a segmentation fault.
---
 hw/dmx/dmxsync.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/hw/dmx/dmxsync.c b/hw/dmx/dmxsync.c
index 1bc242343..b55c9ddf3 100644
--- a/hw/dmx/dmxsync.c
+++ b/hw/dmx/dmxsync.c
@@ -182,7 +182,7 @@ dmxSync(DMXScreenInfo * dmxScreen, Bool now)
 
 /* Do sync or set time for later */
 if (now || !dmxScreen) {
-if (!TimerForce(dmxSyncTimer))
+if (dmxSyncTimer == NULL || !TimerForce(dmxSyncTimer))
 dmxSyncCallback(NULL, 0, NULL);
 /* At this point, dmxSyncPending == 0 because
  * dmxSyncCallback must have been called. */
-- 
2.12.0

___
xorg-devel@lists.x.org: X.Org development
Archives: http://lists.x.org/archives/xorg-devel
Info: https://lists.x.org/mailman/listinfo/xorg-devel

Re: [PATCH] dmx: Fix null pointer dereference

2017-03-12 Thread Tobias Stoeckmann
On Sun, Mar 12, 2017 at 03:47:50PM +0100, walter harms wrote:
> why not patch TimerForce() and solve the problem for once and any one ?

I didn't do it because I am not sure about the implied consequences of
simply accepting NULL. Maybe it's not meant to be used that way.

But here's the alternative possibility.
---
 os/WaitFor.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/os/WaitFor.c b/os/WaitFor.c
index 613608faf..ab5f8a3b8 100644
--- a/os/WaitFor.c
+++ b/os/WaitFor.c
@@ -261,7 +261,7 @@ AdjustWaitForDelay(void *waitTime, int newdelay)
 }
 
 static inline Bool timer_pending(OsTimerPtr timer) {
-return !xorg_list_is_empty(>list);
+return timer != NULL && !xorg_list_is_empty(>list);
 }
 
 /* If time has rewound, re-run every affected timer.
-- 
2.12.0

___
xorg-devel@lists.x.org: X.Org development
Archives: http://lists.x.org/archives/xorg-devel
Info: https://lists.x.org/mailman/listinfo/xorg-devel

[PATCH] render: Fix out of boundary heap access

2017-03-13 Thread Tobias Stoeckmann
ProcRenderCreateRadialGradient and ProcRenderCreateConicalGradient must
be protected against an integer overflow during length check. This is
already included in ProcRenderCreateLinearGradient since the fix for
CVE-2008-2362.

This can only be successfully exploited on a 32 bit system for an
out of boundary read later on. Validated by using ASAN.
---
 render/render.c | 4 
 1 file changed, 4 insertions(+)

diff --git a/render/render.c b/render/render.c
index 8dc1f3425..ccae49a41 100644
--- a/render/render.c
+++ b/render/render.c
@@ -1908,6 +1908,8 @@ ProcRenderCreateRadialGradient(ClientPtr client)
 LEGAL_NEW_RESOURCE(stuff->pid, client);
 
 len = (client->req_len << 2) - sizeof(xRenderCreateRadialGradientReq);
+if (stuff->nStops > UINT32_MAX / (sizeof(xFixed) + sizeof(xRenderColor)))
+return BadLength;
 if (len != stuff->nStops * (sizeof(xFixed) + sizeof(xRenderColor)))
 return BadLength;
 
@@ -1946,6 +1948,8 @@ ProcRenderCreateConicalGradient(ClientPtr client)
 LEGAL_NEW_RESOURCE(stuff->pid, client);
 
 len = (client->req_len << 2) - sizeof(xRenderCreateConicalGradientReq);
+if (stuff->nStops > UINT32_MAX / (sizeof(xFixed) + sizeof(xRenderColor)))
+return BadLength;
 if (len != stuff->nStops * (sizeof(xFixed) + sizeof(xRenderColor)))
 return BadLength;
 
-- 
2.12.0

___
xorg-devel@lists.x.org: X.Org development
Archives: http://lists.x.org/archives/xorg-devel
Info: https://lists.x.org/mailman/listinfo/xorg-devel

[PATCH libXaw] NULL pointer dereference in XawAsciiSinkInitialize

2017-03-13 Thread Tobias Stoeckmann
The function XawAsciiSinkInitialize is prone to a NULL pointer
dereference if no font is available.

Even though a specific check for a NULL font exists, it is called
after GetGC(), which in turn would trigger the NPE in such a case.

Spotted by calling xmessage on a system with an incomplete x font setup:

$ xmessage -b text
Warning: Unable to load any usable ISO8859 font
Segmentation fault
$ _

Signed-off-by: Tobias Stoeckmann <tob...@stoeckmann.org>
---
 src/AsciiSink.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/src/AsciiSink.c b/src/AsciiSink.c
index d776895..1cccb1c 100644
--- a/src/AsciiSink.c
+++ b/src/AsciiSink.c
@@ -1704,10 +1704,10 @@ XawAsciiSinkInitialize(Widget request, Widget cnew,
 {
 AsciiSinkObject sink = (AsciiSinkObject)cnew;
 
-GetGC(sink);
-
 if (!sink->ascii_sink.font) XtError("Aborting: no font found\n");
 
+GetGC(sink);
+
 sink->ascii_sink.cursor_position = 0;
 sink->ascii_sink.laststate = XawisOff;
 sink->ascii_sink.cursor_x = sink->ascii_sink.cursor_y = 0;
-- 
2.12.0

___
xorg-devel@lists.x.org: X.Org development
Archives: http://lists.x.org/archives/xorg-devel
Info: https://lists.x.org/mailman/listinfo/xorg-devel

[PATCH libXau] Avoid out of boundary read access

2017-10-19 Thread Tobias Stoeckmann
If the environment variable HOME is empty, XauFileName triggers an
out of boundary read access (name[1]). If HOME consists of a single
character relative path, the output becomes unexpected, because
"HOME=a" leads to "a.Xauthority" instead of "a/.Xauthority". Granted,
a relative HOME path leads to trouble in general, the code should
properly return "a/.Xauthority" nonetheless.

Signed-off-by: Tobias Stoeckmann <tob...@stoeckmann.org>
---
 AuFileName.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/AuFileName.c b/AuFileName.c
index 37c8b62..2946c80 100644
--- a/AuFileName.c
+++ b/AuFileName.c
@@ -85,6 +85,6 @@ XauFileName (void)
bsize = size;
 }
 snprintf (buf, bsize, "%s%s", name,
-  slashDotXauthority + (name[1] == '\0' ? 1 : 0));
+  slashDotXauthority + (name[0] == '/' && name[1] == '\0' ? 1 : 
0));
 return buf;
 }
-- 
2.14.2

___
xorg-devel@lists.x.org: X.Org development
Archives: http://lists.x.org/archives/xorg-devel
Info: https://lists.x.org/mailman/listinfo/xorg-devel

[PATCH font-util] ucs2any: Fix parser crash on 32 bit

2017-11-08 Thread Tobias Stoeckmann
It is possible to crash ucs2any or provoke successful return value even
though the processing was not successful.

The problem lies within a possible integer overflow when adding elements
with a key which is too large.

You can trigger the issue this way on a 32 bit system:

$ cat > source.bdf << "EOF"
STARTFONT source
CHARS 1
ENCODING 1073741823
EOF
$ ucs2any source.bdf
Segmentation fault
$ _

Another possibility would be to add "ENCODING 1" right after the CHARS
line. In that case, realloc will allocate 0 bytes afterwards which is a
success but might return NULL, e.g. on Linux/glibc systems. Such a
result value is handled as an error and errno is evaluated and returned,
even though there was no error:

$ cat > source.bdf << "EOF"
STARTFONT source
CHARS 1
ENCODING 1
ENCODING 1073741823
EOF
$ ucs2any source.bdf
ucs2any: Success
$ echo $?
0
$ _

Signed-off-by: Tobias Stoeckmann <tob...@stoeckmann.org>
---
 ucs2any.c | 6 ++
 1 file changed, 6 insertions(+)

diff --git a/ucs2any.c b/ucs2any.c
index 10bb029..1f575d1 100644
--- a/ucs2any.c
+++ b/ucs2any.c
@@ -45,6 +45,7 @@
 #endif
 #include 
 #include 
+#include 
 #include 
 #include 
 #include 
@@ -220,6 +221,11 @@ da_add(da_t *da, int key, void *value)
 {
int i = da->size;
if (key >= 0) {
+   if ((size_t)key >= SIZE_MAX / sizeof(void *)) {
+   fprintf(stderr, "%s: Illegal key '%d' encountered!\n",
+   my_name, key);
+   exit(1);
+   }
if (key >= da->size) {
da->size = key + 1;
da->values = zrealloc(da->values,
-- 
2.15.0

___
xorg-devel@lists.x.org: X.Org development
Archives: http://lists.x.org/archives/xorg-devel
Info: https://lists.x.org/mailman/listinfo/xorg-devel

[PATCH libICE] Always terminate strncpy results.

2018-07-30 Thread Tobias Stoeckmann
The function strncpy does not guarantee to append a terminating
NUL character to the destination.

This patch merges libSM's way of handling this issue into libICE.

Signed-off-by: Tobias Stoeckmann 
---
 src/connect.c| 66 +++-
 src/listen.c | 24 +-
 src/listenwk.c   | 24 +-
 src/protosetup.c | 37 +++
 4 files changed, 110 insertions(+), 41 deletions(-)

diff --git a/src/connect.c b/src/connect.c
index 086b7f3..1554ad6 100644
--- a/src/connect.c
+++ b/src/connect.c
@@ -66,8 +66,11 @@ IceOpenConnection (
 
 if (networkIdsList == NULL || *networkIdsList == '\0')
 {
-   strncpy (errorStringRet,
-   "networkIdsList argument is NULL", errorLength);
+   if (errorStringRet && errorLength > 0) {
+   strncpy (errorStringRet,
+   "networkIdsList argument is NULL", errorLength);
+   errorStringRet[errorLength - 1] = '\0';
+   }
return (NULL);
 }
 
@@ -144,7 +147,10 @@ IceOpenConnection (
 
 if ((iceConn = malloc (sizeof (struct _IceConn))) == NULL)
 {
-   strncpy (errorStringRet, "Can't malloc", errorLength);
+   if (errorStringRet && errorLength > 0) {
+   strncpy (errorStringRet, "Can't malloc", errorLength);
+   errorStringRet[errorLength - 1] = '\0';
+   }
return (NULL);
 }
 
@@ -157,7 +163,10 @@ IceOpenConnection (
>connection_string)) == NULL)
 {
free (iceConn);
-   strncpy (errorStringRet, "Could not open network socket", errorLength);
+   if (errorStringRet && errorLength > 0) {
+   strncpy (errorStringRet, "Could not open network socket", 
errorLength);
+   errorStringRet[errorLength - 1] = '\0';
+   }
return (NULL);
 }
 
@@ -195,7 +204,10 @@ IceOpenConnection (
 if ((iceConn->inbuf = iceConn->inbufptr = malloc (ICE_INBUFSIZE)) == NULL)
 {
_IceFreeConnection (iceConn);
-   strncpy (errorStringRet, "Can't malloc", errorLength);
+   if (errorStringRet && errorLength > 0) {
+   strncpy (errorStringRet, "Can't malloc", errorLength);
+   errorStringRet[errorLength - 1] = '\0';
+   }
return (NULL);
 }
 
@@ -204,7 +216,10 @@ IceOpenConnection (
 if ((iceConn->outbuf = iceConn->outbufptr = calloc (1, ICE_OUTBUFSIZE)) == 
NULL)
 {
_IceFreeConnection (iceConn);
-   strncpy (errorStringRet, "Can't malloc", errorLength);
+   if (errorStringRet && errorLength > 0) {
+   strncpy (errorStringRet, "Can't malloc", errorLength);
+   errorStringRet[errorLength - 1] = '\0';
+   }
return (NULL);
 }
 
@@ -257,8 +272,11 @@ IceOpenConnection (
 if (ioErrorOccured)
 {
_IceFreeConnection (iceConn);
-   strncpy (errorStringRet, "IO error occured opening connection",
-errorLength);
+   if (errorStringRet && errorLength > 0) {
+   strncpy (errorStringRet, "IO error occured opening connection",
+errorLength);
+   errorStringRet[errorLength - 1] = '\0';
+   }
return (NULL);
 }
 
@@ -269,9 +287,12 @@ IceOpenConnection (
 */
 
_IceFreeConnection (iceConn);
-   strncpy (errorStringRet,
-   "Internal error - did not receive the expected ByteOrder message",
-errorLength);
+   if (errorStringRet && errorLength > 0) {
+   strncpy (errorStringRet,
+   "Internal error - did not receive the expected ByteOrder "
+   "message", errorLength);
+   errorStringRet[errorLength - 1] = '\0';
+   }
return (NULL);
 }
 
@@ -355,8 +376,11 @@ IceOpenConnection (
 
if (ioErrorOccured)
{
-   strncpy (errorStringRet, "IO error occured opening connection",
-   errorLength);
+   if (errorStringRet && errorLength > 0) {
+   strncpy (errorStringRet, "IO error occured opening connection",
+   errorLength);
+   errorStringRet[errorLength - 1] = '\0';
+   }
_IceFreeConnection (iceConn);
iceConn = NULL;
}
@@ -366,9 +390,12 @@ IceOpenConnection (
{
if (reply.connection_reply.version_index >= _IceVersionCount)
{
-   strncpy (errorStringRet,
-   "Got a bad version index in the Connection Reply",
-   errorLength);
+   if (errorStringRet && errorLength > 0) {
+   strncpy (errorStringRet,
+   "Got a bad version index in the Co

[PATCH app/xlsatoms 1/3] Support xcb_atom_t in range specification.

2018-07-04 Thread Tobias Stoeckmann
The data type xcb_atom_t is an unsigned int (32 bit), but the optional
range argument is parsed with atoi(), which returns a signed int.

Even though it is possible to reach all values through clever casting,
it is more readable by properly using correct data types.

This also fixes a segmentation fault on 32 bit systems if a range is
supplied which overflows size_t:

$ xlsatoms -range 0-1073741824
Segmentation fault (core dumped)

If an invalid range is supplied, an error message is printed. This is
new because previously an invalid range was silently accepted.

$ xlsatoms -range 0--1
$ _
$ xlsatoms-new -range 0--1
xlsatoms-new:  invalid range: 0--1

Signed-off-by: Tobias Stoeckmann 
---
 xlsatoms.c | 51 +--
 1 file changed, 41 insertions(+), 10 deletions(-)

diff --git a/xlsatoms.c b/xlsatoms.c
index d3e0883..2bb5b47 100644
--- a/xlsatoms.c
+++ b/xlsatoms.c
@@ -31,6 +31,7 @@ in this Software without prior written authorization from The 
Open Group.
 # include "config.h"
 #endif
 
+#include 
 #include 
 #include 
 #include 
@@ -45,10 +46,10 @@ static const char *ProgramName;
 static const char *DisplayString;
 
 static void do_name ( xcb_connection_t *c, const char *format, char *name );
-static int parse_range ( char *range, long *lowp, long *highp );
+static int parse_range ( char *range, xcb_atom_t *lowp, xcb_atom_t *highp );
 static void do_range ( xcb_connection_t *c, const char *format, char *range );
 static void list_atoms ( xcb_connection_t *c, const char *format, int mask,
-long low, long high );
+xcb_atom_t low, xcb_atom_t high );
 
 static void 
 usage(const char *errmsg)
@@ -161,8 +162,23 @@ do_name(xcb_connection_t *c, const char *format, char 
*name)
 #define RangeLow (1 << 0)
 #define RangeHigh (1 << 1)
 
+static int
+strtoatom(char *s, xcb_atom_t *atom)
+{
+long long value;
+char *end;
+
+value = strtoll(s, , 10);
+if (s == end || *end != '\0' || value < 0 || value > UINT32_MAX) {
+   return 1;
+}
+
+*atom = value;
+return 0;
+}
+
 static int 
-parse_range(char *range, long *lowp, long *highp)
+parse_range(char *range, xcb_atom_t *lowp, xcb_atom_t *highp)
 {
 char *dash;
 int mask = 0;
@@ -179,35 +195,46 @@ parse_range(char *range, long *lowp, long *highp)
*lowp = 1;
} else {/* low-[high] */
*dash = '\0';
-   *lowp = atoi (range);
+   if (strtoatom(range, lowp)) {
+   *dash = '-';
+   goto invalid;
+   }
*dash = '-';
}
mask |= RangeLow;
dash++;
if (*dash) {/* [low]-high */
-   *highp = atoi (dash);
+   if (strtoatom(dash, highp) || *highp < *lowp) {
+   goto invalid;
+   }
mask |= RangeHigh;
}
 } else {   /* number (low == high) */
-   *lowp = *highp = atoi (range);
+   if (strtoatom(range, lowp)) {
+   goto invalid;
+   }
+   *highp = *lowp;
mask |= (RangeLow | RangeHigh);
 }
 
 return mask;
+invalid:
+fprintf(stderr, "%s:  invalid range: %s\n", ProgramName, range);
+exit(1);
 }
 
 static void
 do_range(xcb_connection_t *c, const char *format, char *range)
 {
 int mask;
-long low, high;
+xcb_atom_t low, high;
 
 mask = parse_range (range, , );
 list_atoms (c, format, mask, low, high);
 }
 
 static int
-say_batch(xcb_connection_t *c, const char *format, xcb_get_atom_name_cookie_t 
*cookie, long low, long count)
+say_batch(xcb_connection_t *c, const char *format, xcb_get_atom_name_cookie_t 
*cookie, xcb_atom_t low, long count)
 {
 xcb_generic_error_t *e;
 char atom_name[1024];
@@ -240,7 +267,7 @@ say_batch(xcb_connection_t *c, const char *format, 
xcb_get_atom_name_cookie_t *c
 }
 
 static void
-list_atoms(xcb_connection_t *c, const char *format, int mask, long low, long 
high)
+list_atoms(xcb_connection_t *c, const char *format, int mask, xcb_atom_t low, 
xcb_atom_t high)
 {
 xcb_get_atom_name_cookie_t *cookie_jar;
 int done = 0;
@@ -250,9 +277,13 @@ list_atoms(xcb_connection_t *c, const char *format, int 
mask, long low, long hig
low = 1;
/* fall through */
   case (RangeLow | RangeHigh):
+   if (high - low >= SIZE_MAX / sizeof(xcb_get_atom_name_cookie_t)) {
+   fprintf(stderr, "Cannot allocate space for %lu atom requests\n", 
(unsigned long) (high - low));
+   return;
+   }
cookie_jar = malloc((high - low + 1) * 
sizeof(xcb_get_atom_name_cookie_t));
 if (!cookie_jar) {
-   fprintf(stderr, "Out of memory allocating space for %ld atom 
requests\n", high - low);
+   fprintf(stderr, "Out of memory allocating space for %lu atom 
requests\n",

[PATCH app/xlsatoms 3/3] Always use chunks when retrieving atoms.

2018-07-04 Thread Tobias Stoeckmann
If a low and high range limit has been specified, all atoms are
retrieved at once. This is also the reason why malloc() is used:
All cookies are stored before collecting the data.

By using chunks it is possible to specify a huge range or even
all possible atoms without running out of memory.

Signed-off-by: Tobias Stoeckmann 
---
 xlsatoms.c | 51 ++-
 1 file changed, 14 insertions(+), 37 deletions(-)

diff --git a/xlsatoms.c b/xlsatoms.c
index 5bed0cc..a971901 100644
--- a/xlsatoms.c
+++ b/xlsatoms.c
@@ -234,7 +234,7 @@ do_range(xcb_connection_t *c, const char *format, char 
*range)
 }
 
 static int
-say_batch(xcb_connection_t *c, const char *format, xcb_get_atom_name_cookie_t 
*cookie, xcb_atom_t low, long count)
+say_batch(xcb_connection_t *c, const char *format, xcb_get_atom_name_cookie_t 
*cookie, xcb_atom_t low, long count, int stop_error)
 {
 xcb_generic_error_t *e;
 char atom_name[1024];
@@ -248,7 +248,7 @@ say_batch(xcb_connection_t *c, const char *format, 
xcb_get_atom_name_cookie_t *c
xcb_get_atom_name_reply_t *r;
r = xcb_get_atom_name_reply(c, cookie[i], );
if (r) {
-   if (!done) {
+   if (!done || !stop_error) {
/* We could just use %.*s in 'format', but we want to be 
compatible
   with legacy command line usage */
snprintf(atom_name, sizeof(atom_name), "%.*s",
@@ -265,50 +265,27 @@ say_batch(xcb_connection_t *c, const char *format, 
xcb_get_atom_name_cookie_t *c
}
 }
 
-return done;
+return done && stop_error;
 }
 
 static void
 list_atoms(xcb_connection_t *c, const char *format, int mask, xcb_atom_t low, 
xcb_atom_t high)
 {
-xcb_get_atom_name_cookie_t *cookie_jar;
+xcb_get_atom_name_cookie_t cookie_jar[ATOMS_PER_BATCH];
 int done = 0;
+long count;
 
-switch (mask) {
-  case RangeHigh:
+if ((mask & RangeLow) == 0)
low = 1;
-   /* fall through */
-  case (RangeLow | RangeHigh):
-   if (high - low >= SIZE_MAX / sizeof(xcb_get_atom_name_cookie_t)) {
-   fprintf(stderr, "Cannot allocate space for %lu atom requests\n", 
(unsigned long) (high - low));
-   return;
-   }
-   cookie_jar = malloc((high - low + 1) * 
sizeof(xcb_get_atom_name_cookie_t));
-if (!cookie_jar) {
-   fprintf(stderr, "Out of memory allocating space for %lu atom 
requests\n", (unsigned long) (high - low));
-   return;
-   }
+if ((mask & RangeHigh) == 0)
+   high = UINT32_MAX;
 
-   say_batch(c, format, cookie_jar, low, high - low + 1);
-   free(cookie_jar);
-   break;
-
-  default:
-   low = 1;
-   /* fall through */
-  case RangeLow:
-   cookie_jar = malloc(ATOMS_PER_BATCH * 
sizeof(xcb_get_atom_name_cookie_t));
-if (!cookie_jar) {
-   fprintf(stderr, "Out of memory allocating space for %ld atom 
requests\n", (long) ATOMS_PER_BATCH);
-   return;
-   }
-   while (!done) {
-   done = say_batch(c, format, cookie_jar, low, ATOMS_PER_BATCH);
-   low += ATOMS_PER_BATCH;
+while (!done) {
+   count = high - low < ATOMS_PER_BATCH - 1 ? high - low + 1 : 
ATOMS_PER_BATCH;
+   done = say_batch(c, format, cookie_jar, low, count, (mask & RangeHigh) 
== 0);
+   if (high - low < UINT32_MAX && low == high - count + 1) {
+   done = 1;
}
-   free(cookie_jar);
-   break;
+   low += count;
 }
-
-return;
 }
-- 
2.18.0

___
xorg-devel@lists.x.org: X.Org development
Archives: http://lists.x.org/archives/xorg-devel
Info: https://lists.x.org/mailman/listinfo/xorg-devel

[PATCH app/xlsatoms 2/3] Actually stop after an invalid atom.

2018-07-04 Thread Tobias Stoeckmann
The manual page states that if no upper range limit has been specified,
no higher atoms will be printed. This is not true for

$ xlsatoms -range 0-

This prints the first 100 atoms, even though it already encountered an
invalid one at 0. The reason is that say_batch works as a batch, i.e.
retrieves 100 atoms at a time. If one of them is invalid, the rest is
still printed.

With this adjustment, xlsatoms behaves as stated in manual page.

Signed-off-by: Tobias Stoeckmann 
---
 xlsatoms.c | 16 +---
 1 file changed, 9 insertions(+), 7 deletions(-)

diff --git a/xlsatoms.c b/xlsatoms.c
index 2bb5b47..5bed0cc 100644
--- a/xlsatoms.c
+++ b/xlsatoms.c
@@ -248,13 +248,15 @@ say_batch(xcb_connection_t *c, const char *format, 
xcb_get_atom_name_cookie_t *c
xcb_get_atom_name_reply_t *r;
r = xcb_get_atom_name_reply(c, cookie[i], );
if (r) {
-   /* We could just use %.*s in 'format', but we want to be compatible
-  with legacy command line usage */
-   snprintf(atom_name, sizeof(atom_name), "%.*s",
-   r->name_len, xcb_get_atom_name_name(r));
-
-   printf (format, i + low, atom_name);
-   putchar ('\n');
+   if (!done) {
+   /* We could just use %.*s in 'format', but we want to be 
compatible
+  with legacy command line usage */
+   snprintf(atom_name, sizeof(atom_name), "%.*s",
+   r->name_len, xcb_get_atom_name_name(r));
+
+   printf (format, i + low, atom_name);
+   putchar ('\n');
+   }
free(r);
}
if (e) {
-- 
2.18.0

___
xorg-devel@lists.x.org: X.Org development
Archives: http://lists.x.org/archives/xorg-devel
Info: https://lists.x.org/mailman/listinfo/xorg-devel

[PATCH app/xlsatoms] Adjust man page to show default format.

2018-07-04 Thread Tobias Stoeckmann
The default format is %lu\t%s, not %ld\t%s, i.e. unsigned.

Signed-off-by: Tobias Stoeckmann 
---
 man/xlsatoms.man | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/man/xlsatoms.man b/man/xlsatoms.man
index afa89bf..34d386e 100644
--- a/man/xlsatoms.man
+++ b/man/xlsatoms.man
@@ -44,7 +44,7 @@ This option specifies the X server to which to connect.
 This option specifies a \fIprintf\fP-style string used to list each atom
 \fI\fP pair, printed in that order (\fIvalue\fP is an \fIunsigned
 long\fP and \fIname\fP is a \fIchar *\fP).  \fIXlsatoms\fP will supply a
-newline at the end of each line.  The default is \fI%ld\\t%s\fP.
+newline at the end of each line.  The default is \fI%lu\\t%s\fP.
 .TP 8
 .B \-range \fI[low]-[high]\fP
 This option specifies the range of atom values to check.  If \fIlow\fP is not
-- 
2.18.0

___
xorg-devel@lists.x.org: X.Org development
Archives: http://lists.x.org/archives/xorg-devel
Info: https://lists.x.org/mailman/listinfo/xorg-devel

[PATCH app/xinit] Buffer overflow with many arguments.

2019-01-18 Thread Tobias Stoeckmann
Command line arguments are copied into clientargv and serverargv without
verifying that enough space is available. A high amount of arguments can
therefore trigger a buffer overflow like this:

$ xinit $(seq 1 500)

Signed-off-by: Tobias Stoeckmann 
---
 xinit.c | 7 ---
 1 file changed, 4 insertions(+), 3 deletions(-)

diff --git a/xinit.c b/xinit.c
index f826b7a..8efd0be 100644
--- a/xinit.c
+++ b/xinit.c
@@ -151,7 +151,6 @@ main(int argc, char *argv[])
 register char **ptr;
 pid_t pid;
 int client_given = 0, server_given = 0;
-int client_args_given = 0, server_args_given = 0;
 int start_of_client_args, start_of_server_args;
 struct sigaction sa, si;
 #ifdef __APPLE__
@@ -174,7 +173,8 @@ main(int argc, char *argv[])
 }
 start_of_client_args = (cptr - client);
 while (argc && strcmp(*argv, "--")) {
-client_args_given++;
+if (cptr > clientargv + 98)
+Fatalx("too many client arguments");
 *cptr++ = *argv++;
 argc--;
 }
@@ -202,7 +202,8 @@ main(int argc, char *argv[])
 
 start_of_server_args = (sptr - server);
 while (--argc >= 0) {
-server_args_given++;
+if (sptr > serverargv + 98)
+Fatalx("too many server arguments");
 *sptr++ = *argv++;
 }
 *sptr = NULL;
-- 
2.20.1

___
xorg-devel@lists.x.org: X.Org development
Archives: http://lists.x.org/archives/xorg-devel
Info: https://lists.x.org/mailman/listinfo/xorg-devel

Re: [PATCH app/xinit] Buffer overflow with many arguments.

2019-02-07 Thread Tobias Stoeckmann
Command line arguments are copied into clientargv and serverargv without
verifying that enough space is available. A high amount of arguments can
therefore trigger a buffer overflow like this:

$ xinit $(seq 1 500)

Signed-off-by: Tobias Stoeckmann 
---
Integrated calculation as suggested by Walter with style according to
rest of the code.
---
 xinit.c | 7 ---
 1 file changed, 4 insertions(+), 3 deletions(-)

diff --git a/xinit.c b/xinit.c
index f826b7a..06c92b2 100644
--- a/xinit.c
+++ b/xinit.c
@@ -151,7 +151,6 @@ main(int argc, char *argv[])
 register char **ptr;
 pid_t pid;
 int client_given = 0, server_given = 0;
-int client_args_given = 0, server_args_given = 0;
 int start_of_client_args, start_of_server_args;
 struct sigaction sa, si;
 #ifdef __APPLE__
@@ -174,7 +173,8 @@ main(int argc, char *argv[])
 }
 start_of_client_args = (cptr - client);
 while (argc && strcmp(*argv, "--")) {
-client_args_given++;
+if (cptr > clientargv + sizeof(clientargv) / sizeof(*clientargv) - 2)
+Fatalx("too many client arguments");
 *cptr++ = *argv++;
 argc--;
 }
@@ -202,7 +202,8 @@ main(int argc, char *argv[])
 
 start_of_server_args = (sptr - server);
 while (--argc >= 0) {
-server_args_given++;
+if (sptr > serverargv + sizeof(serverargv) / sizeof(*serverargv) - 2)
+Fatalx("too many server arguments");
 *sptr++ = *argv++;
 }
 *sptr = NULL;
-- 
2.20.1

___
xorg-devel@lists.x.org: X.Org development
Archives: http://lists.x.org/archives/xorg-devel
Info: https://lists.x.org/mailman/listinfo/xorg-devel