1616#include < vector>
1717
1818#include " klee/ADT/Ref.h"
19+ #include " llvm/IR/IntrinsicInst.h"
1920#include < nlohmann/json.hpp>
2021#include < nonstd/optional.hpp>
2122
@@ -52,9 +53,10 @@ enum ReachWithError {
5253 Reachable,
5354 None,
5455};
56+ using ReachWithErrors = std::vector<ReachWithError>;
5557
5658const char *getErrorString (ReachWithError error);
57- std::string getErrorsString (const std::vector<ReachWithError> &errors);
59+ std::string getErrorsString (const ReachWithErrors &errors);
5860
5961struct FunctionInfo ;
6062struct KBlock ;
@@ -63,11 +65,16 @@ struct ArtifactLocationJson {
6365 optional<std::string> uri;
6466};
6567
68+ struct Message {
69+ std::string text;
70+ };
71+
6672struct RegionJson {
6773 optional<unsigned int > startLine;
6874 optional<unsigned int > endLine;
6975 optional<unsigned int > startColumn;
7076 optional<unsigned int > endColumn;
77+ optional<Message> message;
7178};
7279
7380struct PhysicalLocationJson {
@@ -92,10 +99,6 @@ struct CodeFlowJson {
9299 std::vector<ThreadFlowJson> threadFlows;
93100};
94101
95- struct Message {
96- std::string text;
97- };
98-
99102struct Fingerprints {
100103 std::string cooddy_uid;
101104};
@@ -137,7 +140,7 @@ struct SarifReportJson {
137140NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE_WITH_DEFAULT (ArtifactLocationJson, uri)
138141
139142NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE_WITH_DEFAULT (RegionJson, startLine, endLine,
140- startColumn, endColumn)
143+ startColumn, endColumn, message )
141144
142145NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE_WITH_DEFAULT (PhysicalLocationJson,
143146 artifactLocation, region)
@@ -165,6 +168,148 @@ NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE_WITH_DEFAULT(RunJson, results, tool)
165168
166169NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE_WITH_DEFAULT (SarifReportJson, runs)
167170
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+
168313struct Location {
169314 struct LocationHash {
170315 std::size_t operator ()(const Location *l) const { return l->hash (); }
@@ -184,35 +329,30 @@ struct Location {
184329 }
185330 };
186331 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;
191333
192- static ref<Location> create (std::string filename_, unsigned int startLine_,
334+ static ref<Location> create (std::string && filename_, unsigned int startLine_,
193335 optional<unsigned int > endLine_,
194336 optional<unsigned int > startColumn_,
195- optional<unsigned int > endColumn_);
337+ optional<unsigned int > endColumn_,
338+ ToolName toolName, EventKind &kind);
196339
197- ~Location ();
198- std::size_t hash () const { return hashValue; }
340+ virtual ~Location ();
341+ virtual std::size_t hash () const { return hashValue; }
199342
200343 // / @brief Required by klee::ref-managed objects
201344 class ReferenceCounter _refCount;
202345
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 ;
208347
209348 bool isInside (const std::string &name) const ;
210349
211350 using Instructions = std::unordered_map<
212351 unsigned int ,
213- std::unordered_map<unsigned int , std::unordered_set<unsigned int >>>;
352+ std::unordered_map<unsigned int , std::unordered_set<OpCode >>>;
214353
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 ;
216356
217357 std::string toString () const ;
218358
@@ -226,28 +366,20 @@ struct Location {
226366 static LocationHashSet locations;
227367
228368 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);
236370
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);
241373
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);
250379 }
380+
381+ virtual void isInsideInternal (BlockWithPrecision &bp,
382+ const Instructions &origInsts) const ;
251383};
252384
253385struct RefLocationHash {
@@ -262,9 +394,9 @@ struct RefLocationCmp {
262394
263395struct Result {
264396 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;
268400};
269401
270402struct SarifReport {
0 commit comments