77 lines · cpp
1//== PutenvStackArrayChecker.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-exception6//7//===----------------------------------------------------------------------===//8//9// This file defines PutenvStackArrayChecker which finds calls of ``putenv``10// function with automatic array variable as the argument.11// https://wiki.sei.cmu.edu/confluence/x/6NYxBQ12//13//===----------------------------------------------------------------------===//14 15#include "clang/StaticAnalyzer/Checkers/BuiltinCheckerRegistration.h"16#include "clang/StaticAnalyzer/Core/BugReporter/BugType.h"17#include "clang/StaticAnalyzer/Core/Checker.h"18#include "clang/StaticAnalyzer/Core/CheckerManager.h"19#include "clang/StaticAnalyzer/Core/PathSensitive/CallDescription.h"20#include "clang/StaticAnalyzer/Core/PathSensitive/CallEvent.h"21#include "clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h"22#include "clang/StaticAnalyzer/Core/PathSensitive/MemRegion.h"23 24using namespace clang;25using namespace ento;26 27namespace {28class PutenvStackArrayChecker : public Checker<check::PostCall> {29private:30 BugType BT{this, "'putenv' called with stack-allocated string",31 categories::SecurityError};32 const CallDescription Putenv{CDM::CLibrary, {"putenv"}, 1};33 34public:35 void checkPostCall(const CallEvent &Call, CheckerContext &C) const;36};37} // namespace38 39void PutenvStackArrayChecker::checkPostCall(const CallEvent &Call,40 CheckerContext &C) const {41 if (!Putenv.matches(Call))42 return;43 44 SVal ArgV = Call.getArgSVal(0);45 const Expr *ArgExpr = Call.getArgExpr(0);46 47 if (!ArgV.getAsRegion())48 return;49 50 const auto *SSR =51 ArgV.getAsRegion()->getMemorySpaceAs<StackSpaceRegion>(C.getState());52 if (!SSR)53 return;54 const auto *StackFrameFuncD =55 dyn_cast_or_null<FunctionDecl>(SSR->getStackFrame()->getDecl());56 if (StackFrameFuncD && StackFrameFuncD->isMain())57 return;58 59 StringRef ErrorMsg = "The 'putenv' function should not be called with "60 "arrays that have automatic storage";61 ExplodedNode *N = C.generateErrorNode();62 auto Report = std::make_unique<PathSensitiveBugReport>(BT, ErrorMsg, N);63 64 // Track the argument.65 bugreporter::trackExpressionValue(Report->getErrorNode(), ArgExpr, *Report);66 67 C.emitReport(std::move(Report));68}69 70void ento::registerPutenvStackArray(CheckerManager &Mgr) {71 Mgr.registerChecker<PutenvStackArrayChecker>();72}73 74bool ento::shouldRegisterPutenvStackArray(const CheckerManager &) {75 return true;76}77