brintos

brintos / llvm-project-archived public Read only

0
0
Text · 3.9 KiB · 3e32e9b Raw
120 lines · cpp
1//===----------------------------------------------------------------------===//2//3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.4// See https://llvm.org/LICENSE.txt for license information.5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception6//7//===----------------------------------------------------------------------===//8 9#include "RandomGeneratorSeedCheck.h"10#include "clang/AST/ASTContext.h"11#include "clang/ASTMatchers/ASTMatchFinder.h"12#include "llvm/ADT/STLExtras.h"13 14using namespace clang::ast_matchers;15 16namespace clang::tidy::bugprone {17 18RandomGeneratorSeedCheck::RandomGeneratorSeedCheck(StringRef Name,19                                                   ClangTidyContext *Context)20    : ClangTidyCheck(Name, Context),21      RawDisallowedSeedTypes(22          Options.get("DisallowedSeedTypes", "time_t,std::time_t")) {23  RawDisallowedSeedTypes.split(DisallowedSeedTypes, ',');24}25 26void RandomGeneratorSeedCheck::storeOptions(ClangTidyOptions::OptionMap &Opts) {27  Options.store(Opts, "DisallowedSeedTypes", RawDisallowedSeedTypes);28}29 30void RandomGeneratorSeedCheck::registerMatchers(MatchFinder *Finder) {31  auto RandomGeneratorEngineDecl = cxxRecordDecl(hasAnyName(32      "::std::linear_congruential_engine", "::std::mersenne_twister_engine",33      "::std::subtract_with_carry_engine", "::std::discard_block_engine",34      "::std::independent_bits_engine", "::std::shuffle_order_engine"));35  auto RandomGeneratorEngineTypeMatcher = hasType(hasUnqualifiedDesugaredType(36      recordType(hasDeclaration(RandomGeneratorEngineDecl))));37 38  // std::mt19937 engine;39  // engine.seed();40  //        ^41  // engine.seed(1);42  //        ^43  // const int x = 1;44  // engine.seed(x);45  //        ^46  Finder->addMatcher(47      cxxMemberCallExpr(48          has(memberExpr(has(declRefExpr(RandomGeneratorEngineTypeMatcher)),49                         member(hasName("seed")),50                         unless(hasDescendant(cxxThisExpr())))))51          .bind("seed"),52      this);53 54  // std::mt19937 engine;55  //              ^56  // std::mt19937 engine(1);57  //              ^58  // const int x = 1;59  // std::mt19937 engine(x);60  //              ^61  Finder->addMatcher(62      traverse(TK_AsIs,63               cxxConstructExpr(RandomGeneratorEngineTypeMatcher).bind("ctor")),64      this);65 66  // srand();67  // ^68  // const int x = 1;69  // srand(x);70  // ^71  Finder->addMatcher(72      callExpr(callee(functionDecl(hasAnyName("::srand", "::std::srand"))))73          .bind("srand"),74      this);75}76 77void RandomGeneratorSeedCheck::check(const MatchFinder::MatchResult &Result) {78  const auto *Ctor = Result.Nodes.getNodeAs<CXXConstructExpr>("ctor");79  if (Ctor)80    checkSeed(Result, Ctor);81 82  const auto *Func = Result.Nodes.getNodeAs<CXXMemberCallExpr>("seed");83  if (Func)84    checkSeed(Result, Func);85 86  const auto *Srand = Result.Nodes.getNodeAs<CallExpr>("srand");87  if (Srand)88    checkSeed(Result, Srand);89}90 91template <class T>92void RandomGeneratorSeedCheck::checkSeed(const MatchFinder::MatchResult &Result,93                                         const T *Func) {94  if (Func->getNumArgs() == 0 || Func->getArg(0)->isDefaultArgument()) {95    diag(Func->getExprLoc(),96         "random number generator seeded with a default argument will generate "97         "a predictable sequence of values");98    return;99  }100 101  Expr::EvalResult EVResult;102  if (Func->getArg(0)->EvaluateAsInt(EVResult, *Result.Context)) {103    diag(Func->getExprLoc(),104         "random number generator seeded with a constant value will generate a "105         "predictable sequence of values");106    return;107  }108 109  const std::string SeedType(110      Func->getArg(0)->IgnoreCasts()->getType().getAsString());111  if (llvm::is_contained(DisallowedSeedTypes, SeedType)) {112    diag(Func->getExprLoc(),113         "random number generator seeded with a disallowed source of seed "114         "value will generate a predictable sequence of values");115    return;116  }117}118 119} // namespace clang::tidy::bugprone120