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