From f8164fb647a8e7947cfde137ddd9517b2fab51c4 Mon Sep 17 00:00:00 2001 From: Peter Stephenson Date: Tue, 18 Aug 2015 16:20:48 +0100 Subject: 36227: attempt to fix metafication problem with ztrftime. fmt is treated as metafied on entry; use returned length to ensure we metafy or output the correct length if there are embedded nulls. --- Src/Builtins/sched.c | 3 ++- Src/Modules/datetime.c | 11 +++++++---- Src/Modules/stat.c | 7 +++++-- Src/builtin.c | 7 +++++-- Src/prompt.c | 8 +++++--- Src/utils.c | 30 +++++++++++++++++++++++++++--- Src/watch.c | 5 ++++- 7 files changed, 55 insertions(+), 16 deletions(-) (limited to 'Src') diff --git a/Src/Builtins/sched.c b/Src/Builtins/sched.c index bcf7661f4..5d5dac6b7 100644 --- a/Src/Builtins/sched.c +++ b/Src/Builtins/sched.c @@ -220,7 +220,8 @@ bin_sched(char *nam, char **argv, UNUSED(Options ops), UNUSED(int func)) endstr = "-- "; else endstr = ""; - printf("%3d %s %s%s%s\n", sn, tbuf, flagstr, endstr, sch->cmd); + printf("%3d %s %s%s%s\n", sn, tbuf, flagstr, endstr, + unmeta(sch->cmd)); } return 0; } else if (!argptr[1]) { diff --git a/Src/Modules/datetime.c b/Src/Modules/datetime.c index d9416679f..86c61cf1c 100644 --- a/Src/Modules/datetime.c +++ b/Src/Modules/datetime.c @@ -98,7 +98,7 @@ reverse_strftime(char *nam, char **argv, char *scalar, int quiet) static int output_strftime(char *nam, char **argv, Options ops, UNUSED(int func)) { - int bufsize, x; + int bufsize, x, len; char *endptr = NULL, *scalar = NULL, *buffer; time_t secs; struct tm *t; @@ -131,16 +131,19 @@ output_strftime(char *nam, char **argv, Options ops, UNUSED(int func)) bufsize = strlen(argv[0]) * 8; buffer = zalloc(bufsize); + len = 0; for (x=0; x < 4; x++) { - if (ztrftime(buffer, bufsize, argv[0], t, 0L) >= 0) + if ((len = ztrftime(buffer, bufsize, argv[0], t, 0L)) >= 0) break; buffer = zrealloc(buffer, bufsize *= 2); } + DPUTS(len < 0, "bad output from ztrftime"); if (scalar) { - setsparam(scalar, metafy(buffer, -1, META_DUP)); + setsparam(scalar, metafy(buffer, len, META_DUP)); } else { - printf("%s\n", buffer); + fwrite(buffer, 1, len, stdout); + putchar('\n'); } zfree(buffer, bufsize); diff --git a/Src/Modules/stat.c b/Src/Modules/stat.c index 6fc53894c..396177149 100644 --- a/Src/Modules/stat.c +++ b/Src/Modules/stat.c @@ -197,8 +197,11 @@ stattimeprint(time_t tim, char *outbuf, int flags) } if (flags & STF_STRING) { char *oend = outbuf + strlen(outbuf); - ztrftime(oend, 40, timefmt, (flags & STF_GMT) ? gmtime(&tim) : - localtime(&tim), 0L); + /* Where the heck does "40" come from? */ + int len = ztrftime(oend, 40, timefmt, (flags & STF_GMT) ? gmtime(&tim) : + localtime(&tim), 0L); + if (len > 0) + metafy(oend, len, META_NOALLOC); if (flags & STF_RAW) strcat(oend, ")"); } diff --git a/Src/builtin.c b/Src/builtin.c index 4a97a3163..572a0dd68 100644 --- a/Src/builtin.c +++ b/Src/builtin.c @@ -1783,9 +1783,12 @@ fclist(FILE *f, Options ops, zlong first, zlong last, command, if required */ if (tdfmt != NULL) { struct tm *ltm; + int len; ltm = localtime(&ent->stim); - if (ztrftime(timebuf, 256, tdfmt, ltm, 0L)) - fprintf(f, "%s ", timebuf); + if ((len = ztrftime(timebuf, 256, tdfmt, ltm, 0L)) >= 0) { + fwrite(timebuf, 1, len, f); + fprintf(f, " "); + } } /* display the time taken by the command, if required */ if (OPT_ISSET(ops,'D')) { diff --git a/Src/prompt.c b/Src/prompt.c index 9e8589d5b..be067ee7e 100644 --- a/Src/prompt.c +++ b/Src/prompt.c @@ -271,7 +271,7 @@ static int putpromptchar(int doprint, int endchar, unsigned int *txtchangep) { char *ss, *hostnam; - int t0, arg, test, sep, j, numjobs; + int t0, arg, test, sep, j, numjobs, len; struct tm *tm; struct timezone dummy_tz; struct timeval tv; @@ -673,12 +673,14 @@ putpromptchar(int doprint, int endchar, unsigned int *txtchangep) */ for(j = 0, t0 = strlen(tmfmt)*8; j < 3; j++, t0*=2) { addbufspc(t0); - if (ztrftime(bv->bp, t0, tmfmt, tm, tv.tv_usec) >= 0) + if ((len = ztrftime(bv->bp, t0, tmfmt, tm, tv.tv_usec)) + >= 0) break; } /* There is enough room for this because addbufspc(t0) * allocates room for t0 * 2 bytes. */ - metafy(bv->bp, -1, META_NOALLOC); + if (len >= 0) + metafy(bv->bp, len, META_NOALLOC); bv->bp += strlen(bv->bp); zsfree(tmbuf); break; diff --git a/Src/utils.c b/Src/utils.c index 236661a9f..20e01a207 100644 --- a/Src/utils.c +++ b/Src/utils.c @@ -2878,6 +2878,10 @@ ztrftimebuf(int *bufsizeptr, int decr) * not enough memory --- and return -1. Not guaranteed to be portable, * since the strftime() interface doesn't make any guarantees about * the state of the buffer if it returns zero. + * + * fmt is metafied, but we need to unmetafy it on the fly to + * pass into strftime / combine with the output from strftime. + * The return value in buf is not metafied. */ /**/ @@ -2898,8 +2902,14 @@ ztrftime(char *buf, int bufsize, char *fmt, struct tm *tm, long usec) char *origbuf = buf; - while (*fmt) - if (*fmt == '%') { + while (*fmt) { + if (*fmt == Meta) { + int chr = fmt[1] ^ 32; + if (ztrftimebuf(&bufsize, 1)) + return -1; + *buf++ = chr; + fmt += 2; + } else if (*fmt == '%') { int strip; int digs = 3; @@ -3083,8 +3093,21 @@ strftimehandling: */ { int size = fmt - fmtstart; - char *tmp = zhalloc(size + 1); + char *tmp, *last; + tmp = zhalloc(size + 1); strncpy(tmp, fmtstart, size); + last = fmt-1; + if (*last == Meta) { + /* + * This is for consistency in counting: + * a metafiable character isn't actually + * a valid strftime descriptor. + * + * Previous characters were explicitly checked, + * so can't be metafied. + */ + *last = *++fmt ^ 32; + } tmp[size] = '\0'; *buf = '\1'; if (!strftime(buf, bufsize + 2, tmp, tm)) @@ -3107,6 +3130,7 @@ strftimehandling: return -1; *buf++ = *fmt++; } + } *buf = '\0'; return buf - origbuf; } diff --git a/Src/watch.c b/Src/watch.c index e1bdaa4a0..c804913ad 100644 --- a/Src/watch.c +++ b/Src/watch.c @@ -237,6 +237,7 @@ watchlog2(int inout, WATCH_STRUCT_UTMP *u, char *fmt, int prnt, int fini) time_t timet; struct tm *tm; char *fm2; + int len; # ifdef WATCH_UTMP_UT_HOST char *p; int i; @@ -330,7 +331,9 @@ watchlog2(int inout, WATCH_STRUCT_UTMP *u, char *fmt, int prnt, int fini) } timet = getlogtime(u, inout); tm = localtime(&timet); - ztrftime(buf, 40, fm2, tm, 0L); + len = ztrftime(buf, 40, fm2, tm, 0L); + if (len > 0) + metafy(buf, len, META_NOALLOC); printf("%s", (*buf == ' ') ? buf + 1 : buf); break; case '%': -- cgit 1.4.1