Skip to content

Commit e7c971b

Browse files
committed
[feat] Uninitialized Memory [feat] Sizeless ObjectState
[feat] STP symsize array support
1 parent f1e8720 commit e7c971b

File tree

81 files changed

+4976
-1138
lines changed

Some content is hidden

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

81 files changed

+4976
-1138
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: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -205,7 +205,13 @@ template <class T> class ref {
205205

206206
// assumes non-null arguments
207207
bool equals(const ref &rhs) const {
208-
assert(!isNull() && !rhs.isNull() && "Invalid call to compare()");
208+
if (isNull() && rhs.isNull()) {
209+
return true;
210+
}
211+
if (isNull() || rhs.isNull()) {
212+
return false;
213+
}
214+
// assert(!isNull() && !rhs.isNull() && "Invalid call to compare()");
209215
return get()->equals(*rhs.get());
210216
}
211217

include/klee/ADT/SparseStorage.h

Lines changed: 77 additions & 64 deletions
Original file line numberDiff line numberDiff line change
@@ -5,65 +5,51 @@
55
#include <cstddef>
66
#include <iterator>
77
#include <map>
8+
#include <unordered_map>
89
#include <vector>
910

11+
namespace llvm {
12+
class raw_ostream;
13+
};
14+
1015
namespace klee {
1116

17+
enum class Density {
18+
Sparse,
19+
Dense,
20+
};
21+
1222
template <typename ValueType> class SparseStorage {
1323
private:
14-
size_t capacity;
15-
std::map<size_t, ValueType> internalStorage;
24+
std::unordered_map<size_t, ValueType> internalStorage;
1625
ValueType defaultValue;
1726

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

2029
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;
30+
SparseStorage(const ValueType &defaultValue = ValueType())
31+
: defaultValue(defaultValue) {}
32+
33+
SparseStorage(const std::unordered_map<size_t, ValueType> &internalStorage,
34+
const ValueType &defaultValue)
35+
: defaultValue(defaultValue) {
36+
for (auto &[index, value] : internalStorage) {
37+
store(index, value);
4638
}
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) {}
39+
}
5640

5741
SparseStorage(const std::vector<ValueType> &values,
5842
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];
43+
: defaultValue(defaultValue) {
44+
for (size_t idx = 0; idx < values.size(); ++idx) {
45+
store(idx, values[idx]);
6246
}
6347
}
6448

6549
void store(size_t idx, const ValueType &value) {
66-
if (idx < capacity) {
50+
if (value == defaultValue) {
51+
internalStorage.erase(idx);
52+
} else {
6753
internalStorage[idx] = value;
6854
}
6955
}
@@ -77,55 +63,82 @@ template <typename ValueType> class SparseStorage {
7763
}
7864

7965
ValueType load(size_t idx) const {
80-
assert(idx < capacity && idx >= 0);
8166
return contains(idx) ? internalStorage.at(idx) : defaultValue;
8267
}
8368

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);
69+
size_t sizeOfSetRange() const {
70+
size_t sizeOfRange = 0;
71+
for (auto i : internalStorage) {
72+
sizeOfRange = std::max(i.first, sizeOfRange);
9873
}
99-
100-
capacity = newCapacity;
74+
return sizeOfRange;
10175
}
10276

10377
bool operator==(const SparseStorage<ValueType> &another) const {
104-
return size() == another.size() && defaultValue == another.defaultValue &&
105-
internalStorage == another.internalStorage;
78+
return defaultValue == another.defaultValue && compare(another) == 0;
10679
}
10780

10881
bool operator!=(const SparseStorage<ValueType> &another) const {
10982
return !(*this == another);
11083
}
11184

11285
bool operator<(const SparseStorage &another) const {
113-
return internalStorage < another.internalStorage;
86+
return compare(another) == -1;
11487
}
11588

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

120-
Iterator begin() const { return Iterator(0, this); }
121-
Iterator end() const { return Iterator(size(), this); }
133+
// Specialized for unsigned char in .cpp
134+
void print(llvm::raw_ostream &os, Density) const;
122135
};
123136

124137
template <typename U>
125138
SparseStorage<unsigned char> sparseBytesFromValue(const U &value) {
126139
const unsigned char *valueUnsignedCharIterator =
127140
reinterpret_cast<const unsigned char *>(&value);
128-
SparseStorage<unsigned char> result(sizeof(value));
141+
SparseStorage<unsigned char> result;
129142
result.store(0, valueUnsignedCharIterator,
130143
valueUnsignedCharIterator + sizeof(value));
131144
return result;

include/klee/Expr/ArrayCache.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,9 @@ class ArrayCache {
6464
typedef std::vector<const Array *> ArrayPtrVec;
6565
ArrayPtrVec concreteArrays;
6666

67+
// Number of arrays of each source allocated
68+
std::unordered_map<SymbolicSource::Kind, unsigned> allocatedCount;
69+
6770
unsigned getNextID() const;
6871
};
6972
} // namespace klee

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: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -629,10 +629,7 @@ class Array {
629629

630630
public:
631631
bool isSymbolicArray() const { return !isConstantArray(); }
632-
bool isConstantArray() const {
633-
return isa<ConstantSource>(source) ||
634-
isa<SymbolicSizeConstantSource>(source);
635-
}
632+
bool isConstantArray() const;
636633

637634
const std::string getName() const { return source->toString(); }
638635
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+
KWDV, ///< 'DV'
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)