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

Tobias Stoeckmann tobias at stoeckmann.org
Wed Jul 4 13:28:41 UTC 2018


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 <tobias at stoeckmann.org>
---
 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 <limits.h>
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
@@ -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, &end, 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, &low, &high);
     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", (unsigned long) (high - low));
 	    return;
 	}
 
-- 
2.18.0



More information about the xorg-devel mailing list