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