Skip to content

Commit c460ace

Browse files
authored
fix: Improve bidirectional memory allocation model (#205)
* feat: bidirectional memory proper handling * fix: handling pointers in bitwuzla builder * fix: memory leak in bidirectional * fix: pointer handling in solvers * fix: test headers * fix: caching pointer resolutions wherever safe (in not isolated states)
1 parent b5b4bf9 commit c460ace

22 files changed

Lines changed: 398 additions & 12 deletions

lib/Core/Composer.cpp

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -221,6 +221,17 @@ ExprVisitor::Action ComposeVisitor::visitSelect(const SelectExpr &select) {
221221
processSelect(select.cond, select.trueExpr, select.falseExpr));
222222
}
223223

224+
ExprVisitor::Action
225+
ComposeVisitor::visitPointer(const PointerExpr &pointerExpr) {
226+
return Action::changeTo(processPointer(pointerExpr.base, pointerExpr.value));
227+
}
228+
229+
ref<Expr> ComposeVisitor::processPointer(ref<Expr> base, ref<Expr> value) {
230+
auto trueBase = visit(base)->getValue();
231+
auto trueValue = visit(value)->getValue();
232+
return PointerExpr::create(trueBase, trueValue);
233+
}
234+
224235
ref<ObjectState> ComposeVisitor::shareUpdates(ref<ObjectState> os,
225236
const UpdateList &updates) {
226237
ref<ObjectState> copy(new ObjectState(*os.get()));

lib/Core/Composer.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -200,6 +200,9 @@ class ComposeVisitor : public ExprVisitor {
200200
ExprVisitor::Action visitRead(const ReadExpr &) override;
201201
ExprVisitor::Action visitConcat(const ConcatExpr &concat) override;
202202
ExprVisitor::Action visitSelect(const SelectExpr &) override;
203+
ExprVisitor::Action visitPointer(const PointerExpr &) override;
204+
205+
ref<Expr> processPointer(ref<Expr> base, ref<Expr> value);
203206
ref<Expr> processRead(const Array *root, const UpdateList &updates,
204207
ref<Expr> index, Expr::Width width);
205208
ref<Expr> processSelect(ref<Expr> cond, ref<Expr> trueExpr,

lib/Core/ExecutionState.cpp

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -167,9 +167,9 @@ ExecutionState::ExecutionState(const ExecutionState &state)
167167
forkDisabled(state.forkDisabled), isolated(state.isolated),
168168
finalComposing(state.finalComposing), returnValue(state.returnValue),
169169
gepExprBases(state.gepExprBases), multiplexKF(state.multiplexKF),
170-
prevTargets_(state.prevTargets_), targets_(state.targets_),
171-
prevHistory_(state.prevHistory_), history_(state.history_),
172-
isTargeted_(state.isTargeted_) {
170+
localObjects(state.localObjects), prevTargets_(state.prevTargets_),
171+
targets_(state.targets_), prevHistory_(state.prevHistory_),
172+
history_(state.history_), isTargeted_(state.isTargeted_) {
173173
queryMetaData.id = state.id;
174174
}
175175

lib/Core/ExecutionState.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -405,6 +405,9 @@ class ExecutionState {
405405
// Temp: to know which multiplex path this state has taken
406406
KFunction *multiplexKF = nullptr;
407407

408+
// set with reads from alloca instructions
409+
std::set<ref<const MemoryObject>> localObjects;
410+
408411
private:
409412
PersistentSet<ref<Target>> prevTargets_;
410413
PersistentSet<ref<Target>> targets_;

lib/Core/Executor.cpp

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5391,6 +5391,7 @@ void Executor::run(ExecutionState *initialState,
53915391
} else if (ExecutionMode == ExecutionKind::Bidirectional) {
53925392
InitializerPredicate *predicate = new TraceVerifyPredicate(
53935393
data.specialPoints, *codeGraphInfo.get(), InitializeInJoinBlocks);
5394+
// object manager assumes ownership over predicate
53945395
objectManager->setPredicate(predicate);
53955396
auto initializer = createIsolatedStatesInitializer(predicate, data);
53965397
isolatedStatesInitializer = initializer.get();
@@ -7380,8 +7381,10 @@ void Executor::lazyInitializeLocalObject(ExecutionState &state, StackFrame &sf,
73807381
ref<const MemoryObject> id = lazyInitializeObject(
73817382
state, pointer, target, elementSize, size, true, conditionExpr,
73827383
state.isolated || UseSymbolicSizeLazyInit);
7383-
state.addPointerResolution(pointer, id.get());
7384-
state.addPointerResolution(basePointer, id.get());
7384+
if (!state.isolated) {
7385+
state.addPointerResolution(pointer, id.get());
7386+
state.addPointerResolution(basePointer, id.get());
7387+
}
73857388
state.addConstraint(EqExpr::create(address, id->getBaseExpr()));
73867389
state.addConstraint(
73877390
Expr::createIsZero(EqExpr::create(address, Expr::createPointer(0))));
@@ -7390,6 +7393,14 @@ void Executor::lazyInitializeLocalObject(ExecutionState &state, StackFrame &sf,
73907393
}
73917394
RefObjectPair op = state.addressSpace.findOrLazyInitializeObject(id.get());
73927395
state.addressSpace.bindObject(op.first, op.second.get());
7396+
if (state.localObjects.count(id) == 0) {
7397+
for (auto localObject : state.localObjects) {
7398+
auto localObjectAddress = localObject->getBaseExpr();
7399+
state.constraints.addConstraint(Expr::createIsZero(
7400+
EqExpr::create(id->getBaseExpr(), localObjectAddress)));
7401+
}
7402+
state.localObjects.insert(id);
7403+
}
73937404
}
73947405

73957406
void Executor::lazyInitializeLocalObject(ExecutionState &state,

lib/Core/ObjectManager.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -116,7 +116,7 @@ class ObjectManager {
116116
std::vector<Subscriber *> subscribers;
117117
PForest *processForest;
118118

119-
InitializerPredicate *predicate;
119+
std::unique_ptr<InitializerPredicate> predicate;
120120

121121
public:
122122
ExecutionState *emptyState;
@@ -164,7 +164,7 @@ class ObjectManager {
164164
}
165165

166166
void setPredicate(InitializerPredicate *predicate_) {
167-
predicate = predicate_;
167+
predicate = std::unique_ptr<InitializerPredicate>(predicate_);
168168
}
169169
};
170170

lib/Solver/BitwuzlaBuilder.cpp

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1113,6 +1113,11 @@ Term BitwuzlaBuilder::constructActual(ref<Expr> e, int *width_out) {
11131113
assert(*width_out != 1 && "uncanonicalized FNeg");
11141114
return ctx->mk_term(Kind::FP_NEG, {arg});
11151115
}
1116+
case Expr::Pointer:
1117+
case Expr::ConstantPointer: {
1118+
PointerExpr *pointerExpr = cast<PointerExpr>(e);
1119+
return constructActual(pointerExpr->getValue(), width_out);
1120+
};
11161121

11171122
// unused due to canonicalization
11181123
#if 0
@@ -1124,7 +1129,7 @@ case Expr::Sge:
11241129
#endif
11251130

11261131
default:
1127-
assert(0 && "unhandled Expr type");
1132+
klee_error("unhandled Expr type");
11281133
return getTrue();
11291134
}
11301135
}

lib/Solver/MetaSMTBuilder.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -658,7 +658,7 @@ MetaSMTBuilder<SolverContext>::constructActual(ref<Expr> e, int *width_out) {
658658
switch (e->getKind()) {
659659
case Expr::Pointer:
660660
case Expr::ConstantPointer: {
661-
assert(0 && "unreachable");
661+
return constructActual(e->getValue(), width_out);
662662
}
663663

664664
case Expr::Constant: {

lib/Solver/Z3BitvectorBuilder.cpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -273,7 +273,8 @@ Z3ASTHandle Z3BitvectorBuilder::constructActual(ref<Expr> e, int *width_out) {
273273
switch (e->getKind()) {
274274
case Expr::Pointer:
275275
case Expr::ConstantPointer: {
276-
assert(0 && "unreachable");
276+
auto ptrExpr = cast<PointerExpr>(e);
277+
return constructActual(ptrExpr->getValue(), width_out);
277278
}
278279

279280
case Expr::Constant: {

lib/Solver/Z3CoreBuilder.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -206,7 +206,7 @@ Z3ASTHandle Z3CoreBuilder::constructActual(ref<Expr> e, int *width_out) {
206206
switch (e->getKind()) {
207207
case Expr::Pointer:
208208
case Expr::ConstantPointer: {
209-
assert(0 && "unreachable");
209+
return constructActual(e->getValue(), width_out);
210210
}
211211

212212
case Expr::Constant: {

0 commit comments

Comments
 (0)