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

            Bug ID: 80414
           Summary: [UBSAN] segfault with -fsanitize=undefined
           Product: gcc
           Version: 7.0.1
            Status: UNCONFIRMED
          Severity: normal
          Priority: P3
         Component: sanitizer
          Assignee: unassigned at gcc dot gnu.org
          Reporter: d.khalikov at partner dot samsung.com
                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
  Target Milestone: ---

Created attachment 41191
  --> https://gcc.gnu.org/bugzilla/attachment.cgi?id=41191&action=edit
patch

Hello everyone.

I got segfault on 32 bit host with -fsanitize=undefined

My test case:

# cat test.c 

int main()
{
  long long offset = 10;
  char array[10];
  char c = array[offset];
  return 0;
}

# gcc -o test test.c -fsanitize=undefined -static-libubsan
# ./test

That happens while checking for bounds-strict option on 32 bit host.

As i can see gcc push value of the index to the stack before call 
__ubsan_handle_out_of_bounds

 67         subl    $44, %esp
 68         movl    $10, -32(%ebp)
 69         movl    $0, -28(%ebp)
 70         movl    -32(%ebp), %ebx
 71         movl    -28(%ebp), %esi
 72         movl    %ebx, %eax
 73         cmpl    $9, %eax
 74         jbe     .L2
 75         subl    $8, %esp
 76         pushl   %eax
 77         pushl   $.Lubsan_data0
 78         call    __ubsan_handle_out_of_bounds

instead clang push address of that index

 15         movl    $10, -32(%ebp)
 16         movl    -28(%ebp), %eax
 17         movl    -32(%ebp), %ecx
 18         movl    %ecx, %edx
 19         cmpl    $10, %edx
 20         movl    %eax, -44(%ebp)         # 4-byte Spill
 21         movl    %ecx, -48(%ebp)         # 4-byte Spill
 22         jb      .LBB0_2
 23 # BB#1:
 24         leal    .L__unnamed_1, %eax
 25         leal    -40(%ebp), %ecx
 26         movl    -48(%ebp), %edx         # 4-byte Reload
 27         movl    %edx, -40(%ebp)
 28         movl    -44(%ebp), %esi         # 4-byte Reload
 29         movl    %esi, -36(%ebp)
 30         movl    %eax, (%esp)
 31         movl    %ecx, 4(%esp)
 32         calll   __ubsan_handle_out_of_bounds

In this case fix should be in IR generation for
__ubsan_handle_out_of_bounds.

Looks like tree val should be generated from original tree 
index and not from tree index which 
were converted to bound type.

diff --git a/gcc/ubsan.c b/gcc/ubsan.c
index 17965ef..c56f376 100644
--- a/gcc/ubsan.c
+++ b/gcc/ubsan.c
@@ -672,7 +672,8 @@ ubsan_expand_bounds_ifn (gimple_stmt_iterator *gsi)

   /* Pick up the arguments of the UBSAN_BOUNDS call.  */
   tree type = TREE_TYPE (TREE_TYPE (gimple_call_arg (stmt, 0)));
-  tree index = gimple_call_arg (stmt, 1);
+  tree index, orig_index;
+  index = orig_index = gimple_call_arg (stmt, 1);
   tree orig_index_type = TREE_TYPE (index);
   tree bound = gimple_call_arg (stmt, 2);

@@ -708,9 +709,9 @@ ubsan_expand_bounds_ifn (gimple_stmt_iterator *gsi)
          ? BUILT_IN_UBSAN_HANDLE_OUT_OF_BOUNDS
          : BUILT_IN_UBSAN_HANDLE_OUT_OF_BOUNDS_ABORT;
       tree fn = builtin_decl_explicit (bcode);
-      tree val = force_gimple_operand_gsi (gsi, ubsan_encode_value (index),
-                                          true, NULL_TREE, true,
-                                          GSI_SAME_STMT);
+      tree val
+       = force_gimple_operand_gsi (gsi, ubsan_encode_value (orig_index), true,
+                                   NULL_TREE, true, GSI_SAME_STMT);
       g = gimple_build_call (fn, 2, data, val);
     }
   gimple_set_location (g, loc);

I attached patch.
Tests with make check RUNTESTFLAGS="ubsan.exp" passed for x86 32bit 
and 64 bit host.

Reply via email to