Skip to content

Commit d733a6e

Browse files
committed
json-parser: detect JSON format produced by Snyk Code
... and read version of the tool (but not yet the list of defects)
1 parent 3fdf111 commit d733a6e

File tree

1 file changed

+67
-2
lines changed

1 file changed

+67
-2
lines changed

src/json-parser.cc

Lines changed: 67 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,20 @@ class CovTreeDecoder: public AbstractTreeDecoder {
6464
KeyEventDigger keDigger;
6565
};
6666

67+
/// tree decoder of the JSON format produced by Snyk Code
68+
class SnykTreeDecoder: public AbstractTreeDecoder {
69+
public:
70+
virtual void readScanProps(
71+
TScanProps *pDst,
72+
const pt::ptree *root);
73+
74+
virtual void readRoot(
75+
const pt::ptree **pDefList,
76+
const pt::ptree *root);
77+
78+
virtual bool readNode(Defect *def, pt::ptree::const_iterator defIter);
79+
};
80+
6781
struct JsonParser::Private {
6882
InStream &input;
6983
AbstractTreeDecoder *decoder = nullptr;
@@ -113,6 +127,9 @@ JsonParser::JsonParser(InStream &input):
113127
else if (findChildOf(&node, d->root, "issues"))
114128
// Coverity JSON format
115129
d->decoder = new CovTreeDecoder;
130+
else if (findChildOf(&node, d->root, "runs"))
131+
// JSON format produced by Snyk Code
132+
d->decoder = new SnykTreeDecoder;
116133
else
117134
throw pt::ptree_error("unknown JSON format");
118135

@@ -157,8 +174,7 @@ bool JsonParser::Private::readNext(Defect *def)
157174

158175
// read the current node and move to the next one
159176
this->defNumber++;
160-
this->decoder->readNode(def, this->defIter++);
161-
return true;
177+
return this->decoder->readNode(def, this->defIter++);
162178
}
163179
catch (pt::ptree_error &e) {
164180
this->dataError(e.what());
@@ -353,3 +369,52 @@ bool CovTreeDecoder::readNode(
353369

354370
return true;
355371
}
372+
373+
void SnykTreeDecoder::readScanProps(
374+
TScanProps *pDst,
375+
const pt::ptree *root)
376+
{
377+
// check that we have exactly one run
378+
const pt::ptree *runs;
379+
if (!findChildOf(&runs, *root, "runs") || (1U != runs->size()))
380+
return;
381+
382+
// check which tool was used for the run
383+
const pt::ptree *toolNode;
384+
if (!findChildOf(&toolNode, runs->begin()->second, "tool"))
385+
return;
386+
const pt::ptree *driverNode;
387+
if (!findChildOf(&driverNode, *toolNode, "driver"))
388+
return;
389+
390+
const auto name = valueOf<std::string>(*driverNode, "name", "");
391+
if (name != "SnykCode")
392+
// not a supported tool
393+
return;
394+
395+
const auto version = valueOf<std::string>(*driverNode, "version", "");
396+
if (version.empty())
397+
// no version provided
398+
return;
399+
400+
// record tool version of Snyk Code
401+
(*pDst)["analyzer-version-snyk-code"] = version;
402+
}
403+
404+
void SnykTreeDecoder::readRoot(
405+
const pt::ptree **pDefList,
406+
const pt::ptree *runs)
407+
{
408+
// check that we have exactly one run and return its results
409+
if ((1U != runs->size())
410+
|| !findChildOf(pDefList, runs->begin()->second, "results"))
411+
pDefList = nullptr;
412+
}
413+
414+
bool SnykTreeDecoder::readNode(
415+
Defect *def,
416+
pt::ptree::const_iterator defIter)
417+
{
418+
// TODO
419+
return false;
420+
}

0 commit comments

Comments
 (0)