@@ -153,10 +153,14 @@ class SarifTreeEncoder: public AbstractTreeEncoder {
153153
154154 private:
155155 void initToolVersion ();
156- void serializeCweMap ();
156+ void serializeRules ();
157157
158- typedef std::map<std::string, int > TCweMap ;
158+ using TCweMap = std::map<std::string, int >;
159159 TCweMap cweMap_;
160+
161+ using TShellCheckMap = std::map<std::string, std::string>;
162+ TShellCheckMap shellCheckMap_;
163+
160164 TScanProps scanProps_;
161165 PTree driver_;
162166 PTree results_;
@@ -215,31 +219,87 @@ void SarifTreeEncoder::initToolVersion()
215219 driver_.put <std::string>(" informationUri" , uri);
216220}
217221
218- void SarifTreeEncoder::serializeCweMap ( )
222+ static void sarifEncodeShellCheckRule (PTree *rule, const std::string &ruleID )
219223{
220- PTree ruleList;
224+ // name
225+ rule->put <std::string>(" name" , ruleID);
221226
222- for (const auto &item : cweMap_) {
223- PTree rule;
224- const auto &id = item.first ;
225- rule.put <std::string>(" id" , id);
227+ // properties.tags[]
228+ PTree tagList;
229+ appendNode (&tagList, PTree ({" ShellCheck" }));
230+
231+ PTree props;
232+ props.put_child (" tags" , tagList);
233+ rule->put_child (" properties" , props);
234+
235+ // help.text && help.markdown
236+ PTree help;
237+ const auto helpURI =
238+ " https://github.com/koalaman/shellcheck/wiki/" + ruleID;
239+ help.put <std::string>(" text" , " Defect reference: " + helpURI);
240+
241+ const auto helpMarkdown =
242+ " Defect reference: [" + ruleID +" ](" + helpURI + " )" ;
243+ help.put <std::string>(" markdown" , helpMarkdown);
226244
227- PTree cweList;
228- const auto cwe = item.second ;
229- const auto cweStr = std::to_string (cwe);
230- appendNode (&cweList, PTree (" CWE-" + cweStr));
245+ rule->put_child (" help" , help);
246+ }
247+
248+ static void sarifEncodeCweRule (PTree *rule, const int cwe, bool append = false )
249+ {
250+ PTree cweList;
251+ const auto cweStr = std::to_string (cwe);
252+ appendNode (&cweList, PTree (" CWE-" + cweStr));
231253
232- // properties.cwe[]
254+ // properties.cwe[]
255+ if (append) {
256+ PTree &props = rule->get_child (" properties" );
257+ props.put_child (" cwe" , cweList);
258+ } else {
233259 PTree props;
234260 props.put_child (" cwe" , cweList);
235- rule.put_child (" properties" , props);
261+ rule->put_child (" properties" , props);
262+ }
236263
237- // help.text
264+ // help.text
265+ const auto helpText =
266+ " https://cwe.mitre.org/data/definitions/" + cweStr + " .html" ;
267+
268+ if (append) {
269+ PTree &help = rule->get_child (" help" );
270+ const auto &originalHelpText = help.get_child (" text" ).get_value (" " );
271+ help.put <std::string>(" text" , originalHelpText + ' \n ' + helpText);
272+ } else {
238273 PTree help;
239- const auto helpText =
240- " https://cwe.mitre.org/data/definitions/" + cweStr + " .html" ;
241274 help.put <std::string>(" text" , helpText);
242- rule.put_child (" help" , help);
275+ rule->put_child (" help" , help);
276+ }
277+ }
278+
279+ void SarifTreeEncoder::serializeRules ()
280+ {
281+ PTree ruleList;
282+
283+ for (const auto &item : shellCheckMap_) {
284+ PTree rule;
285+ const auto &id = item.first ;
286+ rule.put <std::string>(" id" , id);
287+
288+ sarifEncodeShellCheckRule (&rule, item.second );
289+ if (1U == cweMap_.count (id))
290+ sarifEncodeCweRule (&rule, cweMap_[id], /* append =*/ true );
291+
292+ appendNode (&ruleList, rule);
293+ }
294+
295+ for (const auto &item : cweMap_) {
296+ const auto &id = item.first ;
297+ if (1U == shellCheckMap_.count (id))
298+ continue ;
299+
300+ PTree rule;
301+ rule.put <std::string>(" id" , id);
302+ sarifEncodeCweRule (&rule, item.second );
243303
244304 appendNode (&ruleList, rule);
245305 }
@@ -259,7 +319,8 @@ static void sarifEncodeMsg(PTree *pDst, const std::string& text)
259319 pDst->put_child (" message" , msg);
260320}
261321
262- static void sarifEncodeLevel (PTree *result, const std::string &event) {
322+ static void sarifEncodeLevel (PTree *result, const std::string &event)
323+ {
263324 std::string level = event;
264325
265326 // cut the [...] suffix from event if present
@@ -350,6 +411,16 @@ void SarifTreeEncoder::appendDef(const Defect &def)
350411 // checker (FIXME: suboptimal mapping to SARIF)
351412 const std::string ruleId = def.checker + " : " + keyEvt.event ;
352413 result.put <std::string>(" ruleId" , ruleId);
414+
415+ if (def.checker == " SHELLCHECK_WARNING" ) {
416+ boost::smatch sm;
417+ static const RE reShellCheckMsg (" (\\ [)?(SC[0-9]+)(\\ ])?$" );
418+ boost::regex_search (keyEvt.event , sm, reShellCheckMsg);
419+
420+ // update ShellCheck rule map
421+ shellCheckMap_[ruleId] = sm[2 ];
422+ }
423+
353424 if (def.cwe )
354425 // update CWE map
355426 cweMap_[ruleId] = def.cwe ;
@@ -423,9 +494,9 @@ void SarifTreeEncoder::writeTo(std::ostream &str)
423494
424495 this ->initToolVersion ();
425496
426- if (!cweMap_.empty ())
497+ if (!cweMap_.empty () || !shellCheckMap_. empty () )
427498 // needs to run before we pick driver_
428- this ->serializeCweMap ();
499+ this ->serializeRules ();
429500
430501 PTree tool;
431502 tool.put_child (" driver" , driver_);
0 commit comments