diff options
author | Denys Vlasenko <vda.linux@googlemail.com> | 2021-07-11 12:25:33 +0200 |
---|---|---|
committer | Denys Vlasenko <vda.linux@googlemail.com> | 2021-07-11 12:25:33 +0200 |
commit | 4ef8841b21e27e7c7f58d3c9901c833b4fa5a862 (patch) | |
tree | a71524a521f7a1f0510b8affd1ba827a543fcb2f | |
parent | 3d57a8490738d9febaa4496eba791e4fbfc91826 (diff) | |
download | busybox-w32-4ef8841b21e27e7c7f58d3c9901c833b4fa5a862.tar.gz busybox-w32-4ef8841b21e27e7c7f58d3c9901c833b4fa5a862.tar.bz2 busybox-w32-4ef8841b21e27e7c7f58d3c9901c833b4fa5a862.zip |
awk: unbreak "printf('%c') can output NUL" testcase
function old new delta
awk_printf 546 593 +47
Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
-rw-r--r-- | editors/awk.c | 43 |
1 files changed, 26 insertions, 17 deletions
diff --git a/editors/awk.c b/editors/awk.c index 0aa7c0804..e765d3fcf 100644 --- a/editors/awk.c +++ b/editors/awk.c | |||
@@ -2309,11 +2309,11 @@ static int awk_getline(rstream *rsm, var *v) | |||
2309 | #if !ENABLE_FEATURE_AWK_GNU_EXTENSIONS | 2309 | #if !ENABLE_FEATURE_AWK_GNU_EXTENSIONS |
2310 | # define awk_printf(a, b) awk_printf(a) | 2310 | # define awk_printf(a, b) awk_printf(a) |
2311 | #endif | 2311 | #endif |
2312 | static char *awk_printf(node *n, int *len) | 2312 | static char *awk_printf(node *n, size_t *len) |
2313 | { | 2313 | { |
2314 | char *b; | 2314 | char *b; |
2315 | char *fmt, *f; | 2315 | char *fmt, *f; |
2316 | int i; | 2316 | size_t i; |
2317 | 2317 | ||
2318 | //tmpvar = nvalloc(1); | 2318 | //tmpvar = nvalloc(1); |
2319 | #define TMPVAR (&G.awk_printf__tmpvar) | 2319 | #define TMPVAR (&G.awk_printf__tmpvar) |
@@ -2333,6 +2333,7 @@ static char *awk_printf(node *n, int *len) | |||
2333 | char c; | 2333 | char c; |
2334 | char sv; | 2334 | char sv; |
2335 | var *arg; | 2335 | var *arg; |
2336 | size_t slen; | ||
2336 | 2337 | ||
2337 | s = f; | 2338 | s = f; |
2338 | while (*f && (*f != '%' || *++f == '%')) | 2339 | while (*f && (*f != '%' || *++f == '%')) |
@@ -2347,6 +2348,7 @@ static char *awk_printf(node *n, int *len) | |||
2347 | /* Tail of fmt with no percent chars, | 2348 | /* Tail of fmt with no percent chars, |
2348 | * or "....%" (percent seen, but no format specifier char found) | 2349 | * or "....%" (percent seen, but no format specifier char found) |
2349 | */ | 2350 | */ |
2351 | slen = strlen(s); | ||
2350 | goto tail; | 2352 | goto tail; |
2351 | } | 2353 | } |
2352 | sv = *++f; | 2354 | sv = *++f; |
@@ -2357,31 +2359,38 @@ static char *awk_printf(node *n, int *len) | |||
2357 | * printf "%99999s", "BOOM" | 2359 | * printf "%99999s", "BOOM" |
2358 | */ | 2360 | */ |
2359 | if (c == 'c') { | 2361 | if (c == 'c') { |
2360 | s = xasprintf(s, is_numeric(arg) ? | 2362 | c = is_numeric(arg) ? getvar_i(arg) : *getvar_s(arg); |
2361 | (char)getvar_i(arg) : *getvar_s(arg)); | 2363 | s = xasprintf(s, c); |
2362 | } else if (c == 's') { | 2364 | /* + 1 if c == NUL: handle printf "%c" 0 case |
2363 | s = xasprintf(s, getvar_s(arg)); | 2365 | * (and printf "%22c" 0 etc, but still fails for e.g. printf "%-22c" 0) */ |
2366 | slen = strlen(s) + (c == '\0'); | ||
2364 | } else { | 2367 | } else { |
2365 | double d = getvar_i(arg); | 2368 | if (c == 's') { |
2366 | if (strchr("diouxX", c)) { | 2369 | s = xasprintf(s, getvar_s(arg)); |
2367 | //TODO: make it wider here (%x -> %llx etc)? | ||
2368 | s = xasprintf(s, (int)d); | ||
2369 | } else if (strchr("eEfFgGaA", c)) { | ||
2370 | s = xasprintf(s, d); | ||
2371 | } else { | 2370 | } else { |
2372 | syntax_error(EMSG_INV_FMT); | 2371 | double d = getvar_i(arg); |
2372 | if (strchr("diouxX", c)) { | ||
2373 | //TODO: make it wider here (%x -> %llx etc)? | ||
2374 | s = xasprintf(s, (int)d); | ||
2375 | } else if (strchr("eEfFgGaA", c)) { | ||
2376 | s = xasprintf(s, d); | ||
2377 | } else { | ||
2378 | syntax_error(EMSG_INV_FMT); | ||
2379 | } | ||
2373 | } | 2380 | } |
2381 | slen = strlen(s); | ||
2374 | } | 2382 | } |
2375 | *f = sv; | 2383 | *f = sv; |
2376 | 2384 | ||
2377 | if (i == 0) { | 2385 | if (i == 0) { |
2378 | b = s; | 2386 | b = s; |
2379 | i = strlen(b); | 2387 | i = slen; |
2380 | continue; | 2388 | continue; |
2381 | } | 2389 | } |
2382 | tail: | 2390 | tail: |
2383 | b = xrealloc(b, i + strlen(s) + 1); | 2391 | b = xrealloc(b, i + slen + 1); |
2384 | i = stpcpy(b + i, s) - b; | 2392 | strcpy(b + i, s); |
2393 | i += slen; | ||
2385 | if (!c) /* tail? */ | 2394 | if (!c) /* tail? */ |
2386 | break; | 2395 | break; |
2387 | free(s); | 2396 | free(s); |
@@ -2926,7 +2935,6 @@ static var *evaluate(node *op, var *res) | |||
2926 | debug_printf_eval("PRINTF\n"); | 2935 | debug_printf_eval("PRINTF\n"); |
2927 | { | 2936 | { |
2928 | FILE *F = stdout; | 2937 | FILE *F = stdout; |
2929 | IF_FEATURE_AWK_GNU_EXTENSIONS(int len;) | ||
2930 | 2938 | ||
2931 | if (op->r.n) { | 2939 | if (op->r.n) { |
2932 | rstream *rsm = newfile(R.s); | 2940 | rstream *rsm = newfile(R.s); |
@@ -2966,6 +2974,7 @@ static var *evaluate(node *op, var *res) | |||
2966 | } | 2974 | } |
2967 | fputs(getvar_s(intvar[ORS]), F); | 2975 | fputs(getvar_s(intvar[ORS]), F); |
2968 | } else { /* PRINTF */ | 2976 | } else { /* PRINTF */ |
2977 | IF_FEATURE_AWK_GNU_EXTENSIONS(size_t len;) | ||
2969 | char *s = awk_printf(op1, &len); | 2978 | char *s = awk_printf(op1, &len); |
2970 | #if ENABLE_FEATURE_AWK_GNU_EXTENSIONS | 2979 | #if ENABLE_FEATURE_AWK_GNU_EXTENSIONS |
2971 | fwrite(s, len, 1, F); | 2980 | fwrite(s, len, 1, F); |