xref: /netbsd-src/external/apache2/llvm/dist/clang/lib/StaticAnalyzer/Checkers/cert/PutenvWithAutoChecker.cpp (revision e038c9c4676b0f19b1b7dd08a940c6ed64a6d5ae)
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