aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--gcc/analyzer/region-model.cc15
-rw-r--r--gcc/testsuite/gcc.dg/analyzer/sprintf-1.c11
2 files changed, 26 insertions, 0 deletions
diff --git a/gcc/analyzer/region-model.cc b/gcc/analyzer/region-model.cc
index 99817ae..7a2f81f 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 f8dc806..e7c2b30 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
+}