Index: clang-tidy/bugprone/MisplacedOperatorInStrlenInAllocCheck.cpp =================================================================== --- clang-tidy/bugprone/MisplacedOperatorInStrlenInAllocCheck.cpp +++ clang-tidy/bugprone/MisplacedOperatorInStrlenInAllocCheck.cpp @@ -48,26 +48,32 @@ const auto Alloc1Func = 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); + Finder->addMatcher( + cxxNewExpr(isArray(), hasArraySize(BadArg)).bind("Alloc"), this); } void MisplacedOperatorInStrlenInAllocCheck::check( const MatchFinder::MatchResult &Result) { - const auto *Alloc = Result.Nodes.getNodeAs("Alloc"); + const Expr *Alloc = Result.Nodes.getNodeAs("Alloc"); + if (!Alloc) + Alloc = Result.Nodes.getNodeAs("Alloc"); + assert(Alloc && "Matched node bound by 'Alloc' shoud be either 'CallExpr'" + " or 'CXXNewExpr'"); + const auto *StrLen = Result.Nodes.getNodeAs("StrLen"); const auto *BinOp = Result.Nodes.getNodeAs("BinOp"); const StringRef StrLenText = Lexer::getSourceText( CharSourceRange::getTokenRange(StrLen->getSourceRange()), *Result.SourceManager, getLangOpts()); - const StringRef StrLenBegin = StrLenText.substr(0, StrLenText.find('(') + 1); const StringRef Arg0Text = Lexer::getSourceText( CharSourceRange::getTokenRange(StrLen->getArg(0)->getSourceRange()), *Result.SourceManager, getLangOpts()); + const StringRef StrLenBegin = StrLenText.substr(0, StrLenText.find(Arg0Text)); const StringRef StrLenEnd = StrLenText.substr( StrLenText.find(Arg0Text) + Arg0Text.size(), StrLenText.size()); Index: docs/ReleaseNotes.rst =================================================================== --- docs/ReleaseNotes.rst +++ docs/ReleaseNotes.rst @@ -64,7 +64,7 @@ ``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()``). + ``alloca()``) or the ``new[]`` operator in `C++`. - Renamed checks to use correct term "implicit conversion" instead of "implicit cast" and modified messages and option names accordingly: Index: docs/clang-tidy/checks/bugprone-misplaced-operator-in-strlen-in-alloc.rst =================================================================== --- docs/clang-tidy/checks/bugprone-misplaced-operator-in-strlen-in-alloc.rst +++ docs/clang-tidy/checks/bugprone-misplaced-operator-in-strlen-in-alloc.rst @@ -6,12 +6,12 @@ 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()``). -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. +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. -Example code: +`C` example code: .. code-block:: c @@ -28,6 +28,24 @@ char *c = (char*) malloc(strlen(str) + 1); +`C++` example code: + +.. code-block:: c++ + + void bad_new(char *str) { + char *c = new char[strlen(str + 1)]; + } + + +As in the `C` code with the ``malloc()`` function, the suggested fix is to +add ``1`` to the return value of ``strlen()`` and not to its argument. In the +example above the fix would be + +.. code-block:: c++ + + char *c = new char[strlen(str) + 1]; + + Example for silencing the diagnostic: .. code-block:: c Index: test/clang-tidy/bugprone-misplaced-operator-in-strlen-in-alloc.cpp =================================================================== --- test/clang-tidy/bugprone-misplaced-operator-in-strlen-in-alloc.cpp +++ test/clang-tidy/bugprone-misplaced-operator-in-strlen-in-alloc.cpp @@ -31,3 +31,29 @@ // CHECK-MESSAGES-NOT: :[[@LINE-1]]:28: warning: addition operator is applied to the argument of strlen // Ignore functions of the strlen family in custom namespaces } + +void bad_new_strlen(char *name) { + char *new_name = new char[std::strlen(name + 1)]; + // CHECK-MESSAGES: :[[@LINE-1]]:20: warning: addition operator is applied to the argument of strlen + // CHECK-FIXES: {{^ char \*new_name = new char\[}}std::strlen(name) + 1{{\];$}} +} + +void good_new_strlen(char *name) { + char *new_name = new char[std::strlen(name) + 1]; + // CHECK-MESSAGES-NOT: :[[@LINE-1]]:20: warning: addition operator is applied to the argument of strlen +} + +class C { + char c; +public: + static void *operator new[](std::size_t count) { + return ::operator new(count); + } +}; + +void bad_custom_new_strlen(char *name) { + C *new_name = new C[std::strlen(name + 1)]; + // CHECK-MESSAGES: :[[@LINE-1]]:17: warning: addition operator is applied to the argument of strlen + // CHECK-FIXES: {{^ C \*new_name = new C\[}}std::strlen(name) + 1{{\];$}} +} +