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