From: David Malcolm Date: Thu, 12 Feb 2026 01:49:44 +0000 (-0500) Subject: analyzer: fix false +ve buffer overflow on sprintf [PR117369] X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=29ad594504dcc1fa736d7305e5a853c08e4e4180;p=thirdparty%2Fgcc.git analyzer: fix false +ve buffer overflow on sprintf [PR117369] 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 --- diff --git a/gcc/analyzer/kf.cc b/gcc/analyzer/kf.cc index b6b4f8f93ac..82aaee1dcb5 100644 --- a/gcc/analyzer/kf.cc +++ b/gcc/analyzer/kf.cc @@ -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 index 00000000000..ed12831daf0 --- /dev/null +++ b/gcc/testsuite/c-c++-common/analyzer/sprintf-pr117369.c @@ -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" } */ +} diff --git a/gcc/testsuite/gcc.dg/analyzer/doom-d_main-IdentifyVersion.c b/gcc/testsuite/gcc.dg/analyzer/doom-d_main-IdentifyVersion.c index e55c378c7ec..a52e3528cfa 100644 --- a/gcc/testsuite/gcc.dg/analyzer/doom-d_main-IdentifyVersion.c +++ b/gcc/testsuite/gcc.dg/analyzer/doom-d_main-IdentifyVersion.c @@ -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 } */