Fix overflow issue
[platform/upstream/libxkbcommon.git] / src / text.c
index 8edc0e3..e85b0eb 100644 (file)
@@ -24,6 +24,8 @@
  *
  ********************************************************/
 
+#include "config.h"
+
 #include "keymap.h"
 #include "text.h"
 
@@ -31,12 +33,10 @@ bool
 LookupString(const LookupEntry tab[], const char *string,
               unsigned int *value_rtrn)
 {
-    const LookupEntry *entry;
-
     if (!string)
         return false;
 
-    for (entry = tab; entry->name; entry++) {
+    for (const LookupEntry *entry = tab; entry->name; entry++) {
         if (istreq(entry->name, string)) {
             *value_rtrn = entry->value;
             return true;
@@ -49,9 +49,7 @@ LookupString(const LookupEntry tab[], const char *string,
 const char *
 LookupValue(const LookupEntry tab[], unsigned int value)
 {
-    const LookupEntry *entry;
-
-    for (entry = tab; entry->name; entry++)
+    for (const LookupEntry *entry = tab; entry->name; entry++)
         if (entry->value == value)
             return entry->name;
 
@@ -80,78 +78,78 @@ const LookupEntry ctrlMaskNames[] = {
 };
 
 const LookupEntry modComponentMaskNames[] = {
-    {"base", XKB_STATE_MODS_DEPRESSED},
-    {"latched", XKB_STATE_MODS_LATCHED},
-    {"locked", XKB_STATE_MODS_LOCKED},
-    {"effective", XKB_STATE_MODS_EFFECTIVE},
-    {"compat", XKB_STATE_MODS_EFFECTIVE},
-    {"any", XKB_STATE_MODS_EFFECTIVE},
-    {"none", 0},
-    {NULL, 0}
+    { "base", XKB_STATE_MODS_DEPRESSED },
+    { "latched", XKB_STATE_MODS_LATCHED },
+    { "locked", XKB_STATE_MODS_LOCKED },
+    { "effective", XKB_STATE_MODS_EFFECTIVE },
+    { "compat", XKB_STATE_MODS_EFFECTIVE },
+    { "any", XKB_STATE_MODS_EFFECTIVE },
+    { "none", 0 },
+    { NULL, 0 }
 };
 
 const LookupEntry groupComponentMaskNames[] = {
-    {"base", XKB_STATE_LAYOUT_DEPRESSED},
-    {"latched", XKB_STATE_LAYOUT_LATCHED},
-    {"locked", XKB_STATE_LAYOUT_LOCKED},
-    {"effective", XKB_STATE_LAYOUT_EFFECTIVE},
-    {"any", XKB_STATE_LAYOUT_EFFECTIVE},
-    {"none", 0},
-    {NULL, 0}
+    { "base", XKB_STATE_LAYOUT_DEPRESSED },
+    { "latched", XKB_STATE_LAYOUT_LATCHED },
+    { "locked", XKB_STATE_LAYOUT_LOCKED },
+    { "effective", XKB_STATE_LAYOUT_EFFECTIVE },
+    { "any", XKB_STATE_LAYOUT_EFFECTIVE },
+    { "none", 0 },
+    { NULL, 0 }
 };
 
 const LookupEntry groupMaskNames[] = {
-    {"group1", 0x01},
-    {"group2", 0x02},
-    {"group3", 0x04},
-    {"group4", 0x08},
-    {"group5", 0x10},
-    {"group6", 0x20},
-    {"group7", 0x40},
-    {"group8", 0x80},
-    {"none", 0x00},
-    {"all", 0xff},
-    {NULL, 0}
+    { "Group1", 0x01 },
+    { "Group2", 0x02 },
+    { "Group3", 0x04 },
+    { "Group4", 0x08 },
+    { "Group5", 0x10 },
+    { "Group6", 0x20 },
+    { "Group7", 0x40 },
+    { "Group8", 0x80 },
+    { "none", 0x00 },
+    { "all", 0xff },
+    { NULL, 0 }
 };
 
 const LookupEntry groupNames[] = {
-    {"group1", 1},
-    {"group2", 2},
-    {"group3", 3},
-    {"group4", 4},
-    {"group5", 5},
-    {"group6", 6},
-    {"group7", 7},
-    {"group8", 8},
-    {NULL, 0}
+    { "Group1", 1 },
+    { "Group2", 2 },
+    { "Group3", 3 },
+    { "Group4", 4 },
+    { "Group5", 5 },
+    { "Group6", 6 },
+    { "Group7", 7 },
+    { "Group8", 8 },
+    { NULL, 0 }
 };
 
 const LookupEntry levelNames[] = {
-    { "level1", 1 },
-    { "level2", 2 },
-    { "level3", 3 },
-    { "level4", 4 },
-    { "level5", 5 },
-    { "level6", 6 },
-    { "level7", 7 },
-    { "level8", 8 },
+    { "Level1", 1 },
+    { "Level2", 2 },
+    { "Level3", 3 },
+    { "Level4", 4 },
+    { "Level5", 5 },
+    { "Level6", 6 },
+    { "Level7", 7 },
+    { "Level8", 8 },
     { NULL, 0 }
 };
 
 const LookupEntry buttonNames[] = {
-    { "button1", 1 },
-    { "button2", 2 },
-    { "button3", 3 },
-    { "button4", 4 },
-    { "button5", 5 },
+    { "Button1", 1 },
+    { "Button2", 2 },
+    { "Button3", 3 },
+    { "Button4", 4 },
+    { "Button5", 5 },
     { "default", 0 },
     { NULL, 0 }
 };
 
 const LookupEntry useModMapValueNames[] = {
-    { "levelone", 1 },
-    { "level1", 1 },
-    { "anylevel", 0 },
+    { "LevelOne", 1 },
+    { "Level1", 1 },
+    { "AnyLevel", 0 },
     { "any", 0 },
     { NULL, 0 }
 };
@@ -179,10 +177,10 @@ const LookupEntry actionTypeNames[] = {
     { "SwitchScreen", ACTION_TYPE_SWITCH_VT },
     { "SetControls", ACTION_TYPE_CTRL_SET },
     { "LockControls", ACTION_TYPE_CTRL_LOCK },
-    { "RedirectKey", ACTION_TYPE_KEY_REDIRECT },
-    { "Redirect", ACTION_TYPE_KEY_REDIRECT },
     { "Private", ACTION_TYPE_PRIVATE },
     /* deprecated actions below here - unused */
+    { "RedirectKey", ACTION_TYPE_NONE },
+    { "Redirect", ACTION_TYPE_NONE },
     { "ISOLock", ACTION_TYPE_NONE },
     { "ActionMessage", ACTION_TYPE_NONE },
     { "MessageAction", ACTION_TYPE_NONE },
@@ -208,74 +206,20 @@ const LookupEntry symInterpretMatchMaskNames[] = {
     { "AnyOf", MATCH_ANY },
     { "AllOf", MATCH_ALL },
     { "Exactly", MATCH_EXACTLY },
+    { NULL, 0 },
 };
 
 const char *
-ModMaskText(const struct xkb_keymap *keymap, xkb_mod_mask_t mask)
-{
-    xkb_mod_index_t i;
-    size_t len;
-    ssize_t rem;
-    char *str;
-    char buf[1024];
-    const struct xkb_mod *mod;
-
-    if (mask == 0)
-        return "none";
-
-    if (mask == MOD_REAL_MASK_ALL)
-        return "all";
-
-    str = buf;
-    buf[0] = '\0';
-    rem = sizeof(buf);
-    darray_enumerate(i, mod, keymap->mods) {
-        if (!(mask & (1 << i)))
-            continue;
-
-        len = snprintf(str, rem, "%s%s",
-                       (str != buf) ? "+" : "",
-                       xkb_atom_text(keymap->ctx, mod->name));
-        rem -= len;
-        str += len;
-
-        if (rem <= 1)
-            break;
-    }
-    str = buf;
-
-    len = strlen(str);
-    if (len >= sizeof(buf))
-        len = sizeof(buf) - 1;
-
-    return strcpy(xkb_context_get_buffer(keymap->ctx, len + 1), str);
-
-}
-
-const char *
-ModIndexText(const struct xkb_keymap *keymap, xkb_mod_index_t ndx)
+ModIndexText(struct xkb_context *ctx, const struct xkb_mod_set *mods,
+             xkb_mod_index_t ndx)
 {
     if (ndx == XKB_MOD_INVALID)
         return "none";
 
-    if (ndx >= darray_size(keymap->mods))
+    if (ndx >= mods->num_mods)
         return NULL;
 
-    return xkb_atom_text(keymap->ctx, darray_item(keymap->mods, ndx).name);
-}
-
-xkb_mod_index_t
-ModNameToIndex(const struct xkb_keymap *keymap, xkb_atom_t name,
-               enum mod_type type)
-{
-    xkb_mod_index_t i;
-    const struct xkb_mod *mod;
-
-    darray_enumerate(i, mod, keymap->mods)
-        if ((mod->type & type) && name == mod->name)
-            return i;
-
-    return XKB_MOD_INVALID;
+    return xkb_atom_text(ctx, mods->mods[ndx].name);
 }
 
 const char *
@@ -297,9 +241,9 @@ const char *
 KeyNameText(struct xkb_context *ctx, xkb_atom_t name)
 {
     const char *sname = xkb_atom_text(ctx, name);
-    size_t len = strlen(sname) + 3;
+    size_t len = strlen_safe(sname) + 3;
     char *buf = xkb_context_get_buffer(ctx, len);
-    snprintf(buf, len, "<%s>", sname);
+    snprintf(buf, len, "<%s>", strempty(sname));
     return buf;
 }
 
@@ -309,49 +253,73 @@ SIMatchText(enum xkb_match_operation type)
     return LookupValue(symInterpretMatchMaskNames, type);
 }
 
-#define GET_TEXT_BUF_SIZE 512
+const char *
+ModMaskText(struct xkb_context *ctx, const struct xkb_mod_set *mods,
+            xkb_mod_mask_t mask)
+{
+    char buf[1024] = {0};
+    size_t pos = 0;
+    xkb_mod_index_t i;
+    const struct xkb_mod *mod;
+
+    if (mask == 0)
+        return "none";
+
+    if (mask == MOD_REAL_MASK_ALL)
+        return "all";
+
+    xkb_mods_enumerate(i, mod, mods) {
+        int ret;
 
-#define append_get_text(...) do { \
-        int _size = snprintf(ret, GET_TEXT_BUF_SIZE, __VA_ARGS__); \
-        if (_size >= GET_TEXT_BUF_SIZE) \
-            return NULL; \
-} while (0)
+        if (!(mask & (1u << i)))
+            continue;
+
+        ret = snprintf(buf + pos, sizeof(buf) - pos, "%s%s",
+                       pos == 0 ? "" : "+",
+                       xkb_atom_text(ctx, mod->name));
+        if (ret <= 0 || pos + ret >= sizeof(buf))
+            break;
+        else
+            pos += ret;
+    }
+
+    return strncpy(xkb_context_get_buffer(ctx, pos + 1), buf, pos + 1);
+}
 
 const char *
-IndicatorStateText(struct xkb_context *ctx, enum xkb_state_component mask)
+LedStateMaskText(struct xkb_context *ctx, enum xkb_state_component mask)
 {
-    unsigned int i;
-    char *ret;
+    char buf[1024] = {0};
+    size_t pos = 0;
 
     if (mask == 0)
         return "0";
 
-    ret = xkb_context_get_buffer(ctx, GET_TEXT_BUF_SIZE);
-    ret[0] = '\0';
-
-    for (i = 0; mask; i++) {
-        const char *name;
+    for (unsigned i = 0; mask; i++) {
+        int ret;
 
-        if (!(mask & (1 << i)))
+        if (!(mask & (1u << i)))
             continue;
 
-        mask &= ~(1 << i);
-        name = LookupValue(modComponentMaskNames, 1 << i);
+        mask &= ~(1u << i);
 
-        if (ret[0] != '\0')
-            append_get_text("%s+%s", ret, name);
+        ret = snprintf(buf + pos, sizeof(buf) - pos, "%s%s",
+                       pos == 0 ? "" : "+",
+                       LookupValue(modComponentMaskNames, 1u << i));
+        if (ret <= 0 || pos + ret >= sizeof(buf))
+            break;
         else
-            append_get_text("%s", name);
+            pos += ret;
     }
 
-    return ret;
+    return strncpy(xkb_context_get_buffer(ctx, pos + 1), buf, pos + 1);
 }
 
 const char *
 ControlMaskText(struct xkb_context *ctx, enum xkb_action_controls mask)
 {
-    unsigned int i;
-    char *ret;
+    char buf[1024] = {0};
+    size_t pos = 0;
 
     if (mask == 0)
         return "none";
@@ -359,23 +327,22 @@ ControlMaskText(struct xkb_context *ctx, enum xkb_action_controls mask)
     if (mask == CONTROL_ALL)
         return "all";
 
-    ret = xkb_context_get_buffer(ctx, GET_TEXT_BUF_SIZE);
-    ret[0] = '\0';
-
-    for (i = 0; mask; i++) {
-        const char *name;
+    for (unsigned i = 0; mask; i++) {
+        int ret;
 
-        if (!(mask & (1 << i)))
+        if (!(mask & (1u << i)))
             continue;
 
-        mask &= ~(1 << i);
-        name = LookupValue(ctrlMaskNames, 1 << i);
+        mask &= ~(1u << i);
 
-        if (ret[0] != '\0')
-            append_get_text("%s+%s", ret, name);
+        ret = snprintf(buf + pos, sizeof(buf) - pos, "%s%s",
+                       pos == 0 ? "" : "+",
+                       LookupValue(ctrlMaskNames, 1u << i));
+        if (ret <= 0 || pos + ret >= sizeof(buf))
+            break;
         else
-            append_get_text("%s", name);
+            pos += ret;
     }
 
-    return ret;
+    return strncpy(xkb_context_get_buffer(ctx, pos + 1), buf, pos + 1);
 }