]> Sergey Matveev's repositories - st.git/blobdiff - st.c
Fix bounds checks of dc.col
[st.git] / st.c
diff --git a/st.c b/st.c
index c71fa0677ee40d7ba71b5b67fbb70b4386500be8..623376e1b172781f66dd21ef220e165a8146eaad 100644 (file)
--- a/st.c
+++ b/st.c
@@ -161,6 +161,7 @@ static void csidump(void);
 static void csihandle(void);
 static void csiparse(void);
 static void csireset(void);
+static void osc_color_response(int, int, int);
 static int eschandle(uchar);
 static void strdump(void);
 static void strhandle(void);
@@ -349,25 +350,10 @@ utf8validate(Rune *u, size_t i)
        return i;
 }
 
-static const char base64_digits[] = {
-       0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-       0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 62, 0, 0, 0,
-       63, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 0, 0, 0, -1, 0, 0, 0, 0, 1,
-       2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21,
-       22, 23, 24, 25, 0, 0, 0, 0, 0, 0, 26, 27, 28, 29, 30, 31, 32, 33, 34,
-       35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 0,
-       0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-       0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-       0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-       0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-       0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-       0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
-};
-
 char
 base64dec_getc(const char **src)
 {
-       while (**src && !isprint(**src))
+       while (**src && !isprint((unsigned char)**src))
                (*src)++;
        return **src ? *((*src)++) : '=';  /* emulate padding if string ends */
 }
@@ -377,6 +363,13 @@ base64dec(const char *src)
 {
        size_t in_len = strlen(src);
        char *result, *dst;
+       static const char base64_digits[256] = {
+               [43] = 62, 0, 0, 0, 63, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61,
+               0, 0, 0, -1, 0, 0, 0, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12,
+               13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 0, 0, 0, 0,
+               0, 0, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39,
+               40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51
+       };
 
        if (in_len % 4)
                in_len += 4 - (in_len % 4);
@@ -946,7 +939,7 @@ ttyresize(int tw, int th)
 }
 
 void
-ttyhangup()
+ttyhangup(void)
 {
        /* Send SIGHUP to shell */
        kill(pid, SIGHUP);
@@ -1776,11 +1769,18 @@ csihandle(void)
        case 'm': /* SGR -- Terminal attribute (color) */
                tsetattr(csiescseq.arg, csiescseq.narg);
                break;
-       case 'n': /* DSR – Device Status Report (cursor position) */
-               if (csiescseq.arg[0] == 6) {
+       case 'n': /* DSR -- Device Status Report */
+               switch (csiescseq.arg[0]) {
+               case 5: /* Status Report "OK" `0n` */
+                       ttywrite("\033[0n", sizeof("\033[0n") - 1, 0);
+                       break;
+               case 6: /* Report Cursor Position (CPR) "<row>;<column>R" */
                        len = snprintf(buf, sizeof(buf), "\033[%i;%iR",
-                                       term.c.y+1, term.c.x+1);
+                                      term.c.y+1, term.c.x+1);
                        ttywrite(buf, len, 0);
+                       break;
+               default:
+                       goto unknown;
                }
                break;
        case 'r': /* DECSTBM -- Set Scrolling Region */
@@ -1843,39 +1843,28 @@ csireset(void)
 }
 
 void
-osc4_color_response(int num)
+osc_color_response(int num, int index, int is_osc4)
 {
        int n;
        char buf[32];
        unsigned char r, g, b;
 
-       if (xgetcolor(num, &r, &g, &b)) {
-               fprintf(stderr, "erresc: failed to fetch osc4 color %d\n", num);
+       if (xgetcolor(is_osc4 ? num : index, &r, &g, &b)) {
+               fprintf(stderr, "erresc: failed to fetch %s color %d\n",
+                       is_osc4 ? "osc4" : "osc",
+                       is_osc4 ? num : index);
                return;
        }
 
-       n = snprintf(buf, sizeof buf, "\033]4;%d;rgb:%02x%02x/%02x%02x/%02x%02x\007",
-                    num, r, r, g, g, b, b);
-
-       ttywrite(buf, n, 1);
-}
-
-void
-osc_color_response(int index, int num)
-{
-       int n;
-       char buf[32];
-       unsigned char r, g, b;
-
-       if (xgetcolor(index, &r, &g, &b)) {
-               fprintf(stderr, "erresc: failed to fetch osc color %d\n", index);
-               return;
+       n = snprintf(buf, sizeof buf, "\033]%s%d;rgb:%02x%02x/%02x%02x/%02x%02x\007",
+                    is_osc4 ? "4;" : "", num, r, r, g, g, b, b);
+       if (n < 0 || n >= sizeof(buf)) {
+               fprintf(stderr, "error: %s while printing %s response\n",
+                       n < 0 ? "snprintf failed" : "truncation occurred",
+                       is_osc4 ? "osc4" : "osc");
+       } else {
+               ttywrite(buf, n, 1);
        }
-
-       n = snprintf(buf, sizeof buf, "\033]%d;rgb:%02x%02x/%02x%02x/%02x%02x\007",
-                    num, r, r, g, g, b, b);
-
-       ttywrite(buf, n, 1);
 }
 
 void
@@ -1883,6 +1872,11 @@ strhandle(void)
 {
        char *p = NULL, *dec;
        int j, narg, par;
+       const struct { int idx; char *str; } osc_table[] = {
+               { defaultfg, "foreground" },
+               { defaultbg, "background" },
+               { defaultcs, "cursor" }
+       };
 
        term.esc &= ~(ESC_STR_END|ESC_STR);
        strparse();
@@ -1917,43 +1911,22 @@ strhandle(void)
                        }
                        return;
                case 10:
-                       if (narg < 2)
-                               break;
-
-                       p = strescseq.args[1];
-
-                       if (!strcmp(p, "?"))
-                               osc_color_response(defaultfg, 10);
-                       else if (xsetcolorname(defaultfg, p))
-                               fprintf(stderr, "erresc: invalid foreground color: %s\n", p);
-                       else
-                               tfulldirt();
-                       return;
                case 11:
-                       if (narg < 2)
-                               break;
-
-                       p = strescseq.args[1];
-
-                       if (!strcmp(p, "?"))
-                               osc_color_response(defaultbg, 11);
-                       else if (xsetcolorname(defaultbg, p))
-                               fprintf(stderr, "erresc: invalid background color: %s\n", p);
-                       else
-                               tfulldirt();
-                       return;
                case 12:
                        if (narg < 2)
                                break;
-
                        p = strescseq.args[1];
-
-                       if (!strcmp(p, "?"))
-                               osc_color_response(defaultcs, 12);
-                       else if (xsetcolorname(defaultcs, p))
-                               fprintf(stderr, "erresc: invalid cursor color: %s\n", p);
-                       else
+                       if ((j = par - 10) < 0 || j >= LEN(osc_table))
+                               break; /* shouldn't be possible */
+
+                       if (!strcmp(p, "?")) {
+                               osc_color_response(par, osc_table[j].idx, 0);
+                       } else if (xsetcolorname(osc_table[j].idx, p)) {
+                               fprintf(stderr, "erresc: invalid %s color: %s\n",
+                                       osc_table[j].str, p);
+                       } else {
                                tfulldirt();
+                       }
                        return;
                case 4: /* color set */
                        if (narg < 3)
@@ -1963,11 +1936,13 @@ strhandle(void)
                case 104: /* color reset */
                        j = (narg > 1) ? atoi(strescseq.args[1]) : -1;
 
-                       if (p && !strcmp(p, "?"))
-                               osc4_color_response(j);
-                       else if (xsetcolorname(j, p)) {
-                               if (par == 104 && narg <= 1)
+                       if (p && !strcmp(p, "?")) {
+                               osc_color_response(j, 0, 1);
+                       } else if (xsetcolorname(j, p)) {
+                               if (par == 104 && narg <= 1) {
+                                       xloadcols();
                                        return; /* color reset without parameter */
+                               }
                                fprintf(stderr, "erresc: invalid color j=%d, p=%s\n",
                                        j, p ? p : "(null)");
                        } else {
@@ -2447,6 +2422,9 @@ check_control_code:
         * they must not cause conflicts with sequences.
         */
        if (control) {
+               /* in UTF-8 mode ignore handling C1 control characters */
+               if (IS_SET(MODE_UTF8) && ISCONTROLC1(u))
+                       return;
                tcontrolcode(u);
                /*
                 * control codes are not shown ever
@@ -2493,8 +2471,10 @@ check_control_code:
                gp = &term.line[term.c.y][term.c.x];
        }
 
-       if (IS_SET(MODE_INSERT) && term.c.x+width < term.col)
+       if (IS_SET(MODE_INSERT) && term.c.x+width < term.col) {
                memmove(gp+width, gp, (term.col - term.c.x - width) * sizeof(Glyph));
+               gp->mode &= ~ATTR_WIDE;
+       }
 
        if (term.c.x+width > term.col) {
                tnewline(1);