[clang-tidy] Add check 'cert-err33-c'.
The CERT rule ERR33-C can be modeled partially by the existing check 'bugprone-unused-return-value'. The existing check is reused with a fixed set of checked functions. Reviewed By: aaron.ballman Differential Revision: https://reviews.llvm.org/D112409
This commit is contained in:
parent
1ca35fc89e
commit
4bcbb3d4d7
|
@ -16,6 +16,7 @@
|
|||
#include "../bugprone/SpuriouslyWakeUpFunctionsCheck.h"
|
||||
#include "../bugprone/SuspiciousMemoryComparisonCheck.h"
|
||||
#include "../bugprone/UnhandledSelfAssignmentCheck.h"
|
||||
#include "../bugprone/UnusedReturnValueCheck.h"
|
||||
#include "../concurrency/ThreadCanceltypeAsynchronousCheck.h"
|
||||
#include "../google/UnnamedNamespaceInHeaderCheck.h"
|
||||
#include "../misc/NewDeleteOverloadsCheck.h"
|
||||
|
@ -39,6 +40,193 @@
|
|||
#include "ThrownExceptionTypeCheck.h"
|
||||
#include "VariadicFunctionDefCheck.h"
|
||||
|
||||
namespace {
|
||||
|
||||
// Checked functions for cert-err33-c.
|
||||
// The following functions are deliberately excluded because they can be called
|
||||
// with NULL argument and in this case the check is not applicable:
|
||||
// `mblen, mbrlen, mbrtowc, mbtowc, wctomb, wctomb_s`.
|
||||
// FIXME: The check can be improved to handle such cases.
|
||||
const llvm::StringRef CertErr33CCheckedFunctions = "::aligned_alloc;"
|
||||
"::asctime_s;"
|
||||
"::at_quick_exit;"
|
||||
"::atexit;"
|
||||
"::bsearch;"
|
||||
"::bsearch_s;"
|
||||
"::btowc;"
|
||||
"::c16rtomb;"
|
||||
"::c32rtomb;"
|
||||
"::calloc;"
|
||||
"::clock;"
|
||||
"::cnd_broadcast;"
|
||||
"::cnd_init;"
|
||||
"::cnd_signal;"
|
||||
"::cnd_timedwait;"
|
||||
"::cnd_wait;"
|
||||
"::ctime_s;"
|
||||
"::fclose;"
|
||||
"::fflush;"
|
||||
"::fgetc;"
|
||||
"::fgetpos;"
|
||||
"::fgets;"
|
||||
"::fgetwc;"
|
||||
"::fopen;"
|
||||
"::fopen_s;"
|
||||
"::fprintf;"
|
||||
"::fprintf_s;"
|
||||
"::fputc;"
|
||||
"::fputs;"
|
||||
"::fputwc;"
|
||||
"::fputws;"
|
||||
"::fread;"
|
||||
"::freopen;"
|
||||
"::freopen_s;"
|
||||
"::fscanf;"
|
||||
"::fscanf_s;"
|
||||
"::fseek;"
|
||||
"::fsetpos;"
|
||||
"::ftell;"
|
||||
"::fwprintf;"
|
||||
"::fwprintf_s;"
|
||||
"::fwrite;"
|
||||
"::fwscanf;"
|
||||
"::fwscanf_s;"
|
||||
"::getc;"
|
||||
"::getchar;"
|
||||
"::getenv;"
|
||||
"::getenv_s;"
|
||||
"::gets_s;"
|
||||
"::getwc;"
|
||||
"::getwchar;"
|
||||
"::gmtime;"
|
||||
"::gmtime_s;"
|
||||
"::localtime;"
|
||||
"::localtime_s;"
|
||||
"::malloc;"
|
||||
"::mbrtoc16;"
|
||||
"::mbrtoc32;"
|
||||
"::mbsrtowcs;"
|
||||
"::mbsrtowcs_s;"
|
||||
"::mbstowcs;"
|
||||
"::mbstowcs_s;"
|
||||
"::memchr;"
|
||||
"::mktime;"
|
||||
"::mtx_init;"
|
||||
"::mtx_lock;"
|
||||
"::mtx_timedlock;"
|
||||
"::mtx_trylock;"
|
||||
"::mtx_unlock;"
|
||||
"::printf_s;"
|
||||
"::putc;"
|
||||
"::putwc;"
|
||||
"::raise;"
|
||||
"::realloc;"
|
||||
"::remove;"
|
||||
"::rename;"
|
||||
"::scanf;"
|
||||
"::scanf_s;"
|
||||
"::setlocale;"
|
||||
"::setvbuf;"
|
||||
"::signal;"
|
||||
"::snprintf;"
|
||||
"::snprintf_s;"
|
||||
"::sprintf;"
|
||||
"::sprintf_s;"
|
||||
"::sscanf;"
|
||||
"::sscanf_s;"
|
||||
"::strchr;"
|
||||
"::strerror_s;"
|
||||
"::strftime;"
|
||||
"::strpbrk;"
|
||||
"::strrchr;"
|
||||
"::strstr;"
|
||||
"::strtod;"
|
||||
"::strtof;"
|
||||
"::strtoimax;"
|
||||
"::strtok;"
|
||||
"::strtok_s;"
|
||||
"::strtol;"
|
||||
"::strtold;"
|
||||
"::strtoll;"
|
||||
"::strtoul;"
|
||||
"::strtoull;"
|
||||
"::strtoumax;"
|
||||
"::strxfrm;"
|
||||
"::swprintf;"
|
||||
"::swprintf_s;"
|
||||
"::swscanf;"
|
||||
"::swscanf_s;"
|
||||
"::thrd_create;"
|
||||
"::thrd_detach;"
|
||||
"::thrd_join;"
|
||||
"::thrd_sleep;"
|
||||
"::time;"
|
||||
"::timespec_get;"
|
||||
"::tmpfile;"
|
||||
"::tmpfile_s;"
|
||||
"::tmpnam;"
|
||||
"::tmpnam_s;"
|
||||
"::tss_create;"
|
||||
"::tss_get;"
|
||||
"::tss_set;"
|
||||
"::ungetc;"
|
||||
"::ungetwc;"
|
||||
"::vfprintf;"
|
||||
"::vfprintf_s;"
|
||||
"::vfscanf;"
|
||||
"::vfscanf_s;"
|
||||
"::vfwprintf;"
|
||||
"::vfwprintf_s;"
|
||||
"::vfwscanf;"
|
||||
"::vfwscanf_s;"
|
||||
"::vprintf_s;"
|
||||
"::vscanf;"
|
||||
"::vscanf_s;"
|
||||
"::vsnprintf;"
|
||||
"::vsnprintf_s;"
|
||||
"::vsprintf;"
|
||||
"::vsprintf_s;"
|
||||
"::vsscanf;"
|
||||
"::vsscanf_s;"
|
||||
"::vswprintf;"
|
||||
"::vswprintf_s;"
|
||||
"::vswscanf;"
|
||||
"::vswscanf_s;"
|
||||
"::vwprintf_s;"
|
||||
"::vwscanf;"
|
||||
"::vwscanf_s;"
|
||||
"::wcrtomb;"
|
||||
"::wcschr;"
|
||||
"::wcsftime;"
|
||||
"::wcspbrk;"
|
||||
"::wcsrchr;"
|
||||
"::wcsrtombs;"
|
||||
"::wcsrtombs_s;"
|
||||
"::wcsstr;"
|
||||
"::wcstod;"
|
||||
"::wcstof;"
|
||||
"::wcstoimax;"
|
||||
"::wcstok;"
|
||||
"::wcstok_s;"
|
||||
"::wcstol;"
|
||||
"::wcstold;"
|
||||
"::wcstoll;"
|
||||
"::wcstombs;"
|
||||
"::wcstombs_s;"
|
||||
"::wcstoul;"
|
||||
"::wcstoull;"
|
||||
"::wcstoumax;"
|
||||
"::wcsxfrm;"
|
||||
"::wctob;"
|
||||
"::wctrans;"
|
||||
"::wctype;"
|
||||
"::wmemchr;"
|
||||
"::wprintf_s;"
|
||||
"::wscanf;"
|
||||
"::wscanf_s;";
|
||||
|
||||
} // namespace
|
||||
|
||||
namespace clang {
|
||||
namespace tidy {
|
||||
namespace cert {
|
||||
|
@ -99,6 +287,10 @@ public:
|
|||
"cert-dcl37-c");
|
||||
// ENV
|
||||
CheckFactories.registerCheck<CommandProcessorCheck>("cert-env33-c");
|
||||
// ERR
|
||||
CheckFactories.registerCheck<bugprone::UnusedReturnValueCheck>(
|
||||
"cert-err33-c");
|
||||
CheckFactories.registerCheck<StrToNumCheck>("cert-err34-c");
|
||||
// EXP
|
||||
CheckFactories.registerCheck<bugprone::SuspiciousMemoryComparisonCheck>(
|
||||
"cert-exp42-c");
|
||||
|
@ -108,8 +300,6 @@ public:
|
|||
"cert-flp37-c");
|
||||
// FIO
|
||||
CheckFactories.registerCheck<misc::NonCopyableObjectsCheck>("cert-fio38-c");
|
||||
// ERR
|
||||
CheckFactories.registerCheck<StrToNumCheck>("cert-err34-c");
|
||||
// MSC
|
||||
CheckFactories.registerCheck<LimitedRandomnessCheck>("cert-msc30-c");
|
||||
CheckFactories.registerCheck<ProperlySeededRandomGeneratorCheck>(
|
||||
|
@ -131,6 +321,7 @@ public:
|
|||
ClangTidyOptions Options;
|
||||
ClangTidyOptions::OptionMap &Opts = Options.CheckOptions;
|
||||
Opts["cert-dcl16-c.NewSuffixes"] = "L;LL;LU;LLU";
|
||||
Opts["cert-err33-c.CheckedFunctions"] = CertErr33CCheckedFunctions;
|
||||
Opts["cert-oop54-cpp.WarnOnlyIfThisHasSuspiciousField"] = "false";
|
||||
Opts["cert-str34-c.DiagnoseSignedUnsignedCharComparisons"] = "false";
|
||||
return Options;
|
||||
|
|
|
@ -103,6 +103,11 @@ New checks
|
|||
New check aliases
|
||||
^^^^^^^^^^^^^^^^^
|
||||
|
||||
- New alias :doc:`cert-err33-c
|
||||
<clang-tidy/checks/cert-err33-c>` to
|
||||
:doc:`bugprone-unused-return-value
|
||||
<clang-tidy/checks/bugprone-unused-return-value>` was added.
|
||||
|
||||
- New alias :doc:`cert-exp42-c
|
||||
<clang-tidy/checks/cert-exp42-c>` to
|
||||
:doc:`bugprone-suspicious-memory-comparison
|
||||
|
|
|
@ -45,3 +45,6 @@ Options
|
|||
- ``std::basic_string::empty()`` and ``std::vector::empty()``. Not using the
|
||||
return value often indicates that the programmer confused the function with
|
||||
``clear()``.
|
||||
|
||||
`cert-err33-c <cert-err33-c.html>`_ is an alias of this check that checks a
|
||||
fixed and large set of standard library functions.
|
||||
|
|
199
clang-tools-extra/docs/clang-tidy/checks/cert-err33-c.rst
Normal file
199
clang-tools-extra/docs/clang-tidy/checks/cert-err33-c.rst
Normal file
|
@ -0,0 +1,199 @@
|
|||
.. title:: clang-tidy - cert-err33-c
|
||||
|
||||
cert-err33-c
|
||||
============
|
||||
|
||||
Warns on unused function return values. Many of the standard library functions
|
||||
return a value that indicates if the call was successful. Ignoring the returned
|
||||
value can cause unexpected behavior if an error has occured. The following
|
||||
functions are checked:
|
||||
|
||||
* aligned_alloc()
|
||||
* asctime_s()
|
||||
* at_quick_exit()
|
||||
* atexit()
|
||||
* bsearch()
|
||||
* bsearch_s()
|
||||
* btowc()
|
||||
* c16rtomb()
|
||||
* c32rtomb()
|
||||
* calloc()
|
||||
* clock()
|
||||
* cnd_broadcast()
|
||||
* cnd_init()
|
||||
* cnd_signal()
|
||||
* cnd_timedwait()
|
||||
* cnd_wait()
|
||||
* ctime_s()
|
||||
* fclose()
|
||||
* fflush()
|
||||
* fgetc()
|
||||
* fgetpos()
|
||||
* fgets()
|
||||
* fgetwc()
|
||||
* fopen()
|
||||
* fopen_s()
|
||||
* fprintf()
|
||||
* fprintf_s()
|
||||
* fputc()
|
||||
* fputs()
|
||||
* fputwc()
|
||||
* fputws()
|
||||
* fread()
|
||||
* freopen()
|
||||
* freopen_s()
|
||||
* fscanf()
|
||||
* fscanf_s()
|
||||
* fseek()
|
||||
* fsetpos()
|
||||
* ftell()
|
||||
* fwprintf()
|
||||
* fwprintf_s()
|
||||
* fwrite()
|
||||
* fwscanf()
|
||||
* fwscanf_s()
|
||||
* getc()
|
||||
* getchar()
|
||||
* getenv()
|
||||
* getenv_s()
|
||||
* gets_s()
|
||||
* getwc()
|
||||
* getwchar()
|
||||
* gmtime()
|
||||
* gmtime_s()
|
||||
* localtime()
|
||||
* localtime_s()
|
||||
* malloc()
|
||||
* mbrtoc16()
|
||||
* mbrtoc32()
|
||||
* mbsrtowcs()
|
||||
* mbsrtowcs_s()
|
||||
* mbstowcs()
|
||||
* mbstowcs_s()
|
||||
* memchr()
|
||||
* mktime()
|
||||
* mtx_init()
|
||||
* mtx_lock()
|
||||
* mtx_timedlock()
|
||||
* mtx_trylock()
|
||||
* mtx_unlock()
|
||||
* printf_s()
|
||||
* putc()
|
||||
* putwc()
|
||||
* raise()
|
||||
* realloc()
|
||||
* remove()
|
||||
* rename()
|
||||
* setlocale()
|
||||
* setvbuf()
|
||||
* scanf()
|
||||
* scanf_s()
|
||||
* signal()
|
||||
* snprintf()
|
||||
* snprintf_s()
|
||||
* sprintf()
|
||||
* sprintf_s()
|
||||
* sscanf()
|
||||
* sscanf_s()
|
||||
* strchr()
|
||||
* strerror_s()
|
||||
* strftime()
|
||||
* strpbrk()
|
||||
* strrchr()
|
||||
* strstr()
|
||||
* strtod()
|
||||
* strtof()
|
||||
* strtoimax()
|
||||
* strtok()
|
||||
* strtok_s()
|
||||
* strtol()
|
||||
* strtold()
|
||||
* strtoll()
|
||||
* strtoumax()
|
||||
* strtoul()
|
||||
* strtoull()
|
||||
* strxfrm()
|
||||
* swprintf()
|
||||
* swprintf_s()
|
||||
* swscanf()
|
||||
* swscanf_s()
|
||||
* thrd_create()
|
||||
* thrd_detach()
|
||||
* thrd_join()
|
||||
* thrd_sleep()
|
||||
* time()
|
||||
* timespec_get()
|
||||
* tmpfile()
|
||||
* tmpfile_s()
|
||||
* tmpnam()
|
||||
* tmpnam_s()
|
||||
* tss_create()
|
||||
* tss_get()
|
||||
* tss_set()
|
||||
* ungetc()
|
||||
* ungetwc()
|
||||
* vfprintf()
|
||||
* vfprintf_s()
|
||||
* vfscanf()
|
||||
* vfscanf_s()
|
||||
* vfwprintf()
|
||||
* vfwprintf_s()
|
||||
* vfwscanf()
|
||||
* vfwscanf_s()
|
||||
* vprintf_s()
|
||||
* vscanf()
|
||||
* vscanf_s()
|
||||
* vsnprintf()
|
||||
* vsnprintf_s()
|
||||
* vsprintf()
|
||||
* vsprintf_s()
|
||||
* vsscanf()
|
||||
* vsscanf_s()
|
||||
* vswprintf()
|
||||
* vswprintf_s()
|
||||
* vswscanf()
|
||||
* vswscanf_s()
|
||||
* vwprintf_s()
|
||||
* vwscanf()
|
||||
* vwscanf_s()
|
||||
* wcrtomb()
|
||||
* wcschr()
|
||||
* wcsftime()
|
||||
* wcspbrk()
|
||||
* wcsrchr()
|
||||
* wcsrtombs()
|
||||
* wcsrtombs_s()
|
||||
* wcsstr()
|
||||
* wcstod()
|
||||
* wcstof()
|
||||
* wcstoimax()
|
||||
* wcstok()
|
||||
* wcstok_s()
|
||||
* wcstol()
|
||||
* wcstold()
|
||||
* wcstoll()
|
||||
* wcstombs()
|
||||
* wcstombs_s()
|
||||
* wcstoumax()
|
||||
* wcstoul()
|
||||
* wcstoull()
|
||||
* wcsxfrm()
|
||||
* wctob()
|
||||
* wctrans()
|
||||
* wctype()
|
||||
* wmemchr()
|
||||
* wprintf_s()
|
||||
* wscanf()
|
||||
* wscanf_s()
|
||||
|
||||
This check is an alias of check `bugprone-unused-return-value <bugprone-unused-return-value.html>`_
|
||||
with a fixed set of functions.
|
||||
|
||||
The check corresponds to a part of CERT C Coding Standard rule `ERR33-C.
|
||||
Detect and handle standard library errors
|
||||
<https://wiki.sei.cmu.edu/confluence/display/c/ERR33-C.+Detect+and+handle+standard+library+errors>`_.
|
||||
The list of checked functions is taken from the rule, with following exception:
|
||||
|
||||
* The check can not differentiate if a function is called with ``NULL``
|
||||
argument. Therefore the following functions are not checked:
|
||||
``mblen``, ``mbrlen``, ``mbrtowc``, ``mbtowc``, ``wctomb``, ``wctomb_s``
|
|
@ -333,6 +333,7 @@ Clang-Tidy Checks
|
|||
`cert-dcl03-c <cert-dcl03-c.html>`_, `misc-static-assert <misc-static-assert.html>`_, "Yes"
|
||||
`cert-dcl16-c <cert-dcl16-c.html>`_, `readability-uppercase-literal-suffix <readability-uppercase-literal-suffix.html>`_, "Yes"
|
||||
`cert-dcl37-c <cert-dcl37-c.html>`_, `bugprone-reserved-identifier <bugprone-reserved-identifier.html>`_, "Yes"
|
||||
`cert-err33-c <cert-err33-c.html>`_, `bugprone-unused-return-value <bugprone-unused-return-value.html>`_,
|
||||
`cert-dcl51-cpp <cert-dcl51-cpp.html>`_, `bugprone-reserved-identifier <bugprone-reserved-identifier.html>`_, "Yes"
|
||||
`cert-dcl54-cpp <cert-dcl54-cpp.html>`_, `misc-new-delete-overloads <misc-new-delete-overloads.html>`_,
|
||||
`cert-dcl59-cpp <cert-dcl59-cpp.html>`_, `google-build-namespaces <google-build-namespaces.html>`_,
|
||||
|
|
25
clang-tools-extra/test/clang-tidy/checkers/cert-err33-c.c
Normal file
25
clang-tools-extra/test/clang-tidy/checkers/cert-err33-c.c
Normal file
|
@ -0,0 +1,25 @@
|
|||
// RUN: %check_clang_tidy %s cert-err33-c %t
|
||||
|
||||
typedef __SIZE_TYPE__ size_t;
|
||||
void *aligned_alloc(size_t alignment, size_t size);
|
||||
void test_aligned_alloc() {
|
||||
aligned_alloc(2, 10);
|
||||
// CHECK-NOTES: [[@LINE-1]]:3: warning: the value returned by this function should be used
|
||||
// CHECK-NOTES: [[@LINE-2]]:3: note: cast the expression to void to silence this warning
|
||||
}
|
||||
|
||||
long strtol(const char *restrict nptr, char **restrict endptr, int base);
|
||||
void test_strtol() {
|
||||
strtol("123", 0, 10);
|
||||
// CHECK-NOTES: [[@LINE-1]]:3: warning: the value returned by this function should be used
|
||||
// CHECK-NOTES: [[@LINE-2]]:3: note: cast the expression to void to silence this warning
|
||||
}
|
||||
|
||||
typedef char wchar_t;
|
||||
int wscanf_s(const wchar_t *restrict format, ...);
|
||||
void test_wscanf_s() {
|
||||
int Val;
|
||||
wscanf_s("%i", &Val);
|
||||
// CHECK-NOTES: [[@LINE-1]]:3: warning: the value returned by this function should be used
|
||||
// CHECK-NOTES: [[@LINE-2]]:3: note: cast the expression to void to silence this warning
|
||||
}
|
Loading…
Reference in a new issue