diff options
author | Thorsten Wißmann <edu@thorsten-wissmann.de> | 2012-02-12 23:58:36 +0100 |
---|---|---|
committer | Thorsten Wißmann <edu@thorsten-wissmann.de> | 2012-02-13 00:00:14 +0100 |
commit | b69d1b3e0a13ea511800c6a24c1bd139f17e5fe0 (patch) | |
tree | f02aab1e2e12c925d17f0697ea7cae6263c4c907 /src/utils.c | |
parent | 5208faff415d99476c8c39934d2cb4522b29ac88 (diff) |
use XGetTextProperty for strings of unknown length
Do not use XGetWindowProperty() because it needs many calls until a
string of a (at compile time) unknown length is received. This causes a
race-condition if the value is changed between calls of
XGetWindowProperty() and can cause invalid values or even a xerror.
Example: Say you have a property with the value "123456789" and a
bufsize of 4. Then the first XGetWindowProperty call returns "1234". If
the value is changed to "123" and XGetWindowProperty is called again
with offset 4 then it would call a xerror. If the value is changed to
"abcdefgh" then the result would be "1234efgh".
Many thanks to Florian Bruhin (The-Compiler) for spotting this bug and
for making it reproducible!
Diffstat (limited to 'src/utils.c')
-rw-r--r-- | src/utils.c | 56 |
1 files changed, 20 insertions, 36 deletions
diff --git a/src/utils.c b/src/utils.c index 27d4629d..656d3ba0 100644 --- a/src/utils.c +++ b/src/utils.c @@ -40,46 +40,30 @@ unsigned long getcolor(const char *colstr) { return color.pixel; } +// inspired by dwm's gettextprop() GString* window_property_to_g_string(Display* dpy, Window window, Atom atom) { - GString* result = g_string_new(""); - long bufsize = 10; - char *buf; - Atom type; - int format; - unsigned long items, bytes; - long offset = 0; - bool parse_error_occured = false; - Atom req_type = ATOM("UTF8_STRING"); - Atom req_type_string = ATOM("STRING"); - do { - int status = XGetWindowProperty(dpy, window, - atom, offset, bufsize, False, - req_type, &type, &format, - &items, &bytes, (unsigned char**)&buf); - if (status == Success - && req_type != req_type_string - && req_type_string == type) { - req_type = req_type_string; - continue; - } - if (status != Success || format != 8 || req_type != type) { - parse_error_occured = true; - break; // then stop parsing - } else { - result = g_string_append(result, buf); - offset += bufsize; - XFree(buf); - } - HSDebug("XGetWindowProperty received: \"%s\"\n", result->str); - } while (bytes > 0); - // - if (parse_error_occured) { - // then just return NULL - g_string_free(result, true); + GString* result = NULL; + char** list = NULL; + int n = 0; + XTextProperty prop; + + if (0 == XGetTextProperty(dpy, window, &prop, atom)) { return NULL; + } + // convert text property to a gstring + result = g_string_new(""); + if (prop.encoding == XA_STRING || prop.encoding == ATOM("UTF8_STRING")) { + result = g_string_new((char*)prop.value); } else { - return result; + if (XmbTextPropertyToTextList(dpy, &prop, &list, &n) >= Success + && n > 0 && *list) + { + result = g_string_new(*list); + XFreeStringList(list); + } } + XFree(prop.value); + return result; } GString* window_class_to_g_string(Display* dpy, Window window) { |