]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
analyzer: fix false +ve buffer overflow on sprintf [PR117369]
authorDavid Malcolm <dmalcolm@redhat.com>
Thu, 12 Feb 2026 01:49:44 +0000 (20:49 -0500)
committerDavid Malcolm <dmalcolm@redhat.com>
Thu, 12 Feb 2026 01:49:44 +0000 (20:49 -0500)
gcc/analyzer/ChangeLog:
PR analyzer/117369
* kf.cc (kf_sprintf::impl_call_pre): Use the capacity of the
region when "faking" a write to the destination buffer, to
avoid buffer overflow false +ves.

gcc/testsuite/ChangeLog:
PR analyzer/117369
* c-c++-common/analyzer/sprintf-pr117369.c: New test.
* gcc.dg/analyzer/doom-d_main-IdentifyVersion.c: Update expected
results to reflect complexity limits being hit earlier.

Signed-off-by: David Malcolm <dmalcolm@redhat.com>
gcc/analyzer/kf.cc
gcc/testsuite/c-c++-common/analyzer/sprintf-pr117369.c [new file with mode: 0644]
gcc/testsuite/gcc.dg/analyzer/doom-d_main-IdentifyVersion.c

index b6b4f8f93acbc7ada30984d2354ee86ba80aadc2..82aaee1dcb58180403bbb98df161d0265d3a2c87 100644 (file)
@@ -1245,6 +1245,12 @@ public:
     const svalue *dst_ptr = cd.get_arg_svalue (0);
     const region *dst_reg
       = model->deref_rvalue (dst_ptr, cd.get_arg_tree (0), ctxt);
+    /* Restrict the region we consider to be affected to the valid capacity
+       so that we don't trigger buffer overflow false positives.  */
+    const svalue *capacity = model->get_capacity (dst_reg);
+    dst_reg = model->get_manager ()->get_sized_region (dst_reg,
+                                                      NULL_TREE,
+                                                      capacity);
     const svalue *content = cd.get_or_create_conjured_svalue (dst_reg);
     model->set_value (dst_reg, content, ctxt);
     cd.set_any_lhs_with_defaults ();
diff --git a/gcc/testsuite/c-c++-common/analyzer/sprintf-pr117369.c b/gcc/testsuite/c-c++-common/analyzer/sprintf-pr117369.c
new file mode 100644 (file)
index 0000000..ed12831
--- /dev/null
@@ -0,0 +1,13 @@
+/* { dg-additional-options "-O" } */
+
+extern int
+sprintf (char *__restrict __s,
+        const char *__restrict __format, ...)
+  __attribute__ ((__nothrow__));
+
+int
+main()
+{
+  char buf[16];
+  sprintf(buf + 1, "."); /* { dg-bogus "buffer overflow" } */
+}
index e55c378c7ecc44b9304c5c008b5064e17ab18d5d..a52e3528cfa18d71d3550a0b1dc51e73c5063710 100644 (file)
@@ -220,53 +220,59 @@ IdentifyVersion(void)
   if (!access(doom2wad, 4)) {
     gamemode = commercial;
     D_AddFile(doom2wad);
-    return; /* { dg-warning "leak of 'doom2wad'" } */
-    /* { dg-warning "leak of 'doomuwad'"    "leak" { target *-*-* } .-1 } */
-    /* { dg-warning "leak of 'doomwad'"     "leak" { target *-*-* } .-2 } */
-    /* { dg-warning "leak of 'doom1wad'"    "leak" { target *-*-* } .-3 } */
-    /* { dg-warning "leak of 'plutoniawad'" "leak" { target *-*-* } .-4 } */
-    /* { dg-warning "leak of 'tntwad'"      "leak" { target *-*-* } .-5 } */
-    /* { dg-warning "leak of 'doom2fwad'"   "leak" { target *-*-* } .-6 } */
+    return; /* { dg-warning "leak of 'doom2wad'" "" { xfail *-*-* } } */
+    /* { dg-warning "leak of 'doomuwad'"    "leak" { xfail *-*-* } .-1 } */
+    /* { dg-warning "leak of 'doomwad'"     "leak" { xfail *-*-* } .-2 } */
+    /* { dg-warning "leak of 'doom1wad'"    "leak" { xfail *-*-* } .-3 } */
+    /* { dg-warning "leak of 'plutoniawad'" "leak" { xfail *-*-* } .-4 } */
+    /* { dg-warning "leak of 'tntwad'"      "leak" { xfail *-*-* } .-5 } */
+    /* { dg-warning "leak of 'doom2fwad'"   "leak" { xfail *-*-* } .-6 } */
   }
 
   if (!access(plutoniawad, 4)) {
     gamemode = commercial;
     D_AddFile(plutoniawad);
-    return; /* { dg-warning "leak of 'doom2wad'" } */
-    /* { dg-warning "leak of 'doomuwad'"    "leak" { target *-*-* } .-1 } */
-    /* { dg-warning "leak of 'doomwad'"     "leak" { target *-*-* } .-2 } */
-    /* { dg-warning "leak of 'doom1wad'"    "leak" { target *-*-* } .-3 } */
-    /* { dg-warning "leak of 'plutoniawad'" "leak" { target *-*-* } .-4 } */
-    /* { dg-warning "leak of 'tntwad'"      "leak" { target *-*-* } .-5 } */
-    /* { dg-warning "leak of 'doom2fwad'"   "leak" { target *-*-* } .-6 } */
+    return; /* { dg-warning "leak of 'doom2wad'" "" { xfail *-*-* } } */
+    /* { dg-warning "leak of 'doomuwad'"    "leak" { xfail *-*-* } .-1 } */
+    /* { dg-warning "leak of 'doomwad'"     "leak" { xfail *-*-* } .-2 } */
+    /* { dg-warning "leak of 'doom1wad'"    "leak" { xfail *-*-* } .-3 } */
+    /* { dg-warning "leak of 'plutoniawad'" "leak" { xfail *-*-* } .-4 } */
+    /* { dg-warning "leak of 'tntwad'"      "leak" { xfail *-*-* } .-5 } */
+    /* { dg-warning "leak of 'doom2fwad'"   "leak" { xfail *-*-* } .-6 } */
   }
 
   if (!access(tntwad, 4)) {
     gamemode = commercial;
     D_AddFile(tntwad);
-    return; /* { dg-warning "leak of 'doom2wad'" } */
-    /* { dg-warning "leak of 'doomuwad'"    "leak" { target *-*-* } .-1 } */
-    /* { dg-warning "leak of 'doomwad'"     "leak" { target *-*-* } .-2 } */
-    /* { dg-warning "leak of 'doom1wad'"    "leak" { target *-*-* } .-3 } */
-    /* { dg-warning "leak of 'plutoniawad'" "leak" { target *-*-* } .-4 } */
-    /* { dg-warning "leak of 'tntwad'"      "leak" { target *-*-* } .-5 } */
-    /* { dg-warning "leak of 'doom2fwad'"   "leak" { target *-*-* } .-6 } */
+    return; /* { dg-warning "leak of 'doom2wad'"  "" { xfail *-*-* } } */
+    /* { dg-warning "leak of 'doomuwad'"    "leak" { xfail *-*-* } .-1 } */
+    /* { dg-warning "leak of 'doomwad'"     "leak" { xfail *-*-* } .-2 } */
+    /* { dg-warning "leak of 'doom1wad'"    "leak" { xfail *-*-* } .-3 } */
+    /* { dg-warning "leak of 'plutoniawad'" "leak" { xfail *-*-* } .-4 } */
+    /* { dg-warning "leak of 'tntwad'"      "leak" { xfail *-*-* } .-5 } */
+    /* { dg-warning "leak of 'doom2fwad'"   "leak" { xfail *-*-* } .-6 } */
   }
 
   if (!access(doomuwad, 4)) {
     gamemode = retail;
     D_AddFile(doomuwad);
-    return; /* { dg-warning "leak of 'doom2wad'" } */
-    /* { dg-warning "leak of 'doomuwad'"    "leak" { target *-*-* } .-1 } */
-    /* { dg-warning "leak of 'doomwad'"     "leak" { target *-*-* } .-2 } */
-    /* { dg-warning "leak of 'doom1wad'"    "leak" { target *-*-* } .-3 } */
-    /* { dg-warning "leak of 'plutoniawad'" "leak" { target *-*-* } .-4 } */
-    /* { dg-warning "leak of 'tntwad'"      "leak" { target *-*-* } .-5 } */
-    /* { dg-warning "leak of 'doom2fwad'"   "leak" { target *-*-* } .-6 } */
+    return; /* { dg-warning "leak of 'doom2wad'"  "" { xfail *-*-* } } */
+    /* { dg-warning "leak of 'doomuwad'"    "leak" { xfail *-*-* } .-1 } */
+    /* { dg-warning "leak of 'doomwad'"     "leak" { xfail *-*-* } .-2 } */
+    /* { dg-warning "leak of 'doom1wad'"    "leak" { xfail *-*-* } .-3 } */
+    /* { dg-warning "leak of 'plutoniawad'" "leak" { xfail *-*-* } .-4 } */
+    /* { dg-warning "leak of 'tntwad'"      "leak" { xfail *-*-* } .-5 } */
+    /* { dg-warning "leak of 'doom2fwad'"   "leak" { xfail *-*-* } .-6 } */
   }
 
   /* [...snip...] */
 
   printf("Game mode indeterminate.\n");
   gamemode = indetermined;
-}
+} /* { dg-warning "leak of 'doom2wad'" } */
+/* { dg-warning "leak of 'doomuwad'"    "leak" { target *-*-* } .-1 } */
+/* { dg-warning "leak of 'doomwad'"     "leak" { target *-*-* } .-2 } */
+/* { dg-warning "leak of 'doom1wad'"    "leak" { target *-*-* } .-3 } */
+/* { dg-warning "leak of 'plutoniawad'" "leak" { target *-*-* } .-4 } */
+/* { dg-warning "leak of 'tntwad'"      "leak" { target *-*-* } .-5 } */
+/* { dg-warning "leak of 'doom2fwad'"   "leak" { target *-*-* } .-6 } */