// MallocSizeofChecker.cpp - Check for dubious malloc arguments ---*- C++ -*-=//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// Reports inconsistencies between the casted type of the return value of a
// malloc/calloc/realloc call and the operand of any sizeof expressions
// contained within its argument(s).
//
//===----------------------------------------------------------------------===//

#include "ClangSACheckers.h"
#include "clang/AST/StmtVisitor.h"
#include "clang/AST/TypeLoc.h"
#include "clang/StaticAnalyzer/Core/BugReporter/BugReporter.h"
#include "clang/StaticAnalyzer/Core/Checker.h"
#include "clang/StaticAnalyzer/Core/CheckerManager.h"
#include "clang/StaticAnalyzer/Core/PathSensitive/AnalysisManager.h"
#include "llvm/ADT/SmallString.h"
#include "llvm/Support/raw_ostream.h"

using namespace clang;
using namespace ento;

namespace {

typedef std::pair<const TypeSourceInfo *, const CallExpr *> TypeCallPair;
typedef llvm::PointerUnion<const Stmt *, const VarDecl *> ExprParent;

class CastedAllocFinder
  : public ConstStmtVisitor<CastedAllocFinder, TypeCallPair> {
  IdentifierInfo *II_malloc, *II_calloc, *II_realloc;

public:
  struct CallRecord {
    ExprParent CastedExprParent;
    const Expr *CastedExpr;
    const TypeSourceInfo *ExplicitCastType;
    const CallExpr *AllocCall;

    CallRecord(ExprParent CastedExprParent, const Expr *CastedExpr,
               const TypeSourceInfo *ExplicitCastType,
               const CallExpr *AllocCall)
      : CastedExprParent(CastedExprParent), CastedExpr(CastedExpr),
        ExplicitCastType(ExplicitCastType), AllocCall(AllocCall) {}
  };

  typedef std::vector<CallRecord> CallVec;
  CallVec Calls;

  CastedAllocFinder(ASTContext *Ctx) :
    II_malloc(&Ctx->Idents.get("malloc")),
    II_calloc(&Ctx->Idents.get("calloc")),
    II_realloc(&Ctx->Idents.get("realloc")) {}

  void VisitChild(ExprParent Parent, const Stmt *S) {
    TypeCallPair AllocCall = Visit(S);
    if (AllocCall.second && AllocCall.second != S)
      Calls.push_back(CallRecord(Parent, cast<Expr>(S), AllocCall.first,
                                 AllocCall.second));
  }

  void VisitChildren(const Stmt *S) {
    for (const Stmt *Child : S->children())
      if (Child)
        VisitChild(S, Child);
  }

  TypeCallPair VisitCastExpr(const CastExpr *E) {
    return Visit(E->getSubExpr());
  }

  TypeCallPair VisitExplicitCastExpr(const ExplicitCastExpr *E) {
    return TypeCallPair(E->getTypeInfoAsWritten(),
                        Visit(E->getSubExpr()).second);
  }

  TypeCallPair VisitParenExpr(const ParenExpr *E) {
    return Visit(E->getSubExpr());
  }

  TypeCallPair VisitStmt(const Stmt *S) {
    VisitChildren(S);
    return TypeCallPair();
  }

  TypeCallPair VisitCallExpr(const CallExpr *E) {
    VisitChildren(E);
    const FunctionDecl *FD = E->getDirectCallee();
    if (FD) {
      IdentifierInfo *II = FD->getIdentifier();
      if (II == II_malloc || II == II_calloc || II == II_realloc)
        return TypeCallPair((const TypeSourceInfo *)nullptr, E);
    }
    return TypeCallPair();
  }

  TypeCallPair VisitDeclStmt(const DeclStmt *S) {
    for (const auto *I : S->decls())
      if (const VarDecl *VD = dyn_cast<VarDecl>(I))
        if (const Expr *Init = VD->getInit())
          VisitChild(VD, Init);
    return TypeCallPair();
  }
};

class SizeofFinder : public ConstStmtVisitor<SizeofFinder> {
public:
  std::vector<const UnaryExprOrTypeTraitExpr *> Sizeofs;

  void VisitBinMul(const BinaryOperator *E) {
    Visit(E->getLHS());
    Visit(E->getRHS());
  }

  void VisitImplicitCastExpr(const ImplicitCastExpr *E) {
    return Visit(E->getSubExpr());
  }

  void VisitParenExpr(const ParenExpr *E) {
    return Visit(E->getSubExpr());
  }

  void VisitUnaryExprOrTypeTraitExpr(const UnaryExprOrTypeTraitExpr *E) {
    if (E->getKind() != UETT_SizeOf)
      return;

    Sizeofs.push_back(E);
  }
};

// Determine if the pointee and sizeof types are compatible.  Here
// we ignore constness of pointer types.
static bool typesCompatible(ASTContext &C, QualType A, QualType B) {
  // sizeof(void*) is compatible with any other pointer.
  if (B->isVoidPointerType() && A->getAs<PointerType>())
    return true;

  while (true) {
    A = A.getCanonicalType();
    B = B.getCanonicalType();
  
    if (A.getTypePtr() == B.getTypePtr())
      return true;
    
    if (const PointerType *ptrA = A->getAs<PointerType>())
      if (const PointerType *ptrB = B->getAs<PointerType>()) {
        A = ptrA->getPointeeType();
        B = ptrB->getPointeeType();
        continue;
      }
      
    break;
  }
  
  return false;
}

static bool compatibleWithArrayType(ASTContext &C, QualType PT, QualType T) {
  // Ex: 'int a[10][2]' is compatible with 'int', 'int[2]', 'int[10][2]'.
  while (const ArrayType *AT = T->getAsArrayTypeUnsafe()) {
    QualType ElemType = AT->getElementType();
    if (typesCompatible(C, PT, AT->getElementType()))
      return true;
    T = ElemType;
  }

  return false;
}

class MallocSizeofChecker : public Checker<check::ASTCodeBody> {
public:
  void checkASTCodeBody(const Decl *D, AnalysisManager& mgr,
                        BugReporter &BR) const {
    AnalysisDeclContext *ADC = mgr.getAnalysisDeclContext(D);
    CastedAllocFinder Finder(&BR.getContext());
    Finder.Visit(D->getBody());
    for (CastedAllocFinder::CallVec::iterator i = Finder.Calls.begin(),
         e = Finder.Calls.end(); i != e; ++i) {
      QualType CastedType = i->CastedExpr->getType();
      if (!CastedType->isPointerType())
        continue;
      QualType PointeeType = CastedType->getAs<PointerType>()->getPointeeType();
      if (PointeeType->isVoidType())
        continue;

      for (CallExpr::const_arg_iterator ai = i->AllocCall->arg_begin(),
           ae = i->AllocCall->arg_end(); ai != ae; ++ai) {
        if (!(*ai)->getType()->isIntegralOrUnscopedEnumerationType())
          continue;

        SizeofFinder SFinder;
        SFinder.Visit(*ai);
        if (SFinder.Sizeofs.size() != 1)
          continue;

        QualType SizeofType = SFinder.Sizeofs[0]->getTypeOfArgument();

        if (typesCompatible(BR.getContext(), PointeeType, SizeofType))
          continue;

        // If the argument to sizeof is an array, the result could be a
        // pointer to any array element.
        if (compatibleWithArrayType(BR.getContext(), PointeeType, SizeofType))
          continue;

        const TypeSourceInfo *TSI = nullptr;
        if (i->CastedExprParent.is<const VarDecl *>()) {
          TSI =
              i->CastedExprParent.get<const VarDecl *>()->getTypeSourceInfo();
        } else {
          TSI = i->ExplicitCastType;
        }

        SmallString<64> buf;
        llvm::raw_svector_ostream OS(buf);

        OS << "Result of ";
        const FunctionDecl *Callee = i->AllocCall->getDirectCallee();
        if (Callee && Callee->getIdentifier())
          OS << '\'' << Callee->getIdentifier()->getName() << '\'';
        else
          OS << "call";
        OS << " is converted to a pointer of type '"
            << PointeeType.getAsString() << "', which is incompatible with "
            << "sizeof operand type '" << SizeofType.getAsString() << "'";
        SmallVector<SourceRange, 4> Ranges;
        Ranges.push_back(i->AllocCall->getCallee()->getSourceRange());
        Ranges.push_back(SFinder.Sizeofs[0]->getSourceRange());
        if (TSI)
          Ranges.push_back(TSI->getTypeLoc().getSourceRange());

        PathDiagnosticLocation L =
            PathDiagnosticLocation::createBegin(i->AllocCall->getCallee(),
                BR.getSourceManager(), ADC);

        BR.EmitBasicReport(D, this, "Allocator sizeof operand mismatch",
                           categories::UnixAPI, OS.str(), L, Ranges);
      }
    }
  }
};

}

void ento::registerMallocSizeofChecker(CheckerManager &mgr) {
  mgr.registerChecker<MallocSizeofChecker>();
}
