From 3443d4de2a8d85f4621b2e7d83521f4a0bc67537 Mon Sep 17 00:00:00 2001 From: NeilBrown Date: Sun, 20 Aug 2023 08:32:30 +1000 Subject: [PATCH] display-ncurses: Improve attr parsing Move the attr parsing code from lib-renderline into core-misc.c and use it in display-ncurses to avoid using a fixed-size char array that we never test for overflow. Signed-off-by: NeilBrown --- core-misc.c | 94 +++++++++++++++++++++++++++++++++++++++++++ display-ncurses.c | 46 ++++++++++----------- lib-renderline.c | 100 ---------------------------------------------- misc.h | 18 +++++++++ 4 files changed, 133 insertions(+), 125 deletions(-) diff --git a/core-misc.c b/core-misc.c index 28a2ebe5..6475aadf 100644 --- a/core-misc.c +++ b/core-misc.c @@ -549,3 +549,97 @@ bool debugger_is_present(void) } return _debugger_present; } + +/* attr parsing */ +const char *afind_val(const char **cp safe, const char *end) +{ + const char *c = *cp; + const char *ret; + + if (!c) + return NULL; + if (!end) + end = c + strlen(c); + while (c < end && *c != ':' && *c != ',') + c++; + if (c == end) { + *cp = NULL; + return NULL; + } + if (*c == ',') { + while (*c == ',' && c < end) + c++; + if (c == end) { + *cp = NULL; + return NULL; + } + *cp = c; + return NULL; + } + c += 1; + ret = c; + while (c < end && *c != ',') + c++; + while (c < end && *c == ',') + c++; + if (c == end) + c = NULL; + *cp = c; + return ret; +} + +char *aupdate(char **cp safe, const char *v) +{ + /* duplicate value at v and store in *cp, freeing what is there + * first + */ + const char *end = v; + + while (end && *end != ',' && *end >= ' ') + end += 1; + + free(*cp); + if (v) + *cp = strndup(v, end-v); + else + *cp = NULL; + return *cp; +} + +bool amatch(const char *a safe, const char *m safe) +{ + while (*a && *a == *m) { + a += 1; + m += 1; + } + if (*m) + /* Didn't match all of m */ + return False; + if (*a != ':' && *a != ',' && *a >= ' ') + /* Didn't match all of a */ + return False; + return True; +} + +bool aprefix(const char *a safe, const char *m safe) +{ + while (*a && *a == *m) { + a += 1; + m += 1; + } + if (*m) + /* Didn't match all of m */ + return False; + return True; +} + +long anum(const char *v safe) +{ + char *end = NULL; + long ret = strtol(v, &end, 10); + if (end == v || !end || + (*end != ',' && *end >= ' ')) + /* Not a valid number - use zero */ + return 0; + return ret; +} diff --git a/display-ncurses.c b/display-ncurses.c index 8e7436f4..0b1eda07 100644 --- a/display-ncurses.c +++ b/display-ncurses.c @@ -804,8 +804,8 @@ static int cvt_attrs(struct pane *p safe, struct pane *home safe, { struct display_data *dd = &home->data; int attr = 0; - char tmp[40]; - const char *a; + const char *a, *v; + char *col = NULL; PANEL *pan = NULL; int fg = COLOR_BLACK; int bg = COLOR_WHITE+8; @@ -825,39 +825,35 @@ static int cvt_attrs(struct pane *p safe, struct pane *home safe, if (dbg >= 0) bg = dbg; } - a = attrs; - while (a && *a) { - const char *c; - if (*a == ',') { - a++; - continue; - } - c = strchr(a, ','); - if (!c) - c = a+strlen(a); - strncpy(tmp, a, c-a); - tmp[c-a] = 0; - if (strcmp(tmp, "inverse")==0) attr |= A_STANDOUT; - else if (strcmp(tmp, "noinverse")==0) attr &= ~A_STANDOUT; - else if (strcmp(tmp, "bold")==0) attr |= A_BOLD; - else if (strcmp(tmp, "nobold")==0) attr &= ~A_BOLD; - else if (strcmp(tmp, "underline")==0) attr |= A_UNDERLINE; - else if (strcmp(tmp, "nounderline")==0) attr &= ~A_UNDERLINE; - else if (strstarts(tmp, "fg:")) { + + foreach_attr(a, v, attrs, NULL) { + if (amatch(a, "inverse")) + attr |= A_STANDOUT; + else if (amatch(a, "noinverse")) + attr &= ~A_STANDOUT; + else if (amatch(a, "bold")) + attr |= A_BOLD; + else if (amatch(a, "nobold")) + attr &= ~A_BOLD; + else if (amatch(a, "underline")) + attr |= A_UNDERLINE; + else if (amatch(a, "nounderline")) + attr &= ~A_UNDERLINE; + else if (amatch(a, "fg") && v) { struct call_return cr = call_ret(all, "colour:map", home, - 0, NULL, tmp+3); + 0, NULL, aupdate(&col, v)); int rgb[3] = {cr.i, cr.i2, cr.x}; fg = find_col(dd, rgb); - } else if (strstarts(tmp, "bg:")) { + } else if (amatch(a, "bg") && v) { struct call_return cr = call_ret(all, "colour:map", home, - 0, NULL, tmp+3); + 0, NULL, aupdate(&col, v)); int rgb[3] = {cr.i, cr.i2, cr.x}; bg = find_col(dd, rgb); } - a = c; } + free(col); if (fg != COLOR_BLACK || bg != COLOR_WHITE+8) *pairp = to_pair(dd, fg, bg); return attr; diff --git a/lib-renderline.c b/lib-renderline.c index 436f7491..1708c1b0 100644 --- a/lib-renderline.c +++ b/lib-renderline.c @@ -141,106 +141,6 @@ struct rline_data { }; #include "core-pane.h" -/* Sequentially set _attr to the an attr name, and _val to - * either the val (following ":") or NULL. - * _attr is valid up to : or , or < space and _val is valid up to , or = ' ') - /* Didn't match all of a */ - return False; - return True; -} - -static bool aprefix(const char *a safe, const char *m safe) -{ - while (*a && *a == *m) { - a += 1; - m += 1; - } - if (*m) - /* Didn't match all of m */ - return False; - return True; -} - -static long anum(const char *v safe) -{ - char *end = NULL; - long ret = strtol(v, &end, 10); - if (end == v || !end || - (*end != ',' && *end >= ' ')) - /* Not a valid number - use zero */ - return 0; - return ret; -} - -static void aupdate(char **cp safe, const char *v) -{ - /* duplicate value at v and store in *cp, freeing what is there - * first - */ - const char *end = v; - - while (end && *end != ',' && *end >= ' ') - end += 1; - - free(*cp); - if (v) - *cp = strndup(v, end-v); - else - *cp = NULL; -} - static void aappend(struct buf *b safe, char const *a safe) { const char *end = a; diff --git a/misc.h b/misc.h index 848f30d5..83bf6550 100644 --- a/misc.h +++ b/misc.h @@ -150,4 +150,22 @@ void do_unalloc(struct mempool *pool safe, const void *obj, int size); #define unalloc_str_safe(var, pool) \ unalloc_buf_safe(var, strlen(var)+1, pool) +/* attrs parsing */ + +/* Sequentially set _attr to the an attr name, and _val to + * either the val (following ":") or NULL. + * _attr is valid up to : or , or < space and _val is valid up to , or