[PATCH] sanitizer: do not ICE for pointer cmp/sub

Martin Liška mliska@suse.cz
Thu Dec 10 08:31:33 GMT 2020


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



More information about the Gcc-patches mailing list