Submitter: Stoughton (US)
Submission Date: 2006-03-28
Source: The Austin Group
Reference Document:
AI-053.txt, DR 217
Version: 1.3
Date:2007-09-06
Subject: asctime()
Summary: asctime() tm_year gt
9999
This is a potential defect forwarded from the Austin Group.
If asctime()
is called with a tm
structure whose tm_year
field results in a
year > 9999 (which is possible with 64-bit
time_t
), the current specification of
asctime()
would result in
asctime()
to overrunning a 26-character
buffer; the specification says the
sprintf()
format for printing the year is
"%d", and (eg) a 5-digit number would print 5 characters,
overrunning the buffer.
Similarly, since the user can create the input
struct tm
, it is possible for the user to
set the fields of the struct tm
to values
that are outside the normal bounds. In such a case, the
sprintf()
format given in the
asctime()
specification can result in a
buffer overrun. For example, if tm_hour
is
100
, the sprintf()
format .2d
writes the string "100", which
could result in a buffer overrun. The specification should be
updated to state the algorithm can be used as long as the
values of the tm
struct are restricted to
the normal bounds.
Suggested Technical Corrigendum
Change 7.23.3.1 para 2 from:
The asctime function converts the broken-down time in the
structure pointed to by timeptr
into a
string in the form:
To:
The(NB, see 7.23.1 para 4 for the specifications of the "normal ranges").asctime()
function shall convert the broken-down time in the structure pointed to bytimeptr
into a string in the form, provided the broken-down time in the fields of the structure pointed to bytimeptr
contain values that are within the normal ranges as defined in<time.h>
, and the calculated year does not exceed four digits:
Also, add after the example code, and before the "Returns" section, the following new paragraph:
Otherwise, if any of the fields of thetm
structure pointed to bytimeptr
contain values that are outside the normal ranges, the behavior ofasctime()
is undefined. If the calculated year exceeds four digits, the behavior is undefined.
Committee Discussion (for history only)
The proposed resolution invalidates code that strictly conforms to the C99 standard. Here is a contrived example (though there are some examples that are not contrived):
#include <time.h> #include <stdio.h> struct tm tm; int main (void) { tm.tm_wday = 0; tm.tm_mon = 0; tm.tm_mday = -99; tm.tm_hour = 99; tm.tm_min = 99; tm.tm_sec = 99; tm.tm_year = -999 - 1900; printf ("%s\n", asctime (&tm)); return 0; }
This code strictly conforms to C99, with well-defined behavior, and some implementations prints "Sun Jan-99 99:99:99 -999". The proposed resolution places extra constraints on asctime's arguments that would cause the above code to have undefined behavior.
The original interpretation request considered by the Austin Group contained an additional requirement, that the calculated year should not precede the Epoch (the date and time associated with (time_t)0). This restriction was removed in forwarding this to the C committee, since there is no C equivalent concept. However, if the calculated year is less than 1000, problems may occur, so perhaps the wording should be:
If the calculated year is less than 1000 or greater than 9999, the behavior is undefined.
Note: This appears to be a duplicate of DR 217, which advises no consensus / no change.
It was also pointed out that the Proposed Technical
Corrigendum does not fix all of the issues, such as if
tm_mon=4
and
tm_mday=31
, both valid numbers, but not a
valid date.
Technical Corrigendum
Add after the example code, and before the "Returns" section, the following new paragraph:
If any of the fields of theAdd footnote *:tm
structure pointed to bytimeptr
contain values that are outside the normal ranges*, the behavior ofasctime()
is undefined. If the calculated year exceeds four digits, or is less than the year 1000, the behavior is undefined.
See 7.23.1 para 4 for the specifications of the "normal ranges".Previous Defect Report < - > Next Defect Report