fix possible overflow
[dmenu.git] / dmenu.c
diff --git a/dmenu.c b/dmenu.c
index a8a6290..c4b7908 100644 (file)
--- a/dmenu.c
+++ b/dmenu.c
@@ -3,6 +3,7 @@
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
+#include <strings.h>
 #include <unistd.h>
 #include <X11/Xlib.h>
 #include <X11/Xatom.h>
@@ -30,7 +31,7 @@ static void grabkeyboard(void);
 static void insert(const char *str, ssize_t n);
 static void keypress(XKeyEvent *ev);
 static void match(Bool sub);
-static size_t nextrune(int incr);
+static size_t nextrune(int inc);
 static void paste(void);
 static void readstdin(void);
 static void run(void);
@@ -134,7 +135,7 @@ appenditem(Item *item, Item **list, Item **last) {
 
 void
 calcoffsets(void) {
-       unsigned int i, n;
+       int i, n;
 
        if(lines > 0)
                n = lines * bh;
@@ -231,13 +232,14 @@ insert(const char *str, ssize_t n) {
 void
 keypress(XKeyEvent *ev) {
        char buf[32];
-       size_t len;
        KeySym ksym;
 
-       len = strlen(text);
        XLookupString(ev, buf, sizeof buf, &ksym, NULL);
-       if(ev->state & ControlMask)
-               switch(tolower(ksym)) {
+       if(ev->state & ControlMask) {
+               KeySym lower, upper;
+
+               XConvertCase(ksym, &lower, &upper);
+               switch(lower) {
                default:
                        return;
                case XK_a:
@@ -290,13 +292,14 @@ keypress(XKeyEvent *ev) {
                        XConvertSelection(dc->dpy, XA_PRIMARY, utf8, utf8, win, CurrentTime);
                        return;
                }
+       }
        switch(ksym) {
        default:
                if(!iscntrl(*buf))
                        insert(buf, strlen(buf));
                break;
        case XK_Delete:
-               if(cursor == len)
+               if(text[cursor] == '\0')
                        return;
                cursor = nextrune(+1);
        case XK_BackSpace:
@@ -304,8 +307,8 @@ keypress(XKeyEvent *ev) {
                        insert(NULL, nextrune(-1) - cursor);
                break;
        case XK_End:
-               if(cursor < len) {
-                       cursor = len;
+               if(text[cursor] != '\0') {
+                       cursor = strlen(text);
                        break;
                }
                if(next) {
@@ -358,7 +361,7 @@ keypress(XKeyEvent *ev) {
                fputs((sel && !(ev->state & ShiftMask)) ? sel->text : text, stdout);
                exit(EXIT_SUCCESS);
        case XK_Right:
-               if(cursor < len) {
+               if(text[cursor] != '\0') {
                        cursor = nextrune(+1);
                        break;
                }
@@ -385,11 +388,11 @@ void
 match(Bool sub) {
        size_t len = strlen(text);
        Item *lexact, *lprefix, *lsubstr, *exactend, *prefixend, *substrend;
-       Item *item, *next = NULL;
+       Item *item, *lnext;
 
        lexact = lprefix = lsubstr = exactend = prefixend = substrend = NULL;
-       for(item = sub ? matches : items; item && item->text; item = next) {
-               next = sub ? item->right : item + 1;
+       for(item = sub ? matches : items; item && item->text; item = lnext) {
+               lnext = sub ? item->right : item + 1;
                if(!fstrncmp(text, item->text, len + 1))
                        appenditem(item, &lexact, &exactend);
                else if(!fstrncmp(text, item->text, len))
@@ -423,10 +426,10 @@ match(Bool sub) {
 }
 
 size_t
-nextrune(int incr) {
-       size_t n, len = strlen(text);
+nextrune(int inc) {
+       ssize_t n;
 
-       for(n = cursor + incr; n >= 0 && n < len && (text[n] & 0xc0) == 0x80; n += incr);
+       for(n = cursor + inc; n + inc >= 0 && (text[n] & 0xc0) == 0x80; n += inc);
        return n;
 }
 
@@ -439,7 +442,7 @@ paste(void) {
 
        XGetWindowProperty(dc->dpy, win, utf8, 0, (sizeof text / 4) + 1, False,
                           utf8, &da, &di, &dl, &dl, (unsigned char **)&p);
-       insert(p, (q = strchr(p, '\n')) ? q-p : strlen(p));
+       insert(p, (q = strchr(p, '\n')) ? q-p : (ssize_t)strlen(p));
        XFree(p);
        drawmenu();
 }