Although ctime and asctime provide a buffer large enough for any date string, ctime_r and asctime_r are documented to work with a buffer of at least 26 bytes, while with large inputs, they may write up to 33 (or more, if int is wider than 32 bits) bytes into that user-provided buffer. While letting ctime and asctime return a pointer to a string (including NUL) that is longer than 26 bytes is not bad in isolation, applications may rely on the documentation's implication that the result always fits in a 26-byte buffer, and thus copy it without checking the length. If you continue to support year numbers of 5 or more digits, you should consider avoiding the overflow that currently causes them to format year numbers like `-2147483648'. See the example below. As a point of reference, Solaris 10's functions return NULL if the resulting year would be 10000 or greater. ------------------------------------------------ /* This demonstrates two problems with ctime, asctime, ctime_r and asctime_r when time_t is a 64-bit type: - integer overflow when tm_year is within 1900 of INT_MAX - user-space buffer overflow when tm_year is 9100 (10000-1900) or larger, if the caller provides a 26-byte buffer to ctime_r or asctime_r. */ /* Show that with 64-bit time_t, glibc's ctime_r and asctime_r can write more than the implied maximum of 26 bytes into the user-supplied buffer. With the current (CVS) implementation they can write up to 33 bytes. */ #include <time.h> #include <stdlib.h> #include <string.h> #include <stdio.h> int main () { time_t t = 67767976233529200; time_t i; for (i = 0; i < 2; i++) { time_t k = t - i; char buf[100]; char *p = ctime_r (&k, buf); printf ("t=%lu\n", k); if (p) fputs (p, stdout); } exit (0); } Here's the result of running that code on an 64-bit system: $ gcc -O -Wall -W ctime.c && ./a.out t=67767976233529200 Wed Jan 1 00:00:00 -2147483648 t=67767976233529199 Tue Dec 31 23:59:59 2147483647
The current code now uses snprintf to prevent buffer overflows.