Never try to compute size for offset when the object size is -1, which
is either unknown maximum or uninitialized minimum irrespective of the
osi->pass number.

gcc/ChangeLog:

        PR tree-optimization/pr103961
        * tree-object-size.c (plus_stmt_object_size): Always avoid
        computing offset for -1 size.

gcc/testsuite/ChangeLog:

        PR tree-optimization/pr103961
        * gcc.dg/pr103961.c: New test case.

Co-authored-by: Jakub Jelinek <ja...@redhat.com>
Signed-off-by: Siddhesh Poyarekar <siddh...@gotplt.org>
---
Tested with i686 build+test, x86_64 bootstrap build+test and ubsan
bootstrap.

 gcc/testsuite/gcc.dg/pr103961.c | 30 ++++++++++++++++++++++++++++++
 gcc/tree-object-size.c          | 11 ++++-------
 2 files changed, 34 insertions(+), 7 deletions(-)
 create mode 100644 gcc/testsuite/gcc.dg/pr103961.c

diff --git a/gcc/testsuite/gcc.dg/pr103961.c b/gcc/testsuite/gcc.dg/pr103961.c
new file mode 100644
index 00000000000..2cd52884e3b
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/pr103961.c
@@ -0,0 +1,30 @@
+/* { dg-do compile } */
+/* { dg-options "-O2" } */
+
+extern void abort ();
+
+extern inline __attribute__ ((__gnu_inline__)) int
+sprintf (char *restrict s, const char *restrict fmt, ...)
+{
+  return __builtin___sprintf_chk (s, 1, __builtin_object_size (s, 1),
+                                 fmt, __builtin_va_arg_pack ());
+}
+
+void
+cap_to_text (int c)
+{
+  char buf[1572];
+  char *p;
+  int n, t;
+  p = 20 + buf;
+  for (t = 8; t--; )
+    {
+      for (n = 0; n < c; n++)
+       p += sprintf (p, "a,");
+      p--;
+      if (__builtin_object_size (p, 1) == 0)
+       abort ();
+    }
+}
+
+/* { dg-final { scan-assembler-not "abort" } } */
diff --git a/gcc/tree-object-size.c b/gcc/tree-object-size.c
index fbaf57a20f8..f7cc323591c 100644
--- a/gcc/tree-object-size.c
+++ b/gcc/tree-object-size.c
@@ -990,13 +990,10 @@ plus_stmt_object_size (struct object_size_info *osi, tree 
var, gimple *stmt)
          addr_object_size (osi, op0, object_size_type, &bytes, &wholesize);
        }
 
-      /* In the first pass, do not compute size for offset if either the
-        maximum size is unknown or the minimum size is not initialized yet;
-        the latter indicates a dependency loop and will be resolved in
-        subsequent passes.  We attempt to compute offset for 0 minimum size
-        too because a negative offset could be within bounds of WHOLESIZE,
-        giving a non-zero result for VAR.  */
-      if (osi->pass != 0 || !size_unknown_p (bytes, 0))
+      /* size_for_offset doesn't make sense for -1 size, but it does for size 0
+        since the wholesize could be non-zero and a negative offset could give
+        a non-zero size.  */
+      if (!size_unknown_p (bytes, 0))
        bytes = size_for_offset (bytes, op1, wholesize);
     }
   else
-- 
2.33.1

Reply via email to