Subclause 7.27.3.1 of the C Standard [ISO/IEC 9899:2011] provides the following sample implementation of the asctime() function:
...
This function is supposed to output a character string of 26 characters at most, including the terminating null character. If we count the length indicated by the format directives, we arrive at 25. Taking into account the terminating null character, the array size of the string appears sufficient.
However, this implementation assumes that the values of the struct tm data in timeptr are within normal ranges and does nothing to enforce the range limit. If any of the values print more characters than expected, the sprintf() function may overflow the result array. For instance, if tm_year has the value 12345, then 27 characters (including the terminating null character) are printed, resulting in a buffer overflow.
...
Noncompliant Code Example (asctime())
You can sanitize the data before invoking asctime():
| Code Block | ||||
|---|---|---|---|---|
| ||||
#include <time.h>
int validate_tm(struct tm* time) {
/*
* The range of valid values of the tm_sec member is [0, 60]
* inclusive (to allow for leap seconds).
*/
if (time->tm_sec < 0 || time->tm_sec > 60) return 0;
if (time->tm_min < 0 || time->tm_min >= 60) return 0;
if (time->tm_hour < 0 || time->tm_hour >= 24) return 0;
if (time->tm_mday <= 0 || time->tm_mday > 31) return 0;
if (time->tm_mon < 0 || time->tm_mon >= 12) return 0;
/* While otherOther years are legit, theybut may overflow asctime()'s buffer */
if (time->tm_year < -999 || time->tm_year > 9999) return 0;
if (time->tm_wday < 0 || time->tm_wday >= 7) return 0;
if (time->tm_yday < 0 || time->tm_yday >= 366) return 0;
return 1;
}
void func(void) {
struct tm time_tm;
/* Initialize time_tm */
if (!validate_tm(&time_tm)) {
/* Handle error */
}
char *time = asctime(&time_tm);
} |
Note that while that although this example is safer due to sanitizing the data, it is still non-compliant noncompliant because asctime() is obsolete. See MSC34MSC24-C. Do not use deprecated or obsolete obsolescent functions.
Compliant Solution (Annex K, asctime_s())
...
| Code Block | ||||
|---|---|---|---|---|
| ||||
#include <time.h>
void func(void) {
struct tm time;
const size_t maxsize = 26;
char s[maxsize];
/* currentCurrent time representation for locale */
const char *format = "%c";
const struct tm *timeptr;
size_t size = strftime(s, maxsize, format, timeptr);
} |
This call has the same effects as asctime(), but it also ensures that no more than maxsize chars are printed, preventing buffer overflow.
Risk Assessment
On implementations that do not detect output-string-length overflow, it is possible to overflow the output buffers, resulting in a vulnerability.
Rule | Severity | Likelihood | Remediation Cost | Priority | Level |
|---|---|---|---|---|---|
MSC33-C | High | Likely | Low | P27 | L1 |
Related Vulnerabilities
Search for vulnerabilities resulting from the violation of this rule on the CERT website.
...
Bibliography
| [ISO/IEC 9899:2011] | Subclause 7.27.3.1, "The asctime Function" |
| [Open Group 2008] | "asctime, asctime_r—Convert Date and Time to a String" |
...