Successfully bootstrapped & regrtested on x86_64-pc-linux-gnu.
Pushed to trunk as r13-1774-g742377ed0f0931.

gcc/analyzer/ChangeLog:
        * sm-taint.cc (tainted_array_index::emit): Bulletproof against
        NULL m_arg.
        (tainted_array_index::describe_final_event): Likewise.
        (tainted_size::emit): Likewise.
        (tainted_size::describe_final_event): Likewise.

Signed-off-by: David Malcolm <dmalc...@redhat.com>
---
 gcc/analyzer/sm-taint.cc | 247 ++++++++++++++++++++++++++-------------
 1 file changed, 164 insertions(+), 83 deletions(-)

diff --git a/gcc/analyzer/sm-taint.cc b/gcc/analyzer/sm-taint.cc
index 0486c01aaca..51bfe06835d 100644
--- a/gcc/analyzer/sm-taint.cc
+++ b/gcc/analyzer/sm-taint.cc
@@ -212,53 +212,96 @@ public:
     diagnostic_metadata m;
     /* CWE-129: "Improper Validation of Array Index".  */
     m.add_cwe (129);
-    switch (m_has_bounds)
-      {
-      default:
-       gcc_unreachable ();
-      case BOUNDS_NONE:
-       return warning_meta (rich_loc, m, get_controlling_option (),
-                            "use of attacker-controlled value %qE"
-                            " in array lookup without bounds checking",
-                            m_arg);
-       break;
-      case BOUNDS_UPPER:
-       return warning_meta (rich_loc, m, get_controlling_option (),
-                            "use of attacker-controlled value %qE"
-                            " in array lookup without checking for negative",
-                            m_arg);
-       break;
-      case BOUNDS_LOWER:
-       return warning_meta (rich_loc, m, get_controlling_option (),
-                            "use of attacker-controlled value %qE"
-                            " in array lookup without upper-bounds checking",
-                            m_arg);
-       break;
-      }
+    if (m_arg)
+      switch (m_has_bounds)
+       {
+       default:
+         gcc_unreachable ();
+       case BOUNDS_NONE:
+         return warning_meta (rich_loc, m, get_controlling_option (),
+                              "use of attacker-controlled value %qE"
+                              " in array lookup without bounds checking",
+                              m_arg);
+         break;
+       case BOUNDS_UPPER:
+         return warning_meta (rich_loc, m, get_controlling_option (),
+                              "use of attacker-controlled value %qE"
+                              " in array lookup without checking for negative",
+                              m_arg);
+         break;
+       case BOUNDS_LOWER:
+         return warning_meta (rich_loc, m, get_controlling_option (),
+                              "use of attacker-controlled value %qE"
+                              " in array lookup without upper-bounds checking",
+                              m_arg);
+         break;
+       }
+    else
+      switch (m_has_bounds)
+       {
+       default:
+         gcc_unreachable ();
+       case BOUNDS_NONE:
+         return warning_meta (rich_loc, m, get_controlling_option (),
+                              "use of attacker-controlled value"
+                              " in array lookup without bounds checking");
+         break;
+       case BOUNDS_UPPER:
+         return warning_meta (rich_loc, m, get_controlling_option (),
+                              "use of attacker-controlled value"
+                              " in array lookup without checking for"
+                              " negative");
+         break;
+       case BOUNDS_LOWER:
+         return warning_meta (rich_loc, m, get_controlling_option (),
+                              "use of attacker-controlled value"
+                              " in array lookup without upper-bounds"
+                              " checking");
+         break;
+       }
   }
 
   label_text describe_final_event (const evdesc::final_event &ev) final 
override
   {
-    switch (m_has_bounds)
-      {
-      default:
-       gcc_unreachable ();
-      case BOUNDS_NONE:
-       return ev.formatted_print
-         ("use of attacker-controlled value %qE in array lookup"
-          " without bounds checking",
-          m_arg);
-      case BOUNDS_UPPER:
-       return ev.formatted_print
-         ("use of attacker-controlled value %qE"
-          " in array lookup without checking for negative",
-          m_arg);
-      case BOUNDS_LOWER:
-       return ev.formatted_print
-         ("use of attacker-controlled value %qE"
-          " in array lookup without upper-bounds checking",
-          m_arg);
-      }
+    if (m_arg)
+      switch (m_has_bounds)
+       {
+       default:
+         gcc_unreachable ();
+       case BOUNDS_NONE:
+         return ev.formatted_print
+           ("use of attacker-controlled value %qE in array lookup"
+            " without bounds checking",
+            m_arg);
+       case BOUNDS_UPPER:
+         return ev.formatted_print
+           ("use of attacker-controlled value %qE"
+            " in array lookup without checking for negative",
+            m_arg);
+       case BOUNDS_LOWER:
+         return ev.formatted_print
+           ("use of attacker-controlled value %qE"
+            " in array lookup without upper-bounds checking",
+            m_arg);
+       }
+    else
+      switch (m_has_bounds)
+       {
+       default:
+         gcc_unreachable ();
+       case BOUNDS_NONE:
+         return ev.formatted_print
+           ("use of attacker-controlled value in array lookup"
+            " without bounds checking");
+       case BOUNDS_UPPER:
+         return ev.formatted_print
+           ("use of attacker-controlled value"
+            " in array lookup without checking for negative");
+       case BOUNDS_LOWER:
+         return ev.formatted_print
+           ("use of attacker-controlled value"
+            " in array lookup without upper-bounds checking");
+       }
   }
 };
 
@@ -394,50 +437,88 @@ public:
   {
     diagnostic_metadata m;
     m.add_cwe (129);
-    switch (m_has_bounds)
-      {
-      default:
-       gcc_unreachable ();
-      case BOUNDS_NONE:
-       return warning_meta (rich_loc, m, get_controlling_option (),
-                            "use of attacker-controlled value %qE as size"
-                            " without bounds checking",
-                            m_arg);
-       break;
-      case BOUNDS_UPPER:
-       return warning_meta (rich_loc, m, get_controlling_option (),
-                            "use of attacker-controlled value %qE as size"
-                            " without lower-bounds checking",
-                            m_arg);
-       break;
-      case BOUNDS_LOWER:
-       return warning_meta (rich_loc, m, get_controlling_option (),
-                            "use of attacker-controlled value %qE as size"
-                            " without upper-bounds checking",
-                            m_arg);
-       break;
-      }
+    if (m_arg)
+      switch (m_has_bounds)
+       {
+       default:
+         gcc_unreachable ();
+       case BOUNDS_NONE:
+         return warning_meta (rich_loc, m, get_controlling_option (),
+                              "use of attacker-controlled value %qE as size"
+                              " without bounds checking",
+                              m_arg);
+         break;
+       case BOUNDS_UPPER:
+         return warning_meta (rich_loc, m, get_controlling_option (),
+                              "use of attacker-controlled value %qE as size"
+                              " without lower-bounds checking",
+                              m_arg);
+         break;
+       case BOUNDS_LOWER:
+         return warning_meta (rich_loc, m, get_controlling_option (),
+                              "use of attacker-controlled value %qE as size"
+                              " without upper-bounds checking",
+                              m_arg);
+         break;
+       }
+    else
+      switch (m_has_bounds)
+       {
+       default:
+         gcc_unreachable ();
+       case BOUNDS_NONE:
+         return warning_meta (rich_loc, m, get_controlling_option (),
+                              "use of attacker-controlled value as size"
+                              " without bounds checking");
+         break;
+       case BOUNDS_UPPER:
+         return warning_meta (rich_loc, m, get_controlling_option (),
+                              "use of attacker-controlled value as size"
+                              " without lower-bounds checking");
+         break;
+       case BOUNDS_LOWER:
+         return warning_meta (rich_loc, m, get_controlling_option (),
+                              "use of attacker-controlled value as size"
+                              " without upper-bounds checking");
+         break;
+       }
   }
 
   label_text describe_final_event (const evdesc::final_event &ev) final 
override
   {
-    switch (m_has_bounds)
-      {
-      default:
-       gcc_unreachable ();
-      case BOUNDS_NONE:
-       return ev.formatted_print ("use of attacker-controlled value %qE"
-                                  " as size without bounds checking",
-                                  m_arg);
-      case BOUNDS_UPPER:
-       return ev.formatted_print ("use of attacker-controlled value %qE"
-                                  " as size without lower-bounds checking",
-                                  m_arg);
-      case BOUNDS_LOWER:
-       return ev.formatted_print ("use of attacker-controlled value %qE"
-                                  " as size without upper-bounds checking",
-                                  m_arg);
-      }
+    if (m_arg)
+      switch (m_has_bounds)
+       {
+       default:
+         gcc_unreachable ();
+       case BOUNDS_NONE:
+         return ev.formatted_print ("use of attacker-controlled value %qE"
+                                    " as size without bounds checking",
+                                    m_arg);
+       case BOUNDS_UPPER:
+         return ev.formatted_print ("use of attacker-controlled value %qE"
+                                    " as size without lower-bounds checking",
+                                    m_arg);
+       case BOUNDS_LOWER:
+         return ev.formatted_print ("use of attacker-controlled value %qE"
+                                    " as size without upper-bounds checking",
+                                    m_arg);
+       }
+    else
+      switch (m_has_bounds)
+       {
+       default:
+         gcc_unreachable ();
+       case BOUNDS_NONE:
+         return ev.formatted_print ("use of attacker-controlled value"
+                                    " as size without bounds checking");
+       case BOUNDS_UPPER:
+         return ev.formatted_print ("use of attacker-controlled value"
+                                    " as size without lower-bounds checking");
+       case BOUNDS_LOWER:
+         return ev.formatted_print ("use of attacker-controlled value"
+                                    " as size without upper-bounds checking");
+       }
   }
 };
 
-- 
2.26.3

Reply via email to