Hello.

In C FE we have troubles to instrument top-level pointer comparison
(and subtraction):

/home/marxin/Programming/gcc/gcc/testsuite/c-c++-common/asan/pr98204.c:5:1: 
internal compiler error: in pointer_diff, at c/c-typeck.c:3954
    5 | static long i=((char*)&(v.c)-(char*)&v);
      | ^~~~~~

and

 gcc /home/marxin/Programming/gcc/gcc/testsuite/c-c++-common/asan/pr98204.c -c 
-fsanitize=address,pointer-compare
/home/marxin/Programming/gcc/gcc/testsuite/c-c++-common/asan/pr98204.c:6:16: 
error: initializer element is not constant
    6 | static long i2=((char*)&(v.c)<(char*)&v);
      |                ^

The patch fixes that by not instrumenting that when current_function_decl
is NULL_TREE.

On the contrary, C++ is fine with that and does the emission in ctor:

$ + /home/marxin/Programming/gcc/gcc/testsuite/c-c++-common/asan/pr98204.c -c 
-fsanitize=address,pointer-compare,pointer-subtract 
-fdump-tree-gimple=/dev/stdout
...
void __static_initialization_and_destruction_0 (int __initialize_p, int 
__priority)
{
  if (__initialize_p == 1) goto <D.2830>; else goto <D.2831>;
  <D.2830>:
  __builtin___asan_before_dynamic_init 
("/home/marxin/Programming/gcc/gcc/testsuite/c-c++-common/asan/pr98204.c");
  if (__priority == 65535) goto <D.2832>; else goto <D.2833>;
  <D.2832>:
  __builtin___sanitizer_ptr_sub (&v.c, &v);
  i = 0;
  __builtin___sanitizer_ptr_cmp (&v.c, &v);

Are we able to do something similar for C FE, or are we fine with the suggested 
patch?

Patch can bootstrap on x86_64-linux-gnu and survives regression tests.

Ready to be installed?
Thanks,
Martin

gcc/c/ChangeLog:

        PR sanitizer/98204
        * c-typeck.c (pointer_diff): Do not emit a top-level
        sanitization.
        (build_binary_op): Likewise.

gcc/testsuite/ChangeLog:

        PR sanitizer/98204
        * c-c++-common/asan/pr98204.c: New test.
---
 gcc/c/c-typeck.c                          | 6 +++---
 gcc/testsuite/c-c++-common/asan/pr98204.c | 6 ++++++
 2 files changed, 9 insertions(+), 3 deletions(-)
 create mode 100644 gcc/testsuite/c-c++-common/asan/pr98204.c

diff --git a/gcc/c/c-typeck.c b/gcc/c/c-typeck.c
index 138af073925..7d58e8de342 100644
--- a/gcc/c/c-typeck.c
+++ b/gcc/c/c-typeck.c
@@ -3949,10 +3949,9 @@ pointer_diff (location_t loc, tree op0, tree op1, tree 
*instrument_expr)
     pedwarn (loc, OPT_Wpointer_arith,
             "pointer to a function used in subtraction");
- if (sanitize_flags_p (SANITIZE_POINTER_SUBTRACT))
+  if (current_function_decl != NULL_TREE
+      && sanitize_flags_p (SANITIZE_POINTER_SUBTRACT))
     {
-      gcc_assert (current_function_decl != NULL_TREE);
-
       op0 = save_expr (op0);
       op1 = save_expr (op1);
@@ -12324,6 +12323,7 @@ build_binary_op (location_t location, enum tree_code code,
        }
if ((code0 == POINTER_TYPE || code1 == POINTER_TYPE)
+         && current_function_decl != NULL_TREE
          && sanitize_flags_p (SANITIZE_POINTER_COMPARE))
        {
          op0 = save_expr (op0);
diff --git a/gcc/testsuite/c-c++-common/asan/pr98204.c 
b/gcc/testsuite/c-c++-common/asan/pr98204.c
new file mode 100644
index 00000000000..7532646d712
--- /dev/null
+++ b/gcc/testsuite/c-c++-common/asan/pr98204.c
@@ -0,0 +1,6 @@
+/* PR sanitizer/98204 */
+/* { dg-options "-fsanitize=address,pointer-subtract,pointer-compare" } */
+
+struct{int c;}v;
+static long i=((char*)&(v.c)-(char*)&v);
+static long i2=((char*)&(v.c)<(char*)&v);
--
2.29.2

Reply via email to