
But the C standard says that sometimes fewer bytes of output must be generated (in particular, if the year is in the range -99 through 999)...
What I find at http://www.opengroup.org/onlinepubs/009695399/functions/asctime.html (you may have to register via http://www.unix-systems.org/version3/iso_std.html to access the above, and your URLage may vary) is this text: The asctime() function shall convert the broken-down time in the structure pointed to by timeptr into a string in the form: Sun Sep 16 01:03:52 1973\n\0 using the equivalent of the following algorithm: char *asctime(const struct tm *timeptr) { static char wday_name[7][3] = { "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat" }; static char mon_name[12][3] = { "Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec" }; static char result[26]; sprintf(result, "%.3s %.3s%3d %.2d:%.2d:%.2d %d\n", wday_name[timeptr->tm_wday], mon_name[timeptr->tm_mon], timeptr->tm_mday, timeptr->tm_hour, timeptr->tm_min, timeptr->tm_sec, 1900 + timeptr->tm_year); return result; } That last "%d" in the sprintf would indeed produce less than four digits of year output in some cases. Of course we might also take the above as meaning that it's mandatory for asctime to overflow a buffer (and potentially dump core) for other cases (take tm_year >= 10000, please). Sidebar: I believe kre is proposing padding with spaces rather than zeroes. --ado

"Olson, Arthur David (NIH/NCI)" <olsona@dc37a.nci.nih.gov> writes:
That last "%d" in the sprintf would indeed produce less than four digits of year output in some cases.
Yes, that's right.
Of course we might also take the above as meaning that it's mandatory for asctime to overflow a buffer (and potentially dump core) for other cases (take tm_year >= 10000, please).
This issue has come up on the comp.std.c newsgroup, most recently in the enormous "Buffer overflow in the C standard?" thread that started May 28. Here's a URL if you want to read the gory details: http://groups.google.com/groups?threadm=c972ch%24h97%241%40news-reader4.wana... The consensus opinion is that, if the asctime code that you quoted has defined behavior, then a conforming C implementation must exhibit that behavior; if not, the implementation is free to do whatever it wants to, because the behavior is undefined. At least, this is the opinion endorsed by the members of the standardization committee in comp.std.c, and I vaguely recall that they affirmed it in response to a defect report. Therefore, when tm_year >= 10000, the asctime implementation is allowed to dump core or generate a wrong answer (because of the buffer overflow in the standard code), but it is not required to do so: it can return a correct string (by using a larger static buffer than required; the standard allows this). Similarly, when tm_year == INT_MAX, the implementation is allowed to dump core or generate a wrong answer (since adding 1900 overflows the int value in the standard code); but the implementation can return a correct string instead (by using a wider integer to do arithmetic).
Sidebar: I believe kre is proposing padding with spaces rather than zeroes.
Well, the Unix V7 code generated only years in the range 1900-2099, regardless of what tm_year was. (I doubt whether that's what he wants. :-)

Olson, Arthur David (NIH/NCI) said:
What I find at http://www.opengroup.org/onlinepubs/009695399/functions/asctime.html
matches the C Standard.
sprintf(result, "%.3s %.3s%3d %.2d:%.2d:%.2d %d\n", wday_name[timeptr->tm_wday], mon_name[timeptr->tm_mon], timeptr->tm_mday, timeptr->tm_hour, timeptr->tm_min, timeptr->tm_sec, 1900 + timeptr->tm_year);
Analysing this, we get: * tm_wday must be in the range 0 to 6, and 3 characters are output - if it's outside this range, the behaviour is undefined * a space is output * tm_mon must be in the range 0 to 11, and 3 characters are output - if it's outside this range, the behaviour is undefined * tm_mday is output: - if it is in the range 0 to 9, two spaces preceed it - else if it is in the range -9 to 99, one space preceeds it - otherwise it is output unchanged * a space is output * tm_hour, tm_min, and tm_sec are output, separated by a colon - for each, at least two digits are to appear (-1 appears as "-01") * a space is output * 1900+tm_year is output using the minimum number of characters possible. * a newline is output If the result involves outputting more than 25 characters, the behaviour is undefined. If it only involves 25, the output *MUST* take that form.
That last "%d" in the sprintf would indeed produce less than four digits of year output in some cases.
Right. Consider the case where tm_year = -1200 and tm_hour = 999. "Sun Jan 12 999:01:01 700" is *required* as the result.
Of course we might also take the above as meaning that it's mandatory for asctime to overflow a buffer (and potentially dump core) for other cases (take tm_year >= 10000, please).
It's mandatory to overflow the buffer, at which point the code can do whatever it likes because C and POSIX don't mandate any behaviour. -- Clive D.W. Feather | Work: <clive@demon.net> | Tel: +44 20 8495 6138 Internet Expert | Home: <clive@davros.org> | Fax: +44 870 051 9937 Demon Internet | WWW: http://www.davros.org | Mobile: +44 7973 377646 Thus plc | |
participants (3)
-
Clive D.W. Feather
-
Olson, Arthur David (NIH/NCI)
-
Paul Eggert