Commit e879828717a8b7bdf12efbbf9a1baeb20e1fcdd2

Kristian Høgsberg 2010-10-08T15:33:18

Don't return a static buffer in public API

diff --git a/include/X11/extensions/XKBcommon.h b/include/X11/extensions/XKBcommon.h
index c1bc270..0b6fb77 100644
--- a/include/X11/extensions/XKBcommon.h
+++ b/include/X11/extensions/XKBcommon.h
@@ -797,15 +797,11 @@ xkb_canonicalise_components(struct xkb_component_names * names,
  * Converts a keysym to a string; will return unknown Unicode codepoints
  * as "Ua1b2", and other unknown keysyms as "0xabcd1234".
  *
- * The string returned may become invalidated after the next call to
- * xkb_keysym_to_string: if you need to preserve it, then you must
- * duplicate it.
- *
  * This is uint32_t rather than KeySym, as KeySym changes size between
  * client and server (no, really).
  */
-_X_EXPORT extern char *
-xkb_keysym_to_string(uint32_t ks);
+_X_EXPORT extern void
+xkb_keysym_to_string(uint32_t ks, char *buffer, size_t size);
 
 /*
  * See xkb_keysym_to_string comments: this function will accept any string
diff --git a/src/keysym.c b/src/keysym.c
index 9316fc1..9fd3764 100644
--- a/src/keysym.c
+++ b/src/keysym.c
@@ -37,21 +37,22 @@ authorization from the authors.
 
 #include "ks_tables.h"
 
-char *
-xkb_keysym_to_string(uint32_t ks)
+void
+xkb_keysym_to_string(uint32_t ks, char *buffer, size_t size)
 {
     int i, n, h, idx;
     const unsigned char *entry;
-    static char ret[11];
     unsigned char val1, val2, val3, val4;
 
-    if ((ks & ((unsigned long) ~0x1fffffff)) != 0)
-        return NULL;
+    if ((ks & ((unsigned long) ~0x1fffffff)) != 0) {
+        snprintf(buffer, size, "Invalid");
+        return;
+    }
 
     /* Not listed in keysymdef.h for hysterical raisins. */
     if (ks == NoSymbol) {
-        sprintf(ret, "NoSymbol");
-        return ret;
+        snprintf(buffer, size, "NoSymbol");
+        return;
     }
 
     /* Try to find it in our hash table. */
@@ -68,8 +69,10 @@ xkb_keysym_to_string(uint32_t ks)
             entry = &_XkeyTable[idx];
 
             if ((entry[0] == val1) && (entry[1] == val2) &&
-                (entry[2] == val3) && (entry[3] == val4))
-                return ((char *)entry + 4);
+                (entry[2] == val3) && (entry[3] == val4)) {
+		snprintf(buffer, size, "%s", entry + 4);
+		return;
+	    }
 
             if (!--n)
                 break;
@@ -80,15 +83,12 @@ xkb_keysym_to_string(uint32_t ks)
         }
     }
 
-    /* Unnamed Unicode codepoint. */
-    if (ks >= 0x01000100 && ks <= 0x0110ffff) {
-        sprintf(ret, "U%lx", ks & 0xffffffUL);
-        return ret;
-    }
-
-    /* Unnamed, non-Unicode, symbol (shouldn't generally happen). */
-    sprintf(ret, "0x%08x", ks);
-    return ret;
+    if (ks >= 0x01000100 && ks <= 0x0110ffff)
+	/* Unnamed Unicode codepoint. */
+        snprintf(buffer, size, "U%lx", ks & 0xffffffUL);
+    else
+	/* Unnamed, non-Unicode, symbol (shouldn't generally happen). */
+	snprintf(buffer, size, "0x%08x", ks);
 }
 
 uint32_t
diff --git a/src/text.c b/src/text.c
index fc3cc45..1f82979 100644
--- a/src/text.c
+++ b/src/text.c
@@ -281,7 +281,11 @@ XkbcActionTypeText(unsigned type)
 char *
 XkbcKeysymText(uint32_t sym)
 {
-    return xkb_keysym_to_string(sym);
+    static char buffer[16];
+
+    xkb_keysym_to_string(sym, buffer, sizeof buffer);
+
+    return buffer;
 }
 
 char *
diff --git a/test/xkey.c b/test/xkey.c
index 9d7a08f..78baedd 100644
--- a/test/xkey.c
+++ b/test/xkey.c
@@ -15,8 +15,10 @@ static void print_keysym(const char *s)
 
 static void print_string(KeySym ks)
 {
-    char *s = xkb_keysym_to_string(ks);
-    printf("%s\n", s ? s : "NULL");
+    char s[16];
+
+    xkb_keysym_to_string(ks, s, sizeof s);
+    printf("%s\n", s);
 }
 
 int main(int argc, char *argv[])