Skip to content

Commit c3553c0

Browse files
ocelaiwomisonijnik
authored andcommitted
[feat] Uninitialized Memory [feat] Sizeless ObjectState
[feat] STP and MetaSMT symsize array support
1 parent d5ff4df commit c3553c0

File tree

83 files changed

+4973
-1175
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

83 files changed

+4973
-1175
lines changed

include/klee/ADT/KTest.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,7 @@ struct KTest {
4646

4747
unsigned numObjects;
4848
KTestObject *objects;
49+
unsigned uninitCoeff;
4950
};
5051

5152
/* returns the current .ktest file format version */

include/klee/ADT/Ref.h

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -215,6 +215,19 @@ template <class T> class ref {
215215
bool operator!=(const ref &rhs) const { return !equals(rhs); }
216216
};
217217

218+
template <typename T> class OptionalRefEq {
219+
public:
220+
bool operator()(const ref<T> &lhs, const ref<T> &rhs) {
221+
if (lhs.isNull() && rhs.isNull()) {
222+
return true;
223+
}
224+
if (lhs.isNull() || rhs.isNull()) {
225+
return false;
226+
}
227+
return lhs.get()->equals(*rhs.get());
228+
}
229+
};
230+
218231
template <class T>
219232
inline llvm::raw_ostream &operator<<(llvm::raw_ostream &os, const ref<T> &e) {
220233
os << *e;

include/klee/ADT/SparseStorage.h

Lines changed: 80 additions & 65 deletions
Original file line numberDiff line numberDiff line change
@@ -3,67 +3,56 @@
33

44
#include <cassert>
55
#include <cstddef>
6+
#include <functional>
67
#include <iterator>
78
#include <map>
9+
#include <unordered_map>
810
#include <vector>
911

12+
namespace llvm {
13+
class raw_ostream;
14+
};
15+
1016
namespace klee {
1117

12-
template <typename ValueType> class SparseStorage {
18+
enum class Density {
19+
Sparse,
20+
Dense,
21+
};
22+
23+
template <typename ValueType, typename Eq = std::equal_to<ValueType>>
24+
class SparseStorage {
1325
private:
14-
size_t capacity;
15-
std::map<size_t, ValueType> internalStorage;
26+
std::unordered_map<size_t, ValueType> internalStorage;
1627
ValueType defaultValue;
28+
Eq eq;
1729

1830
bool contains(size_t key) const { return internalStorage.count(key) != 0; }
1931

2032
public:
21-
struct Iterator {
22-
using iterator_category = std::input_iterator_tag;
23-
using difference_type = std::ptrdiff_t;
24-
using value_type = ValueType;
25-
using pointer = ValueType *;
26-
using reference = ValueType &;
27-
28-
private:
29-
size_t idx;
30-
const SparseStorage *owner;
31-
32-
public:
33-
Iterator(size_t idx, const SparseStorage *owner) : idx(idx), owner(owner) {}
34-
35-
value_type operator*() const { return owner->load(idx); }
36-
37-
Iterator &operator++() {
38-
++idx;
39-
return *this;
40-
}
41-
42-
Iterator operator++(int) {
43-
Iterator snap = *this;
44-
++(*this);
45-
return snap;
33+
SparseStorage(const ValueType &defaultValue = ValueType())
34+
: defaultValue(defaultValue) {}
35+
36+
SparseStorage(const std::unordered_map<size_t, ValueType> &internalStorage,
37+
const ValueType &defaultValue)
38+
: defaultValue(defaultValue) {
39+
for (auto &[index, value] : internalStorage) {
40+
store(index, value);
4641
}
47-
48-
bool operator==(const Iterator &other) const { return idx == other.idx; }
49-
50-
bool operator!=(const Iterator &other) const { return !(*this == other); }
51-
};
52-
53-
SparseStorage(size_t capacity = 0,
54-
const ValueType &defaultValue = ValueType())
55-
: capacity(capacity), defaultValue(defaultValue) {}
42+
}
5643

5744
SparseStorage(const std::vector<ValueType> &values,
5845
const ValueType &defaultValue = ValueType())
59-
: capacity(values.capacity()), defaultValue(defaultValue) {
60-
for (size_t idx = 0; idx < values.capacity(); ++idx) {
61-
internalStorage[idx] = values[idx];
46+
: defaultValue(defaultValue) {
47+
for (size_t idx = 0; idx < values.size(); ++idx) {
48+
store(idx, values[idx]);
6249
}
6350
}
6451

6552
void store(size_t idx, const ValueType &value) {
66-
if (idx < capacity) {
53+
if (eq(value, defaultValue)) {
54+
internalStorage.erase(idx);
55+
} else {
6756
internalStorage[idx] = value;
6857
}
6958
}
@@ -77,55 +66,81 @@ template <typename ValueType> class SparseStorage {
7766
}
7867

7968
ValueType load(size_t idx) const {
80-
assert(idx < capacity && idx >= 0);
8169
return contains(idx) ? internalStorage.at(idx) : defaultValue;
8270
}
8371

84-
size_t size() const { return capacity; }
85-
86-
void resize(size_t newCapacity) {
87-
assert(newCapacity >= 0);
88-
// Free to extend
89-
if (newCapacity >= capacity) {
90-
capacity = newCapacity;
91-
return;
92-
}
93-
94-
// Truncate unnessecary elements
95-
auto iterOnNewSize = internalStorage.lower_bound(newCapacity);
96-
while (iterOnNewSize != internalStorage.end()) {
97-
iterOnNewSize = internalStorage.erase(iterOnNewSize);
72+
size_t sizeOfSetRange() const {
73+
size_t sizeOfRange = 0;
74+
for (auto i : internalStorage) {
75+
sizeOfRange = std::max(i.first, sizeOfRange);
9876
}
99-
100-
capacity = newCapacity;
77+
return sizeOfRange;
10178
}
10279

10380
bool operator==(const SparseStorage<ValueType> &another) const {
104-
return size() == another.size() && defaultValue == another.defaultValue &&
105-
internalStorage == another.internalStorage;
81+
return defaultValue == another.defaultValue && compare(another) == 0;
10682
}
10783

10884
bool operator!=(const SparseStorage<ValueType> &another) const {
10985
return !(*this == another);
11086
}
11187

11288
bool operator<(const SparseStorage &another) const {
113-
return internalStorage < another.internalStorage;
89+
return compare(another) == -1;
11490
}
11591

11692
bool operator>(const SparseStorage &another) const {
117-
return internalStorage > another.internalStorage;
93+
return compare(another) == 1;
94+
}
95+
96+
int compare(const SparseStorage<ValueType> &other) const {
97+
auto ordered = calculateOrderedStorage();
98+
auto otherOrdered = other.calculateOrderedStorage();
99+
100+
if (ordered == otherOrdered) {
101+
return 0;
102+
} else {
103+
return ordered < otherOrdered ? -1 : 1;
104+
}
105+
}
106+
107+
std::map<size_t, ValueType> calculateOrderedStorage() const {
108+
std::map<size_t, ValueType> ordered;
109+
for (const auto &i : internalStorage) {
110+
ordered.insert(i);
111+
}
112+
return ordered;
113+
}
114+
115+
std::vector<ValueType> getFirstNIndexes(size_t n) const {
116+
std::vector<ValueType> vectorized(n);
117+
for (size_t i = 0; i < n; i++) {
118+
vectorized[i] = load(i);
119+
}
120+
return vectorized;
121+
}
122+
123+
const std::unordered_map<size_t, ValueType> &storage() const {
124+
return internalStorage;
125+
};
126+
127+
const ValueType &defaultV() const { return defaultValue; };
128+
129+
void reset() { internalStorage.clear(); }
130+
131+
void reset(ValueType newDefault) {
132+
defaultValue = newDefault;
133+
internalStorage.clear();
118134
}
119135

120-
Iterator begin() const { return Iterator(0, this); }
121-
Iterator end() const { return Iterator(size(), this); }
136+
void print(llvm::raw_ostream &os, Density) const;
122137
};
123138

124139
template <typename U>
125140
SparseStorage<unsigned char> sparseBytesFromValue(const U &value) {
126141
const unsigned char *valueUnsignedCharIterator =
127142
reinterpret_cast<const unsigned char *>(&value);
128-
SparseStorage<unsigned char> result(sizeof(value));
143+
SparseStorage<unsigned char> result;
129144
result.store(0, valueUnsignedCharIterator,
130145
valueUnsignedCharIterator + sizeof(value));
131146
return result;

include/klee/Expr/ArrayCache.h

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -61,10 +61,9 @@ class ArrayCache {
6161
klee::EquivArrayCmpFn>
6262
ArrayHashSet;
6363
ArrayHashSet cachedSymbolicArrays;
64-
typedef std::vector<const Array *> ArrayPtrVec;
65-
ArrayPtrVec concreteArrays;
6664

67-
unsigned getNextID() const;
65+
// Number of arrays of each source allocated
66+
std::unordered_map<SymbolicSource::Kind, unsigned> allocatedCount;
6867
};
6968
} // namespace klee
7069

include/klee/Expr/Assignment.h

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -95,8 +95,10 @@ class AssignmentEvaluator : public ExprEvaluator {
9595
inline ref<Expr> Assignment::evaluate(const Array *array, unsigned index,
9696
bool allowFreeValues) const {
9797
assert(array);
98+
auto sizeExpr = evaluate(array->size);
9899
bindings_ty::iterator it = bindings.find(array);
99-
if (it != bindings.end() && index < it->second.size()) {
100+
if (it != bindings.end() && isa<ConstantExpr>(sizeExpr) &&
101+
index < cast<ConstantExpr>(sizeExpr)->getZExtValue()) {
100102
return ConstantExpr::alloc(it->second.load(index), array->getRange());
101103
} else {
102104
if (allowFreeValues) {

include/klee/Expr/Expr.h

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -415,7 +415,7 @@ struct Expr::CreateArg {
415415
// Comparison operators
416416

417417
inline bool operator==(const Expr &lhs, const Expr &rhs) {
418-
return lhs.compare(rhs) == 0;
418+
return lhs.equals(rhs);
419419
}
420420

421421
inline bool operator<(const Expr &lhs, const Expr &rhs) {
@@ -636,10 +636,7 @@ class Array {
636636

637637
public:
638638
bool isSymbolicArray() const { return !isConstantArray(); }
639-
bool isConstantArray() const {
640-
return isa<ConstantSource>(source) ||
641-
isa<SymbolicSizeConstantSource>(source);
642-
}
639+
bool isConstantArray() const { return isa<ConstantSource>(source); }
643640

644641
const std::string getName() const { return source->toString(); }
645642
const std::string getIdentifier() const {

include/klee/Expr/Parser/Lexer.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,8 @@ struct Token {
3232
KWFalse, ///< 'false'
3333
KWQuery, ///< 'query'
3434
KWPath, ///< 'path'
35+
KWDefault, ///< 'default'
36+
KWNull, ///< 'null'
3537
KWReserved, ///< fp[0-9]+([.].*)?, i[0-9]+
3638
KWSymbolic, ///< 'symbolic'
3739
KWTrue, ///< 'true'

include/klee/Expr/SourceBuilder.h

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
#define KLEE_SOURCEBUILDER_H
33

44
#include "klee/ADT/Ref.h"
5+
#include "klee/ADT/SparseStorage.h"
56
#include "klee/Expr/SymbolicSource.h"
67
#include "klee/Module/KModule.h"
78

@@ -12,10 +13,13 @@ class SourceBuilder {
1213
SourceBuilder() = delete;
1314

1415
static ref<SymbolicSource>
15-
constant(const std::vector<ref<ConstantExpr>> &constantValues);
16-
static ref<SymbolicSource> symbolicSizeConstant(unsigned defaultValue);
17-
static ref<SymbolicSource> symbolicSizeConstantAddress(unsigned defaultValue,
18-
unsigned version);
16+
constant(SparseStorage<ref<ConstantExpr>> constantValues);
17+
18+
static ref<SymbolicSource> uninitialized(unsigned version,
19+
const KInstruction *allocSite);
20+
static ref<SymbolicSource>
21+
symbolicSizeConstantAddress(unsigned version, const KInstruction *allocSite,
22+
ref<Expr> size);
1923
static ref<SymbolicSource> makeSymbolic(const std::string &name,
2024
unsigned version);
2125
static ref<SymbolicSource> lazyInitializationAddress(ref<Expr> pointer);

0 commit comments

Comments
 (0)