Merge branch 'jk/ansi-color'
[git/git.git] / color.c
diff --git a/color.c b/color.c
index a5b6581..81c2676 100644 (file)
--- a/color.c
+++ b/color.c
@@ -160,27 +160,34 @@ int color_parse(const char *value, char *dst)
        return color_parse_mem(value, strlen(value), dst);
 }
 
+void color_set(char *dst, const char *color_bytes)
+{
+       xsnprintf(dst, COLOR_MAXLEN, "%s", color_bytes);
+}
+
 /*
  * Write the ANSI color codes for "c" to "out"; the string should
  * already have the ANSI escape code in it. "out" should have enough
  * space in it to fit any color.
  */
-static char *color_output(char *out, const struct color *c, char type)
+static char *color_output(char *out, int len, const struct color *c, char type)
 {
        switch (c->type) {
        case COLOR_UNSPECIFIED:
        case COLOR_NORMAL:
                break;
        case COLOR_ANSI:
+               if (len < 2)
+                       die("BUG: color parsing ran out of space");
                *out++ = type;
                *out++ = '0' + c->value;
                break;
        case COLOR_256:
-               out += sprintf(out, "%c8;5;%d", type, c->value);
+               out += xsnprintf(out, len, "%c8;5;%d", type, c->value);
                break;
        case COLOR_RGB:
-               out += sprintf(out, "%c8;2;%d;%d;%d", type,
-                              c->red, c->green, c->blue);
+               out += xsnprintf(out, len, "%c8;2;%d;%d;%d", type,
+                                c->red, c->green, c->blue);
                break;
        }
        return out;
@@ -195,12 +202,13 @@ int color_parse_mem(const char *value, int value_len, char *dst)
 {
        const char *ptr = value;
        int len = value_len;
+       char *end = dst + COLOR_MAXLEN;
        unsigned int attr = 0;
        struct color fg = { COLOR_UNSPECIFIED };
        struct color bg = { COLOR_UNSPECIFIED };
 
        if (!strncasecmp(value, "reset", len)) {
-               strcpy(dst, GIT_COLOR_RESET);
+               xsnprintf(dst, end - dst, GIT_COLOR_RESET);
                return 0;
        }
 
@@ -239,12 +247,19 @@ int color_parse_mem(const char *value, int value_len, char *dst)
                        goto bad;
        }
 
+#undef OUT
+#define OUT(x) do { \
+       if (dst == end) \
+               die("BUG: color parsing ran out of space"); \
+       *dst++ = (x); \
+} while(0)
+
        if (attr || !color_empty(&fg) || !color_empty(&bg)) {
                int sep = 0;
                int i;
 
-               *dst++ = '\033';
-               *dst++ = '[';
+               OUT('\033');
+               OUT('[');
 
                for (i = 0; attr; i++) {
                        unsigned bit = (1 << i);
@@ -252,27 +267,28 @@ int color_parse_mem(const char *value, int value_len, char *dst)
                                continue;
                        attr &= ~bit;
                        if (sep++)
-                               *dst++ = ';';
-                       dst += sprintf(dst, "%d", i);
+                               OUT(';');
+                       dst += xsnprintf(dst, end - dst, "%d", i);
                }
                if (!color_empty(&fg)) {
                        if (sep++)
-                               *dst++ = ';';
+                               OUT(';');
                        /* foreground colors are all in the 3x range */
-                       dst = color_output(dst, &fg, '3');
+                       dst = color_output(dst, end - dst, &fg, '3');
                }
                if (!color_empty(&bg)) {
                        if (sep++)
-                               *dst++ = ';';
+                               OUT(';');
                        /* background colors are all in the 4x range */
-                       dst = color_output(dst, &bg, '4');
+                       dst = color_output(dst, end - dst, &bg, '4');
                }
-               *dst++ = 'm';
+               OUT('m');
        }
-       *dst = 0;
+       OUT(0);
        return 0;
 bad:
        return error(_("invalid color value: %.*s"), value_len, value);
+#undef OUT
 }
 
 int git_config_colorbool(const char *var, const char *value)