18#include "llvm/ADT/Statistic.h"
19#include "llvm/Support/SMTAPI.h"
20#include "llvm/Support/Timer.h"
22#define DEBUG_TYPE "Z3CrosscheckOracle"
24STATISTIC(NumZ3QueriesDone,
"Number of Z3 queries done");
25STATISTIC(NumTimesZ3TimedOut,
"Number of times Z3 query timed out");
27 "Number of times Z3 query exhausted the rlimit");
28STATISTIC(NumTimesZ3SpendsTooMuchTimeOnASingleEQClass,
29 "Number of times report equivalenece class was cut because it spent "
30 "too much time in Z3");
33 "Number of Z3 queries accepting a report");
35 "Number of Z3 queries rejecting a report");
37 "Number of times rejecting an report equivalenece class");
44 : Constraints(
ConstraintMap::Factory().getEmptyMap()), Result(Result),
51 addConstraints(EndPathNode,
true);
54 llvm::SMTSolverRef RefutationSolver = llvm::CreateZ3Solver();
55 if (Opts.Z3CrosscheckRLimitThreshold)
56 RefutationSolver->setUnsignedParam(
"rlimit",
57 Opts.Z3CrosscheckRLimitThreshold);
58 if (Opts.Z3CrosscheckTimeoutThreshold)
59 RefutationSolver->setUnsignedParam(
"timeout",
60 Opts.Z3CrosscheckTimeoutThreshold);
65 for (
const auto &[Sym,
Range] : Constraints) {
66 auto RangeIt =
Range.begin();
69 RefutationSolver, Ctx, Sym, RangeIt->From(), RangeIt->To(),
71 while ((++RangeIt) !=
Range.end()) {
72 SMTConstraints = RefutationSolver->mkOr(
74 RangeIt->From(), RangeIt->To(),
77 RefutationSolver->addConstraint(SMTConstraints);
81 llvm::TimeRecord Start = llvm::TimeRecord::getCurrentTime(
true);
82 std::optional<bool> IsSAT = RefutationSolver->check();
83 llvm::TimeRecord Diff = llvm::TimeRecord::getCurrentTime(
false);
87 static_cast<unsigned>(Diff.getWallTime() * 1000),
88 RefutationSolver->getStatistics()->getUnsigned(
"rlimit count"),
92void Z3CrosscheckVisitor::addConstraints(
93 const ExplodedNode *N,
bool OverwriteConstraintsOnExistingSyms) {
99 for (
auto const &[Sym,
Range] : NewCs) {
100 if (!Constraints.contains(Sym)) {
102 Constraints =
CF.add(Constraints, Sym,
Range);
103 }
else if (OverwriteConstraintsOnExistingSyms) {
105 Constraints =
CF.remove(Constraints, Sym);
106 Constraints =
CF.add(Constraints, Sym,
Range);
114 addConstraints(N,
false);
129 ++NumTimesZ3QueryAcceptsReport;
134 if (Opts.Z3CrosscheckTimeoutThreshold &&
136 ++NumTimesZ3TimedOut;
137 ++NumTimesZ3QueryRejectEQClass;
141 if (Opts.Z3CrosscheckRLimitThreshold &&
142 Query.
UsedRLimit >= Opts.Z3CrosscheckRLimitThreshold) {
143 ++NumTimesZ3ExhaustedRLimit;
144 ++NumTimesZ3QueryRejectEQClass;
148 if (Opts.Z3CrosscheckEQClassTimeoutThreshold &&
149 AccumulatedZ3QueryTimeInEqClass >
150 Opts.Z3CrosscheckEQClassTimeoutThreshold) {
151 ++NumTimesZ3SpendsTooMuchTimeOnASingleEQClass;
152 ++NumTimesZ3QueryRejectEQClass;
158 ++NumTimesZ3QueryRejectReport;
STATISTIC(NumZ3QueriesDone, "Number of Z3 queries done")
Holds long-lived AST nodes (such as types and decls) that can be referred to throughout the semantic ...
Stores options for the analyzer from the command line.
ASTContext & getASTContext() const
const ProgramStateRef & getState() const
A Range represents the closed range [from, to].
static llvm::SMTExprRef getRangeExpr(llvm::SMTSolverRef &Solver, ASTContext &Ctx, SymbolRef Sym, const llvm::APSInt &From, const llvm::APSInt &To, bool InRange)
Z3Decision interpretQueryResult(const Z3CrosscheckVisitor::Z3Result &Meta)
Updates the internal state with the new Z3Result and makes a decision how to proceed:
PathDiagnosticPieceRef VisitNode(const ExplodedNode *N, BugReporterContext &BRC, PathSensitiveBugReport &BR) override
Return a diagnostic piece which should be associated with the given node.
void Profile(llvm::FoldingSetNodeID &ID) const override
Z3CrosscheckVisitor(Z3CrosscheckVisitor::Z3Result &Result, const AnalyzerOptions &Opts)
void finalizeVisitor(BugReporterContext &BRC, const ExplodedNode *EndPathNode, PathSensitiveBugReport &BR) override
Last function called on the visitor, no further calls to VisitNode would follow.
llvm::ImmutableMap< SymbolRef, RangeSet > ConstraintMap
@ CF
Indicates that the tracked object is a CF object.
std::shared_ptr< PathDiagnosticPiece > PathDiagnosticPieceRef
ConstraintMap getConstraintMap(ProgramStateRef State)
The JSON file list parser is used to communicate input to InstallAPI.
unsigned Z3QueryTimeMilliseconds
std::optional< bool > IsSAT