void StringLiteralWithEmbeddedNulCheck::registerMatchers(MatchFinder *Finder) {
  // Match a string that contains embedded NUL character. Extra-checks are
  // applied in |check| to find incorectly escaped characters.
  Finder->addMatcher(stringLiteral(containsNul()).bind("strlit"), this);

  // The remaining checks only apply to C++.
  if (!getLangOpts().CPlusPlus)
    return;

  const auto StrLitWithNul =
      ignoringParenImpCasts(stringLiteral(containsNul()).bind("truncated"));

  // Match string constructor.
  const auto StringConstructorExpr = expr(anyOf(
      cxxConstructExpr(argumentCountIs(1),
                       hasDeclaration(cxxMethodDecl(hasName("basic_string")))),
      // If present, the second argument is the alloc object which must not
      // be present explicitly.
      cxxConstructExpr(argumentCountIs(2),
                       hasDeclaration(cxxMethodDecl(hasName("basic_string"))),
                       hasArgument(1, cxxDefaultArgExpr()))));

  // Detect passing a suspicious string literal to a string constructor.
  // example: std::string str = "abc\0def";
  Finder->addMatcher(
      cxxConstructExpr(StringConstructorExpr, hasArgument(0, StrLitWithNul)),
      this);

  // Detect passing a suspicious string literal through an overloaded operator.
  Finder->addMatcher(cxxOperatorCallExpr(hasAnyArgument(StrLitWithNul)), this);
}
void StrCatAppendCheck::registerMatchers(MatchFinder *Finder) {
  if (!getLangOpts().CPlusPlus)
  	return;
  const auto StrCat = functionDecl(hasName("::absl::StrCat"));
  // The arguments of absl::StrCat are implicitly converted to AlphaNum. This 
  // matches to the arguments because of that behavior. 
  const auto AlphaNum = IgnoringTemporaries(cxxConstructExpr(
      argumentCountIs(1), hasType(cxxRecordDecl(hasName("::absl::AlphaNum"))),
      hasArgument(0, ignoringImpCasts(declRefExpr(to(equalsBoundNode("LHS")),
                                                  expr().bind("Arg0"))))));

  const auto HasAnotherReferenceToLhs =
      callExpr(hasAnyArgument(expr(hasDescendant(declRefExpr(
          to(equalsBoundNode("LHS")), unless(equalsBoundNode("Arg0")))))));

  // Now look for calls to operator= with an object on the LHS and a call to
  // StrCat on the RHS. The first argument of the StrCat call should be the same
  // as the LHS. Ignore calls from template instantiations.
  Finder->addMatcher(
      cxxOperatorCallExpr(
          unless(isInTemplateInstantiation()), hasOverloadedOperatorName("="),
          hasArgument(0, declRefExpr(to(decl().bind("LHS")))),
          hasArgument(1, IgnoringTemporaries(
                             callExpr(callee(StrCat), hasArgument(0, AlphaNum),
                                      unless(HasAnotherReferenceToLhs))
                                 .bind("Call"))))
          .bind("Op"),
      this);
}
void InaccurateEraseCheck::registerMatchers(MatchFinder *Finder) {
  // Only register the matchers for C++; the functionality currently does not
  // provide any benefit to other languages, despite being benign.
  if (!getLangOpts().CPlusPlus)
    return;

  const auto EndCall =
      callExpr(
          callee(functionDecl(hasAnyName("remove", "remove_if", "unique"))),
          hasArgument(
              1,
              anyOf(cxxConstructExpr(has(ignoringImplicit(
                        cxxMemberCallExpr(callee(cxxMethodDecl(hasName("end"))))
                            .bind("end")))),
                    anything())))
          .bind("alg");

  const auto DeclInStd = type(hasUnqualifiedDesugaredType(
      tagType(hasDeclaration(decl(isInStdNamespace())))));
  Finder->addMatcher(
      cxxMemberCallExpr(
          on(anyOf(hasType(DeclInStd), hasType(pointsTo(DeclInStd)))),
          callee(cxxMethodDecl(hasName("erase"))), argumentCountIs(1),
          hasArgument(0, has(ignoringImplicit(
                             anyOf(EndCall, has(ignoringImplicit(EndCall)))))),
          unless(isInTemplateInstantiation()))
          .bind("erase"),
      this);
}
void InaccurateEraseCheck::registerMatchers(MatchFinder *Finder) {
  // Only register the matchers for C++; the functionality currently does not
  // provide any benefit to other languages, despite being benign.
  if (!getLangOpts().CPlusPlus)
    return;

  const auto CheckForEndCall = hasArgument(
      1, anyOf(cxxConstructExpr(has(ignoringParenImpCasts(
                   cxxMemberCallExpr(callee(cxxMethodDecl(hasName("end"))))
                       .bind("InaccEndCall")))),
               anything()));

  Finder->addMatcher(
      cxxMemberCallExpr(
          on(hasType(namedDecl(matchesName("^::std::")))),
          callee(cxxMethodDecl(hasName("erase"))), argumentCountIs(1),
          hasArgument(0, has(ignoringParenImpCasts(
                             callExpr(callee(functionDecl(matchesName(
                                          "^::std::(remove(_if)?|unique)$"))),
                                      CheckForEndCall)
                                 .bind("InaccAlgCall")))),
          unless(isInTemplateInstantiation()))
          .bind("InaccErase"),
      this);
}
void MakeSmartPtrCheck::registerMatchers(ast_matchers::MatchFinder *Finder) {
  if (!isLanguageVersionSupported(getLangOpts()))
    return;

  // Calling make_smart_ptr from within a member function of a type with a
  // private or protected constructor would be ill-formed.
  auto CanCallCtor = unless(has(ignoringImpCasts(
      cxxConstructExpr(hasDeclaration(decl(unless(isPublic())))))));

  Finder->addMatcher(
      cxxBindTemporaryExpr(has(ignoringParenImpCasts(
          cxxConstructExpr(
              hasType(getSmartPointerTypeMatcher()), argumentCountIs(1),
              hasArgument(0,
                          cxxNewExpr(hasType(pointsTo(qualType(hasCanonicalType(
                                         equalsBoundNode(PointerType))))),
                                     CanCallCtor)
                              .bind(NewExpression)),
              unless(isInTemplateInstantiation()))
              .bind(ConstructorCall)))),
      this);

  Finder->addMatcher(
      cxxMemberCallExpr(
          thisPointerType(getSmartPointerTypeMatcher()),
          callee(cxxMethodDecl(hasName("reset"))),
          hasArgument(0, cxxNewExpr(CanCallCtor).bind(NewExpression)),
          unless(isInTemplateInstantiation()))
          .bind(ResetCall),
      this);
}
/// \brief Creates a matcher that finds the \c std::auto_ptr copy-ctor and
/// assign-operator expressions.
///
/// \c AutoPtrOwnershipTransferId is assigned to the argument of the expression,
/// this is the part that has to be wrapped by \c std::move().
///
/// \code
///   std::auto_ptr<int> i, j;
///   i = j;
///   ~~~~^
/// \endcode
StatementMatcher makeTransferOwnershipExprMatcher() {
  return anyOf(
      cxxOperatorCallExpr(allOf(hasOverloadedOperatorName("="),
                                callee(cxxMethodDecl(ofClass(AutoPtrDecl))),
                                hasArgument(1, MovableArgumentMatcher))),
      cxxConstructExpr(allOf(hasType(AutoPtrType), argumentCountIs(1),
                             hasArgument(0, MovableArgumentMatcher))));
}
void ShrinkToFitCheck::registerMatchers(MatchFinder *Finder) {
  // Swap as a function need not to be considered, because rvalue can not
  // be bound to a non-const reference.
  const auto ShrinkableAsMember =
      memberExpr(member(valueDecl().bind("ContainerDecl")));
  const auto ShrinkableAsDecl =
      declRefExpr(hasDeclaration(valueDecl().bind("ContainerDecl")));
  const auto CopyCtorCall = constructExpr(
      hasArgument(0, anyOf(ShrinkableAsMember, ShrinkableAsDecl,
                           unaryOperator(has(ShrinkableAsMember)),
                           unaryOperator(has(ShrinkableAsDecl)))));
  const auto SwapParam = expr(anyOf(
      memberExpr(member(equalsBoundNode("ContainerDecl"))),
      declRefExpr(hasDeclaration(equalsBoundNode("ContainerDecl"))),
      unaryOperator(has(memberExpr(member(equalsBoundNode("ContainerDecl"))))),
      unaryOperator(
          has(declRefExpr(hasDeclaration(equalsBoundNode("ContainerDecl")))))));

  Finder->addMatcher(
      memberCallExpr(on(hasType(namedDecl(stlShrinkableContainer()))),
                     callee(methodDecl(hasName("swap"))),
                     has(memberExpr(hasDescendant(CopyCtorCall))),
                     hasArgument(0, SwapParam.bind("ContainerToShrink")),
                     unless(isInTemplateInstantiation()))
          .bind("CopyAndSwapTrick"),
      this);
}
void InefficientAlgorithmCheck::registerMatchers(MatchFinder *Finder) {
  // Only register the matchers for C++; the functionality currently does not
  // provide any benefit to other languages, despite being benign.
  if (!getLangOpts().CPlusPlus)
    return;

  const std::string Algorithms =
      "^::std::(find|count|equal_range|lower_bound|upper_bound)$";
  const auto ContainerMatcher = classTemplateSpecializationDecl(
      matchesName("^::std::(unordered_)?(multi)?(set|map)$"));
  const auto Matcher =
      callExpr(
          callee(functionDecl(matchesName(Algorithms))),
          hasArgument(
              0, constructExpr(has(memberCallExpr(
                     callee(methodDecl(hasName("begin"))),
                     on(declRefExpr(
                            hasDeclaration(decl().bind("IneffContObj")),
                            anyOf(hasType(ContainerMatcher.bind("IneffCont")),
                                  hasType(pointsTo(
                                      ContainerMatcher.bind("IneffContPtr")))))
                            .bind("IneffContExpr")))))),
          hasArgument(1, constructExpr(has(memberCallExpr(
                             callee(methodDecl(hasName("end"))),
                             on(declRefExpr(hasDeclaration(
                                 equalsBoundNode("IneffContObj")))))))),
          hasArgument(2, expr().bind("AlgParam")),
          unless(isInTemplateInstantiation()))
          .bind("IneffAlg");

  Finder->addMatcher(Matcher, this);
}
void MisplacedOperatorInStrlenInAllocCheck::registerMatchers(
    MatchFinder *Finder) {
  const auto StrLenFunc = functionDecl(anyOf(
      hasName("::strlen"), hasName("::std::strlen"), hasName("::strnlen"),
      hasName("::std::strnlen"), hasName("::strnlen_s"),
      hasName("::std::strnlen_s"), hasName("::wcslen"),
      hasName("::std::wcslen"), hasName("::wcsnlen"), hasName("::std::wcsnlen"),
      hasName("::wcsnlen_s"), hasName("std::wcsnlen_s")));

  const auto BadUse =
      callExpr(callee(StrLenFunc),
               hasAnyArgument(ignoringImpCasts(
                   binaryOperator(
                       hasOperatorName("+"),
                       hasRHS(ignoringParenImpCasts(integerLiteral(equals(1)))))
                       .bind("BinOp"))))
          .bind("StrLen");

  const auto BadArg = anyOf(
      allOf(unless(binaryOperator(
                hasOperatorName("+"), hasLHS(BadUse),
                hasRHS(ignoringParenImpCasts(integerLiteral(equals(1)))))),
            hasDescendant(BadUse)),
      BadUse);

  const auto Alloc0Func =
      functionDecl(anyOf(hasName("::malloc"), hasName("std::malloc"),
                         hasName("::alloca"), hasName("std::alloca")));
  const auto Alloc1Func =
      functionDecl(anyOf(hasName("::calloc"), hasName("std::calloc"),
                         hasName("::realloc"), hasName("std::realloc")));

  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);
}
void ReplaceAutoPtrCheck::registerMatchers(MatchFinder *Finder) {
  // Only register the matchers for C++; the functionality currently does not
  // provide any benefit to other languages, despite being benign.
  if (!getLangOpts().CPlusPlus)
    return;

  auto AutoPtrDecl = recordDecl(hasName("auto_ptr"), isFromStdNamespace());
  auto AutoPtrType = qualType(hasDeclaration(AutoPtrDecl));

  //   std::auto_ptr<int> a;
  //        ^~~~~~~~~~~~~
  //
  //   typedef std::auto_ptr<int> int_ptr_t;
  //                ^~~~~~~~~~~~~
  //
  //   std::auto_ptr<int> fn(std::auto_ptr<int>);
  //        ^~~~~~~~~~~~~         ^~~~~~~~~~~~~
  Finder->addMatcher(typeLoc(loc(qualType(AutoPtrType,
                                          // Skip elaboratedType() as the named
                                          // type will match soon thereafter.
                                          unless(elaboratedType()))))
                         .bind(AutoPtrTokenId),
                     this);

  //   using std::auto_ptr;
  //   ^~~~~~~~~~~~~~~~~~~
  Finder->addMatcher(usingDecl(hasAnyUsingShadowDecl(hasTargetDecl(allOf(
                                   hasName("auto_ptr"), isFromStdNamespace()))))
                         .bind(AutoPtrTokenId),
                     this);

  // Find ownership transfers via copy construction and assignment.
  // AutoPtrOwnershipTransferId is bound to the the part that has to be wrapped
  // into std::move().
  //   std::auto_ptr<int> i, j;
  //   i = j;
  //   ~~~~^
  auto MovableArgumentMatcher =
      expr(isLValue(), hasType(AutoPtrType)).bind(AutoPtrOwnershipTransferId);

  Finder->addMatcher(
      cxxOperatorCallExpr(hasOverloadedOperatorName("="),
                          callee(cxxMethodDecl(ofClass(AutoPtrDecl))),
                          hasArgument(1, MovableArgumentMatcher)),
      this);
  Finder->addMatcher(cxxConstructExpr(hasType(AutoPtrType), argumentCountIs(1),
                                      hasArgument(0, MovableArgumentMatcher)),
                     this);
}
void SlicingCheck::registerMatchers(MatchFinder *Finder) {
  // When we see:
  //   class B : public A { ... };
  //   A a;
  //   B b;
  //   a = b;
  // The assignment is OK if:
  //   - the assignment operator is defined as taking a B as second parameter,
  //   or
  //   - B does not define any additional members (either variables or
  //   overrides) wrt A.
  //
  // The same holds for copy ctor calls. This also captures stuff like:
  //   void f(A a);
  //   f(b);

  //  Helpers.
  const auto OfBaseClass = ofClass(cxxRecordDecl().bind("BaseDecl"));
  const auto IsDerivedFromBaseDecl =
      cxxRecordDecl(isDerivedFrom(equalsBoundNode("BaseDecl")))
          .bind("DerivedDecl");
  const auto HasTypeDerivedFromBaseDecl =
      anyOf(hasType(IsDerivedFromBaseDecl),
            hasType(references(IsDerivedFromBaseDecl)));
  const auto IsWithinDerivedCtor =
      hasParent(cxxConstructorDecl(ofClass(equalsBoundNode("DerivedDecl"))));

  // Assignement slicing: "a = b;" and "a = std::move(b);" variants.
  const auto SlicesObjectInAssignment =
      callExpr(callee(cxxMethodDecl(anyOf(isCopyAssignmentOperator(),
                                          isMoveAssignmentOperator()),
                                    OfBaseClass)),
               hasArgument(1, HasTypeDerivedFromBaseDecl));

  // Construction slicing: "A a{b};" and "f(b);" variants. Note that in case of
  // slicing the letter will create a temporary and therefore call a ctor.
  const auto SlicesObjectInCtor = cxxConstructExpr(
      hasDeclaration(cxxConstructorDecl(
          anyOf(isCopyConstructor(), isMoveConstructor()), OfBaseClass)),
      hasArgument(0, HasTypeDerivedFromBaseDecl),
      // We need to disable matching on the call to the base copy/move
      // constructor in DerivedDecl's constructors.
      unless(IsWithinDerivedCtor));

  Finder->addMatcher(
      expr(anyOf(SlicesObjectInAssignment, SlicesObjectInCtor)).bind("Call"),
      this);
}
void FasterStringFindCheck::registerMatchers(MatchFinder *Finder) {
  if (!getLangOpts().CPlusPlus)
    return;

  const auto SingleChar =
      expr(ignoringParenCasts(stringLiteral(hasSize(1)).bind("literal")));

  const auto StringFindFunctions =
      anyOf(hasName("find"), hasName("rfind"), hasName("find_first_of"),
            hasName("find_first_not_of"), hasName("find_last_of"),
            hasName("find_last_not_of"));

  llvm::Optional<ast_matchers::internal::Matcher<NamedDecl>> IsStringClass;

  for (const auto &ClassName : StringLikeClasses) {
    const auto HasName = hasName(ClassName);
    IsStringClass = IsStringClass ? anyOf(*IsStringClass, HasName) : HasName;
  }

  if (IsStringClass) {
    Finder->addMatcher(
        cxxMemberCallExpr(
            callee(functionDecl(StringFindFunctions).bind("func")),
            anyOf(argumentCountIs(1), argumentCountIs(2)),
            hasArgument(0, SingleChar),
            on(expr(hasType(recordDecl(*IsStringClass)),
                    unless(hasSubstitutedType())))),
        this);
  }
}
void ProBoundsConstantArrayIndexCheck::registerMatchers(MatchFinder *Finder) {
  if (!getLangOpts().CPlusPlus)
    return;

  Finder->addMatcher(arraySubscriptExpr(hasBase(ignoringImpCasts(hasType(
                                            constantArrayType().bind("type")))),
                                        hasIndex(expr().bind("index")))
                         .bind("expr"),
                     this);

  Finder->addMatcher(
      cxxOperatorCallExpr(
          hasOverloadedOperatorName("[]"),
          hasArgument(
              0, hasType(cxxRecordDecl(hasName("::std::array")).bind("type"))),
          hasArgument(1, expr().bind("index")))
          .bind("expr"),
      this);
}
void AvoidBindCheck::registerMatchers(MatchFinder *Finder) {
  if (!getLangOpts().CPlusPlus14) // Need C++14 for generic lambdas.
    return;

  Finder->addMatcher(
      callExpr(callee(namedDecl(hasName("::std::bind"))),
               hasArgument(0, declRefExpr(to(functionDecl().bind("f")))))
          .bind("bind"),
      this);
}
void DurationSubtractionCheck::registerMatchers(MatchFinder *Finder) {
  Finder->addMatcher(
      binaryOperator(
          hasOperatorName("-"),
          hasLHS(callExpr(callee(functionDecl(DurationConversionFunction())
                                     .bind("function_decl")),
                          hasArgument(0, expr().bind("lhs_arg")))))
          .bind("binop"),
      this);
}
Exemple #16
0
Variable Programme::getVariable(std::string var) const {
	if(hasArgument(var)) {
		return arguments[indexOfVar(arguments, var)];
	}
	else if(hasVariable(var)) {
		return variables[indexOfVar(variables, var)];
	}
	else {
		throw "Le programme \""+nom+"\" ne dispose d'aucune variable \""+var+"\".";
	}
}
Exemple #17
0
void Programme::setVariable(Variable& var) {
	if(hasArgument(var.getNom())) {
		arguments[indexOfVar(arguments, var.getNom())] = var;
	}
	else if(hasVariable(var.getNom())) {
		variables[indexOfVar(variables, var.getNom())] = var;
	}
	else {
		throw "La variable \""+var.getNom()+"\" n'existe pas dans le programme \""+nom+"\".";
	}
}
void InefficientStringConcatenationCheck::registerMatchers(
    MatchFinder *Finder) {
  if (!getLangOpts().CPlusPlus)
    return;

  const auto BasicStringType =
      hasType(qualType(hasUnqualifiedDesugaredType(recordType(
          hasDeclaration(cxxRecordDecl(hasName("::std::basic_string")))))));

  const auto BasicStringPlusOperator = cxxOperatorCallExpr(
      hasOverloadedOperatorName("+"),
      hasAnyArgument(ignoringImpCasts(declRefExpr(BasicStringType))));

  const auto PlusOperator =
      cxxOperatorCallExpr(
          hasOverloadedOperatorName("+"),
          hasAnyArgument(ignoringImpCasts(declRefExpr(BasicStringType))),
          hasDescendant(BasicStringPlusOperator))
          .bind("plusOperator");

  const auto AssignOperator = cxxOperatorCallExpr(
      hasOverloadedOperatorName("="),
      hasArgument(0, declRefExpr(BasicStringType,
                                 hasDeclaration(decl().bind("lhsStrT")))
                         .bind("lhsStr")),
      hasArgument(1, stmt(hasDescendant(declRefExpr(
                         hasDeclaration(decl(equalsBoundNode("lhsStrT"))))))),
      hasDescendant(BasicStringPlusOperator));

  if (StrictMode) {
    Finder->addMatcher(cxxOperatorCallExpr(anyOf(AssignOperator, PlusOperator)),
                       this);
  } else {
    Finder->addMatcher(
        cxxOperatorCallExpr(anyOf(AssignOperator, PlusOperator),
                            hasAncestor(stmt(anyOf(cxxForRangeStmt(),
                                                   whileStmt(), forStmt())))),
        this);
  }
}
void DurationConversionCastCheck::registerMatchers(MatchFinder *Finder) {
  auto CallMatcher = ignoringImpCasts(callExpr(
      callee(functionDecl(DurationConversionFunction()).bind("func_decl")),
      hasArgument(0, expr().bind("arg"))));

  Finder->addMatcher(
      expr(anyOf(
          cxxStaticCastExpr(hasSourceExpression(CallMatcher)).bind("cast_expr"),
          cStyleCastExpr(hasSourceExpression(CallMatcher)).bind("cast_expr"),
          cxxFunctionalCastExpr(hasSourceExpression(CallMatcher))
              .bind("cast_expr"))),
      this);
}
/// If `Node` is a call to the inverse of `Scale`, return that inverse's
/// argument, otherwise None.
static llvm::Optional<std::string>
rewriteInverseTimeCall(const MatchFinder::MatchResult &Result,
                       DurationScale Scale, const Expr &Node) {
  llvm::StringRef InverseFunction = getTimeInverseForScale(Scale);
  if (const auto *MaybeCallArg = selectFirst<const Expr>(
          "e", match(callExpr(callee(functionDecl(hasName(InverseFunction))),
                              hasArgument(0, expr().bind("e"))),
                     Node, *Result.Context))) {
    return tooling::fixit::getText(*MaybeCallArg, *Result.Context).str();
  }

  return llvm::None;
}
void UnconventionalAssignOperatorCheck::registerMatchers(
    ast_matchers::MatchFinder *Finder) {
  // Only register the matchers for C++; the functionality currently does not
  // provide any benefit to other languages, despite being benign.
  if (!getLangOpts().CPlusPlus)
    return;

  const auto HasGoodReturnType = cxxMethodDecl(returns(lValueReferenceType(
      pointee(unless(isConstQualified()),
              anyOf(autoType(), hasDeclaration(equalsBoundNode("class")))))));

  const auto IsSelf = qualType(
      anyOf(hasDeclaration(equalsBoundNode("class")),
            referenceType(pointee(hasDeclaration(equalsBoundNode("class"))))));
  const auto IsAssign =
      cxxMethodDecl(unless(anyOf(isDeleted(), isPrivate(), isImplicit())),
                    hasName("operator="), ofClass(recordDecl().bind("class")))
          .bind("method");
  const auto IsSelfAssign =
      cxxMethodDecl(IsAssign, hasParameter(0, parmVarDecl(hasType(IsSelf))))
          .bind("method");

  Finder->addMatcher(
      cxxMethodDecl(IsAssign, unless(HasGoodReturnType)).bind("ReturnType"),
      this);

  const auto BadSelf = referenceType(
      anyOf(lValueReferenceType(pointee(unless(isConstQualified()))),
            rValueReferenceType(pointee(isConstQualified()))));

  Finder->addMatcher(
      cxxMethodDecl(IsSelfAssign,
                    hasParameter(0, parmVarDecl(hasType(BadSelf))))
          .bind("ArgumentType"),
      this);

  Finder->addMatcher(
      cxxMethodDecl(IsSelfAssign, anyOf(isConst(), isVirtual())).bind("cv"),
      this);

  const auto IsBadReturnStatement = returnStmt(unless(has(ignoringParenImpCasts(
      anyOf(unaryOperator(hasOperatorName("*"), hasUnaryOperand(cxxThisExpr())),
            cxxOperatorCallExpr(argumentCountIs(1),
                                callee(unresolvedLookupExpr()),
                                hasArgument(0, cxxThisExpr())))))));
  const auto IsGoodAssign = cxxMethodDecl(IsAssign, HasGoodReturnType);

  Finder->addMatcher(returnStmt(IsBadReturnStatement, forFunction(IsGoodAssign))
                         .bind("returnStmt"),
                     this);
}
void CommandProcessorCheck::registerMatchers(MatchFinder *Finder) {
  Finder->addMatcher(
      callExpr(
          callee(functionDecl(anyOf(hasName("::system"), hasName("::popen"),
                                    hasName("::_popen")))
                     .bind("func")),
          // Do not diagnose when the call expression passes a null pointer
          // constant to system(); that only checks for the presence of a
          // command processor, which is not a security risk by itself.
          unless(callExpr(callee(functionDecl(hasName("::system"))),
                          argumentCountIs(1),
                          hasArgument(0, nullPointerConstant()))))
          .bind("expr"),
      this);
}
void StringIntegerAssignmentCheck::registerMatchers(MatchFinder *Finder) {
  if (!getLangOpts().CPlusPlus)
    return;
  Finder->addMatcher(
      cxxOperatorCallExpr(
          anyOf(hasOverloadedOperatorName("="),
                hasOverloadedOperatorName("+=")),
          callee(cxxMethodDecl(ofClass(classTemplateSpecializationDecl(
              hasName("::std::basic_string"),
              hasTemplateArgument(0, refersToType(qualType().bind("type"))))))),
          hasArgument(1,
                      ignoringImpCasts(expr(hasType(isInteger()),
                                            unless(hasType(isAnyCharacter())))
                                           .bind("expr"))),
          unless(isInTemplateInstantiation())),
      this);
}
QString ScriptArguments::applyArguments(const QString & command) const {
	if(command.length() == 0) { return QString(); }
	
	static const QRegExp     argumentRegExp(QString("%1[^%1]+%1").arg(argChar));
	static const QRegExp argumentTrimRegExp(QString("^%1|%1$").arg(argChar));

	QString newCommand, tempCommand;

	tempCommand = applyConditionals(command);

	QStringList argumentParts = tempCommand.split(argumentRegExp, QString::KeepEmptyParts);
	
	
	QStringList arguments;
	int position = 0;
	while((position = argumentRegExp.indexIn(tempCommand, position)) != -1)  {
		arguments << argumentRegExp.cap(0).replace(argumentTrimRegExp, "");
		position += argumentRegExp.matchedLength();
	}

	bool argumentFirst = !(argumentParts.size() > 0 && tempCommand.startsWith(argumentParts[0]), Qt::CaseSensitive);

	int j = 0;
	for(int i=0;i<argumentParts.size();i++) {
		if(!argumentFirst) {
			newCommand.append(argumentParts[i]);
		}

		if(j < arguments.size()) {
			if(hasArgument(arguments[j])) {
				newCommand.append(getValue(arguments[j]));
			}
			else {
				newCommand.append(QString("%1%2%1").arg(argChar).arg(arguments[j]));
			}

			j++;
		}

		if(argumentFirst) {
			newCommand.append(argumentParts[i]);
		}
	}
	
	return newCommand;
}
void MoveConstructorInitCheck::registerMatchers(MatchFinder *Finder) {
  // Only register the matchers for C++11; the functionality currently does not
  // provide any benefit to other languages, despite being benign.
  if (!getLangOpts().CPlusPlus11)
    return;

  Finder->addMatcher(
      cxxConstructorDecl(
          unless(isImplicit()),
          allOf(isMoveConstructor(),
                hasAnyConstructorInitializer(
                    cxxCtorInitializer(
                        withInitializer(cxxConstructExpr(hasDeclaration(
                            cxxConstructorDecl(isCopyConstructor())
                                .bind("ctor")))))
                        .bind("move-init")))),
      this);

  auto NonConstValueMovableAndExpensiveToCopy =
      qualType(allOf(unless(pointerType()), unless(isConstQualified()),
                     hasDeclaration(cxxRecordDecl(hasMethod(cxxConstructorDecl(
                         isMoveConstructor(), unless(isDeleted()))))),
                     matchers::isExpensiveToCopy()));

  // This checker is also used to implement cert-oop11-cpp, but when using that
  // form of the checker, we do not want to diagnose movable parameters.
  if (!UseCERTSemantics) {
    Finder->addMatcher(
        cxxConstructorDecl(
            allOf(
                unless(isMoveConstructor()),
                hasAnyConstructorInitializer(withInitializer(cxxConstructExpr(
                    hasDeclaration(cxxConstructorDecl(isCopyConstructor())),
                    hasArgument(
                        0,
                        declRefExpr(
                            to(parmVarDecl(
                                   hasType(
                                       NonConstValueMovableAndExpensiveToCopy))
                                   .bind("movable-param")))
                            .bind("init-arg")))))))
            .bind("ctor-decl"),
        this);
  }
}
void FasterStringFindCheck::registerMatchers(MatchFinder *Finder) {
  if (!getLangOpts().CPlusPlus)
    return;

  const auto SingleChar =
      expr(ignoringParenCasts(stringLiteral(hasSize(1)).bind("literal")));
  const auto StringFindFunctions =
      hasAnyName("find", "rfind", "find_first_of", "find_first_not_of",
                 "find_last_of", "find_last_not_of");

  Finder->addMatcher(
      cxxMemberCallExpr(
          callee(functionDecl(StringFindFunctions).bind("func")),
          anyOf(argumentCountIs(1), argumentCountIs(2)),
          hasArgument(0, SingleChar),
          on(expr(
              hasType(hasUnqualifiedDesugaredType(recordType(hasDeclaration(
                  recordDecl(hasAnyName(SmallVector<StringRef, 4>(
                      StringLikeClasses.begin(), StringLikeClasses.end()))))))),
              unless(hasSubstitutedType())))),
      this);
}
Exemple #27
0
bool Programme::hasVariable(std::string var) const {
	return hasVar(variables, var) || hasArgument(var);
}
QString ScriptArguments::applyConditionalsHelper(const QString & command) const {
	if(command.length() == 0) { return command; }
	
	QString tempCommand;

	int depth = 0;
	int start = -1;
	int opt = -1;
	int end = -1;
	int last = 0;
	for(int i=0;i<command.length();i++) {
		if(command[i] == condOpenChar) {
			depth++;
			if(start < 0) {
				start = i;
			}
			else {
				if(opt < 0) {
					return command;
				}
			}
		}
		else if(command[i] == condOptionChar) {
			if(start >= 0 && opt < 0) {
				opt = i;
			}
		}
		else if(command[i] == condCloseChar) {
			depth--;
			if(depth == 0) {
				end = i;
			}
		}

		if(depth < 0) { return command; }

		if(start >= 0 && end >= 0) {
			if(start >= end || opt < 0) { return command; }

			QString variable = command.mid(start + 1, opt - start - 1);
			QString text = command.mid(opt + 1, end - opt - 1);
			QString leftover = command.mid(last, start - last);

			tempCommand.append(leftover);
			
			if(hasArgument(variable) && getValue(variable).length() > 0) {
				tempCommand.append(text);
			}

			last = end + 1;
			start = -1;
			opt = -1;
			end = -1;
		}
	}

	QString leftover = command.mid(last, command.length() - last);

	tempCommand.append(leftover);

	int brackets = 0;
	for(int i=0;i<tempCommand.length();i++) {
		if(tempCommand[i] == condOpenChar) {
			brackets++;
		}
		else if(tempCommand[i] == condCloseChar) {
			brackets++;
		}
	}

	if(brackets > 0) {
		return applyConditionalsHelper(tempCommand);
	}
	
	return tempCommand;
}
Exemple #29
0
bool Programme::isBeforeVar(std::string isbef, std::string var) const {
	int idBef = indexOfVar(variables, isbef);
	return hasArgument(isbef)
	 || ( idBef < indexOfVar(variables, var) && idBef >= 0 );
}
void UpgradeDurationConversionsCheck::registerMatchers(MatchFinder *Finder) {
  if (!getLangOpts().CPlusPlus)
    return;

  // For the arithmetic calls, we match only the uses of the templated operators
  // where the template parameter is not a built-in type. This means the
  // instantiation makes use of an available user defined conversion to
  // `int64_t`.
  //
  // The implementation of these templates will be updated to fail SFINAE for
  // non-integral types. We match them to suggest an explicit cast.

  // Match expressions like `a *= b` and `a /= b` where `a` has type
  // `absl::Duration` and `b` is not of a built-in type.
  Finder->addMatcher(
      cxxOperatorCallExpr(
          argumentCountIs(2),
          hasArgument(
              0, expr(hasType(cxxRecordDecl(hasName("::absl::Duration"))))),
          hasArgument(1, expr().bind("arg")),
          callee(functionDecl(
              hasParent(functionTemplateDecl()),
              unless(hasTemplateArgument(0, refersToType(builtinType()))),
              hasAnyName("operator*=", "operator/=")))),
      this);

  // Match expressions like `a.operator*=(b)` and `a.operator/=(b)` where `a`
  // has type `absl::Duration` and `b` is not of a built-in type.
  Finder->addMatcher(
      cxxMemberCallExpr(
          callee(cxxMethodDecl(
              ofClass(cxxRecordDecl(hasName("::absl::Duration"))),
              hasParent(functionTemplateDecl()),
              unless(hasTemplateArgument(0, refersToType(builtinType()))),
              hasAnyName("operator*=", "operator/="))),
          argumentCountIs(1), hasArgument(0, expr().bind("arg"))),
      this);

  // Match expressions like `a * b`, `a / b`, `operator*(a, b)`, and
  // `operator/(a, b)` where `a` has type `absl::Duration` and `b` is not of a
  // built-in type.
  Finder->addMatcher(
      callExpr(callee(functionDecl(
                   hasParent(functionTemplateDecl()),
                   unless(hasTemplateArgument(0, refersToType(builtinType()))),
                   hasAnyName("::absl::operator*", "::absl::operator/"))),
               argumentCountIs(2),
               hasArgument(0, expr(hasType(
                                  cxxRecordDecl(hasName("::absl::Duration"))))),
               hasArgument(1, expr().bind("arg"))),
      this);

  // Match expressions like `a * b` and `operator*(a, b)` where `a` is not of a
  // built-in type and `b` has type `absl::Duration`.
  Finder->addMatcher(
      callExpr(callee(functionDecl(
                   hasParent(functionTemplateDecl()),
                   unless(hasTemplateArgument(0, refersToType(builtinType()))),
                   hasName("::absl::operator*"))),
               argumentCountIs(2), hasArgument(0, expr().bind("arg")),
               hasArgument(1, expr(hasType(cxxRecordDecl(
                                  hasName("::absl::Duration")))))),
      this);

  // For the factory functions, we match only the non-templated overloads that
  // take an `int64_t` parameter. Within these calls, we care about implicit
  // casts through a user defined conversion to `int64_t`.
  //
  // The factory functions will be updated to be templated and SFINAE on whether
  // the template parameter is an integral type. This complements the already
  // existing templated overloads that only accept floating point types.

  // Match calls like:
  //   `absl::Nanoseconds(x)`
  //   `absl::Microseconds(x)`
  //   `absl::Milliseconds(x)`
  //   `absl::Seconds(x)`
  //   `absl::Minutes(x)`
  //   `absl::Hours(x)`
  // where `x` is not of a built-in type.
  Finder->addMatcher(
      implicitCastExpr(
          anyOf(hasCastKind(CK_UserDefinedConversion),
                has(implicitCastExpr(hasCastKind(CK_UserDefinedConversion)))),
          hasParent(callExpr(
              callee(functionDecl(DurationFactoryFunction(),
                  unless(hasParent(functionTemplateDecl())))),
              hasArgument(0, expr().bind("arg"))))),
      this);
}