CertC-MSC24¶
Do not use deprecated or obsolescent functions
Required inputs: IR
Do not use deprecated or obsolescent functions when more secure equivalent functions are available. Deprecated functions are defined by the C Standard. Obsolescent functions are defined by this recommendation.
Deprecated Functions
The
gets() function was deprecated by Technical Corrigendum 3 to C99
and eliminated from C11. The Annex K
gets_s() function is a recommended alternative to
gets().
Obsolescent Functions
Functions in the first column of the following table are hereby defined to be obsolescent functions. To remediate invocations of obsolescent functions, an application might use inline coding that, in all respects, conforms to this guideline, or an alternative library that, in all respects, conforms to this guideline, or alternative non-obsolescent functions.
| Obsolescent Function |
Recommended Alternative |
Rationale |
|---|---|---|
asctime() |
asctime_s
|
Non-reentrant |
atof
|
strtod
|
No error detection |
atoi
|
strtol
|
No error detection |
atol
|
strtol
|
No error detection |
atoll
|
strtoll
|
No error detection |
ctime
|
ctime_s
|
Non-reentrant |
fopen
|
fopen_s
|
No exclusive access to file |
freopen
|
freopen_s
|
No exclusive access to file |
rewind
|
fseek
|
No error detection |
setbuf
|
setvbuf
|
No error detection |
The
atof
, and
(), atoi
(), atol
()atoll
functions are obsolescent because the
()strtod
(), strtof
(), strtol
(), strtold
(), strtoll
(), strtoul(), and
strtoull
functions can emulate their usage and have more robust
error handling capabilities. See
INT05-C.
Do not use input functions to convert character data if they cannot handle all
possible inputs.
()
The
fopen
and
()freopen
functions are obsolescent because the
()fopen_s
and
()freopen_s
functions can emulate their usage and improve security
by protecting the file from unauthorized access by setting its file protection
and opening the file with exclusive access [
ISO/IEC
WG14 N1173].
()
The
setbuf
function is obsolescent because
()setbuf
does not return a value and can be emulated using
()setvbuf
. See
ERR07-C.
Prefer functions that support error checking over equivalent functions that
don't.
()
The
rewind
function is obsolescent because
()rewind
does not return a value and can be emulated using
()fseek
. See
ERR07-C.
Prefer functions that support error checking over equivalent functions that
don't.
()
The
asctime
and
()ctime
functions are obsolescent because they use non-reentrant
static buffers and can be emulated using
()asctime_s
and
()ctime_s
.
()
Unchecked Obsolescent Functions
If you are using platforms that support Annex K, then functions in the first column of the following table are hereby defined to be obsolescent functions, with functions in the second column being the recommended alternatives from Annex K.
| Obsolescent Function |
Recommended Alternative |
|---|---|
| bsearch() | bsearch_s() |
| fprintf() | fprintf_s() |
| fscanf() | fscanf_s() |
| fwprintf() | fwprintf_s() |
| fwscanf() | fwscanf_s() |
| getenv() | getenv_s() |
| gmtime() | gmtime_s() |
| localtime() | localtime_s() |
| mbsrtowcs() | mbsrtowcs_s() |
| mbstowcs() | mbstowcs_s() |
| memcpy() | memcpy_s() |
| memmove() | memmove_s() |
| printf() | printf_s() |
| qsort() | qsort_s() |
| scanf() | scanf_s() |
| snprintf() | snprintf_s() |
| sprintf() | sprintf_s() |
| sscanf() | sscanf_s() |
| strcat() | strcat_s() |
| strcpy() | strcpy_s() |
| strerror() | strerror_s() |
| strlen() | strnlen_s() |
| strncat() | strncat_s() |
| strncpy() | strncpy_s() |
| strtok() | strtok_s() |
| swprintf() | swprintf_s() |
| swscanf() | swscanf_s() |
| vfprintf() | vfprintf_s() |
| vfscanf() | vfscanf_s() |
| vfwprintf() | vfwprintf_s() |
| vfwscanf() | vfwscanf_s() |
| vprintf() | vprintf_s() |
| vscanf() | vscanf_s() |
| vsnprintf() | vsnprintf_s() |
| vsprintf() | vsprintf_s() |
| vsscanf() | vsscanf_s() |
| vswprintf() | vswprintf_s() |
| vswscanf() | vswscanf_s() |
| vwprintf() | vwprintf_s() |
| vwscanf() | vwscanf_s() |
| wcrtomb() | wcrtomb_s() |
| wcscat() | wcscat_s() |
| wcscpy() | wcscpy_s() |
| wcslen() | wcsnlen_s() |
| wcsncat() | wcsncat_s() |
| wcsncpy() | wcsncpy_s() |
| wcsrtombs() | wcsrtombs_s() |
| wcstok() | wcstok_s() |
| wcstombs() | wcstombs_s() |
| wctomb() | wctomb_s() |
| wmemcpy() | wmemcpy_s() |
| wmemmove() | wmemmove_s() |
| wprintf() | wprintf_s() |
| wscanf() | wscanf_s() |
For information on the
tmpfile() and
tmpfile_s() functions, see
FIO21-C.
Do not create temporary files in shared directories.
For information on
the
memset() and
memset_s() functions, see
MSC06-C.
Beware of compiler optimizations.
To remediate invocations of obsolescent functions, an application might use any of the following recommended functions from ISO/IEC TR 24731-2, Extensions to the C Library-Part II: Dynamic Allocation Functions [ ISO/IEC TR 24731-2]:
asprintf |
aswprintf |
fmemopen |
fscanf |
fwscanf |
getdelim |
getline |
getwdelim |
getwline |
open_memstream |
open_wmemstream |
strdup |
strndup |
Noncompliant Code Example
In this noncompliant code example, the obsolescent functions
strcat() and
strcpy() are used:
#include <string.h>
#include <stdio.h>
enum { BUFSIZE = 32 };
void complain(const char *msg) {
static const char prefix[] = "Error: ";
static const char suffix[] = "\n";
char buf[BUFSIZE];
strcpy(buf, prefix);
strcat(buf, msg);
strcat(buf, suffix);
fputs(buf, stderr);
}
Compliant Solution
In this compliant solution,
strcat() and
strcpy() are replaced by
strcat_s() and
strcpy_s():
#define __STDC_WANT_LIB_EXT1__
#include <string.h>
#include <stdio.h>
enum { BUFFERSIZE = 256 };
void complain(const char *msg) {
static const char prefix[] = "Error: ";
static const char suffix[] = "\n";
char buf[BUFFERSIZE];
strcpy_s(buf, BUFFERSIZE, prefix);
strcat_s(buf, BUFFERSIZE, msg);
strcat_s(buf, BUFFERSIZE, suffix);
fputs(buf, stderr);
}
Risk Assessment
The deprecated and obsolescent functions enumerated in this guideline are commonly associated with software vulnerabilities.
| Rule | Severity | Likelihood | Remediation Cost | Priority | Level |
|---|---|---|---|---|---|
| MSC24-C | High | Probable | Medium | P12 | L1 |
Related Guidelines
| CERT C Secure Coding Standard |
ERR07-C.
Prefer functions that support error checking over equivalent functions that
don't INT05-C. Do not use input functions to convert character data if they cannot handle all possible inputs ERR34-C. Detect errors when converting a string to a number STR06-C. Do not assume that strtok() leaves the parse string unchanged STR07-C. Use the bounds-checking interfaces for string manipulation |
| ISO/IEC TR 24772 | Use of Libraries [TRJ] |
| MISRA C:2012 | Rule 21.3 (required) |
| MITRE CWE |
CWE-20, Insufficient input validation CWE-73, External control of file name or path CWE-79, Improper Neutralization of Input During Web Page Generation ('Cross-site Scripting') CWE-89, Improper Neutralization of Special Elements used in an SQL Command ('SQL Injection') CWE-91, XML Injection (aka Blind XPath Injection) CWE-94, Improper Control of Generation of Code ('Code Injection') CWE-114, Process Control CWE-120, Buffer Copy without Checking Size of Input ('Classic Buffer Overflow') CWE-192, Integer coercion error CWE-197, Numeric truncation error CWE-367, Time-of-check, time-of-use race condition CWE-464, Addition of data structure sentinel CWE-601, URL Redirection to Untrusted Site ('Open Redirect') CWE-676, Use of potentially dangerous function |
Bibliography
| [ Apple 2006] | Apple Secure Coding Guide, "Avoiding Race Conditions and Insecure File Operations" |
| [ Burch 2006] | Specifications for Managed Strings, Second Edition |
| [ Drepper 2006] | Section 2.2.1 "Identification When Opening" |
| [ IEEE Std 1003.1:2013] | XSH, System Interfaces,
open
|
| ISO/IEC 23360-1:2006 | |
| [ ISO/IEC WG14 N1173] | Rationale for TR 24731 Extensions to the C Library Part I: Bounds-checking interfaces |
| [ Klein 2002] | "Bullet Proof Integer Input Using
strtol()" |
| [ Linux 2008] | strtok(3) |
| [ Seacord 2013] | Chapter 2, "Strings" Chapter 8, "File I/O" |
| [ Seacord 2005b] | "Managed String Library for C, C/C++" |
Possible Messages
Key |
Text |
Severity |
Disabled |
|---|---|---|---|
forbidden_libfunc_call |
Do not use deprecated or obsolescent functions. |
None |
False |
Options¶
This rule shares the following common options: exclude_in_macros, exclude_messages_in_system_headers, excludes, extend_exclude_to_macro_invocations, includes, justification_checker, languages, post_processing, provider, report_at, severity
The following places define options that affect this rule: Stylechecks, Analysis-GlobalOptions
blacklist¶
blacklist
Dictionary of header globbing to (list of) function name globbing(s) of forbidden functions.Type: dict[bauhaus.analysis.config.FileGlobPattern, list[bauhaus.analysis.config.GlobPattern]]
Default:
{ '*stdlib.h': ['atof', 'atoi', 'atol', 'atoll', 'bsearch', 'getenv', 'gmtime', 'mbstowcs', 'qsort', 'wcstombs', 'wctomb', 'wmemcpy'], '*string.h': ['memcpy', 'memmove', 'strcat', 'strcpy', 'strerror', 'strncat', 'strncpy', 'strtok'], 'stdio.h': ['fopen', 'freopen', 'rewind', 'setbuf', 'fprintf', 'fscanf', 'fwprintf', 'fwscanf', 'printf', 'setbuf', 'snprintf', 'sprintf', 'sscanf', 'vfprintf', 'vfscanf', 'vprintf', 'vscanf', 'vsnprintf', 'vsprintf', 'vsscanf', 'wprintf', 'wscanf'], 'time.h': ['asctime', 'ctime', 'localtime'], 'wchar.h': ['mbsrtowcs', 'swprintf', 'swscanf', 'vfwprintf', 'vfwscanf', 'vswprintf', 'vswscanf', 'vwprintf', 'vwscanf', 'wcrtomb', 'wcscat', 'wcscpy', 'wcsncat', 'wcsncpy', 'wcsrtombs', 'wcstok', 'wmemmove'] }