[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