blob: ec401cfa898595a005972eb4668bd88996febb3a [file] [log] [blame]
Zhongxing Xub0a05f7c2009-11-08 13:10:34 +00001//==- CheckSizeofPointer.cpp - Check for sizeof on pointers ------*- C++ -*-==//
2//
Chandler Carruth2946cd72019-01-19 08:50:56 +00003// 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
Zhongxing Xub0a05f7c2009-11-08 13:10:34 +00006//
7//===----------------------------------------------------------------------===//
8//
9// This file defines a check for unintended use of sizeof() on pointer
10// expressions.
11//
12//===----------------------------------------------------------------------===//
13
Kristof Umann76a21502018-12-15 16:23:51 +000014#include "clang/StaticAnalyzer/Checkers/BuiltinCheckerRegistration.h"
Anna Zaksc29bed32011-09-20 21:38:35 +000015#include "clang/AST/StmtVisitor.h"
Ted Kremenekf8cbac42011-02-10 01:03:03 +000016#include "clang/StaticAnalyzer/Core/BugReporter/BugReporter.h"
Chandler Carruth3a022472012-12-04 09:13:33 +000017#include "clang/StaticAnalyzer/Core/Checker.h"
Anna Zaksc29bed32011-09-20 21:38:35 +000018#include "clang/StaticAnalyzer/Core/PathSensitive/AnalysisManager.h"
Zhongxing Xub0a05f7c2009-11-08 13:10:34 +000019
20using namespace clang;
Ted Kremenek98857c92010-12-23 07:20:52 +000021using namespace ento;
Zhongxing Xub0a05f7c2009-11-08 13:10:34 +000022
23namespace {
Kovarththanan Rajaratnam65c65662009-11-28 06:07:30 +000024class WalkAST : public StmtVisitor<WalkAST> {
Zhongxing Xub0a05f7c2009-11-08 13:10:34 +000025 BugReporter &BR;
Alexander Kornienko4aca9b12014-02-11 21:49:21 +000026 const CheckerBase *Checker;
Ted Kremenek81ce1c82011-10-24 01:32:45 +000027 AnalysisDeclContext* AC;
Zhongxing Xub0a05f7c2009-11-08 13:10:34 +000028
29public:
Alexander Kornienko4aca9b12014-02-11 21:49:21 +000030 WalkAST(BugReporter &br, const CheckerBase *checker, AnalysisDeclContext *ac)
31 : BR(br), Checker(checker), AC(ac) {}
Peter Collingbournee190dee2011-03-11 19:24:49 +000032 void VisitUnaryExprOrTypeTraitExpr(UnaryExprOrTypeTraitExpr *E);
Zhongxing Xub0a05f7c2009-11-08 13:10:34 +000033 void VisitStmt(Stmt *S) { VisitChildren(S); }
34 void VisitChildren(Stmt *S);
35};
Alexander Kornienkoab9db512015-06-22 23:07:51 +000036}
Zhongxing Xub0a05f7c2009-11-08 13:10:34 +000037
38void WalkAST::VisitChildren(Stmt *S) {
Benjamin Kramer973431b2015-07-03 15:12:24 +000039 for (Stmt *Child : S->children())
40 if (Child)
41 Visit(Child);
Zhongxing Xub0a05f7c2009-11-08 13:10:34 +000042}
43
44// CWE-467: Use of sizeof() on a Pointer Type
Peter Collingbournee190dee2011-03-11 19:24:49 +000045void WalkAST::VisitUnaryExprOrTypeTraitExpr(UnaryExprOrTypeTraitExpr *E) {
46 if (E->getKind() != UETT_SizeOf)
Zhongxing Xub0a05f7c2009-11-08 13:10:34 +000047 return;
48
Eric Christopherc9e2a682014-05-20 17:10:39 +000049 // If an explicit type is used in the code, usually the coder knows what they are
Zhongxing Xu9a7448c2009-11-10 04:20:20 +000050 // doing.
51 if (E->isArgumentType())
52 return;
53
Zhongxing Xub0a05f7c2009-11-08 13:10:34 +000054 QualType T = E->getTypeOfArgument();
55 if (T->isPointerType()) {
Zhongxing Xu537db5d2009-11-10 07:52:53 +000056
Ted Kremenek3a0678e2015-09-08 03:50:52 +000057 // Many false positives have the form 'sizeof *p'. This is reasonable
58 // because people know what they are doing when they intentionally
Zhongxing Xu537db5d2009-11-10 07:52:53 +000059 // dereference the pointer.
60 Expr *ArgEx = E->getArgumentExpr();
Zhongxing Xuf9667222009-11-10 08:33:44 +000061 if (!isa<DeclRefExpr>(ArgEx->IgnoreParens()))
Zhongxing Xu537db5d2009-11-10 07:52:53 +000062 return;
63
Anna Zaksc29bed32011-09-20 21:38:35 +000064 PathDiagnosticLocation ELoc =
65 PathDiagnosticLocation::createBegin(E, BR.getSourceManager(), AC);
Alexander Kornienko4aca9b12014-02-11 21:49:21 +000066 BR.EmitBasicReport(AC->getDecl(), Checker,
Ted Kremenek5a10f082012-04-04 18:11:35 +000067 "Potential unintended use of sizeof() on pointer type",
Jordan Rose6feda282013-10-04 00:25:24 +000068 categories::LogicError,
Zhongxing Xu85000202009-11-09 07:29:39 +000069 "The code calls sizeof() on a pointer type. "
70 "This can produce an unexpected result.",
Jordan Rose42b42482013-10-07 17:16:59 +000071 ELoc, ArgEx->getSourceRange());
Zhongxing Xub0a05f7c2009-11-08 13:10:34 +000072 }
73}
74
Argyrios Kyrtzidisaf45aca2011-02-17 21:39:33 +000075//===----------------------------------------------------------------------===//
76// SizeofPointerChecker
77//===----------------------------------------------------------------------===//
78
79namespace {
Argyrios Kyrtzidis6a5674f2011-03-01 01:16:21 +000080class SizeofPointerChecker : public Checker<check::ASTCodeBody> {
Argyrios Kyrtzidisaf45aca2011-02-17 21:39:33 +000081public:
82 void checkASTCodeBody(const Decl *D, AnalysisManager& mgr,
83 BugReporter &BR) const {
Alexander Kornienko4aca9b12014-02-11 21:49:21 +000084 WalkAST walker(BR, this, mgr.getAnalysisDeclContext(D));
Argyrios Kyrtzidisaf45aca2011-02-17 21:39:33 +000085 walker.Visit(D->getBody());
86 }
87};
88}
89
90void ento::registerSizeofPointerChecker(CheckerManager &mgr) {
91 mgr.registerChecker<SizeofPointerChecker>();
Zhongxing Xub0a05f7c2009-11-08 13:10:34 +000092}
Kristof Umann058a7a42019-01-26 14:23:08 +000093
94bool ento::shouldRegisterSizeofPointerChecker(const LangOptions &LO) {
95 return true;
96}