aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
authorMarek Polacek <polacek@redhat.com>2023-01-25 17:19:54 -0500
committerMarek Polacek <polacek@redhat.com>2023-01-26 12:59:17 -0500
commita82ce9c8d155ecda2d1c647d5c588f29e21ef4a3 (patch)
treef1734094f3c014be00b7230cba8bc907c7a8155b /gcc
parent6dd4578f4779b27b2115d78226ff7df46c939061 (diff)
downloadgcc-a82ce9c8d155ecda2d1c647d5c588f29e21ef4a3.zip
gcc-a82ce9c8d155ecda2d1c647d5c588f29e21ef4a3.tar.gz
gcc-a82ce9c8d155ecda2d1c647d5c588f29e21ef4a3.tar.bz2
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.
Diffstat (limited to 'gcc')
-rw-r--r--gcc/opts.cc9
-rw-r--r--gcc/testsuite/c-c++-common/asan/pointer-subtract-5.c15
-rw-r--r--gcc/testsuite/c-c++-common/asan/pointer-subtract-6.c15
-rw-r--r--gcc/testsuite/c-c++-common/asan/pointer-subtract-7.c15
-rw-r--r--gcc/testsuite/c-c++-common/asan/pointer-subtract-8.c15
5 files changed, 68 insertions, 1 deletions
diff --git a/gcc/opts.cc b/gcc/opts.cc
index 9ba47d7..a032cd4 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 0000000..867eda0
--- /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 0000000..785b90b
--- /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 0000000..11b6340
--- /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 0000000..ac2b9c3
--- /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;
+}