void PointerAndIntegralOperationCheck::registerMatchers(MatchFinder *Finder) { const auto PointerExpr = expr(hasType(pointerType())); const auto BoolExpr = ignoringParenImpCasts(hasType(booleanType())); const auto CharExpr = ignoringParenImpCasts(hasType(isAnyCharacter())); const auto BinOpWithPointerExpr = binaryOperator(unless(anyOf(hasOperatorName(","), hasOperatorName("="))), hasEitherOperand(PointerExpr)); const auto AssignToPointerExpr = binaryOperator(hasOperatorName("="), hasLHS(PointerExpr)); const auto CompareToPointerExpr = binaryOperator(matchers::isRelationalOperator(), hasEitherOperand(PointerExpr)); // Detect expression like: ptr = (x != y); Finder->addMatcher(binaryOperator(AssignToPointerExpr, hasRHS(BoolExpr)) .bind("assign-bool-to-pointer"), this); // Detect expression like: ptr = A[i]; where A is char*. Finder->addMatcher(binaryOperator(AssignToPointerExpr, hasRHS(CharExpr)) .bind("assign-char-to-pointer"), this); // Detect expression like: ptr < false; Finder->addMatcher( binaryOperator(BinOpWithPointerExpr, hasEitherOperand(ignoringParenImpCasts(cxxBoolLiteral()))) .bind("pointer-and-bool-literal"), this); // Detect expression like: ptr < 'a'; Finder->addMatcher(binaryOperator(BinOpWithPointerExpr, hasEitherOperand(ignoringParenImpCasts( characterLiteral()))) .bind("pointer-and-char-literal"), this); // Detect expression like: ptr < 0; Finder->addMatcher(binaryOperator(CompareToPointerExpr, hasEitherOperand(ignoringParenImpCasts( integerLiteral(equals(0))))) .bind("compare-pointer-to-zero"), this); // Detect expression like: ptr < nullptr; Finder->addMatcher(binaryOperator(CompareToPointerExpr, hasEitherOperand(ignoringParenImpCasts( cxxNullPtrLiteralExpr()))) .bind("compare-pointer-to-null"), this); }
void SuspiciousStringCompareCheck::registerMatchers(MatchFinder *Finder) { // Match relational operators. const auto ComparisonUnaryOperator = unaryOperator(hasOperatorName("!")); const auto ComparisonBinaryOperator = binaryOperator(matchers::isComparisonOperator()); const auto ComparisonOperator = expr(anyOf(ComparisonUnaryOperator, ComparisonBinaryOperator)); // Add the list of known string compare-like functions and add user-defined // functions. std::vector<std::string> FunctionNames = utils::options::parseStringList( (llvm::Twine(KnownStringCompareFunctions) + StringCompareLikeFunctions) .str()); // Match a call to a string compare functions. const auto FunctionCompareDecl = functionDecl(hasAnyName(std::vector<StringRef>(FunctionNames.begin(), FunctionNames.end()))) .bind("decl"); const auto DirectStringCompareCallExpr = callExpr(hasDeclaration(FunctionCompareDecl)).bind("call"); const auto MacroStringCompareCallExpr = conditionalOperator(anyOf( hasTrueExpression(ignoringParenImpCasts(DirectStringCompareCallExpr)), hasFalseExpression(ignoringParenImpCasts(DirectStringCompareCallExpr)))); // The implicit cast is not present in C. const auto StringCompareCallExpr = ignoringParenImpCasts( anyOf(DirectStringCompareCallExpr, MacroStringCompareCallExpr)); if (WarnOnImplicitComparison) { // Detect suspicious calls to string compare: // 'if (strcmp())' -> 'if (strcmp() != 0)' Finder->addMatcher( stmt(anyOf(ifStmt(hasCondition(StringCompareCallExpr)), whileStmt(hasCondition(StringCompareCallExpr)), doStmt(hasCondition(StringCompareCallExpr)), forStmt(hasCondition(StringCompareCallExpr)), binaryOperator( anyOf(hasOperatorName("&&"), hasOperatorName("||")), hasEitherOperand(StringCompareCallExpr)))) .bind("missing-comparison"), this); } if (WarnOnLogicalNotComparison) { // Detect suspicious calls to string compared with '!' operator: // 'if (!strcmp())' -> 'if (strcmp() == 0)' Finder->addMatcher(unaryOperator(hasOperatorName("!"), hasUnaryOperand(ignoringParenImpCasts( StringCompareCallExpr))) .bind("logical-not-comparison"), this); } // Detect suspicious cast to an inconsistant type (i.e. not integer type). Finder->addMatcher( implicitCastExpr(unless(hasType(isInteger())), hasSourceExpression(StringCompareCallExpr)) .bind("invalid-conversion"), this); // Detect suspicious operator with string compare function as operand. Finder->addMatcher( binaryOperator( unless(anyOf(matchers::isComparisonOperator(), hasOperatorName("&&"), hasOperatorName("||"), hasOperatorName("="))), hasEitherOperand(StringCompareCallExpr)) .bind("suspicious-operator"), this); // Detect comparison to invalid constant: 'strcmp() == -1'. const auto InvalidLiteral = ignoringParenImpCasts( anyOf(integerLiteral(unless(equals(0))), unaryOperator( hasOperatorName("-"), has(ignoringParenImpCasts(integerLiteral(unless(equals(0)))))), characterLiteral(), cxxBoolLiteral())); Finder->addMatcher(binaryOperator(matchers::isComparisonOperator(), hasEitherOperand(StringCompareCallExpr), hasEitherOperand(InvalidLiteral)) .bind("invalid-comparison"), this); }