i3 - improved tiling WM


libi3/root_atom_contents: handle data of arbitrary length

Patch status: needinfo

Patch by Lancelot SIX

Long description:

Handle data fetched from xcb_get_property_unchecked with arbitrary
length. This avoids having to rely on PATH_MAX macro where it is not
necessary.

To apply this patch, use:
curl http://cr.i3wm.org/patch/333/raw.patch | git am

b/libi3/root_atom_contents.c

17
@@ -31,6 +31,11 @@ char *root_atom_contents(const char *atomname, xcb_connection_t *provided_conn,
18
     xcb_intern_atom_cookie_t atom_cookie;
19
     xcb_intern_atom_reply_t *atom_reply;
20
     char *content;
21
+    /* xcb_get_property_unsafe needs the size of the required property
22
+     * expressed in words (4 bytes). Therefore, content_max_size should always
23
+     * be a multiple of 4. */
24
+    size_t content_max_size = 1024;
25
+    size_t content_size;
26
     xcb_connection_t *conn = provided_conn;
27
 
28
     if (provided_conn == NULL &&
29
@@ -50,13 +55,32 @@ char *root_atom_contents(const char *atomname, xcb_connection_t *provided_conn,
30
     xcb_get_property_cookie_t prop_cookie;
31
     xcb_get_property_reply_t *prop_reply;
32
     prop_cookie = xcb_get_property_unchecked(conn, false, root, atom_reply->atom,
33
-                                             XCB_GET_PROPERTY_TYPE_ANY, 0, PATH_MAX);
34
+                                             XCB_GET_PROPERTY_TYPE_ANY, 0, (content_max_size / 4));
35
     prop_reply = xcb_get_property_reply(conn, prop_cookie, NULL);
36
     if (prop_reply == NULL) {
37
         free(atom_reply);
38
         return NULL;
39
     }
40
-    if (xcb_get_property_value_length(prop_reply) == 0) {
41
+    content_size = xcb_get_property_value_length(prop_reply);
42
+    if (content_size > 0 && prop_reply->bytes_after > 0) {
43
+        /* We received an incomplete value. Ask again but with a properly
44
+         * adjusted size. */
45
+        content_max_size += prop_reply->bytes_after;
46
+        if ((content_max_size % 4) != 0)
47
+            content_max_size += 4 - (content_max_size % 4);
48
+
49
+        /* Repeat the request, with adjusted size */
50
+        free(prop_reply);
51
+        prop_cookie = xcb_get_property_unchecked(conn, false, root, atom_reply->atom,
52
+                                                 XCB_GET_PROPERTY_TYPE_ANY, 0, (content_max_size / 4));
53
+        prop_reply = xcb_get_property_reply(conn, prop_cookie, NULL);
54
+        if (prop_reply == NULL) {
55
+            free(atom_reply);
56
+            return NULL;
57
+        }
58
+        content_size = xcb_get_property_value_length(prop_reply);
59
+    }
60
+    if (content_size == 0) {
61
         free(atom_reply);
62
         free(prop_reply);
63
         return NULL;