[PATCH] D91000: [clang-tidy] CERT MSC24-C Obsolescent Functions check
Balázs Benics via Phabricator via cfe-commits
cfe-commits at lists.llvm.org
Mon Nov 9 05:37:39 PST 2020
steakhal added a comment.
Quoting the revision summary:
> This checker guards against using some vulnerable C functions which are mentioned in MSC24-C in obsolescent functions table.
Why don't we check the rest of the functions as well?
`asctime`, `atof`, `atoi`, `atol`, `atoll`, `ctime`, `fopen`, `freopen`, `rewind`, `setbuf`
Hm, I get that `cert-err34-c` will already diagnose the uses of `atof`, `atoi`, `atol`, `atoll`, but then why do we check `vfscanf`, `vscanf` then?
We should probably omit these, while documenting this.
On the other hand, I would recommend checking `asctime`, `ctime`, `fopen`, `freopen`, `rewind`, `setbuf` for the sake of completeness.
What do you think?
There is a mismatch between your code and docs too, regarding the function you check for.
In the code you match for `vsprintf`, `vsscanf`, `vswprintf`, `vswcanf`, `wcrtomb`, `wcscat`, but none of these are mentioned in the docs.
> The checker warns only if `STDC_LIB_EXT1` macro is defined and the value of `STDC_WANT_LIB_EXT1` macro is `1` in this case it suggests the corresponding functions from Annex K instead the vulnerable function.
I would suggest mentioning these macros and their **purpose** in the docs.
Eg. that the `STDC_WANT_LIB_EXT1` should be defined to `1` but the other is left to the implementation.
That being said, I would request more tests, demonstrating that this macro detection works accordingly.
This checker might be a bit noisy. Have you tried it on open-source projects?
If it is, we should probably note that in the docs as well.
In the tests, It is a good practice to demonstrate that the offered recommendation does not trigger yet another warning.
Don't forget to put a `no-warning` to highlight that.
================
Comment at: clang-tools-extra/clang-tidy/cert/ObsolescentFunctionsCheck.cpp:30
+ "::vfprintf", "::vfscanf", "vfwprintf", "vfwscanf", "vprintf", "::vscanf",
+ "::vsnprintf", "::vsprintf", "::vsscanf", "::vswprintf", "::vswcanf",
+ "::wcrtomb", "::wcscat", "::wcscpy", "::wcsncat", "::wcsncpy",
----------------
Hm, it must be a typo.
`vswcanf` -> `vswscanf`
By the same token, I miss these functions from this enumeration.
`vfwprintf`, `vfwscanf`, `vprintf`, `vwprintf`, `vwscanf`
However, they are present in the cert table you mentioned.
================
Comment at: clang-tools-extra/clang-tidy/cert/ObsolescentFunctionsCheck.cpp:33
+ "::wcsrtombs", "::wcstok", "::wcstombs", "::wctomb", "::wmemcpy",
+ "::wmemmove", "::wprintf", "::wscanf", "::strlen"));
+ Finder->addMatcher(
----------------
Why is `strlen` an //obsolescent// function? I don't feel it justified, even if there was a [[ https://wiki.sei.cmu.edu/confluence/display/c/MSC24-C.+Do+not+use+deprecated+or+obsolescent+functions?focusedCommentId=88019519#comment-88019519 | comment ]] about it on the cert page.
================
Comment at: clang-tools-extra/clang-tidy/cert/ObsolescentFunctionsCheck.cpp:69
+ AreSafeFunctionsWanted = IntValue.getZExtValue();
+ if (AreSafeFunctionsWanted.hasValue()) {
+ AnnexKIsWanted = AreSafeFunctionsWanted.getValue();
----------------
Eugene.Zelenko wrote:
> Please elide braces.
Please also check if the value is `1`, as your summary and the standard requires.
================
Comment at: clang-tools-extra/clang-tidy/cert/ObsolescentFunctionsCheck.cpp:77-79
+ std::pair<bool, bool> AnnexKUsage = UsingAnnexK();
+ bool AnnexKIsAvailable = std::get<0>(AnnexKUsage);
+ bool AnnexKIsWanted = std::get<1>(AnnexKUsage);
----------------
================
Comment at: clang-tools-extra/clang-tidy/cert/ObsolescentFunctionsCheck.cpp:87-89
+ diag(Function->getExprLoc(), "Unsafe function " + FunctionName + " used. " +
+ "Safe " + FunctionName +
+ "_s can be used instead.");
----------------
We should probably use `llvm::Twine` instead of multiple `std::string` constructions.
I might be wrong though.
================
Comment at: clang-tools-extra/clang-tidy/cert/ObsolescentFunctionsCheck.cpp:89
+ "Safe " + FunctionName +
+ "_s can be used instead.");
+ }
----------------
`can` -> `should`
The same at the other diagnostic message.
================
Comment at: clang-tools-extra/clang-tidy/cert/ObsolescentFunctionsCheck.cpp:91
+ }
+ if (const auto *FunctionPointer = Result.Nodes.getNodeAs<VarDecl>("fp")) {
+ if (const FunctionDecl *FD = Result.Nodes.getNodeAs<FunctionDecl>("fnp")) {
----------------
This and the previous `if` statement is exclusive, am I right?
If we have a match, that is **either** a callexpr **or** a vardecl.
I would prefer a `return` at the end of the previous `if` and an assert here that the `FunctionPointer` must be non-null.
================
Comment at: clang-tools-extra/clang-tidy/cert/ObsolescentFunctionsCheck.h:27
+ void check(const ast_matchers::MatchFinder::MatchResult &Result) override;
+ const std::pair<bool, bool> UsingAnnexK();
+ void registerPPCallbacks(const SourceManager &SM, Preprocessor *PP,
----------------
It should be private.
================
Comment at: clang-tools-extra/docs/clang-tidy/checks/cert-obsolescent-functions.rst:10
+ strcat, strcpy, strerror, strncat, strncpy, strtok, swprintf, swscanf,
+ vfprintf, vfscanf, vfwprintf, vfwscanf, vprintf, vscanf vsnprintf, vspr,
+ wcscpy, wcsncat, wcsncpy wcsrtombs, wcstok, wcstombs, wctomb, wmemcpy,
----------------
Another typo.
================
Comment at: clang-tools-extra/docs/clang-tidy/checks/cert-obsolescent-functions.rst:19-23
+ #define __STDC_WANT_LIB_EXT1__ 1
+ int i = 2;
+ int j = 3;
+ memmove(&i, &j, sizeof(int)); // diagnosed if __STDC_LIB_EXT1__ is defined in a
+ // header, memmove_s usage is suggested instead.
----------------
I'm not convinced by this example.
AFAIK, the intended usage is to define the `__STDC_WANT_LIB_EXT1__` to `1` before the `string.h` header included.
It's important to provide a good example, as this checker will be silent if not used correctly.
================
Comment at: clang-tools-extra/docs/clang-tidy/checks/cert-obsolescent-functions.rst:23
+ memmove(&i, &j, sizeof(int)); // diagnosed if __STDC_LIB_EXT1__ is defined in a
+ // header, memmove_s usage is suggested instead.
----------------
We should probably align this comment as well.
Repository:
rG LLVM Github Monorepo
CHANGES SINCE LAST ACTION
https://reviews.llvm.org/D91000/new/
https://reviews.llvm.org/D91000
More information about the cfe-commits
mailing list