From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: by sourceware.org (Postfix, from userid 1734) id 3D6103858D28; Thu, 26 Jan 2023 17:59:46 +0000 (GMT) DKIM-Filter: OpenDKIM Filter v2.11.0 sourceware.org 3D6103858D28 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gcc.gnu.org; s=default; t=1674755986; bh=eyOlVFq10eCNM911prS7RPyZjzwQdu1ZzTSulNjmgKQ=; h=From:To:Subject:Date:From; b=JU3yJDF9UJ6iF2+ZComMoRENAK+1qJh+Kx280w4cdkn9U2g93LteIrUMVMPN6mOMI o0g9yZLoIK8Jodcnb+cIOMyULYu0pnyAiQU47J8hmAUuiKQvmOqZMnW4wibuqVqVp1 PDJnaMnPuNB4OKFbWmDr6LdSPrCHqmU5ioI2KdM8= MIME-Version: 1.0 Content-Transfer-Encoding: 7bit Content-Type: text/plain; charset="utf-8" From: Marek Polacek To: gcc-cvs@gcc.gnu.org Subject: [gcc r13-5399] opts: SANITIZE_ADDRESS wrongly cleared [PR108543] X-Act-Checkin: gcc X-Git-Author: Marek Polacek X-Git-Refname: refs/heads/trunk X-Git-Oldrev: 6dd4578f4779b27b2115d78226ff7df46c939061 X-Git-Newrev: a82ce9c8d155ecda2d1c647d5c588f29e21ef4a3 Message-Id: <20230126175946.3D6103858D28@sourceware.org> Date: Thu, 26 Jan 2023 17:59:46 +0000 (GMT) List-Id: https://gcc.gnu.org/g:a82ce9c8d155ecda2d1c647d5c588f29e21ef4a3 commit r13-5399-ga82ce9c8d155ecda2d1c647d5c588f29e21ef4a3 Author: Marek Polacek Date: Wed Jan 25 17:19:54 2023 -0500 opts: SANITIZE_ADDRESS wrongly cleared [PR108543] Here we crash on a null fndecl ultimately because we haven't defined the built-ins described in sanitizer.def. So builtin_decl_explicit (BUILT_IN_ASAN_POINTER_SUBTRACT); returns NULL_TREE, causing an ICE later. DEF_SANITIZER_BUILTIN only actually defines the built-ins when flag_sanitize has SANITIZE_ADDRESS, or some of the other SANITIZE_*, but it doesn't check SANITIZE_KERNEL_ADDRESS or SANITIZE_USER_ADDRESS. Unfortunately, with -fsanitize=address -fno-sanitize=kernel-address or -fsanitize=kernel-address -fno-sanitize=address SANITIZE_ADDRESS ends up being unset from flag_sanitize even though _USER/_KERNEL are set. That's because -fsanitize=address means SANITIZE_ADDRESS | SANITIZE_USER_ADDRESS and -fsanitize=kernel-address is SANITIZE_ADDRESS | SANITIZE_KERNEL_ADDRESS but parse_sanitizer_options does flags &= ~sanitizer_opts[i].flag; so the subsequent -fno- unsets SANITIZE_ADDRESS. Then no sanitizer built-ins are actually defined. I'm not sure why SANITIZE_ADDRESS isn't just SANITIZE_USER_ADDRESS | SANITIZE_KERNEL_ADDRESS, I don't think we need 3 bits. PR middle-end/108543 gcc/ChangeLog: * opts.cc (parse_sanitizer_options): Don't always clear SANITIZE_ADDRESS if it was previously set. gcc/testsuite/ChangeLog: * c-c++-common/asan/pointer-subtract-5.c: New test. * c-c++-common/asan/pointer-subtract-6.c: New test. * c-c++-common/asan/pointer-subtract-7.c: New test. * c-c++-common/asan/pointer-subtract-8.c: New test. Diff: --- gcc/opts.cc | 9 ++++++++- gcc/testsuite/c-c++-common/asan/pointer-subtract-5.c | 15 +++++++++++++++ gcc/testsuite/c-c++-common/asan/pointer-subtract-6.c | 15 +++++++++++++++ gcc/testsuite/c-c++-common/asan/pointer-subtract-7.c | 15 +++++++++++++++ gcc/testsuite/c-c++-common/asan/pointer-subtract-8.c | 15 +++++++++++++++ 5 files changed, 68 insertions(+), 1 deletion(-) diff --git a/gcc/opts.cc b/gcc/opts.cc index 9ba47d7deaa..a032cd4ce58 100644 --- a/gcc/opts.cc +++ b/gcc/opts.cc @@ -2246,7 +2246,14 @@ parse_sanitizer_options (const char *p, location_t loc, int scode, flags |= sanitizer_opts[i].flag; } else - flags &= ~sanitizer_opts[i].flag; + { + flags &= ~sanitizer_opts[i].flag; + /* Don't always clear SANITIZE_ADDRESS if it was previously + set: -fsanitize=address -fno-sanitize=kernel-address should + leave SANITIZE_ADDRESS set. */ + if (flags & (SANITIZE_KERNEL_ADDRESS | SANITIZE_USER_ADDRESS)) + flags |= SANITIZE_ADDRESS; + } found = true; break; } diff --git a/gcc/testsuite/c-c++-common/asan/pointer-subtract-5.c b/gcc/testsuite/c-c++-common/asan/pointer-subtract-5.c new file mode 100644 index 00000000000..867eda0e61e --- /dev/null +++ b/gcc/testsuite/c-c++-common/asan/pointer-subtract-5.c @@ -0,0 +1,15 @@ +/* PR middle-end/108543 */ +/* { dg-do compile } */ +/* { dg-options "-fsanitize=address -fno-sanitize=kernel-address -fsanitize=pointer-subtract" } */ + +struct S { + long _M_p; +}; + +typedef struct S S; + +__PTRDIFF_TYPE__ +f (S __x, S __y) +{ + return &__x._M_p - &__y._M_p; +} diff --git a/gcc/testsuite/c-c++-common/asan/pointer-subtract-6.c b/gcc/testsuite/c-c++-common/asan/pointer-subtract-6.c new file mode 100644 index 00000000000..785b90b3d98 --- /dev/null +++ b/gcc/testsuite/c-c++-common/asan/pointer-subtract-6.c @@ -0,0 +1,15 @@ +/* PR middle-end/108543 */ +/* { dg-do compile } */ +/* { dg-options "-fsanitize=kernel-address -fno-sanitize=address -fsanitize=pointer-subtract" } */ + +struct S { + long _M_p; +}; + +typedef struct S S; + +__PTRDIFF_TYPE__ +f (S __x, S __y) +{ + return &__x._M_p - &__y._M_p; +} diff --git a/gcc/testsuite/c-c++-common/asan/pointer-subtract-7.c b/gcc/testsuite/c-c++-common/asan/pointer-subtract-7.c new file mode 100644 index 00000000000..11b63401b8c --- /dev/null +++ b/gcc/testsuite/c-c++-common/asan/pointer-subtract-7.c @@ -0,0 +1,15 @@ +/* PR middle-end/108543 */ +/* { dg-do compile } */ +/* { dg-options "-fno-sanitize=kernel-address -fsanitize=address -fsanitize=pointer-subtract" } */ + +struct S { + long _M_p; +}; + +typedef struct S S; + +__PTRDIFF_TYPE__ +f (S __x, S __y) +{ + return &__x._M_p - &__y._M_p; +} diff --git a/gcc/testsuite/c-c++-common/asan/pointer-subtract-8.c b/gcc/testsuite/c-c++-common/asan/pointer-subtract-8.c new file mode 100644 index 00000000000..ac2b9c3c1d9 --- /dev/null +++ b/gcc/testsuite/c-c++-common/asan/pointer-subtract-8.c @@ -0,0 +1,15 @@ +/* PR middle-end/108543 */ +/* { dg-do compile } */ +/* { dg-options "-fno-sanitize=address -fsanitize=kernel-address -fsanitize=pointer-subtract" } */ + +struct S { + long _M_p; +}; + +typedef struct S S; + +__PTRDIFF_TYPE__ +f (S __x, S __y) +{ + return &__x._M_p - &__y._M_p; +}