Versions Compared

Key

  • This line was added.
  • This line was removed.
  • Formatting was changed.

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
bgColor#FFcccc
langc
#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
bgColor#ccccff
langc
#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

...