CodeQL / Analyze (actions) (push) Canceled after 0s
CodeQL / Analyze (python) (push) Canceled after 0s
pre-commit / pre-commit (push) Canceled after 0s
Multi-Arch CI / setup (push) Canceled after 0s
Publish build_manylinux_x86_64 images / publish_build_manylinux_x86_64 (push) Canceled after 0s
Setup (Multi-Arch) / setup (push) Canceled after 0s
Multi-Arch CI / Linux::${{ fromJSON(needs.setup.outputs.linux_build_config || '{}').build_variant_label || 'skip' }} (push) Canceled after 0s
Publish TheRock Docker image / build-and-push-image (push) Canceled after 0s
Publish no_rocm_image_ubi10 image / publish_no_rocm_image_ubi10 (push) Canceled after 0s
Multi-Arch CI / Windows::${{ fromJSON(needs.setup.outputs.windows_build_config || '{}').build_variant_label || 'skip' }} (push) Canceled after 0s
Publish TheRock Docker image / build-and-push-image (push) Canceled after 0s
Multi-Arch CI / Manifest Diff (push) Canceled after 0s
TheRock Manifest Diff Report / Generate Manifest Diff Report (push) Canceled after 0s
Multi-Arch CI / CI Summary (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04 images / publish_no_rocm_image_ubuntu24_04 (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04_ocl_rt images / publish_no_rocm_image_ubuntu24_04_ocl_rt (push) Canceled after 0s
Publish TheRock Docker image / build-and-push-image (push) Canceled after 0s
Publish TheRock Docker image / build-and-push-image (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04 images / publish_no_rocm_image_ubuntu24_04_rocgdb (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04_rocgdb images / publish_no_rocm_image_ubuntu24_04_rocgdb (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04 images / publish_no_rocm_image_ubuntu24_04_ocl_rt (push) Canceled after 0s
Publish TheRock Docker image / build-and-push-image (push) Canceled after 0s
Unit Tests / Unit Tests :: ubuntu-24.04 (push) Canceled after 0s
Unit Tests / Unit Tests :: windows-2022 (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04 images / publish_no_rocm_image_ubuntu24_04_media (push) Canceled after 0s
Unit Tests / Unit Tests Summary (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04 images / publish_no_rocm_image_ubuntu24_04_openmpi (push) Canceled after 0s
239 lines
8.9 KiB
ReStructuredText
239 lines
8.9 KiB
ReStructuredText
.. title:: clang-tidy - bugprone-unsafe-functions
|
|
|
|
bugprone-unsafe-functions
|
|
=========================
|
|
|
|
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 the
|
|
**Annex 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
|
|
<https://wiki.sei.cmu.edu/confluence/display/c/MSC24-C.+Do+not+use+deprecated+or+obsolescent+functions>`_.
|
|
- Rule `MSC33-C. Do not pass invalid data to the asctime() function
|
|
<https://wiki.sei.cmu.edu/confluence/display/c/MSC33-C.+Do+not+pass+invalid+data+to+the+asctime%28%29+function>`_.
|
|
|
|
`cert-msc24-c` and `cert-msc33-c` redirect here as aliases of this check.
|
|
|
|
Unsafe functions
|
|
----------------
|
|
|
|
The following functions are reported if :option:`ReportDefaultFunctions`
|
|
is 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: ``strftime``
|
|
- ``gets``, suggested replacement: ``fgets``
|
|
|
|
The following functions are always checked, regardless of *Annex K*
|
|
availability:
|
|
|
|
- ``rewind``, suggested replacement: ``fseek``
|
|
- ``setbuf``, suggested replacement: ``setvbuf``
|
|
- ``std::get_temporary_buffer``, suggested replacement: "plain" allocation
|
|
with ``operator new[]``
|
|
|
|
If :option:`ReportMoreUnsafeFunctions` is enabled,
|
|
the following functions are also checked:
|
|
|
|
- ``bcmp``, suggested replacement: ``memcmp``
|
|
- ``bcopy``, suggested replacement: ``memcpy_s`` if *Annex K* is available,
|
|
or ``memcpy``
|
|
- ``bzero``, suggested replacement: ``memset_s`` if *Annex K* is available,
|
|
or ``memset``
|
|
- ``getpw``, suggested replacement: ``getpwuid``
|
|
- ``vfork``, suggested replacement: ``posix_spawn``
|
|
|
|
Although mentioned in the associated CERT rules, the following functions are
|
|
**ignored** 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 **before**
|
|
including any system headers.
|
|
|
|
.. _CustomFunctions:
|
|
|
|
Custom functions
|
|
----------------
|
|
|
|
The option :option:`CustomFunctions` allows the user to define custom functions
|
|
to be checked. The format is the following, without newlines:
|
|
|
|
.. code::
|
|
|
|
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
|
|
``original`` in the default namespace. A similar diagnostic can also be printed
|
|
using a fully custom reason.
|
|
|
|
.. code:: c
|
|
|
|
// 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:
|
|
|
|
.. code:: c
|
|
|
|
// 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::ifstream``
|
|
has 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
|
|
-------
|
|
|
|
.. option:: 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`.
|
|
|
|
.. option:: 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 :ref:`custom functions<CustomFunctions>`.
|
|
Default is `true`.
|
|
|
|
.. option:: 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 :ref:`Custom functions<CustomFunctions>`.
|
|
|
|
Examples
|
|
--------
|
|
|
|
.. code-block:: c++
|
|
|
|
#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;
|
|
}
|
|
}
|