clang: lib/StaticAnalyzer/Checkers/ArrayBoundChecker.cpp Source File (original) (raw)

1

2

3

4

5

6

7

8

9

10

11

12

13

25#include "llvm/ADT/APSInt.h"

26#include "llvm/Support/FormatVariadic.h"

27#include "llvm/Support/raw_ostream.h"

28#include

29

30using namespace clang;

31using namespace ento;

32using namespace taint;

33using llvm::formatv;

34

35namespace {

36

37

38

39

40

43 const auto *ASE = dyn_cast(E);

44 if (!ASE)

45 return nullptr;

46

47 const MemRegion *SubscriptBaseReg = C.getSVal(ASE->getBase()).getAsRegion();

48 if (!SubscriptBaseReg)

49 return nullptr;

50

51

52

53

55 return nullptr;

56

57 return ASE;

58}

59

60

61

62

63static std::optional determineElementType(const Expr *E,

65 const auto *ASE = getAsCleanArraySubscriptExpr(E, C);

66 if (!ASE)

67 return std::nullopt;

68

69 return ASE->getType();

70}

71

72static std::optional<int64_t>

73determineElementSize(const std::optional T, const CheckerContext &C) {

74 if (T)

75 return std::nullopt;

76 return C.getASTContext().getTypeSizeInChars(*T).getQuantity();

77}

78

79class StateUpdateReporter {

80 const MemSpaceRegion *Space;

81 const SubRegion *Reg;

82 const NonLoc ByteOffsetVal;

83 const std::optional ElementType;

84 const std::optional<int64_t> ElementSize;

85 bool AssumedNonNegative = false;

86 std::optional AssumedUpperBound = std::nullopt;

87

88public:

89 StateUpdateReporter(const SubRegion *R, NonLoc ByteOffsVal, const Expr *E,

90 CheckerContext &C)

91 : Space(R->getMemorySpace(C.getState())), Reg(R),

92 ByteOffsetVal(ByteOffsVal), ElementType(determineElementType(E, C)),

93 ElementSize(determineElementSize(ElementType, C)) {}

94

95 void recordNonNegativeAssumption() { AssumedNonNegative = true; }

96 void recordUpperBoundAssumption(NonLoc UpperBoundVal) {

97 AssumedUpperBound = UpperBoundVal;

98 }

99

100 bool assumedNonNegative() { return AssumedNonNegative; }

101

102 const NoteTag *createNoteTag(CheckerContext &C) const;

103

104private:

105 std::string getMessage(PathSensitiveBugReport &BR) const;

106

107

108

109

110

111

112

113

114

115

116

117

118

119

120

121 static bool providesInformationAboutInteresting(SymbolRef Sym,

122 PathSensitiveBugReport &BR);

123 static bool providesInformationAboutInteresting(SVal SV,

124 PathSensitiveBugReport &BR) {

125 return providesInformationAboutInteresting(SV.getAsSymbol(), BR);

126 }

127};

128

129struct Messages {

130 std::string Short, Full;

131};

132

133enum class BadOffsetKind { Negative, Overflowing, Indeterminate };

134

135constexpr llvm::StringLiteral Adjectives[] = {"a negative", "an overflowing",

136 "a negative or overflowing"};

137static StringRef asAdjective(BadOffsetKind Problem) {

138 return Adjectives[static_cast<int>(Problem)];

139}

140

141constexpr llvm::StringLiteral Prepositions[] = {"preceding", "after the end of",

142 "around"};

143static StringRef asPreposition(BadOffsetKind Problem) {

144 return Prepositions[static_cast<int>(Problem)];

145}

146

147

148

149

150

151

152

153

154class ArrayBoundChecker : public Checker<check::PostStmt,

155 check::PostStmt,

156 check::PostStmt> {

157 BugType BT{this, "Out-of-bound access"};

159

160 void performCheck(const Expr *E, CheckerContext &C) const;

161

162 void reportOOB(CheckerContext &C, ProgramStateRef ErrorState, Messages Msgs,

163 NonLoc Offset, std::optional Extent,

164 bool IsTaintBug = false) const;

165

166 static void markPartsInteresting(PathSensitiveBugReport &BR,

168 bool MarkTaint);

169

170 static bool isFromCtypeMacro(const Expr *E, ASTContext &AC);

171

172 static bool isOffsetObviouslyNonnegative(const Expr *E, CheckerContext &C);

173

174 static bool isIdiomaticPastTheEndPtr(const Expr *E, ProgramStateRef State,

175 NonLoc Offset, NonLoc Limit,

176 CheckerContext &C);

177 static bool isInAddressOf(const Stmt *S, ASTContext &AC);

178

179public:

180 void checkPostStmt(const ArraySubscriptExpr *E, CheckerContext &C) const {

181 performCheck(E, C);

182 }

183 void checkPostStmt(const UnaryOperator *E, CheckerContext &C) const {

185 performCheck(E, C);

186 }

187 void checkPostStmt(const MemberExpr *E, CheckerContext &C) const {

189 performCheck(E->getBase(), C);

190 }

191};

192

193}

194

195

196

197

198

199

200static std::optional<std::pair<const SubRegion *, NonLoc>>

204

206 };

207

208 const SubRegion *OwnerRegion = nullptr;

210

212 dyn_cast_or_null(Location.getAsRegion());

213

214 while (CurRegion) {

216 if (!Index)

217 return std::nullopt;

218

220

221

222

223

225 return std::nullopt;

226

227

230 auto Delta = EvalBinOp(BO_Mul, *Index, Size);

231 if (!Delta)

232 return std::nullopt;

233

234

235 Offset = EvalBinOp(BO_Add, *Offset, *Delta);

236 if (!Offset)

237 return std::nullopt;

238

240

241

242 CurRegion = dyn_cast_or_null(OwnerRegion);

243 }

244

245 if (OwnerRegion)

246 return std::make_pair(OwnerRegion, *Offset);

247

248 return std::nullopt;

249}

250

251

252

253

254

255

256

257

258

259

260

261

262

263

264

265

266

267

268

269

270

271static std::pair<NonLoc, nonloc::ConcreteInt>

274 const llvm::APSInt &extentVal = extent.getValue();

276 if (SymVal && SymVal->isExpression()) {

277 if (const SymIntExpr *SIE = dyn_cast(SymVal->getSymbol())) {

278 llvm::APSInt constant = APSIntType(extentVal).convert(SIE->getRHS());

279 switch (SIE->getOpcode()) {

280 case BO_Mul:

281

282

283 if ((extentVal % constant) != 0)

284 return std::pair<NonLoc, nonloc::ConcreteInt>(offset, extent);

285 else

288 svalBuilder.makeIntVal(extentVal / constant), svalBuilder);

289 case BO_Add:

292 svalBuilder.makeIntVal(extentVal - constant), svalBuilder);

293 default:

294 break;

295 }

296 }

297 }

298

299 return std::pair<NonLoc, nonloc::ConcreteInt>(offset, extent);

300}

301

304 return MaxV && MaxV->isNegative();

305}

306

309 return T->isUnsignedIntegerType();

310}

311

312

313

314

315

316

317

318

319static std::pair<ProgramStateRef, ProgramStateRef>

321 SValBuilder &SVB, bool CheckEquality = false) {

323 std::tie(Value, Threshold) =

325 }

326

327

328

329

330

331

332

333

335 if (CheckEquality) {

336

337 return {nullptr, State};

338 }

339

340 return {State, nullptr};

341 }

343

344

345 return {nullptr, State};

346 }

347

348

349

350

351

352

353

354

355

356

357

359 auto BelowThreshold =

362

363 if (BelowThreshold)

364 return State->assume(*BelowThreshold);

365

366 return {nullptr, nullptr};

367}

368

371 if (std::string RegName = Region->getDescriptiveName(); !RegName.empty())

372 return RegName;

373

374

375

377 if (StringRef Name = FR->getDecl()->getName(); !Name.empty())

378 return formatv("the field '{0}'", Name);

379 return "the unnamed field";

380 }

381

383 return "the memory returned by 'alloca'";

384

386 return "the heap area";

387

389 return "the string literal";

390

391 return "the region";

392}

393

396 return ConcreteVal->getValue()->tryExtValue();

397 }

398 return std::nullopt;

399}

400

404

405

406

407

408

410 std::optional<int64_t> &Val2, int64_t Divisor) {

411 if (!Divisor)

412 return false;

413 const bool Val1HasRemainder = Val1 && *Val1 % Divisor;

414 const bool Val2HasRemainder = Val2 && *Val2 % Divisor;

415 if (Val1HasRemainder || Val2HasRemainder)

416 return false;

417 if (Val1)

418 *Val1 /= Divisor;

419 if (Val2)

420 *Val2 /= Divisor;

421 return true;

422}

423

427 std::optional Extent, SVal Location,

428 BadOffsetKind Problem) {

429 std::string RegName = getRegionName(Space, Region);

430 const auto *EReg = Location.getAsRegion()->getAs<ElementRegion>();

431 assert(EReg && "this checker only handles element access");

432 QualType ElemType = EReg->getElementType();

433

436

438

439 bool UseByteOffsets = tryDividePair(OffsetN, ExtentN, ElemSize);

440 const char *OffsetOrIndex = UseByteOffsets ? "byte offset" : "index";

441

443 llvm::raw_svector_ostream Out(Buf);

444 Out << "Access of ";

445 if (OffsetN && !ExtentN && !UseByteOffsets) {

446

447

448

449

450

451 Out << "'" << ElemType.getAsString() << "' element in ";

452 }

453 Out << RegName << " at ";

454 if (OffsetN) {

455 if (Problem == BadOffsetKind::Negative)

456 Out << "negative ";

457 Out << OffsetOrIndex << " " << *OffsetN;

458 } else {

459 Out << asAdjective(Problem) << " " << OffsetOrIndex;

460 }

461 if (ExtentN) {

462 Out << ", while it holds only ";

463 if (*ExtentN != 1)

464 Out << *ExtentN;

465 else

466 Out << "a single";

467 if (UseByteOffsets)

468 Out << " byte";

469 else

470 Out << " '" << ElemType.getAsString() << "' element";

471

472 if (*ExtentN > 1)

473 Out << "s";

474 }

475

476 return {formatv("Out of bound access to memory {0} {1}",

477 asPreposition(Problem), RegName),

478 std::string(Buf)};

479}

480

482 const SubRegion *Region, const char *OffsetName,

483 bool AlsoMentionUnderflow) {

484 std::string RegName = getRegionName(Space, Region);

485 return {formatv("Potential out of bound access to {0} with tainted {1}",

486 RegName, OffsetName),

487 formatv("Access of {0} with a tainted {1} that may be {2}too large",

488 RegName, OffsetName,

489 AlsoMentionUnderflow ? "negative or " : "")};

490}

491

493

494 if (!AssumedNonNegative && !AssumedUpperBound)

495 return nullptr;

496

497 return C.getNoteTag([*this](PathSensitiveBugReport &BR) -> std::string {

498 return getMessage(BR);

499 });

500}

501

502std::string StateUpdateReporter::getMessage(PathSensitiveBugReport &BR) const {

503 bool ShouldReportNonNegative = AssumedNonNegative;

504 if (!providesInformationAboutInteresting(ByteOffsetVal, BR)) {

505 if (AssumedUpperBound &&

506 providesInformationAboutInteresting(*AssumedUpperBound, BR)) {

507

508

509

510 ShouldReportNonNegative = false;

511 } else {

512

513 return "";

514 }

515 }

516

517 std::optional<int64_t> OffsetN = getConcreteValue(ByteOffsetVal);

518 std::optional<int64_t> ExtentN = getConcreteValue(AssumedUpperBound);

519

520 const bool UseIndex =

521 ElementSize && tryDividePair(OffsetN, ExtentN, *ElementSize);

522

523 SmallString<256> Buf;

524 llvm::raw_svector_ostream Out(Buf);

525 Out << "Assuming ";

526 if (UseIndex) {

527 Out << "index ";

528 if (OffsetN)

529 Out << "'" << OffsetN << "' ";

530 } else if (AssumedUpperBound) {

531 Out << "byte offset ";

532 if (OffsetN)

533 Out << "'" << OffsetN << "' ";

534 } else {

535 Out << "offset ";

536 }

537

538 Out << "is";

539 if (ShouldReportNonNegative) {

540 Out << " non-negative";

541 }

542 if (AssumedUpperBound) {

543 if (ShouldReportNonNegative)

544 Out << " and";

545 Out << " less than ";

546 if (ExtentN)

547 Out << *ExtentN << ", ";

548 if (UseIndex && ElementType)

549 Out << "the number of '" << ElementType->getAsString()

550 << "' elements in ";

551 else

552 Out << "the extent of ";

554 }

555 return std::string(Out.str());

556}

557

558bool StateUpdateReporter::providesInformationAboutInteresting(

559 SymbolRef Sym, PathSensitiveBugReport &BR) {

560 if (!Sym)

561 return false;

563

564

566 return true;

567

568

569

571 return false;

572 }

573 return false;

574}

575

576void ArrayBoundChecker::performCheck(const Expr *E, CheckerContext &C) const {

577 const SVal Location = C.getSVal(E);

578

579

580

581

582

583

584 if (isFromCtypeMacro(E, C.getASTContext()))

585 return;

586

588 SValBuilder &SVB = C.getSValBuilder();

589

590 const std::optional<std::pair<const SubRegion *, NonLoc>> &RawOffset =

592

593 if (!RawOffset)

594 return;

595

596 auto [Reg, ByteOffset] = *RawOffset;

597

598

599

600 StateUpdateReporter SUR(Reg, ByteOffset, E, C);

601

602

603 const MemSpaceRegion *Space = Reg->getMemorySpace(State);

605

606

607

608

609

610

611

614

615 if (PrecedesLowerBound) {

616

617

618 if (isOffsetObviouslyNonnegative(E, C)) {

619

620

621

622

623

624

625

626

627

628

629

630

631

632

633

634

635 if (!WithinLowerBound) {

636

637 C.addSink();

638 return;

639 }

640

641

642

643 } else {

644 if (!WithinLowerBound) {

645

646 Messages Msgs = getNonTaintMsgs(C.getASTContext(), Space, Reg,

647 ByteOffset, std::nullopt,

648 Location, BadOffsetKind::Negative);

649 reportOOB(C, PrecedesLowerBound, Msgs, ByteOffset, std::nullopt);

650 return;

651 }

652

653

654 SUR.recordNonNegativeAssumption();

655 }

656 }

657

658

659

660

661 if (WithinLowerBound)

662 State = WithinLowerBound;

663 }

664

665

667 if (auto KnownSize = Size.getAs()) {

668

669

670

671

672

673 bool AlsoMentionUnderflow = SUR.assumedNonNegative();

674

675 auto [WithinUpperBound, ExceedsUpperBound] =

677

678 if (ExceedsUpperBound) {

679

680 if (!WithinUpperBound) {

681

682

683

684 if (isIdiomaticPastTheEndPtr(E, ExceedsUpperBound, ByteOffset,

685 *KnownSize, C)) {

686 C.addTransition(ExceedsUpperBound, SUR.createNoteTag(C));

687 return;

688 }

689

690 BadOffsetKind Problem = AlsoMentionUnderflow

691 ? BadOffsetKind::Indeterminate

692 : BadOffsetKind::Overflowing;

693 Messages Msgs =

695 *KnownSize, Location, Problem);

696 reportOOB(C, ExceedsUpperBound, Msgs, ByteOffset, KnownSize);

697 return;

698 }

699

700 if (isTainted(State, ByteOffset)) {

701

702

703

704

705

706 const char *OffsetName = "offset";

707 if (const auto *ASE = dyn_cast(E))

708 if (isTainted(State, ASE->getIdx(), C.getLocationContext()))

709 OffsetName = "index";

710

711 Messages Msgs =

712 getTaintMsgs(Space, Reg, OffsetName, AlsoMentionUnderflow);

713 reportOOB(C, ExceedsUpperBound, Msgs, ByteOffset, KnownSize,

714 true);

715 return;

716 }

717

718

719 SUR.recordUpperBoundAssumption(*KnownSize);

720 }

721

722

723

724

725 if (WithinUpperBound)

726 State = WithinUpperBound;

727 }

728

729

730 C.addTransition(State, SUR.createNoteTag(C));

731}

732

733void ArrayBoundChecker::markPartsInteresting(PathSensitiveBugReport &BR,

735 NonLoc Val, bool MarkTaint) {

737

738

739

740

741

744 }

745

746 if (MarkTaint) {

747

748

749

750

753 }

754}

755

756void ArrayBoundChecker::reportOOB(CheckerContext &C, ProgramStateRef ErrorState,

757 Messages Msgs, NonLoc Offset,

758 std::optional Extent,

759 bool IsTaintBug ) const {

760

761 ExplodedNode *ErrorNode = C.generateErrorNode(ErrorState);

762 if (!ErrorNode)

763 return;

764

765 auto BR = std::make_unique(

766 IsTaintBug ? TaintBT : BT, Msgs.Short, Msgs.Full, ErrorNode);

767

768

769

770

771

772

773

774

775

776

777

778

779

780

781 markPartsInteresting(*BR, ErrorState, Offset, IsTaintBug);

782 if (Extent)

783 markPartsInteresting(*BR, ErrorState, *Extent, IsTaintBug);

784

785 C.emitReport(std::move(BR));

786}

787

788bool ArrayBoundChecker::isFromCtypeMacro(const Expr *E, ASTContext &ACtx) {

791 return false;

792

795

796 if (MacroName.size() < 7 || MacroName[0] != 'i' || MacroName[1] != 's')

797 return false;

798

799 return ((MacroName == "isalnum") || (MacroName == "isalpha") ||

800 (MacroName == "isblank") || (MacroName == "isdigit") ||

801 (MacroName == "isgraph") || (MacroName == "islower") ||

802 (MacroName == "isnctrl") || (MacroName == "isprint") ||

803 (MacroName == "ispunct") || (MacroName == "isspace") ||

804 (MacroName == "isupper") || (MacroName == "isxdigit"));

805}

806

807bool ArrayBoundChecker::isOffsetObviouslyNonnegative(const Expr *E,

808 CheckerContext &C) {

809 const ArraySubscriptExpr *ASE = getAsCleanArraySubscriptExpr(E, C);

810 if (!ASE)

811 return false;

813}

814

815bool ArrayBoundChecker::isInAddressOf(const Stmt *S, ASTContext &ACtx) {

817 do {

818 const DynTypedNodeList Parents = ParentCtx.getParents(*S);

819 if (Parents.empty())

820 return false;

821 S = Parents[0].get();

822 } while (isa_and_nonnull<ParenExpr, ImplicitCastExpr>(S));

823 const auto *UnaryOp = dyn_cast_or_null(S);

824 return UnaryOp && UnaryOp->getOpcode() == UO_AddrOf;

825}

826

827bool ArrayBoundChecker::isIdiomaticPastTheEndPtr(const Expr *E,

829 NonLoc Offset, NonLoc Limit,

830 CheckerContext &C) {

833 State, Offset, Limit, C.getSValBuilder(), true);

834 return EqualsToThreshold && !NotEqualToThreshold;

835 }

836 return false;

837}

838

839void ento::registerArrayBoundChecker(CheckerManager &mgr) {

841}

842

843bool ento::shouldRegisterArrayBoundChecker(const CheckerManager &mgr) {

844 return true;

845}

static std::pair< ProgramStateRef, ProgramStateRef > compareValueToThreshold(ProgramStateRef State, NonLoc Value, NonLoc Threshold, SValBuilder &SVB, bool CheckEquality=false)

Definition ArrayBoundChecker.cpp:320

static std::string getRegionName(const MemSpaceRegion *Space, const SubRegion *Region)

Definition ArrayBoundChecker.cpp:369

static std::optional< std::pair< const SubRegion *, NonLoc > > computeOffset(ProgramStateRef State, SValBuilder &SVB, SVal Location)

For a given Location that can be represented as a symbolic expression Arr[Idx] (or perhaps Arr[Idx1][...

Definition ArrayBoundChecker.cpp:201

static bool isNegative(SValBuilder &SVB, ProgramStateRef State, NonLoc Value)

Definition ArrayBoundChecker.cpp:302

static std::optional< int64_t > getConcreteValue(NonLoc SV)

Definition ArrayBoundChecker.cpp:394

static Messages getTaintMsgs(const MemSpaceRegion *Space, const SubRegion *Region, const char *OffsetName, bool AlsoMentionUnderflow)

Definition ArrayBoundChecker.cpp:481

static bool isUnsigned(SValBuilder &SVB, NonLoc Value)

Definition ArrayBoundChecker.cpp:307

static Messages getNonTaintMsgs(const ASTContext &ACtx, const MemSpaceRegion *Space, const SubRegion *Region, NonLoc Offset, std::optional< NonLoc > Extent, SVal Location, BadOffsetKind Problem)

Definition ArrayBoundChecker.cpp:424

static std::pair< NonLoc, nonloc::ConcreteInt > getSimplifiedOffsets(NonLoc offset, nonloc::ConcreteInt extent, SValBuilder &svalBuilder)

Definition ArrayBoundChecker.cpp:272

static bool tryDividePair(std::optional< int64_t > &Val1, std::optional< int64_t > &Val2, int64_t Divisor)

Try to divide Val1 and Val2 (in place) by Divisor and return true if it can be performed (Divisor is ...

Definition ArrayBoundChecker.cpp:409

Holds long-lived AST nodes (such as types and decls) that can be referred to throughout the semantic ...

SourceManager & getSourceManager()

ParentMapContext & getParentMapContext()

Returns the dynamic AST node parent map context.

const LangOptions & getLangOpts() const

CharUnits getTypeSizeInChars(QualType T) const

Return the size of the specified (complete) type T, in characters.

ArraySubscriptExpr - [C99 6.5.2.1] Array Subscripting.

QuantityType getQuantity() const

getQuantity - Get the raw integer representation of this quantity.

This represents one expression.

static StringRef getImmediateMacroName(SourceLocation Loc, const SourceManager &SM, const LangOptions &LangOpts)

Retrieve the name of the immediate macro expansion.

DynTypedNodeList getParents(const NodeT &Node)

Returns the parents of the given node (within the traversal scope).

A (possibly-)qualified type.

static std::string getAsString(SplitQualType split, const PrintingPolicy &Policy)

SourceLocation getBeginLoc() const LLVM_READONLY

bool isUnsignedIntegerOrEnumerationType() const

Determines whether this is an integer type that is unsigned or an enumeration types whose underlying ...

bool isIncompleteType(NamedDecl **Def=nullptr) const

Types are partitioned into 3 broad categories (C99 6.2.5p1): object types, function types,...

A record of the "type" of an APSInt, used for conversions.

llvm::APSInt convert(const llvm::APSInt &Value) const LLVM_READONLY

Convert and return a new APSInt with the given value, but this type's bit width and signedness.

CHECKER * registerChecker(AT &&...Args)

Register a single-part checker (derived from Checker): construct its singleton instance,...

Simple checker classes that implement one frontend (i.e.

ElementRegion is used to represent both array elements and casts.

QualType getElementType() const

MemRegion - The root abstract class for all memory regions.

LLVM_ATTRIBUTE_RETURNS_NONNULL const MemRegion * StripCasts(bool StripBaseAndDerivedCasts=true) const

std::string getDescriptiveName(bool UseQuotes=true) const

Get descriptive name for memory region.

const RegionTy * getAs() const

MemSpaceRegion - A memory region that represents a "memory space"; for example, the set of global var...

The tag upon which the TagVisitor reacts.

void markInteresting(SymbolRef sym, bugreporter::TrackingKind TKind=bugreporter::TrackingKind::Thorough)

Marks a symbol as interesting.

bool isInteresting(SymbolRef sym) const

NonLoc makeArrayIndex(uint64_t idx)

ASTContext & getContext()

nonloc::ConcreteInt makeIntVal(const IntegerLiteral *integer)

QualType getArrayIndexType() const

virtual SVal evalBinOpNN(ProgramStateRef state, BinaryOperator::Opcode op, NonLoc lhs, NonLoc rhs, QualType resultTy)=0

Create a new value which represents a binary expression with two non- location operands.

QualType getConditionType() const

virtual const llvm::APSInt * getMaxValue(ProgramStateRef state, SVal val)=0

Tries to get the maximal possible (integer) value of a given SVal.

NonLoc makeZeroArrayIndex()

SVal - This represents a symbolic expression, which can be either an L-value or an R-value.

SymbolRef getAsSymbol(bool IncludeBaseRegions=false) const

If this SVal wraps a symbol return that SymbolRef.

std::optional< T > getAs() const

Convert to the specified SVal type, returning std::nullopt if this SVal is not of the desired type.

SubRegion - A region that subsets another larger region.

LLVM_ATTRIBUTE_RETURNS_NONNULL const MemRegion * getSuperRegion() const

llvm::iterator_range< symbol_iterator > symbols() const

Value representing integer constant.

APSIntPtr getValue() const

Represents symbolic expression that isn't a location.

const char *const TaintedData

std::vector< SymbolRef > getTaintedSymbols(ProgramStateRef State, const Stmt *S, const LocationContext *LCtx, TaintTagType Kind=TaintTagGeneric)

Returns the tainted Symbols for a given Statement and state.

bool isTainted(ProgramStateRef State, const Stmt *S, const LocationContext *LCtx, TaintTagType Kind=TaintTagGeneric)

Check if the statement has a tainted value in the given state.

IntrusiveRefCntPtr< const ProgramState > ProgramStateRef

const SymExpr * SymbolRef

DefinedOrUnknownSVal getDynamicExtent(ProgramStateRef State, const MemRegion *MR, SValBuilder &SVB)

BinarySymExprImpl< const SymExpr *, APSIntPtr, SymExpr::Kind::SymIntExprKind > SymIntExpr

Represents a symbolic expression like 'x' + 3.

The JSON file list parser is used to communicate input to InstallAPI.

bool isa(CodeGen::Address addr)

const FunctionProtoType * T