16
16
#include < vector>
17
17
18
18
#include " klee/ADT/Ref.h"
19
+ #include " llvm/IR/IntrinsicInst.h"
19
20
#include < nlohmann/json.hpp>
20
21
#include < nonstd/optional.hpp>
21
22
@@ -52,9 +53,10 @@ enum ReachWithError {
52
53
Reachable,
53
54
None,
54
55
};
56
+ using ReachWithErrors = std::vector<ReachWithError>;
55
57
56
58
const char *getErrorString (ReachWithError error);
57
- std::string getErrorsString (const std::vector<ReachWithError> &errors);
59
+ std::string getErrorsString (const ReachWithErrors &errors);
58
60
59
61
struct FunctionInfo ;
60
62
struct KBlock ;
@@ -63,11 +65,16 @@ struct ArtifactLocationJson {
63
65
optional<std::string> uri;
64
66
};
65
67
68
+ struct Message {
69
+ std::string text;
70
+ };
71
+
66
72
struct RegionJson {
67
73
optional<unsigned int > startLine;
68
74
optional<unsigned int > endLine;
69
75
optional<unsigned int > startColumn;
70
76
optional<unsigned int > endColumn;
77
+ optional<Message> message;
71
78
};
72
79
73
80
struct PhysicalLocationJson {
@@ -92,10 +99,6 @@ struct CodeFlowJson {
92
99
std::vector<ThreadFlowJson> threadFlows;
93
100
};
94
101
95
- struct Message {
96
- std::string text;
97
- };
98
-
99
102
struct Fingerprints {
100
103
std::string cooddy_uid;
101
104
};
@@ -137,7 +140,7 @@ struct SarifReportJson {
137
140
NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE_WITH_DEFAULT (ArtifactLocationJson, uri)
138
141
139
142
NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE_WITH_DEFAULT (RegionJson, startLine, endLine,
140
- startColumn, endColumn)
143
+ startColumn, endColumn, message )
141
144
142
145
NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE_WITH_DEFAULT (PhysicalLocationJson,
143
146
artifactLocation, region)
@@ -165,6 +168,148 @@ NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE_WITH_DEFAULT(RunJson, results, tool)
165
168
166
169
NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE_WITH_DEFAULT (SarifReportJson, runs)
167
170
171
+ enum class Precision { NotFound = 0 , Line = 1 , Column = 2 , Instruction = 3 };
172
+
173
+ template <class T > struct WithPrecision {
174
+ T *ptr;
175
+ Precision precision;
176
+
177
+ explicit WithPrecision (T *p, Precision pr) : ptr(p), precision(pr) {}
178
+ explicit WithPrecision (T *p) : WithPrecision(p, Precision::NotFound) {}
179
+ explicit WithPrecision () : WithPrecision(nullptr ) {}
180
+
181
+ void setNotFound () { precision = Precision::NotFound; }
182
+ bool isNotFound () const { return precision == Precision::NotFound; }
183
+ };
184
+
185
+ struct KBlock ;
186
+ struct KInstruction ;
187
+
188
+ using BlockWithPrecision = WithPrecision<KBlock>;
189
+ using InstrWithPrecision = WithPrecision<KInstruction>;
190
+
191
+ inline size_t hash_combine2 (std::size_t s, std::size_t v) {
192
+ return s ^ (v + 0x9e3779b9 + (s << 6 ) + (s >> 2 ));
193
+ }
194
+
195
+ template <class T > inline void hash_combine (std::size_t &s, const T &v) {
196
+ std::hash<T> h;
197
+ s = hash_combine2 (s, h (v));
198
+ }
199
+
200
+ enum class ReachWithoutError {
201
+ Reach = 0 ,
202
+ Return,
203
+ NPESource,
204
+ Free,
205
+ BranchFalse,
206
+ BranchTrue,
207
+ Call,
208
+ AfterCall
209
+ };
210
+
211
+ struct EventKind final {
212
+ const bool isError;
213
+ const ReachWithErrors kinds;
214
+ const ReachWithoutError kind;
215
+ size_t hashValue = 0 ;
216
+ void computeHash () {
217
+ hash_combine (hashValue, isError);
218
+ for (auto k : kinds)
219
+ hash_combine (hashValue, k);
220
+ hash_combine (hashValue, kind);
221
+ }
222
+ EventKind (ReachWithErrors &&kinds)
223
+ : isError(true ), kinds(kinds), kind(ReachWithoutError::Reach) {
224
+ computeHash ();
225
+ }
226
+ EventKind (ReachWithoutError kind) : isError(false ), kind(kind) {
227
+ computeHash ();
228
+ }
229
+ };
230
+ } // namespace klee
231
+
232
+ namespace std {
233
+ template <> struct hash <klee::EventKind> {
234
+ size_t operator ()(const klee::EventKind &k) const { return k.hashValue ; }
235
+ };
236
+ } // namespace std
237
+
238
+ namespace klee {
239
+ enum class ToolName { Unknown = 0 , SecB, clang, CppCheck, Infer, Cooddy };
240
+
241
+ class LineColumnRange ;
242
+
243
+ struct LocRange {
244
+ virtual LineColumnRange getRange () const = 0;
245
+ virtual ~LocRange () = default ;
246
+ virtual Precision maxPrecision () const = 0;
247
+ virtual size_t hash () const = 0;
248
+ virtual std::string toString () const = 0;
249
+ bool hasInside (KInstruction *ki) const ;
250
+ void hasInside (InstrWithPrecision &kp);
251
+ virtual void setRange (const KInstruction *ki) = 0;
252
+
253
+ protected:
254
+ virtual bool hasInsideInternal (InstrWithPrecision &kp) const = 0;
255
+ };
256
+
257
+ class LineColumnRange final : public LocRange {
258
+ size_t startLine;
259
+ size_t startColumn;
260
+ size_t endLine;
261
+ size_t endColumn;
262
+ static const size_t empty = std::numeric_limits<size_t >::max();
263
+
264
+ bool inline onlyLine () const { return startColumn == empty; }
265
+
266
+ public:
267
+ explicit LineColumnRange (size_t startLine, size_t startColumn, size_t endLine,
268
+ size_t endColumn)
269
+ : startLine(startLine), startColumn(startColumn), endLine(endLine),
270
+ endColumn(endColumn) {
271
+ assert (startLine <= endLine);
272
+ assert (startLine != endLine || startColumn <= endColumn);
273
+ }
274
+ explicit LineColumnRange (size_t startLine, size_t endLine)
275
+ : LineColumnRange(startLine, empty, endLine, empty) {}
276
+ explicit LineColumnRange (const KInstruction *ki) { setRange (ki); }
277
+
278
+ void setRange (const KInstruction *ki) final ;
279
+
280
+ LineColumnRange getRange () const final { return *this ; }
281
+
282
+ void clearColumns () { startColumn = (endColumn = empty); }
283
+
284
+ Precision maxPrecision () const final {
285
+ return onlyLine () ? Precision::Line : Precision::Column;
286
+ }
287
+
288
+ size_t hash () const final {
289
+ size_t hashValue = 0 ;
290
+ hashValue = hash_combine2 (hashValue, startLine);
291
+ hashValue = hash_combine2 (hashValue, endLine);
292
+ hashValue = hash_combine2 (hashValue, startColumn);
293
+ return hash_combine2 (hashValue, endColumn);
294
+ }
295
+
296
+ std::string toString () const final {
297
+ if (onlyLine ())
298
+ return std::to_string (startLine) + " -" + std::to_string (endLine);
299
+ return std::to_string (startLine) + " :" + std::to_string (startColumn) + " -" +
300
+ std::to_string (endLine) + " :" + std::to_string (endColumn);
301
+ }
302
+
303
+ bool hasInsideInternal (InstrWithPrecision &kp) const final ;
304
+
305
+ bool operator ==(const LineColumnRange &p) const {
306
+ return startLine == p.startLine && endLine == p.endLine &&
307
+ startColumn == p.startColumn && endColumn == p.endColumn ;
308
+ }
309
+ };
310
+
311
+ using OpCode = unsigned ;
312
+
168
313
struct Location {
169
314
struct LocationHash {
170
315
std::size_t operator ()(const Location *l) const { return l->hash (); }
@@ -184,35 +329,30 @@ struct Location {
184
329
}
185
330
};
186
331
std::string filename;
187
- unsigned int startLine;
188
- unsigned int endLine;
189
- optional<unsigned int > startColumn;
190
- optional<unsigned int > endColumn;
332
+ std::unique_ptr<LocRange> range;
191
333
192
- static ref<Location> create (std::string filename_, unsigned int startLine_,
334
+ static ref<Location> create (std::string && filename_, unsigned int startLine_,
193
335
optional<unsigned int > endLine_,
194
336
optional<unsigned int > startColumn_,
195
- optional<unsigned int > endColumn_);
337
+ optional<unsigned int > endColumn_,
338
+ ToolName toolName, EventKind &kind);
196
339
197
- ~Location ();
198
- std::size_t hash () const { return hashValue; }
340
+ virtual ~Location ();
341
+ virtual std::size_t hash () const { return hashValue; }
199
342
200
343
// / @brief Required by klee::ref-managed objects
201
344
class ReferenceCounter _refCount;
202
345
203
- bool operator ==(const Location &other) const {
204
- return filename == other.filename && startLine == other.startLine &&
205
- endLine == other.endLine && startColumn == other.startColumn &&
206
- endColumn == other.endColumn ;
207
- }
346
+ bool operator ==(const Location &other) const ;
208
347
209
348
bool isInside (const std::string &name) const ;
210
349
211
350
using Instructions = std::unordered_map<
212
351
unsigned int ,
213
- std::unordered_map<unsigned int , std::unordered_set<unsigned int >>>;
352
+ std::unordered_map<unsigned int , std::unordered_set<OpCode >>>;
214
353
215
- bool isInside (KBlock *block, const Instructions &origInsts) const ;
354
+ void isInside (InstrWithPrecision &kp, const Instructions &origInsts) const ;
355
+ void isInside (BlockWithPrecision &bp, const Instructions &origInsts) const ;
216
356
217
357
std::string toString () const ;
218
358
@@ -226,28 +366,20 @@ struct Location {
226
366
static LocationHashSet locations;
227
367
228
368
size_t hashValue = 0 ;
229
- void computeHash () {
230
- hash_combine (hashValue, filename);
231
- hash_combine (hashValue, startLine);
232
- hash_combine (hashValue, endLine);
233
- hash_combine (hashValue, startColumn);
234
- hash_combine (hashValue, endColumn);
235
- }
369
+ void computeHash (EventKind &kind);
236
370
237
- template <class T > inline void hash_combine (std::size_t &s, const T &v) {
238
- std::hash<T> h;
239
- s ^= h (v) + 0x9e3779b9 + (s << 6 ) + (s >> 2 );
240
- }
371
+ static Location *createCooddy (std::string &&filename_, LineColumnRange &range,
372
+ EventKind &kind);
241
373
242
- Location (std::string filename_, unsigned int startLine_,
243
- optional<unsigned int > endLine_, optional<unsigned int > startColumn_,
244
- optional<unsigned int > endColumn_)
245
- : filename(filename_), startLine(startLine_),
246
- endLine (endLine_.has_value() ? *endLine_ : startLine_),
247
- startColumn(startColumn_),
248
- endColumn(endColumn_.has_value() ? endColumn_ : startColumn_) {
249
- computeHash ();
374
+ protected:
375
+ Location (std::string &&filename_, std::unique_ptr<LocRange> range,
376
+ EventKind &kind)
377
+ : filename(std::move(filename_)), range(std::move(range)) {
378
+ computeHash (kind);
250
379
}
380
+
381
+ virtual void isInsideInternal (BlockWithPrecision &bp,
382
+ const Instructions &origInsts) const ;
251
383
};
252
384
253
385
struct RefLocationHash {
@@ -262,9 +394,9 @@ struct RefLocationCmp {
262
394
263
395
struct Result {
264
396
std::vector<ref<Location>> locations;
265
- std::vector<optional<json>> metadatas;
266
- std::string id;
267
- std::vector<ReachWithError> errors;
397
+ const std::vector<optional<json>> metadatas;
398
+ const std::string id;
399
+ const ReachWithErrors errors;
268
400
};
269
401
270
402
struct SarifReport {
0 commit comments