tidy - bugprone-unsafe-functions — Extra Clang Tools 22.0.0git documentation (original) (raw)
Checks for functions that have safer, more secure replacements available, or are considered deprecated due to design flaws. The check heavily relies on the functions from theAnnex K. “Bounds-checking interfaces” of C11.
The check implements the following rules from the CERT C Coding Standard:
- Recommendation MSC24-C. Do not use deprecated or obsolescent functions.
- Rule MSC33-C. Do not pass invalid data to the asctime() function.
cert-msc24-c and cert-msc33-c redirect here as aliases of this check.
Unsafe functions¶
The following functions are reported if ReportDefaultFunctionsis enabled.
If Annex K. is available, a replacement from Annex K. is suggested for the following functions:
asctime, asctime_r, bsearch, ctime, fopen, fprintf,freopen, fscanf, fwprintf, fwscanf, getenv, gets,gmtime, localtime, mbsrtowcs, mbstowcs, memcpy,memmove, memset, printf, qsort, scanf, snprintf,sprintf, sscanf, strcat, strcpy, strerror, strlen,strncat, strncpy, strtok, swprintf, swscanf, vfprintf,vfscanf, vfwprintf, vfwscanf, vprintf, vscanf,vsnprintf, vsprintf, vsscanf, vswprintf, vswscanf,vwprintf, vwscanf, wcrtomb, wcscat, wcscpy,wcslen, wcsncat, wcsncpy, wcsrtombs, wcstok, wcstombs,wctomb, wmemcpy, wmemmove, wprintf, wscanf.
If Annex K. is not available, replacements are suggested only for the following functions from the previous list:
asctime,asctime_r, suggested replacement:strftimegets, suggested replacement:fgets
The following functions are always checked, regardless of _Annex K_availability:
rewind, suggested replacement:fseeksetbuf, suggested replacement:setvbuf
If ReportMoreUnsafeFunctions is enabled, the following functions are also checked:
bcmp, suggested replacement:memcmpbcopy, suggested replacement:memcpy_sif Annex K is available, ormemcpybzero, suggested replacement:memset_sif Annex K is available, ormemsetgetpw, suggested replacement:getpwuidvfork, suggested replacement:posix_spawn
Although mentioned in the associated CERT rules, the following functions areignored by the check:
atof, atoi, atol, atoll, tmpfile.
The availability of Annex K is determined based on the following macros:
__STDC_LIB_EXT1__: feature macro, which indicates the presence of_Annex K. “Bounds-checking interfaces”_ in the library implementation__STDC_WANT_LIB_EXT1__: user-defined macro, which indicates that the user requests the functions from Annex K. to be defined.
Both macros have to be defined to suggest replacement functions from Annex K. __STDC_LIB_EXT1__ is defined by the library implementation, and__STDC_WANT_LIB_EXT1__ must be defined to 1 by the user beforeincluding any system headers.
Custom functions¶
The option CustomFunctions allows the user to define custom functions to be checked. The format is the following, without newlines:
bugprone-unsafe-functions.CustomFunctions=" functionRegex1[, replacement1[, reason1]]; functionRegex2[, replacement2[, reason2]]; ... "
The functions are matched using POSIX extended regular expressions.(Note: The regular expressions do not support negative (?!) matches.)
The reason is optional and is used to provide additional information about the reasoning behind the replacement. The default reason is is marked as unsafe.
If replacement is empty, the default text it should not be used will be shown instead of the suggestion for a replacement.
If the reason starts with the character >, the reason becomes fully custom. The default suffix is disabled even if a replacement is present, and only the reason message is shown after the matched function, to allow better control over the suggestions. (The starting > and whitespace directly after it are trimmed from the message.)
As an example, the following configuration matches only the function originalin the default namespace. A similar diagnostic can also be printed using a fully custom reason.
// bugprone-unsafe-functions.CustomFunctions: // ^original$, replacement, is deprecated; // Using the fully custom message syntax: // ^suspicious$,,> should be avoided if possible. original(); // warning: function 'original' is deprecated; 'replacement' should be used instead. suspicious(); // warning: function 'suspicious' should be avoided if possible. ::std::original(); // no-warning original_function(); // no-warning
If the regular expression contains the character :, it is matched against the qualified name (i.e. std::original), otherwise the regex is matched against the unqualified name (original). If the regular expression starts with ::(or ^::), it is matched against the fully qualified name (::std::original).
One of the use cases for fully custom messages is suggesting compiler options and warning flags:
// bugprone-unsafe-functions.CustomFunctions: // ^memcpy$,,>is recommended to have compiler hardening using '_FORTIFY_SOURCE'; // ^printf$,,>is recommended to have the '-Werror=format-security' compiler warning flag;
memcpy(dest, src, 999'999); // warning: function 'memcpy' is recommended to have compiler hardening using '_FORTIFY_SOURCE' printf(raw_str); // warning: function 'printf' is recommended to have the '-Werror=format-security' compiler warning flag
Note
Fully qualified names can contain template parameters on certain C++ classes, but not on C++ functions. Type aliases are resolved before matching.
As an example, the member function open in the class std::ifstreamhas a fully qualified name of ::std::basic_ifstream<char>::open.
The example could also be matched with the regex::std::basic_ifstream<[^>]*>::open, which matches all potential template parameters, but does not match nested template classes.
Options¶
ReportMoreUnsafeFunctions¶
When true, additional functions from widely used APIs (such as POSIX) are added to the list of reported functions. See the main documentation of the check for the complete list as to what this option enables. Default is true.
ReportDefaultFunctions¶
When true, the check reports the default set of functions. Consider changing the setting to false if you only want to see custom functions matched via custom functions. Default is true.
CustomFunctions¶
A semicolon-separated list of custom functions to be matched. A matched function contains a regular expression, an optional name of the replacement function, and an optional reason, separated by comma. For more information, see Custom functions.
Examples¶
#ifndef STDC_LIB_EXT1 #error "Annex K is not supported by the current standard library implementation." #endif
#define STDC_WANT_LIB_EXT1 1
#include <string.h> // Defines functions from Annex K. #include <stdio.h>
enum { BUFSIZE = 32 };
void Unsafe(const char *Msg) { static const char Prefix[] = "Error: "; static const char Suffix[] = "\n"; char Buf[BUFSIZE] = {0};
strcpy(Buf, Prefix); // warning: function 'strcpy' is not bounds-checking; 'strcpy_s' should be used instead. strcat(Buf, Msg); // warning: function 'strcat' is not bounds-checking; 'strcat_s' should be used instead. strcat(Buf, Suffix); // warning: function 'strcat' is not bounds-checking; 'strcat_s' should be used instead. if (fputs(buf, stderr) < 0) { // error handling return; } }
void UsingSafeFunctions(const char *Msg) { static const char Prefix[] = "Error: "; static const char Suffix[] = "\n"; char Buf[BUFSIZE] = {0};
if (strcpy_s(Buf, BUFSIZE, Prefix) != 0) { // error handling return; }
if (strcat_s(Buf, BUFSIZE, Msg) != 0) { // error handling return; }
if (strcat_s(Buf, BUFSIZE, Suffix) != 0) { // error handling return; }
if (fputs(Buf, stderr) < 0) { // error handling return; } }