Prevent digit-gobbling for all but %l and %e, which can't be fixed.

Discuss in the BUGS section of the manpage, problems involved with
the use of %C, %e, %l, %p, %U and %W.

PR:		13901
Reported by:	scott@chronis.pobox.com
This commit is contained in:
Sheldon Hearn 1999-12-08 15:49:10 +00:00
parent 7313447c12
commit 398592ffe1
2 changed files with 85 additions and 12 deletions

View file

@ -95,6 +95,45 @@ function appeared in
.Pp
.Sh BUGS
The
.Fa %C
format specifier only accepts centuries within the range 19 to 99.
.Pp
Both the
.Fa %e
and
.Fa %l
format specifiers may incorrectly scan one too many digits
if the intended values comprise only a single digit
and that digit is followed immediately by another digit.
Both specifiers accept zero-padded values,
even though they are both defined as taking unpadded values.
.Pp
The
.Fa %p
format specifier has no effect unless it is parsed
.Em after
hour-related specifiers.
Specifying
.Fa %l
without
.Fa %p
will produce undefined results.
Note that 12AM
.Pq ante meridiem
is taken as midnight
and 12PM
.Pq post meridiem
is taken as noon.
.Pp
The
.Fa %U
and
.Fa %W
format specifiers accept any value within the range 00 to 53
without validating against other values supplied (like month
or day of the year, for example).
.Pp
The
.Fa %Z
format specifier only accepts time zone abbreviations of the local time zone,
or the value "GMT".

View file

@ -129,9 +129,12 @@ label:
if (!isdigit((unsigned char)*buf))
return 0;
for (i = 0; *buf != 0 && isdigit((unsigned char)*buf); buf++) {
/* XXX This will break for 3-digit centuries. */
len = 2;
for (i = 0; len && *buf != 0 && isdigit((unsigned char)*buf); buf++) {
i *= 10;
i += *buf - '0';
len--;
}
if (i < 19)
return 0;
@ -206,9 +209,11 @@ label:
if (!isdigit((unsigned char)*buf))
return 0;
for (i = 0; *buf != 0 && isdigit((unsigned char)*buf); buf++) {
len = 3;
for (i = 0; len && *buf != 0 && isdigit((unsigned char)*buf); buf++) {
i *= 10;
i += *buf - '0';
len--;
}
if (i < 1 || i > 366)
return 0;
@ -224,9 +229,11 @@ label:
if (!isdigit((unsigned char)*buf))
return 0;
for (i = 0; *buf != 0 && isdigit((unsigned char)*buf); buf++) {
len = 2;
for (i = 0; len && *buf != 0 && isdigit((unsigned char)*buf); buf++) {
i *= 10;
i += *buf - '0';
len--;
}
if (c == 'M') {
@ -248,12 +255,22 @@ label:
case 'I':
case 'k':
case 'l':
/*
* Of these, %l is the only specifier explicitly
* documented as not being zero-padded. However,
* there is no harm in allowing zero-padding.
*
* XXX The %l specifier may gobble one too many
* digits if used incorrectly.
*/
if (!isdigit((unsigned char)*buf))
return 0;
for (i = 0; *buf != 0 && isdigit((unsigned char)*buf); buf++) {
len = 2;
for (i = 0; len && *buf != 0 && isdigit((unsigned char)*buf); buf++) {
i *= 10;
i += *buf - '0';
len--;
}
if (c == 'H' || c == 'k') {
if (i > 23)
@ -269,6 +286,10 @@ label:
break;
case 'p':
/*
* XXX This is bogus if parsed before hour-related
* specifiers.
*/
len = strlen(Locale->am);
if (strncasecmp(buf, Locale->am, len) == 0) {
if (tm->tm_hour > 12)
@ -326,9 +347,11 @@ label:
if (!isdigit((unsigned char)*buf))
return 0;
for (i = 0; *buf != 0 && isdigit((unsigned char)*buf); buf++) {
len = 2;
for (i = 0; len && *buf != 0 && isdigit((unsigned char)*buf); buf++) {
i *= 10;
i += *buf - '0';
len--;
}
if (i > 53)
return 0;
@ -342,10 +365,7 @@ label:
if (!isdigit((unsigned char)*buf))
return 0;
for (i = 0; *buf != 0 && isdigit((unsigned char)*buf); buf++) {
i *= 10;
i += *buf - '0';
}
i = *buf - '0';
if (i > 6)
return 0;
@ -358,12 +378,22 @@ label:
case 'd':
case 'e':
/*
* The %e specifier is explicitly documented as not
* being zero-padded but there is no harm in allowing
* such padding.
*
* XXX The %e specifier may gobble one too many
* digits if used incorrectly.
*/
if (!isdigit((unsigned char)*buf))
return 0;
for (i = 0; *buf != 0 && isdigit((unsigned char)*buf); buf++) {
len = 2;
for (i = 0; len && *buf != 0 && isdigit((unsigned char)*buf); buf++) {
i *= 10;
i += *buf - '0';
len--;
}
if (i > 31)
return 0;
@ -414,9 +444,11 @@ label:
if (!isdigit((unsigned char)*buf))
return 0;
for (i = 0; *buf != 0 && isdigit((unsigned char)*buf); buf++) {
len = 2;
for (i = 0; len && *buf != 0 && isdigit((unsigned char)*buf); buf++) {
i *= 10;
i += *buf - '0';
len--;
}
if (i < 1 || i > 12)
return 0;
@ -436,9 +468,11 @@ label:
if (!isdigit((unsigned char)*buf))
return 0;
for (i = 0; *buf != 0 && isdigit((unsigned char)*buf); buf++) {
len = (c == 'Y') ? 4 : 2;
for (i = 0; len && *buf != 0 && isdigit((unsigned char)*buf); buf++) {
i *= 10;
i += *buf - '0';
len--;
}
if (c == 'Y')
i -= 1900;