gcc/analyzer/ChangeLog:
        PR analyzer/105899
        * region-model.cc (iterable_cluster::iterable_cluster): Add
        symbolic binding keys to m_symbolic_bindings.
        (iterable_cluster::has_symbolic_bindings_p): New.
        (iterable_cluster::m_symbolic_bindings): New field.
        (region_model::scan_for_null_terminator): Treat clusters with
        symbolic bindings as having unknown strlen.

gcc/testsuite/ChangeLog:
        PR analyzer/105899
        * gcc.dg/analyzer/sprintf-1.c: Include "analyzer-decls.h".
        (test_strlen_1): New.
---
 gcc/analyzer/region-model.cc              | 15 +++++++++++++++
 gcc/testsuite/gcc.dg/analyzer/sprintf-1.c | 11 +++++++++++
 2 files changed, 26 insertions(+)

diff --git a/gcc/analyzer/region-model.cc b/gcc/analyzer/region-model.cc
index 99817aee3a93..7a2f81f36e0f 100644
--- a/gcc/analyzer/region-model.cc
+++ b/gcc/analyzer/region-model.cc
@@ -3420,6 +3420,8 @@ public:
            if (concrete_key->get_byte_range (&fragment_bytes))
              m_fragments.safe_push (fragment (fragment_bytes, sval));
          }
+       else
+         m_symbolic_bindings.safe_push (key);
       }
     m_fragments.qsort (fragment::cmp_ptrs);
   }
@@ -3440,8 +3442,14 @@ public:
     return false;
   }
 
+  bool has_symbolic_bindings_p () const
+  {
+    return !m_symbolic_bindings.is_empty ();
+  }
+
 private:
   auto_vec<fragment> m_fragments;
+  auto_vec<const binding_key *> m_symbolic_bindings;
 };
 
 /* Simulate reading the bytes at BYTES from BASE_REG.
@@ -3610,6 +3618,13 @@ region_model::scan_for_null_terminator (const region 
*reg,
   /* No binding for this base_region, or no binding at src_byte_offset
      (or a symbolic binding).  */
 
+  if (c.has_symbolic_bindings_p ())
+    {
+      if (out_sval)
+       *out_sval = m_mgr->get_or_create_unknown_svalue (NULL_TREE);
+      return m_mgr->get_or_create_unknown_svalue (size_type_node);
+    }
+
   /* TODO: the various special-cases seen in
      region_model::get_store_value.  */
 
diff --git a/gcc/testsuite/gcc.dg/analyzer/sprintf-1.c 
b/gcc/testsuite/gcc.dg/analyzer/sprintf-1.c
index f8dc806d6192..e7c2b3089c5b 100644
--- a/gcc/testsuite/gcc.dg/analyzer/sprintf-1.c
+++ b/gcc/testsuite/gcc.dg/analyzer/sprintf-1.c
@@ -1,6 +1,8 @@
 /* See e.g. https://en.cppreference.com/w/c/io/fprintf
    and https://www.man7.org/linux/man-pages/man3/sprintf.3.html */
 
+#include "analyzer-decls.h"
+
 extern int
 sprintf(char* dst, const char* fmt, ...)
   __attribute__((__nothrow__));
@@ -64,3 +66,12 @@ test_fmt_not_terminated (char *dst)
   return sprintf (dst, fmt); /* { dg-warning "stack-based buffer over-read" } 
*/
   /* { dg-message "while looking for null terminator for argument 2 
\\('&fmt'\\) of 'sprintf'..." "event" { target *-*-* } .-1 } */
 }
+
+void
+test_strlen_1 (void)
+{
+  char buf[10];
+  sprintf (buf, "msg: %s\n", "abc");
+  __analyzer_eval (__builtin_strlen (buf) == 8); /* { dg-warning "UNKNOWN" } */
+  // TODO: ideally would be TRUE  
+}
-- 
2.26.3

Reply via email to