|
62 | 62 | #include "klee/Solver/Common.h"
|
63 | 63 | #include "klee/Solver/Solver.h"
|
64 | 64 | #include "klee/Solver/SolverCmdLine.h"
|
| 65 | +#include "klee/Solver/SolverUtil.h" |
65 | 66 | #include "klee/Statistics/TimerStatIncrementer.h"
|
66 | 67 | #include "klee/Support/Casting.h"
|
67 | 68 | #include "klee/Support/ErrorHandling.h"
|
@@ -5424,6 +5425,7 @@ void Executor::executeAlloc(ExecutionState &state, ref<Expr> size, bool isLocal,
|
5424 | 5425 | makeMockValue(state, "symCheckOutOfMemory", Expr::Bool);
|
5425 | 5426 | address = SelectExpr::create(symCheckOutOfMemoryExpr,
|
5426 | 5427 | Expr::createPointer(0), address);
|
| 5428 | + state.outOfMemoryMarkers.push_back(symCheckOutOfMemoryExpr); |
5427 | 5429 | }
|
5428 | 5430 |
|
5429 | 5431 | // state.addPointerResolution(address, mo);
|
@@ -6317,12 +6319,91 @@ void Executor::executeMemoryOperation(
|
6317 | 6319 | StatePair branches =
|
6318 | 6320 | forkInternal(estate, Expr::createIsZero(base), BranchType::MemOp);
|
6319 | 6321 | ExecutionState *bound = branches.first;
|
| 6322 | + |
6320 | 6323 | if (bound) {
|
6321 |
| - auto error = isReadFromSymbolicArray(uniqueBase) |
6322 |
| - ? ReachWithError::MayBeNullPointerException |
6323 |
| - : ReachWithError::MustBeNullPointerException; |
6324 |
| - terminateStateOnTargetError(*bound, error); |
| 6324 | + // If there are no markers on `malloc` returning nullptr, |
| 6325 | + // then `confidence` depends on presence of `unbound` state. |
| 6326 | + if (!bound->outOfMemoryMarkers.empty()) { |
| 6327 | + // bound constraints already contain `Expr::createIsZero()` |
| 6328 | + std::vector<const Array *> markersArrays; |
| 6329 | + markersArrays.reserve(bound->outOfMemoryMarkers.size()); |
| 6330 | + findSymbolicObjects(bound->outOfMemoryMarkers.begin(), |
| 6331 | + bound->outOfMemoryMarkers.end(), markersArrays); |
| 6332 | + |
| 6333 | + // Do some iterations (2-3) to figure out if error is confident. |
| 6334 | + ref<Expr> allExcludedVectorsOfMarkers = Expr::createTrue(); |
| 6335 | + |
| 6336 | + bool convinced = false; |
| 6337 | + for (int tpCheckIteration = 0; tpCheckIteration < 2; ++tpCheckIteration) { |
| 6338 | + ref<SolverResponse> isConfidentResponse; |
| 6339 | + if (!solver->getResponse(bound->constraints.cs(), |
| 6340 | + allExcludedVectorsOfMarkers, |
| 6341 | + isConfidentResponse, bound->queryMetaData)) { |
| 6342 | + terminateStateOnSolverError(*bound, "Query timeout"); |
| 6343 | + } |
| 6344 | + |
| 6345 | + if (isa<ValidResponse>(isConfidentResponse)) { |
| 6346 | + reportStateOnTargetError(*bound, |
| 6347 | + ReachWithError::MustBeNullPointerException); |
| 6348 | + |
| 6349 | + terminateStateOnProgramError( |
| 6350 | + *bound, |
| 6351 | + new ErrorEvent(locationOf(*bound), StateTerminationType::Ptr, |
| 6352 | + "memory error: null pointer exception"), |
| 6353 | + StateTerminationConfidenceCategory::CONFIDENT); |
| 6354 | + convinced = true; |
| 6355 | + break; |
| 6356 | + } |
| 6357 | + |
| 6358 | + // Receive current values of markers |
| 6359 | + std::vector<SparseStorage<unsigned char>> boundSetSolution; |
| 6360 | + isConfidentResponse->tryGetInitialValuesFor(markersArrays, |
| 6361 | + boundSetSolution); |
| 6362 | + Assignment nonConfidentResponseAssignment(markersArrays, |
| 6363 | + boundSetSolution); |
| 6364 | + |
| 6365 | + // Exclude this combinations of markers |
| 6366 | + |
| 6367 | + ref<Expr> conjExcludedVectorOfMarkers = Expr::createTrue(); |
| 6368 | + for (ref<Expr> marker : bound->outOfMemoryMarkers) { |
| 6369 | + conjExcludedVectorOfMarkers = AndExpr::create( |
| 6370 | + conjExcludedVectorOfMarkers, |
| 6371 | + EqExpr::create(marker, |
| 6372 | + nonConfidentResponseAssignment.evaluate(marker))); |
| 6373 | + } |
| 6374 | + |
| 6375 | + allExcludedVectorsOfMarkers = |
| 6376 | + OrExpr::create(allExcludedVectorsOfMarkers, |
| 6377 | + NotExpr::create(conjExcludedVectorOfMarkers)); |
| 6378 | + } |
| 6379 | + |
| 6380 | + if (!convinced) { |
| 6381 | + reportStateOnTargetError(*bound, |
| 6382 | + ReachWithError::MayBeNullPointerException); |
| 6383 | + |
| 6384 | + terminateStateOnProgramError( |
| 6385 | + *bound, |
| 6386 | + new ErrorEvent(locationOf(*bound), StateTerminationType::Ptr, |
| 6387 | + "memory error: null pointer exception"), |
| 6388 | + StateTerminationConfidenceCategory::PROBABLY); |
| 6389 | + } |
| 6390 | + |
| 6391 | + } else { |
| 6392 | + auto error = branches.second != nullptr |
| 6393 | + ? ReachWithError::MayBeNullPointerException |
| 6394 | + : ReachWithError::MustBeNullPointerException; |
| 6395 | + reportStateOnTargetError(*bound, error); |
| 6396 | + |
| 6397 | + terminateStateOnProgramError( |
| 6398 | + *bound, |
| 6399 | + new ErrorEvent(locationOf(*bound), StateTerminationType::Ptr, |
| 6400 | + "memory error: null pointer exception"), |
| 6401 | + branches.second != nullptr |
| 6402 | + ? StateTerminationConfidenceCategory::PROBABLY |
| 6403 | + : StateTerminationConfidenceCategory::CONFIDENT); |
| 6404 | + } |
6325 | 6405 | }
|
| 6406 | + |
6326 | 6407 | if (!branches.second)
|
6327 | 6408 | return;
|
6328 | 6409 | ExecutionState *state = branches.second;
|
@@ -6916,7 +6997,8 @@ void Executor::executeMakeSymbolic(ExecutionState &state,
|
6916 | 6997 | (!AllowSeedTruncation && obj->numBytes > mo->size))) {
|
6917 | 6998 | std::stringstream msg;
|
6918 | 6999 | msg << "replace size mismatch: " << mo->name << "[" << mo->size
|
6919 |
| - << "]" << " vs " << obj->name << "[" << obj->numBytes << "]" |
| 7000 | + << "]" |
| 7001 | + << " vs " << obj->name << "[" << obj->numBytes << "]" |
6920 | 7002 | << " in test\n";
|
6921 | 7003 |
|
6922 | 7004 | terminateStateOnUserError(state, msg.str());
|
@@ -7360,7 +7442,8 @@ void Executor::logState(const ExecutionState &state, int id,
|
7360 | 7442 | *f << "Address memory object: " << object.first->address << "\n";
|
7361 | 7443 | *f << "Memory object size: " << object.first->size << "\n";
|
7362 | 7444 | }
|
7363 |
| - *f << state.symbolics.size() << " symbolics total. " << "Symbolics:\n"; |
| 7445 | + *f << state.symbolics.size() << " symbolics total. " |
| 7446 | + << "Symbolics:\n"; |
7364 | 7447 | size_t sc = 0;
|
7365 | 7448 | for (const auto &symbolic : state.symbolics) {
|
7366 | 7449 | *f << "Symbolic number " << sc++ << "\n";
|
|
0 commit comments