clang  15.0.0git
StringChecker.cpp
Go to the documentation of this file.
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-exception
6 //
7 //===----------------------------------------------------------------------===//
8 //
9 // This file implements the modeling of the std::basic_string type.
10 // This involves checking preconditions of the operations and applying the
11 // effects of the operations, e.g. their post-conditions.
12 //
13 //===----------------------------------------------------------------------===//
14 
20 
21 using namespace clang;
22 using namespace ento;
23 
24 namespace {
25 class 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  {"std", "basic_string", "basic_string"}, 2, 2};
31 
32  bool isCharToStringCtor(const CallEvent &Call, const ASTContext &ACtx) const;
33 
34 public:
35  void checkPreCall(const CallEvent &Call, CheckerContext &C) const;
36 };
37 
38 bool 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 definately 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 
67 void 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 namespace
100 
101 void ento::registerStringChecker(CheckerManager &Mgr) {
102  Mgr.registerChecker<StringChecker>();
103 }
104 
105 bool ento::shouldRegisterStringChecker(const CheckerManager &) { return true; }
CallDescription.h
string
string(SUBSTRING ${CMAKE_CURRENT_BINARY_DIR} 0 ${PATH_LIB_START} PATH_HEAD) string(SUBSTRING $
Definition: CMakeLists.txt:22
clang::ento::ProgramStateRef
IntrusiveRefCntPtr< const ProgramState > ProgramStateRef
Definition: ProgramState_Fwd.h:37
clang::QualType
A (possibly-)qualified type.
Definition: Type.h:731
AttributeLangSupport::C
@ C
Definition: SemaDeclAttr.cpp:55
clang::QualType::getCanonicalType
QualType getCanonicalType() const
Definition: Type.h:6598
clang::index::SymbolRole::Call
@ Call
CallEvent.h
BuiltinCheckerRegistration.h
clang::ASTContext
Holds long-lived AST nodes (such as types and decls) that can be referred to throughout the semantic ...
Definition: ASTContext.h:208
clang::ASTContext::getSizeType
CanQualType getSizeType() const
Return the unique type for "size_t" (C99 7.17), defined in <stddef.h>.
Definition: ASTContext.cpp:5850
clang::CanQual< Type >
clang::interp::Null
bool Null(InterpState &S, CodePtr OpPC)
Definition: Interp.h:820
clang::ento::bugreporter::trackExpressionValue
bool trackExpressionValue(const ExplodedNode *N, const Expr *E, PathSensitiveBugReport &R, TrackingOptions Opts={})
Attempts to add visitors to track expression value back to its point of origin.
clang::Type::isPointerType
bool isPointerType() const
Definition: Type.h:6807
BugType.h
CheckerContext.h
clang::ento::categories::LogicError
const char *const LogicError
Definition: CommonBugCategories.cpp:17
clang
Definition: CalledOnceCheck.h:17
clang::FunctionDecl
Represents a function declaration or definition.
Definition: Decl.h:1872