aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDenys Vlasenko <vda.linux@googlemail.com>2021-07-11 12:25:33 +0200
committerDenys Vlasenko <vda.linux@googlemail.com>2021-07-11 12:25:33 +0200
commit4ef8841b21e27e7c7f58d3c9901c833b4fa5a862 (patch)
treea71524a521f7a1f0510b8affd1ba827a543fcb2f
parent3d57a8490738d9febaa4496eba791e4fbfc91826 (diff)
downloadbusybox-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.c43
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
2312static char *awk_printf(node *n, int *len) 2312static 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);