1
0
Fork 0
mirror of git://git.code.sf.net/p/zsh/code synced 2025-10-16 12:21:18 +02:00

19168: Various problems with size of buffers and pointer usage in ztrftime

This commit is contained in:
Peter Stephenson 2003-10-06 22:46:24 +00:00
parent bbc409eefe
commit ed6a7ba60e
4 changed files with 79 additions and 19 deletions

View file

@ -1,5 +1,9 @@
2003-10-06 Peter Stephenson <pws@pwstephenson.fsnet.co.uk>
* 19168: Src/prompt.c, Src/utils.c, Src/Modules/datetime.c:
various problems with size of buffers and pointer usage
in ztrftime().
* 19167: Src/glob.c, Test/E01options.ztst: NULL at start
of BRACE_CCL range didn't work.

View file

@ -35,10 +35,9 @@ static int
bin_strftime(char *nam, char **argv, Options ops, int func)
{
int bufsize, x;
char *endptr = NULL, *buffer = NULL;
char *endptr = NULL, *buffer;
time_t secs;
struct tm *t;
int size;
secs = (time_t)strtoul(argv[1], &endptr, 10);
if (secs == ULONG_MAX) {
@ -51,15 +50,17 @@ bin_strftime(char *nam, char **argv, Options ops, int func)
t = localtime(&secs);
bufsize = strlen(argv[0]) * 2;
buffer = zalloc(bufsize);
for (x=1;x<4;x++) {
buffer = zrealloc(buffer, bufsize * x);
size = ztrftime(buffer, bufsize * x, argv[0], t);
if (size) x = 4;
for (x=0; x < 4; x++) {
if (ztrftime(buffer, bufsize, argv[0], t))
break;
buffer = zrealloc(buffer, bufsize *= 2);
}
printf("%s\n", buffer);
zfree(buffer, bufsize);
return 0;
}

View file

@ -500,18 +500,23 @@ putpromptchar(int doprint, int endchar)
tmfmt = "%m/%d/%y";
break;
case 'D':
if (fm[1] == '{') /*}*/ {
if (fm[1] == '{' /*}*/) {
for (ss = fm + 2; *ss && *ss != /*{*/ '}'; ss++)
if(*ss == '\\' && ss[1])
ss++;
dd = tmfmt = tmbuf = zalloc(ss - fm);
for (ss = fm + 2; *ss && *ss != /*{*/ '}'; ss++) {
for (ss = fm + 2; *ss && *ss != /*{*/ '}';
ss++) {
if(*ss == '\\' && ss[1])
ss++;
*dd++ = *ss;
}
*dd = 0;
fm = ss - !*ss;
if (!*tmfmt) {
free(tmbuf);
continue;
}
} else
tmfmt = "%y-%m-%d";
break;
@ -523,7 +528,7 @@ putpromptchar(int doprint, int endchar)
tm = localtime(&timet);
for(t0=80; ; t0*=2) {
addbufspc(t0);
if(ztrftime(bp, t0, tmfmt, tm) != t0)
if (ztrftime(bp, t0, tmfmt, tm))
break;
}
bp += strlen(bp);

View file

@ -1685,20 +1685,42 @@ spckword(char **s, int hist, int cmd, int ask)
}
}
/*
* Helper for ztrftime. Called with a pointer to the length left
* in the buffer, and a new string length to decrement from that.
* Returns 0 if the new length fits, 1 otherwise. We assume a terminating
* NUL and return 1 if that doesn't fit.
*/
/**/
static int
ztrftimebuf(int *bufsizeptr, int decr)
{
if (*bufsizeptr <= decr)
return 1;
*bufsizeptr -= decr;
return 0;
}
/*
* Like the system function, this returns the number of characters
* copied, not including the terminating NUL. This may be zero
* if the string didn't fit.
*/
/**/
mod_export int
ztrftime(char *buf, int bufsize, char *fmt, struct tm *tm)
{
int hr12;
int hr12, decr;
#ifndef HAVE_STRFTIME
static char *astr[] =
{"Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"};
static char *estr[] =
{"Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul",
"Aug", "Sep", "Oct", "Nov", "Dec"};
#else
char *origbuf = buf;
#endif
char *origbuf = buf;
char tmp[3];
@ -1707,6 +1729,14 @@ ztrftime(char *buf, int bufsize, char *fmt, struct tm *tm)
while (*fmt)
if (*fmt == '%') {
fmt++;
/*
* Assume this format will take up at least two
* characters. Not always true, but if that matters
* we are so close to the edge it's not a big deal.
* Fix up some longer cases specially when we get to them.
*/
if (ztrftimebuf(&bufsize, 2))
return 0;
switch (*fmt++) {
case 'd':
*buf++ = '0' + tm->tm_mday / 10;
@ -1734,9 +1764,10 @@ ztrftime(char *buf, int bufsize, char *fmt, struct tm *tm)
if (hr12 == 0)
hr12 = 12;
if (hr12 > 9)
*buf++ = '1';
*buf++ = '1';
else if (fmt[-1] == 'l')
*buf++ = ' ';
*buf++ = ' ';
*buf++ = '0' + (hr12 % 10);
break;
case 'm':
@ -1755,11 +1786,20 @@ ztrftime(char *buf, int bufsize, char *fmt, struct tm *tm)
*buf++ = '0' + (tm->tm_year / 10) % 10;
*buf++ = '0' + tm->tm_year % 10;
break;
case '\0':
/* Guard against premature end of string */
*buf++ = '%';
fmt--;
break;
#ifndef HAVE_STRFTIME
case 'a':
if (ztrftimebuf(&bufsize, strlen(astr[tm->tm_wday]) - 2))
return 0;
strucpy(&buf, astr[tm->tm_wday]);
break;
case 'b':
if (ztrftimebuf(&bufsize, strlen(estr[tm->tm_mon]) - 2))
return 0;
strucpy(&buf, estr[tm->tm_mon]);
break;
case 'p':
@ -1772,17 +1812,27 @@ ztrftime(char *buf, int bufsize, char *fmt, struct tm *tm)
*buf++ = fmt[-1];
#else
default:
/*
* Remember we've already allowed for two characters
* in the accounting in bufsize (but nowhere else).
*/
*buf = '\0';
tmp[1] = fmt[-1];
strftime(buf, bufsize - strlen(origbuf), tmp, tm);
buf += strlen(buf);
if (!strftime(buf, bufsize + 2, tmp, tm))
return 0;
decr = strlen(buf);
buf += decr;
bufsize -= decr - 2;
#endif
break;
}
} else
} else {
if (ztrftimebuf(&bufsize, 1))
return 0;
*buf++ = *fmt++;
}
*buf = '\0';
return 0;
return buf - origbuf;
}
/**/