brintos

brintos / llvm-project-archived public Read only

0
0
Text · 2.7 KiB · a40b411 Raw
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