From 8c91ddcacb6ed6936ad78f9695ac97d55bc2bdd0 Mon Sep 17 00:00:00 2001
From: David Malcolm <dmalcolm@redhat.com>
Date: Wed, 13 Nov 2019 09:30:23 -0500
Subject: [PATCH 53/78] cover-letter.txt (not part of patch kit)

---
 cover-letter.txt | 315 +++++++++++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 315 insertions(+)
 create mode 100644 cover-letter.txt

diff --git a/cover-letter.txt b/cover-letter.txt
new file mode 100644
index 0000000..a1bec49
--- /dev/null
+++ b/cover-letter.txt
@@ -0,0 +1,315 @@
+Add a static analysis framework to GCC
+
+This patch kit introduces a static analysis pass for GCC that can diagnose
+various kinds of problems in C code at compile-time (e.g. double-free,
+use-after-free, etc).
+
+The analyzer runs as an IPA pass on the gimple SSA representation.
+It associates state machines with data, with transitions at certain
+statements and edges.  It finds "interesting" interprocedural paths
+through the user's code, in which bogus state transitions happen.
+
+For example, given:
+
+   free (ptr);
+   free (ptr);
+
+at the first call, "ptr" transitions to the "freed" state, and
+at the second call the analyzer complains, since "ptr" is already in
+the "freed" state (unless "ptr" is NULL, in which case it stays in
+the NULL state for both calls).
+
+Specific state machines include a checker for malloc/free,
+and a checker for stdio's FILE stream API, for detecting double-free,
+resource leaks, use-after-free, etc.
+
+There are also two state-machine-based checkers that are just
+proof-of-concept at this stage:
+- a checker for tracking exposure of sensitive data (e.g.
+  writing passwords to log files aka CWE-532), and
+- a checker for tracking "taint", where data potentially under an
+  attacker's control is used without sanitization for things like
+  array indices (CWE-129).
+
+There's a separation between the state machines and the analysis
+engine, so it ought to be relatively easy to add new warnings.
+
+TODO: mention typestate?
+
+For any given diagnostic emitted by a state machine, the analysis engine
+generates the simplest feasible interprocedural path of control flow for
+triggering the diagnostic.
+The patch kit adds support to GCC's diagnostic subsystem for associating
+such a "diagnostic_path" with a diagnostic.
+
+The analyzer itself is implemented as a plugin for GCC; it must
+be explicitly enabled at configure time.
+
+To mitigate feature creep, I've been focusing on implementing double-free
+detection, albeit with an eye to building something that can be developed
+into a more fully-featured static analyzer.  For example, I haven't yet
+attempted to track buffer overflows in this version, but I believe that
+that could be added on top of this foundation.
+
+TODO: example CVE
+
+Patches FIXME-FIXME are preliminary work.
+
+Patches FIXME-FIXME expand GCC's diagnostic subsystem in various ways.
+
+(TODO)
+
+The patch kit also expands GCC's diagnostic subsystem in various ways:
+
+(a) adding the ability to associate a "diagnostic path" with a diagnostic,
+describing a sequence of events predicted by the compiler that
+lead to the problem occurring, with their locations in the user's source,
+and text descriptions.
+
+For example, the following (hypothetical) error has a 3-event path:
+
+ test.c: In function 'make_a_list_of_random_ints_badly':
+ test.c:29:5: error: passing NULL as argument 1 to 'PyList_Append' which
+   requires a non-NULL parameter
+    29 |     PyList_Append(list, item);
+       |     ^~~~~~~~~~~~~~~~~~~~~~~~~
+   'make_a_list_of_random_ints_badly': events 1-3
+                    |
+                    |   25 |   list = PyList_New(0);
+                    |      |          ^~~~~~~~~~~~~
+                    |      |          |
+                    |      |          (1) when 'PyList_New' fails, returning NULL
+                    |   26 |
+                    |   27 |   for (i = 0; i < count; i++) {
+                    |      |   ~~~
+                    |      |   |
+                    |      |   (2) when 'i < count'
+                    |   28 |     item = PyLong_FromLong(random());
+                    |   29 |     PyList_Append(list, item);
+                    |      |     ~~~~~~~~~~~~~~~~~~~~~~~~~
+                    |      |     |
+                    |      |     (3) when calling 'PyList_Append', passing NULL as argument 1
+                    |
+
+The diagnostic-printing code has consolidated the path into a single
+run of events, since all the events are near each other and within the same
+function; more complicated examples (such as interprocedural paths)
+might be printed as multiple runs of events.
+
+(b) adding the ability to associate additional metadata with a diagnostic.
+The only such metadata added by the patch kit are CWE classifications (for
+the new warnings), so that we can emit e.g.:
+
+malloc-1.c: In function ‘test_42a’:
+malloc-1.c:466:1: warning: leak of ‘p’ [CWE-401] [-Wanalyzer-malloc-leak]
+  466 | }
+      | ^
+  ‘test_42a’: events 1-2
+       |
+       |  463 |   void *p = malloc (1024);
+       |      |             ^~~~~~~~~~~~~
+       |      |             |
+       |      |             (1) allocated here
+       |......
+       |  466 | }
+       |      | ~
+       |      | |
+       |      | (2) ‘p’ leaks here; was allocated at (1)
+       |
+
+(c) adding support for embedding URL information in our textual output
+in a form understood by recent versions of terminals
+  https://gist.github.com/egmontkob/eb114294efbcd5adb1944c9f3cb5feda
+so that in the above, the CWE-401 is a clickable link to
+  https://cwe.mitre.org/data/definitions/401.html
+
+More broadly, the options become clickable links to GCC's online
+documentation.
+
+
+Rationale
+=========
+
+There's benefit in integrating the checks directly into the compiler, so
+that the programmer can see the diagnostics as he or she works on the code,
+rather than at some later point.
+
+
+User interface
+==============
+
+--analyzer turns on all the warnings
+
+
+Internals
+=========
+
+
+Performance
+===========
+
+
+Future work
+===========
+
+
+Overview of patch kit
+=====================
+
+
+
+I plan to demonstrate the analyzer, give an overview of the internal
+implementation, its current strengths and limitations, and discuss what
+it would take to get this code into the GCC project (perhaps as an
+optional in-tree plugin).
+
+
+
+diff --git a/gcc/common.opt b/gcc/common.opt
+index 1b9e0f3..6dde0c2 100644
+--- a/gcc/common.opt
++++ b/gcc/common.opt
+@@ -993,6 +1060,30 @@ Align the start of loops.
+ falign-loops=
+ Common RejectNegative Joined Var(str_align_loops) Optimization
+ 
++fanalyzer-checker=
++Common Joined RejectNegative Var(flag_analyzer_checker)
++Restrict the analyzer to run just the named checker (TODO: docs)
++
++fanalyzer-fine-grained
++Common Var(flag_analyzer_fine_grained) Init(0)
++FIXME
++
++fanalyzer-impl=
++Common Joined RejectNegative UInteger Var(flag_analyzer_impl)
++FIXME: for selecting older implementations of the analyzer, to be removed
++
++fanalyzer-state-purge
++Common Var(flag_analyzer_state_purge) Init(1)
++Purge unneeded state during analysis (TODO: docs)
++
++fanalyzer-state-merge
++Common Var(flag_analyzer_state_merge) Init(1)
++FIXME: merge similar-enough states during analysis (TODO: docs)
++
++fanalyzer-call-summaries
++Common Var(flag_analyzer_call_summaries) Init(0)
++FIXME: approximate the effect of function calls to simplify analysis (TODO: docs)
++
+
+TODO in invoke.texi (perhaps in a different patch):
+ fargument-alias
+ Common Ignore
+ Does nothing. Preserved for backward compatibility.
+@@ -1257,6 +1348,10 @@ fdiagnostics-show-line-numbers
+ Common Var(flag_diagnostics_show_line_numbers) Init(1)
+ Show line numbers in the left margin when showing source.
+ 
++fdiagnostics-nn-line-numbers
++Common Var(flag_diagnostics_nn_line_numbers) Init(0)
++FIXME
++
+ fdiagnostics-color
+ Common Alias(fdiagnostics-color=,always,never)
+ ;
+@@ -1281,8 +1376,16 @@ Enum(diagnostic_color_rule) String(always) Value(DIAGNOSTICS_COLOR_YES)
+ EnumValue
+ Enum(diagnostic_color_rule) String(auto) Value(DIAGNOSTICS_COLOR_AUTO)
+ 
++fdiagnostics-urls
++Common Alias(fdiagnostics-urls=,always,never)
++;
++
++fdiagnostics-urls=
++Driver Common Joined RejectNegative Var(flag_diagnostics_show_urls) Enum(diagnostic_color_rule) Init(DIAGNOSTICS_COLOR_NO)
++-fdiagnostics-urls=[never|always|auto]	Embed URLs in diagnostics.
++
+ fdiagnostics-format=
+-Common Joined RejectNegative Enum(diagnostics_output_format)
++Driver Common Joined RejectNegative Enum(diagnostics_output_format)
+ -fdiagnostics-format=[text|json] Select output format.
+ 
+ ; Required for these enum values.
+@@ -1310,6 +1413,30 @@ fdiagnostics-show-option
+ Common Var(flag_diagnostics_show_option) Init(1)
+ Amend appropriate diagnostic messages with the command line option that controls them.
+ 
++fdiagnostics-show-metadata
++Common Var(flag_diagnostics_show_metadata) Init(1)
++FIXME; TODO: add to docs
++
++fdiagnostics-path-format=
++Common Joined RejectNegative Var(flag_diagnostics_path_format) Enum(diagnostic_path_format) Init(DPF_INLINE_EVENTS)
++FIXME; TODO: docs
++
++Enum
++Name(diagnostic_path_format) Type(int)
++
++EnumValue
++Enum(diagnostic_path_format) String(none) Value(DPF_NONE)
++
++EnumValue
++Enum(diagnostic_path_format) String(separate-events) Value(DPF_SEPARATE_EVENTS)
++
++EnumValue
++Enum(diagnostic_path_format) String(inline-events) Value(DPF_INLINE_EVENTS)
++
++fdiagnostics-show-path-depths
++Common Var(flag_diagnostics_show_path_depths) Init(0)
++Show stack depths of events in paths. (TODO: add to docs)
++
+ fdiagnostics-minimum-margin-width=
+ Common Joined UInteger Var(diagnostics_minimum_margin_width) Init(6)
+ Set minimum width of left margin of source code when showing source.
+@@ -1326,6 +1453,50 @@ fdump-
+ Common Joined RejectNegative Var(common_deferred_options) Defer
+ -fdump-<type>	Dump various compiler internals to a file.
+ 
++fdump-analyzer
++Common RejectNegative Var(flag_dump_analyzer)
++FIXME
++
++fdump-analyzer-summaries
++Common RejectNegative Var(flag_dump_analyzer_summaries)
++FIXME
++
++fdump-analyzer-supergraph
++Common RejectNegative Var(flag_dump_analyzer_supergraph)
++FIXME
++
++fdump-analyzer-callgraph
++Common RejectNegative Var(flag_dump_analyzer_callgraph)
++FIXME
++
++fdump-analyzer-exploded-graph
++Common RejectNegative Var(flag_dump_analyzer_exploded_graph)
++FIXME
++
++fdump-analyzer-exploded-nodes
++Common RejectNegative Var(flag_dump_analyzer_exploded_nodes)
++FIXME
++
++fdump-analyzer-exploded-nodes-2
++Common RejectNegative Var(flag_dump_analyzer_exploded_nodes_2)
++FIXME
++
++fdump-analyzer-exploded-nodes-3
++Common RejectNegative Var(flag_dump_analyzer_exploded_nodes_3)
++FIXME
++
++fanalyzer-verbosity=
++Common Joined UInteger Var(analyzer_verbosity) Init(2)
++FIXME
++
++fanalyzer-verbose-edges
++Common Var(flag_analyzer_verbose_edges) Init(0)
++FIXME
++
++fanalyzer-verbose-state-changes
++Common Var(flag_analyzer_verbose_state_changes) Init(0)
++FIXME
++
+ fdump-final-insns
+ Driver RejectNegative
+ 
-- 
1.8.5.3

