aaron.ballman created this revision.
aaron.ballman added reviewers: george.karpenkov, dcoughlin, zaks.anna.

SARIF allows you to export descriptions about rules that are present in the 
SARIF log. This patch exposes the help text table generated into Checkers.inc 
as the rule's "full description" and exports all of the rules present in the 
analysis output.

This information is useful for analysis result viewers like CodeSonar.


https://reviews.llvm.org/D53982

Files:
  lib/StaticAnalyzer/Core/SarifDiagnostics.cpp
  
test/Analysis/diagnostics/Inputs/expected-sarif/sarif-diagnostics-taint-test.c.sarif
  
test/Analysis/diagnostics/Inputs/expected-sarif/sarif-multi-diagnostic-test.c.sarif
  test/Analysis/diagnostics/sarif-multi-diagnostic-test.c

Index: test/Analysis/diagnostics/sarif-multi-diagnostic-test.c
===================================================================
--- test/Analysis/diagnostics/sarif-multi-diagnostic-test.c
+++ test/Analysis/diagnostics/sarif-multi-diagnostic-test.c
@@ -0,0 +1,29 @@
+// RUN: %clang_analyze_cc1 -analyzer-checker=core,alpha.security.taint,debug.TaintTest %s -verify -analyzer-output=sarif -o - | diff -U1 -w -I ".*file:.*sarif-multi-diagnostic-test.c" -I '"version":' -I "2\.0\.0\-csd\.[0-9]*\.beta\." - %S/Inputs/expected-sarif/sarif-multi-diagnostic-test.c.sarif
+#include "../Inputs/system-header-simulator.h"
+
+int atoi(const char *nptr);
+
+void f(void) {
+  char s[80];
+  scanf("%s", s);
+  int d = atoi(s); // expected-warning {{tainted}}
+}
+
+void g(void) {
+  void (*fp)(int);
+  fp(12); // expected-warning {{Called function pointer is an uninitialized pointer value}}
+}
+
+int h(int i) {
+  if (i == 0)
+    return 1 / i; // expected-warning {{Division by zero}}
+  return 0;
+}
+
+int main(void) {
+  f();
+  g();
+  h(0);
+  return 0;
+}
+
Index: test/Analysis/diagnostics/Inputs/expected-sarif/sarif-multi-diagnostic-test.c.sarif
===================================================================
--- test/Analysis/diagnostics/Inputs/expected-sarif/sarif-multi-diagnostic-test.c.sarif
+++ test/Analysis/diagnostics/Inputs/expected-sarif/sarif-multi-diagnostic-test.c.sarif
@@ -0,0 +1,301 @@
+{
+  "$schema": "http://json.schemastore.org/sarif-2.0.0-csd.2.beta.2018-10-10";,
+  "runs": [
+    {
+      "files": {
+        "file:sarif-multi-diagnostic-test.c": {
+          "fileLocation": {
+            "uri": "file:sarif-multi-diagnostic-test.c"
+          },
+          "length": 761,
+          "mimeType": "text/plain",
+          "roles": [
+            "resultFile"
+          ]
+        }
+      },
+      "resources": {
+        "rules": {
+          "core.CallAndMessage": {
+            "fullDescription": {
+              "text": "Check for logical errors for function calls and Objective-C message expressions (e.g., uninitialized arguments, null function pointers)"
+            },
+            "name": {
+              "text": "core.CallAndMessage"
+            }
+          },
+          "core.DivideZero": {
+            "fullDescription": {
+              "text": "Check for division by zero"
+            },
+            "name": {
+              "text": "core.DivideZero"
+            }
+          },
+          "debug.TaintTest": {
+            "fullDescription": {
+              "text": "Mark tainted symbols as such."
+            },
+            "name": {
+              "text": "debug.TaintTest"
+            }
+          }
+        }
+      },
+      "results": [
+        {
+          "codeFlows": [
+            {
+              "threadFlows": [
+                {
+                  "locations": [
+                    {
+                      "importance": "essential",
+                      "location": {
+                        "message": {
+                          "text": "Calling 'f'"
+                        },
+                        "physicalLocation": {
+                          "fileLocation": {
+                            "uri": "file:sarif-multi-diagnostic-test.c"
+                          },
+                          "region": {
+                            "endColumn": 5,
+                            "endLine": 24,
+                            "startColumn": 3,
+                            "startLine": 24
+                          }
+                        }
+                      }
+                    },
+                    {
+                      "importance": "essential",
+                      "location": {
+                        "message": {
+                          "text": "tainted"
+                        },
+                        "physicalLocation": {
+                          "fileLocation": {
+                            "uri": "file:sarif-multi-diagnostic-test.c"
+                          },
+                          "region": {
+                            "endColumn": 17,
+                            "endLine": 9,
+                            "startColumn": 11,
+                            "startLine": 9
+                          }
+                        }
+                      }
+                    }
+                  ]
+                }
+              ]
+            }
+          ],
+          "locations": [
+            {
+              "physicalLocation": {
+                "fileLocation": {
+                  "uri": "file:sarif-multi-diagnostic-test.c"
+                },
+                "region": {
+                  "endColumn": 17,
+                  "endLine": 9,
+                  "startColumn": 11,
+                  "startLine": 9
+                }
+              }
+            }
+          ],
+          "message": {
+            "text": "tainted"
+          },
+          "ruleId": "debug.TaintTest"
+        },
+        {
+          "codeFlows": [
+            {
+              "threadFlows": [
+                {
+                  "locations": [
+                    {
+                      "importance": "essential",
+                      "location": {
+                        "message": {
+                          "text": "Calling 'g'"
+                        },
+                        "physicalLocation": {
+                          "fileLocation": {
+                            "uri": "file:sarif-multi-diagnostic-test.c"
+                          },
+                          "region": {
+                            "endColumn": 5,
+                            "endLine": 25,
+                            "startColumn": 3,
+                            "startLine": 25
+                          }
+                        }
+                      }
+                    },
+                    {
+                      "importance": "essential",
+                      "location": {
+                        "message": {
+                          "text": "'fp' declared without an initial value"
+                        },
+                        "physicalLocation": {
+                          "fileLocation": {
+                            "uri": "file:sarif-multi-diagnostic-test.c"
+                          },
+                          "region": {
+                            "endColumn": 10,
+                            "endLine": 13,
+                            "startColumn": 3,
+                            "startLine": 13
+                          }
+                        }
+                      }
+                    },
+                    {
+                      "importance": "essential",
+                      "location": {
+                        "message": {
+                          "text": "Called function pointer is an uninitialized pointer value"
+                        },
+                        "physicalLocation": {
+                          "fileLocation": {
+                            "uri": "file:sarif-multi-diagnostic-test.c"
+                          },
+                          "region": {
+                            "endColumn": 8,
+                            "endLine": 14,
+                            "startColumn": 3,
+                            "startLine": 14
+                          }
+                        }
+                      }
+                    }
+                  ]
+                }
+              ]
+            }
+          ],
+          "locations": [
+            {
+              "physicalLocation": {
+                "fileLocation": {
+                  "uri": "file:sarif-multi-diagnostic-test.c"
+                },
+                "region": {
+                  "endColumn": 8,
+                  "endLine": 14,
+                  "startColumn": 3,
+                  "startLine": 14
+                }
+              }
+            }
+          ],
+          "message": {
+            "text": "Called function pointer is an uninitialized pointer value"
+          },
+          "ruleId": "core.CallAndMessage"
+        },
+        {
+          "codeFlows": [
+            {
+              "threadFlows": [
+                {
+                  "locations": [
+                    {
+                      "importance": "important",
+                      "location": {
+                        "message": {
+                          "text": "Assuming 'i' is equal to 0"
+                        },
+                        "physicalLocation": {
+                          "fileLocation": {
+                            "uri": "file:sarif-multi-diagnostic-test.c"
+                          },
+                          "region": {
+                            "endColumn": 12,
+                            "endLine": 18,
+                            "startColumn": 7,
+                            "startLine": 18
+                          }
+                        }
+                      }
+                    },
+                    {
+                      "importance": "unimportant",
+                      "location": {
+                        "message": {
+                          "text": "Taking true branch"
+                        },
+                        "physicalLocation": {
+                          "fileLocation": {
+                            "uri": "file:sarif-multi-diagnostic-test.c"
+                          },
+                          "region": {
+                            "endColumn": 3,
+                            "endLine": 18,
+                            "startColumn": 3,
+                            "startLine": 18
+                          }
+                        }
+                      }
+                    },
+                    {
+                      "importance": "essential",
+                      "location": {
+                        "message": {
+                          "text": "Division by zero"
+                        },
+                        "physicalLocation": {
+                          "fileLocation": {
+                            "uri": "file:sarif-multi-diagnostic-test.c"
+                          },
+                          "region": {
+                            "endColumn": 14,
+                            "endLine": 19,
+                            "startColumn": 14,
+                            "startLine": 19
+                          }
+                        }
+                      }
+                    }
+                  ]
+                }
+              ]
+            }
+          ],
+          "locations": [
+            {
+              "physicalLocation": {
+                "fileLocation": {
+                  "uri": "file:sarif-multi-diagnostic-test.c"
+                },
+                "region": {
+                  "endColumn": 14,
+                  "endLine": 19,
+                  "startColumn": 14,
+                  "startLine": 19
+                }
+              }
+            }
+          ],
+          "message": {
+            "text": "Division by zero"
+          },
+          "ruleId": "core.DivideZero"
+        }
+      ],
+      "tool": {
+        "fullName": "clang static analyzer",
+        "language": "en-US",
+        "name": "clang",
+        "version": "clang version 8.0.0 (trunk 345822) (llvm/trunk 345824)"
+      }
+    }
+  ],
+  "version": "2.0.0-csd.2.beta.2018-10-10"
+}
Index: test/Analysis/diagnostics/Inputs/expected-sarif/sarif-diagnostics-taint-test.c.sarif
===================================================================
--- test/Analysis/diagnostics/Inputs/expected-sarif/sarif-diagnostics-taint-test.c.sarif
+++ test/Analysis/diagnostics/Inputs/expected-sarif/sarif-diagnostics-taint-test.c.sarif
@@ -14,6 +14,18 @@
           ]
         }
       },
+      "resources": {
+        "rules": {
+          "debug.TaintTest": {
+            "fullDescription": {
+              "text": "Mark tainted symbols as such."
+            },
+            "name": {
+              "text": "debug.TaintTest"
+            }
+          }
+        }
+      },      
       "results": [
         {
           "codeFlows": [
Index: lib/StaticAnalyzer/Core/SarifDiagnostics.cpp
===================================================================
--- lib/StaticAnalyzer/Core/SarifDiagnostics.cpp
+++ lib/StaticAnalyzer/Core/SarifDiagnostics.cpp
@@ -232,6 +232,43 @@
       {"ruleId", Diag.getCheckName()}};
 }
 
+static StringRef getRuleDescription(StringRef CheckName) {
+  return llvm::StringSwitch<StringRef>(CheckName)
+#define GET_CHECKERS
+#define CHECKER(FULLNAME, CLASS, CXXFILE, HELPTEXT, GROUPINDEX, HIDDEN)        \
+  .Case(FULLNAME, HELPTEXT)
+#include "clang/StaticAnalyzer/Checkers/Checkers.inc"
+#undef CHECKER
+#undef GET_CHECKERS
+      ;
+}
+
+static json::Object createRule(const PathDiagnostic &Diag) {
+  StringRef CheckName = Diag.getCheckName();
+  return json::Object{
+      {"fullDescription", createMessage(getRuleDescription(CheckName))},
+      {"name", createMessage(CheckName)}};
+}
+
+static json::Object createRules(std::vector<const PathDiagnostic *> &Diags) {
+  json::Object Rules;
+  llvm::StringSet<> Seen;
+
+  llvm::for_each(Diags, [&](const PathDiagnostic *D) {
+    StringRef RuleID = D->getCheckName();
+    std::pair<llvm::StringSet<>::iterator, bool> P = Seen.insert(RuleID);
+    if (P.second)
+      Rules[RuleID] = createRule(*D);
+  });
+
+  return Rules;
+}
+
+static json::Object
+createResources(std::vector<const PathDiagnostic *> &Diags) {
+  return json::Object{{"rules", createRules(Diags)}};
+}
+
 static json::Object createRun(std::vector<const PathDiagnostic *> &Diags) {
   json::Array Results;
   json::Object Files;
@@ -241,6 +278,7 @@
   });
 
   return json::Object{{"tool", createTool()},
+                      {"resources", createResources(Diags)},
                       {"results", std::move(Results)},
                       {"files", std::move(Files)}};
 }
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to