clang 20.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
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 namespace
100
101void ento::registerStringChecker(CheckerManager &Mgr) {
102 Mgr.registerChecker<StringChecker>();
103}
104
105bool ento::shouldRegisterStringChecker(const CheckerManager &) { return true; }
Holds long-lived AST nodes (such as types and decls) that can be referred to throughout the semantic ...
Definition: ASTContext.h:187
CanQualType getSizeType() const
Return the unique type for "size_t" (C99 7.17), defined in <stddef.h>.
Represents a function declaration or definition.
Definition: Decl.h:1932
A (possibly-)qualified type.
Definition: Type.h:941
QualType getCanonicalType() const
Definition: Type.h:7802
bool isPointerType() const
Definition: Type.h:8003
A CallDescription is a pattern that can be used to match calls based on the qualified name and the ar...
Represents an abstract call to a function or method along a particular path.
Definition: CallEvent.h:153
CHECKER * registerChecker(AT &&... Args)
Used to register checkers.
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.
bool Null(InterpState &S, CodePtr OpPC, const Descriptor *Desc)
Definition: Interp.h:2258
The JSON file list parser is used to communicate input to InstallAPI.