Versions Compared

Key

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

C99 The C Standard, 7.29.3.1 [ISO/IEC 9899:2024], provides the following definition sample implementation of the asctime() function in Section 7.23.3.1:

Code Block

char *asctime(const struct tm *timeptr)
 {
  static const char wday_name[7][3] = {
    "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"
  };
  static const 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;
}

This function is supposed to output a character string of 26 positions 26 characters at most, including the terminating zeronull character. If we count the length indicated by the format directives, we arrive at 25:

o 3 for the day of the week +
o 1 space +
o 3 for the month +
o 3 for the day in the month +
o 1 space +
o 8 for the hour in hh:mm:ss format +
o 1 space +
o 4 for the year +
o 1 newline.

It makes 25 characters, and taking . Taking into account the terminating zeronull character, the calculation array size of the string appears sufficient is not.

The sprintf() call has undefined behavior if the value of timeptr->tm_year is outside the range -2899, 8099 and consequently the year being represented falls outside the range -999, 9999.

.

However, this implementation assumes that the values of the struct tm data 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 example, if tm_year has the value 12345, then 27 characters (including the terminating null character) are printedThe problem is that the format %d of the printf specification doesn't allow for a maximum size. When you write %.3d it means that at least 3 characters will be output, but it could be much more if, for instance, the input is bigger than 999. In that case, the buffer allocated for asctime is too small to contain the printf result, resulting in a buffer overflow.

The POSIX® Base Specifications [IEEE Std 1003.1:2013] says the following about the asctime() and asctime_r() function primarily exists functions:

These functions are included only for compatibility with older implementations.

...

They have undefined behavior if the resulting string would be too long, so the use of these functions should be discouraged. On implementations that do not detect output string length overflow, it is possible to overflow the output buffers in such a way as to cause applications to fail, or possible system security violations. Also, these functions do not support localized date and time formats. To avoid these problems, applications should

...

use strftime() to generate strings from broken-down times.

The POSIX standard developers decided to mark the The asctime() function obsolescent even though they are in C99 because of the possibility of buffer overflow. C99 also provides the strftime() function which can be used to avoid these problemsappears in the list of obsolescent functions in MSC24-C. Do not use deprecated or obsolescent functions.

Noncompliant Code Example

Avoid using This noncompliant code example invokes the asctime() function .with potentially unsanitized data:

Code Block
bgColor#FFcccc

struct tm time;

time.tm_sec = 60;  /* Seconds [0,60] */
time.tm_min = 59;  /* Minutes [0,59] */ 
time.tm_hour = 23; /* Hour [0,23] */ 
time.tm_mday = 31; /* Day of month [1,31] */
time.tm_mon = 0;  /* Month of year [0,11] */ 
time.tm_year = 8100;  /* Years since 1900 */ 
time.tm_wday = 0; /* Day of week [0,6] (Sunday =0) */ 
time.tm_yday = 365; /* Day of year [0,365] */ 
time.tm_isdst = -1; /* Daylight Savings flag */ 
 
char *time = asctime(&time);

Compliant Solution

Use the strftime() function.

langc
#include <time.h>
 
void func(struct tm *time_tm) {
  char *time = asctime(time_tm);
  /* ... */
}

Compliant Solution (strftime())

The strftime() function allows the programmer to specify a more rigorous format and also to specify the maximum size of the resulting time string:

Code Block
bgColor#ccccff
langc
#include <time.h>

enum { maxsize = 26 };
 
void func(struct tm *time) {
  char s[maxsize];
  /* Current time representation for locale */
  const char *format = "%c";

  
Code Block
bgColor#ccccff

char *s=;
size_t maxsize;
const char *format;
const struct tm *timeptr;

size_t size = strftime(s, maxsize, format, timeptrtime);
}

This call has the same effects as asctime() but also ensures that no more than maxsize characters 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

Detectable

Remediation Cost

Repairable

Priority

Level

STR30

MSC33-C

high

High

Likely

high

No

low

No

P9

L2

Automated Detection

...

Unknown.

Tool

Version

Checker

Description

Astrée
Include Page
Astrée_V
Astrée_V

Supported, but no explicit checker
Axivion Bauhaus Suite

Include Page
Axivion Bauhaus Suite_V
Axivion Bauhaus Suite_V

CertC-MSC33
CodeSonar
Include Page
CodeSonar_V
CodeSonar_V

BADFUNC.TIME_H

Use of <time.h> Time/Date Function

Cppcheck Premium

Include Page
Cppcheck Premium_V
Cppcheck Premium_V

premium-cert-msc33-c
Helix QAC

Include Page
Helix QAC_V
Helix QAC_V

C5032

C++5030


Klocwork
Include Page
Klocwork_V
Klocwork_V

CERT.MSC.ASCTIME


LDRA tool suite
Include Page
LDRA_V
LDRA_V
44 SEnhanced Enforcement
Parasoft C/C++test
Include Page
Parasoft_V
Parasoft_V

CERT_C-MSC33-a

The 'asctime()' and 'asctime_r()' functions should not be used
PC-lint Plus

Include Page
PC-lint Plus_V
PC-lint Plus_V

586

Fully supported

Polyspace Bug Finder

Include Page
Polyspace Bug Finder_V
Polyspace Bug Finder_V

CERT C: Rule MSC33-CChecks for use of obsolete standard function (rule partially covered)


RuleChecker
Include Page
RuleChecker_V
RuleChecker_V

Supported, but no explicit checker

Related Vulnerabilities

Search for vulnerabilities resulting from the violation of this rule on the CERT website.

Other Languages

This rule appears in the C++ Secure Coding Standard as STR30-CPP. Do not attempt to modify string literals.

References

...

Related Guidelines

Key here (explains table format and definitions)

Taxonomy

Taxonomy item

Relationship

CERT C Secure Coding StandardMSC24-C. Do not use deprecated or obsolescent functionsPrior to 2018-01-12: CERT: Unspecified Relationship

Bibliography

[IEEE Std 1003.1:2013]XSH, System Interfaces, asctime
[ISO/IEC 9899:2024]7.29

...

.3.1,

...

"The

...

asctime Function"


...

Image Added Image Added

http://www.opengroup.org/onlinepubs/9699919799/functions/asctime.htmlImage Removed

STR08-C. Use managed strings for development of new string manipulation code      07. Characters and Strings (STR)      Image Modified