brintos

brintos / llvm-project-archived public Read only

0
0
Text · 3.8 KiB · f50b5cd Raw
106 lines · cpp
1//=== StringChecker.cpp -------------------------------------------*- C++ -*--//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// This file implements the modeling of the std::basic_string type.10// This involves checking preconditions of the operations and applying the11// effects of the operations, e.g. their post-conditions.12//13//===----------------------------------------------------------------------===//14 15#include "clang/StaticAnalyzer/Checkers/BuiltinCheckerRegistration.h"16#include "clang/StaticAnalyzer/Core/BugReporter/BugType.h"17#include "clang/StaticAnalyzer/Core/PathSensitive/CallDescription.h"18#include "clang/StaticAnalyzer/Core/PathSensitive/CallEvent.h"19#include "clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h"20 21using namespace clang;22using namespace ento;23 24namespace {25class StringChecker : public Checker<check::PreCall> {26  BugType BT_Null{this, "Dereference of null pointer", categories::LogicError};27  mutable const FunctionDecl *StringConstCharPtrCtor = nullptr;28  mutable CanQualType SizeTypeTy;29  const CallDescription TwoParamStdStringCtor = {30      CDM::CXXMethod, {"std", "basic_string", "basic_string"}, 2, 2};31 32  bool isCharToStringCtor(const CallEvent &Call, const ASTContext &ACtx) const;33 34public:35  void checkPreCall(const CallEvent &Call, CheckerContext &C) const;36};37 38bool StringChecker::isCharToStringCtor(const CallEvent &Call,39                                       const ASTContext &ACtx) const {40  if (!TwoParamStdStringCtor.matches(Call))41    return false;42  const auto *FD = dyn_cast<FunctionDecl>(Call.getDecl());43  assert(FD);44 45  // See if we already cached it.46  if (StringConstCharPtrCtor && StringConstCharPtrCtor == FD)47    return true;48 49  // Verify that the parameters have the expected types:50  // - arg 1: `const CharT *`51  // - arg 2: some allocator - which is definitely not `size_t`.52  const QualType Arg1Ty = Call.getArgExpr(0)->getType().getCanonicalType();53  const QualType Arg2Ty = Call.getArgExpr(1)->getType().getCanonicalType();54 55  if (!Arg1Ty->isPointerType())56    return false;57 58  // It makes sure that we don't select the `string(const char* p, size_t len)`59  // overload accidentally.60  if (Arg2Ty.getCanonicalType() == ACtx.getSizeType())61    return false;62 63  StringConstCharPtrCtor = FD; // Cache the decl of the right overload.64  return true;65}66 67void StringChecker::checkPreCall(const CallEvent &Call,68                                 CheckerContext &C) const {69  if (!isCharToStringCtor(Call, C.getASTContext()))70    return;71  const auto Param = Call.getArgSVal(0).getAs<Loc>();72  if (!Param)73    return;74 75  // We managed to constrain the parameter to non-null.76  ProgramStateRef NotNull, Null;77  std::tie(NotNull, Null) = C.getState()->assume(*Param);78 79  if (NotNull) {80    const auto Callback = [Param](PathSensitiveBugReport &BR) -> std::string {81      return BR.isInteresting(*Param) ? "Assuming the pointer is not null."82                                      : "";83    };84 85    // Emit note only if this operation constrained the pointer to be null.86    C.addTransition(NotNull, Null ? C.getNoteTag(Callback) : nullptr);87    return;88  }89 90  // We found a path on which the parameter is NULL.91  if (ExplodedNode *N = C.generateErrorNode(C.getState())) {92    auto R = std::make_unique<PathSensitiveBugReport>(93        BT_Null, "The parameter must not be null", N);94    bugreporter::trackExpressionValue(N, Call.getArgExpr(0), *R);95    C.emitReport(std::move(R));96  }97}98 99} // end anonymous namespace100 101void ento::registerStringChecker(CheckerManager &Mgr) {102  Mgr.registerChecker<StringChecker>();103}104 105bool ento::shouldRegisterStringChecker(const CheckerManager &) { return true; }106