1*e038c9c4Sjoerg //== PutenvWithAutoChecker.cpp --------------------------------- -*- C++ -*--=//
2*e038c9c4Sjoerg //
3*e038c9c4Sjoerg // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4*e038c9c4Sjoerg // See https://llvm.org/LICENSE.txt for license information.
5*e038c9c4Sjoerg // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6*e038c9c4Sjoerg //
7*e038c9c4Sjoerg //===----------------------------------------------------------------------===//
8*e038c9c4Sjoerg //
9*e038c9c4Sjoerg // This file defines PutenvWithAutoChecker which finds calls of ``putenv``
10*e038c9c4Sjoerg // function with automatic variable as the argument.
11*e038c9c4Sjoerg // https://wiki.sei.cmu.edu/confluence/x/6NYxBQ
12*e038c9c4Sjoerg //
13*e038c9c4Sjoerg //===----------------------------------------------------------------------===//
14*e038c9c4Sjoerg
15*e038c9c4Sjoerg #include "../AllocationState.h"
16*e038c9c4Sjoerg #include "clang/StaticAnalyzer/Checkers/BuiltinCheckerRegistration.h"
17*e038c9c4Sjoerg #include "clang/StaticAnalyzer/Core/BugReporter/BugType.h"
18*e038c9c4Sjoerg #include "clang/StaticAnalyzer/Core/Checker.h"
19*e038c9c4Sjoerg #include "clang/StaticAnalyzer/Core/CheckerManager.h"
20*e038c9c4Sjoerg #include "clang/StaticAnalyzer/Core/PathSensitive/CallEvent.h"
21*e038c9c4Sjoerg #include "clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h"
22*e038c9c4Sjoerg #include "clang/StaticAnalyzer/Core/PathSensitive/MemRegion.h"
23*e038c9c4Sjoerg
24*e038c9c4Sjoerg using namespace clang;
25*e038c9c4Sjoerg using namespace ento;
26*e038c9c4Sjoerg
27*e038c9c4Sjoerg namespace {
28*e038c9c4Sjoerg class PutenvWithAutoChecker : public Checker<check::PostCall> {
29*e038c9c4Sjoerg private:
30*e038c9c4Sjoerg BugType BT{this, "'putenv' function should not be called with auto variables",
31*e038c9c4Sjoerg categories::SecurityError};
32*e038c9c4Sjoerg const CallDescription Putenv{"putenv", 1};
33*e038c9c4Sjoerg
34*e038c9c4Sjoerg public:
35*e038c9c4Sjoerg void checkPostCall(const CallEvent &Call, CheckerContext &C) const;
36*e038c9c4Sjoerg };
37*e038c9c4Sjoerg } // namespace
38*e038c9c4Sjoerg
checkPostCall(const CallEvent & Call,CheckerContext & C) const39*e038c9c4Sjoerg void PutenvWithAutoChecker::checkPostCall(const CallEvent &Call,
40*e038c9c4Sjoerg CheckerContext &C) const {
41*e038c9c4Sjoerg if (!Call.isCalled(Putenv))
42*e038c9c4Sjoerg return;
43*e038c9c4Sjoerg
44*e038c9c4Sjoerg SVal ArgV = Call.getArgSVal(0);
45*e038c9c4Sjoerg const Expr *ArgExpr = Call.getArgExpr(0);
46*e038c9c4Sjoerg const MemSpaceRegion *MSR = ArgV.getAsRegion()->getMemorySpace();
47*e038c9c4Sjoerg
48*e038c9c4Sjoerg if (!isa<StackSpaceRegion>(MSR))
49*e038c9c4Sjoerg return;
50*e038c9c4Sjoerg
51*e038c9c4Sjoerg StringRef ErrorMsg = "The 'putenv' function should not be called with "
52*e038c9c4Sjoerg "arguments that have automatic storage";
53*e038c9c4Sjoerg ExplodedNode *N = C.generateErrorNode();
54*e038c9c4Sjoerg auto Report = std::make_unique<PathSensitiveBugReport>(BT, ErrorMsg, N);
55*e038c9c4Sjoerg
56*e038c9c4Sjoerg // Track the argument.
57*e038c9c4Sjoerg bugreporter::trackExpressionValue(Report->getErrorNode(), ArgExpr, *Report);
58*e038c9c4Sjoerg
59*e038c9c4Sjoerg C.emitReport(std::move(Report));
60*e038c9c4Sjoerg }
61*e038c9c4Sjoerg
registerPutenvWithAuto(CheckerManager & Mgr)62*e038c9c4Sjoerg void ento::registerPutenvWithAuto(CheckerManager &Mgr) {
63*e038c9c4Sjoerg Mgr.registerChecker<PutenvWithAutoChecker>();
64*e038c9c4Sjoerg }
65*e038c9c4Sjoerg
shouldRegisterPutenvWithAuto(const CheckerManager &)66*e038c9c4Sjoerg bool ento::shouldRegisterPutenvWithAuto(const CheckerManager &) { return true; }
67