[Bug sanitizer/82076] New: inconsistencies between sanitizer and -Wstringop-overflow

msebor at gcc dot gnu.org gcc-bugzilla@gcc.gnu.org
Fri Sep 1 17:32:00 GMT 2017


https://gcc.gnu.org/bugzilla/show_bug.cgi?id=82076

            Bug ID: 82076
           Summary: inconsistencies between sanitizer and
                    -Wstringop-overflow
           Product: gcc
           Version: 8.0
            Status: UNCONFIRMED
          Severity: normal
          Priority: P3
         Component: sanitizer
          Assignee: unassigned at gcc dot gnu.org
          Reporter: msebor at gcc dot gnu.org
                CC: dodji at gcc dot gnu.org, dvyukov at gcc dot gnu.org,
                    jakub at gcc dot gnu.org, kcc at gcc dot gnu.org, marxin at gcc dot gnu.org
  Target Milestone: ---

The two options, -fsanitize=undefined, and -Wstringop-overflow, detect disjoint
subsets of undefined accesses.  The inconsistency is due to GCC folding some
calls to functions like memset but not others.  For memcpy, the folder only
folds calls with constant sizes that are powers of 2.  This defeats the
-Wstringop-overflow warning which only considers calls to functions that
weren't folded.  The folded copy expressions (MEM_REFs) are then instrumented
and invalid access are detected.  Calls that aren't folded (i.e., those with
non-constant sizes or with constant sizes that aren't a power of 2), on the
other hand, are examined by -Wstringop-overflow, but they are not subject to
instrumentation.

This makes each option considerably less useful than it could be.  The
sanitizer would be improved by also instrumenting calls to the known memory and
string functions.  -Wstringop-overflow would benefit from delayed folding
(e.g., the folding could be deferred until after the tree-ssa-strlen pass has
run; that would have the nice effect of exposing optimization opportunities in
the strlen pass such as those discussed in bug 81703).

The example below shows the problem.  The first invocation of the compiler
issues a warning but the instrumented program runs to completion without
detecting the out-of-bounds access.  The second GCC invocation doesn't detect
the read past the end but the instrumented program does.  It would be an
improvement if all invocations (i.e., that of the compiler and the sanitized
program) detected the problem.  (It's understood that -Wstringop-overflow can
only detect invalid accesses when the size is either constant or in some range;
similarly, the sanitizer can only detect accesses that actually take place at
runtime, so neither solution can detect 100% of invalid accesses in every
program.)

$ cat t.c && set -x && for N in 3 4; do gcc -DN=$N -O2 -Wall
-fsanitize=undefined t.c && ./a.out ; done
int main (void)
{
    char a[4];
    const char *s = "1";
    __builtin_memcpy (a, s, N);
    __builtin_printf ("%s\n", a);
}
+ for N in 3 4
+ gcc -DN=3 -O2 -Wall -fsanitize=undefined t.c
t.c: In function ‘main’:
t.c:5:5: warning: ‘__builtin_memcpy’ reading 3 bytes from a region of size 2
[-Wstringop-overflow=]
     __builtin_memcpy (a, s, N);
     ^~~~~~~~~~~~~~~~~~~~~~~~~~
+ ./a.out
1
+ for N in 3 4
+ gcc -DN=4 -O2 -Wall -fsanitize=undefined t.c
+ ./a.out
t.c:5:5: runtime error: load of address 0x000000400724 with insufficient space
for an object of type 'char'
0x000000400724: note: pointer points here
  01 00 02 00 31 00 74 2e  63 00 00 00 01 1b 03 3b  30 00 00 00 05 00 00 00  34
fe ff ff 7c 00 00 00
              ^ 
1
++ printf '\033]0;%s on %s %s:%s\007' 'fc-25 (Twenty' x86_64 tor
/opt/notnfs/msebor/build/tmp


More information about the Gcc-bugs mailing list