diff --git a/clang-tools-extra/clang-tidy/bugprone/MisplacedOperatorInStrlenInAllocCheck.cpp b/clang-tools-extra/clang-tidy/bugprone/MisplacedOperatorInStrlenInAllocCheck.cpp index 031663b224cd..f8db0b3ef945 100644 --- a/clang-tools-extra/clang-tidy/bugprone/MisplacedOperatorInStrlenInAllocCheck.cpp +++ b/clang-tools-extra/clang-tidy/bugprone/MisplacedOperatorInStrlenInAllocCheck.cpp @@ -49,10 +49,23 @@ void MisplacedOperatorInStrlenInAllocCheck::registerMatchers( functionDecl(anyOf(hasName("::calloc"), hasName("std::calloc"), hasName("::realloc"), hasName("std::realloc"))); - Finder->addMatcher( - callExpr(callee(Alloc0Func), hasArgument(0, BadArg)).bind("Alloc"), this); - Finder->addMatcher( - callExpr(callee(Alloc1Func), hasArgument(1, BadArg)).bind("Alloc"), this); + const auto Alloc0FuncPtr = + varDecl(hasType(isConstQualified()), + hasInitializer(ignoringParenImpCasts( + declRefExpr(hasDeclaration(Alloc0Func))))); + const auto Alloc1FuncPtr = + varDecl(hasType(isConstQualified()), + hasInitializer(ignoringParenImpCasts( + declRefExpr(hasDeclaration(Alloc1Func))))); + + Finder->addMatcher(callExpr(callee(decl(anyOf(Alloc0Func, Alloc0FuncPtr))), + hasArgument(0, BadArg)) + .bind("Alloc"), + this); + Finder->addMatcher(callExpr(callee(decl(anyOf(Alloc1Func, Alloc1FuncPtr))), + hasArgument(1, BadArg)) + .bind("Alloc"), + this); Finder->addMatcher( cxxNewExpr(isArray(), hasArraySize(BadArg)).bind("Alloc"), this); } diff --git a/clang-tools-extra/docs/clang-tidy/checks/bugprone-misplaced-operator-in-strlen-in-alloc.rst b/clang-tools-extra/docs/clang-tidy/checks/bugprone-misplaced-operator-in-strlen-in-alloc.rst index 463e3b88d482..e6ff2fe10c1c 100644 --- a/clang-tools-extra/docs/clang-tidy/checks/bugprone-misplaced-operator-in-strlen-in-alloc.rst +++ b/clang-tools-extra/docs/clang-tidy/checks/bugprone-misplaced-operator-in-strlen-in-alloc.rst @@ -7,9 +7,11 @@ Finds cases where ``1`` is added to the string in the argument to ``strlen()``, ``strnlen()``, ``strnlen_s()``, ``wcslen()``, ``wcsnlen()``, and ``wcsnlen_s()`` instead of the result and the value is used as an argument to a memory allocation function (``malloc()``, ``calloc()``, ``realloc()``, ``alloca()``) or -the ``new[]`` operator in `C++`. Cases where ``1`` is added both to the -parameter and the result of the ``strlen()``-like function are ignored, as are -cases where the whole addition is surrounded by extra parentheses. +the ``new[]`` operator in `C++`. The check detects error cases even if one of +these functions (except the ``new[]`` operator) is called by a constant function +pointer. Cases where ``1`` is added both to the parameter and the result of the +``strlen()``-like function are ignored, as are cases where the whole addition is +surrounded by extra parentheses. `C` example code: diff --git a/clang-tools-extra/test/clang-tidy/bugprone-misplaced-operator-in-strlen-in-alloc.c b/clang-tools-extra/test/clang-tidy/bugprone-misplaced-operator-in-strlen-in-alloc.c index b26bf244609a..c5deb25e9ac0 100644 --- a/clang-tools-extra/test/clang-tidy/bugprone-misplaced-operator-in-strlen-in-alloc.c +++ b/clang-tools-extra/test/clang-tidy/bugprone-misplaced-operator-in-strlen-in-alloc.c @@ -75,3 +75,11 @@ void intentional3(char *name) { // CHECK-MESSAGES-NOT: :[[@LINE-1]]:28: warning: addition operator is applied to the argument of strlen // If expression is in extra parentheses, consider it as intentional } + +void (*(*const alloc_ptr)(size_t)) = malloc; + +void bad_indirect_alloc(char *name) { + char *new_name = (char *)alloc_ptr(strlen(name + 1)); + // CHECK-MESSAGES: :[[@LINE-1]]:28: warning: addition operator is applied to the argument of strlen + // CHECK-FIXES: {{^ char \*new_name = \(char \*\)alloc_ptr\(}}strlen(name) + 1{{\);$}} +}