diff options
author | Tobias Stoeckmann <tobias@stoeckmann.org> | 2018-07-04 15:28:41 +0200 |
---|---|---|
committer | Alan Coopersmith <alan.coopersmith@oracle.com> | 2018-11-12 11:41:47 -0800 |
commit | 22a8eb00662a926cd5df52ba15851a31104ae41e (patch) | |
tree | 1c6adbc816d7cb2286a3c4954f03be80bc56b7ec | |
parent | c0812822f34affaae3c3eced8a625535e515a290 (diff) |
Support xcb_atom_t in range specification.
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@stoeckmann.org>
Signed-off-by: Alan Coopersmith <alan.coopersmith@oracle.com>
-rw-r--r-- | xlsatoms.c | 51 |
1 files changed, 41 insertions, 10 deletions
@@ -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; } |