CastToStructChecker.cpp 2.5 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879
  1. //=== CastToStructChecker.cpp - Fixed address usage checker ----*- C++ -*--===//
  2. //
  3. // The LLVM Compiler Infrastructure
  4. //
  5. // This file is distributed under the University of Illinois Open Source
  6. // License. See LICENSE.TXT for details.
  7. //
  8. //===----------------------------------------------------------------------===//
  9. //
  10. // This files defines CastToStructChecker, a builtin checker that checks for
  11. // cast from non-struct pointer to struct pointer.
  12. // This check corresponds to CWE-588.
  13. //
  14. //===----------------------------------------------------------------------===//
  15. #include "clang/StaticAnalyzer/BugReporter/BugType.h"
  16. #include "clang/StaticAnalyzer/PathSensitive/CheckerVisitor.h"
  17. #include "InternalChecks.h"
  18. using namespace clang;
  19. using namespace ento;
  20. namespace {
  21. class CastToStructChecker
  22. : public CheckerVisitor<CastToStructChecker> {
  23. BuiltinBug *BT;
  24. public:
  25. CastToStructChecker() : BT(0) {}
  26. static void *getTag();
  27. void PreVisitCastExpr(CheckerContext &C, const CastExpr *B);
  28. };
  29. }
  30. void *CastToStructChecker::getTag() {
  31. static int x;
  32. return &x;
  33. }
  34. void CastToStructChecker::PreVisitCastExpr(CheckerContext &C,
  35. const CastExpr *CE) {
  36. const Expr *E = CE->getSubExpr();
  37. ASTContext &Ctx = C.getASTContext();
  38. QualType OrigTy = Ctx.getCanonicalType(E->getType());
  39. QualType ToTy = Ctx.getCanonicalType(CE->getType());
  40. const PointerType *OrigPTy = dyn_cast<PointerType>(OrigTy.getTypePtr());
  41. const PointerType *ToPTy = dyn_cast<PointerType>(ToTy.getTypePtr());
  42. if (!ToPTy || !OrigPTy)
  43. return;
  44. QualType OrigPointeeTy = OrigPTy->getPointeeType();
  45. QualType ToPointeeTy = ToPTy->getPointeeType();
  46. if (!ToPointeeTy->isStructureOrClassType())
  47. return;
  48. // We allow cast from void*.
  49. if (OrigPointeeTy->isVoidType())
  50. return;
  51. // Now the cast-to-type is struct pointer, the original type is not void*.
  52. if (!OrigPointeeTy->isRecordType()) {
  53. if (ExplodedNode *N = C.generateNode()) {
  54. if (!BT)
  55. BT = new BuiltinBug("Cast from non-struct type to struct type",
  56. "Casting a non-structure type to a structure type "
  57. "and accessing a field can lead to memory access "
  58. "errors or data corruption.");
  59. RangedBugReport *R = new RangedBugReport(*BT,BT->getDescription(), N);
  60. R->addRange(CE->getSourceRange());
  61. C.EmitReport(R);
  62. }
  63. }
  64. }
  65. void ento::RegisterCastToStructChecker(ExprEngine &Eng) {
  66. Eng.registerCheck(new CastToStructChecker());
  67. }