From 49340d93edc778b193cb40b59cf94dbe38650013 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Tue, 9 Jul 2024 03:04:26 +0200 Subject: awk: do not infinitely recurse getvar_s() if CONVFMT is set to a numeric value function old new delta fmt_num 247 257 +10 evaluate 3385 3379 -6 getvar_s 111 102 -9 ------------------------------------------------------------------------------ (add/remove: 0/0 grow/shrink: 1/2 up/down: 10/-15) Total: -5 bytes Signed-off-by: Denys Vlasenko --- editors/awk.c | 20 ++++++++++++++------ 1 file changed, 14 insertions(+), 6 deletions(-) diff --git a/editors/awk.c b/editors/awk.c index ff6d6350b..8bc214b69 100644 --- a/editors/awk.c +++ b/editors/awk.c @@ -532,6 +532,7 @@ static const char vValues[] ALIGN1 = "%.6g\0" "%.6g\0" " \0" " \0" "\n\0" "\n\0" "\0" "\0" "\034\0" "\0" "\377"; +#define str_percent_dot_6g vValues /* hash size may grow to these values */ #define FIRST_PRIME 61 @@ -922,7 +923,7 @@ static double my_strtod_or_hexoct(char **pp) /* -------- working with variables (set/get/copy/etc) -------- */ -static void fmt_num(const char *format, double n) +static const char *fmt_num(const char *format, double n) { if (n == (long long)n) { snprintf(g_buf, MAXVARFMT, "%lld", (long long)n); @@ -939,6 +940,7 @@ static void fmt_num(const char *format, double n) syntax_error(EMSG_INV_FMT); } } + return g_buf; } static xhash *iamarray(var *a) @@ -1025,8 +1027,15 @@ static const char *getvar_s(var *v) { /* if v is numeric and has no cached string, convert it to string */ if ((v->type & (VF_NUMBER | VF_CACHED)) == VF_NUMBER) { - fmt_num(getvar_s(intvar[CONVFMT]), v->number); - v->string = xstrdup(g_buf); + const char *convfmt = str_percent_dot_6g; /* "%.6g" */ + /* Get CONVFMT, unless we already recursed on it: + * someone might try to cause stack overflow by setting + * CONVFMT=9 (a numeric, not string, value) + */ + if (v != intvar[CONVFMT]) + convfmt = getvar_s(intvar[CONVFMT]); + /* Convert the value */ + v->string = xstrdup(fmt_num(convfmt, v->number)); v->type |= VF_CACHED; } return (v->string == NULL) ? "" : v->string; @@ -3097,9 +3106,8 @@ static var *evaluate(node *op, var *res) for (;;) { var *v = evaluate(nextarg(&op1), TMPVAR0); if (v->type & VF_NUMBER) { - fmt_num(getvar_s(intvar[OFMT]), - getvar_i(v)); - fputs(g_buf, F); + fputs(fmt_num(getvar_s(intvar[OFMT]), getvar_i(v)), + F); } else { fputs(getvar_s(v), F); } -- cgit v1.2.3-55-g6feb