[clang] [-Wunsafe-buffer-usage] Warning Libc functions (PR #101583)
Ziqing Luo via cfe-commits
cfe-commits at lists.llvm.org
Wed Aug 28 13:34:10 PDT 2024
================
@@ -1025,6 +1421,92 @@ class DataInvocationGadget : public WarningGadget {
DeclUseList getClaimedVarUseSites() const override { return {}; }
};
+class UnsafeLibcFunctionCallGadget : public WarningGadget {
+ const CallExpr *const Call;
+ constexpr static const char *const Tag = "UnsafeLibcFunctionCall";
+ // Extra tags for additional information:
+ constexpr static const char *const UnsafeSprintfTag =
+ "UnsafeLibcFunctionCall_sprintf";
+ constexpr static const char *const UnsafeSizedByTag =
+ "UnsafeLibcFunctionCall_sized_by";
+ constexpr static const char *const UnsafeStringTag =
+ "UnsafeLibcFunctionCall_string";
+ constexpr static const char *const UnsafeVaListTag =
+ "UnsafeLibcFunctionCall_va_list";
+
+ enum UnsafeKind {
+ OTHERS = 0, // no specific information, the callee function is unsafe
+ SPRINTF = 1, // never call `-sprintf`s, call `-snprintf`s instead.
+ SIZED_BY = 2, // a pair of function arguments have "__sized_by" relation but
+ // they do not conform to safe patterns
+ STRING = 3, // an argument is a pointer-to-char-as-string but does not
+ // guarantee null-termination
+ VA_LIST = 4, // one of the `-printf`s function that take va_list, which is
+ // considered unsafe as it is not compile-time check
+ } WarnedFunKind = OTHERS;
+
+public:
+ UnsafeLibcFunctionCallGadget(const MatchFinder::MatchResult &Result)
+ : WarningGadget(Kind::UnsafeLibcFunctionCall),
+ Call(Result.Nodes.getNodeAs<CallExpr>(Tag)) {
+ if (Result.Nodes.getNodeAs<CallExpr>(UnsafeSprintfTag))
+ WarnedFunKind = SPRINTF;
+ else if (Result.Nodes.getNodeAs<CallExpr>(UnsafeStringTag))
+ WarnedFunKind = STRING;
+ else if (Result.Nodes.getNodeAs<CallExpr>(UnsafeSizedByTag))
+ WarnedFunKind = SIZED_BY;
+ else if (Result.Nodes.getNodeAs<CallExpr>(UnsafeVaListTag))
+ WarnedFunKind = VA_LIST;
+ }
+
+ static Matcher matcher() {
+ return stmt(
+ stmt(
+ anyOf(
+ // Match a call to a predefined unsafe libc function (unless the
+ // call has a sole string literal argument):
+ callExpr(callee(functionDecl(
+ libc_func_matchers::isPredefinedUnsafeLibcFunc())),
+ unless(allOf(hasArgument(0, expr(stringLiteral())),
+ hasNumArgs(1)))),
+ // Match a call to one of the `v*printf` functions taking
+ // va-list, which cannot be checked at compile-time:
+ callExpr(callee(functionDecl(
+ libc_func_matchers::isUnsafeVaListPrintfFunc())))
+ .bind(UnsafeVaListTag),
----------------
ziqingluo-90 wrote:
right, that's a good point!
https://github.com/llvm/llvm-project/pull/101583
More information about the cfe-commits
mailing list