-----------------------------------------------
From: Yury Gribov
Sent: Friday, August 22, 2014 12:47PM
To: GCC Patches
Cc: Jakub Jelinek, Marek Polacek, t...@alumni.duke.edu, sabrina...@gmail.com
Subject: [PATCH] Fix Asan ICEs on unexpected types (PR62140, PR61897)
On 08/22/2014 12:47 PM, Yury Gribov wrote:
Hi all,
Asan pass currently ICEs if it sees int arguments used in
memcmp/memset/etc. functions (it expects uintptr_t there). Attached
patch fixes this.
Related bugreports:
* https://gcc.gnu.org/bugzilla/show_bug.cgi?id=62140
* https://gcc.gnu.org/bugzilla/show_bug.cgi?id=61897
This was bootstrapped on x64 and regtested for x64 and i686 and also
Asan-bootstrapped for x64.
Ok to commit?
BTW regarding ChangeLog: should I mention both bugs (they are
duplicates) or just one of them?
-Y
commit e3324d8d3528f0cb1a56e784f0887a4743a3e0f2
Author: Yury Gribov <y.gri...@samsung.com>
Date: Wed Aug 20 13:56:03 2014 +0400
2014-08-22 Yury Gribov <y.gri...@samsung.com>
gcc/
PR sanitizer/62140
* asan.c (asan_mem_ref_get_end): Handle non-ptroff_t lengths.
(build_check_stmt): Likewise.
(instrument_strlen_call): Likewise.
(asan_expand_check_ifn): Likewise and fix types.
(maybe_cast_to_ptrmode): New function.
gcc/testsuite/
PR sanitizer/62140
* c-c++-common/asan/pr62140-1.c: New test.
* c-c++-common/asan/pr62140-2.c: New test.
diff --git a/gcc/asan.c b/gcc/asan.c
index 15c0737..ea1d3eb 100644
--- a/gcc/asan.c
+++ b/gcc/asan.c
@@ -318,6 +318,9 @@ asan_mem_ref_get_end (tree start, tree len)
if (len == NULL_TREE || integer_zerop (len))
return start;
+ if (!ptrofftype_p (len))
+ len = convert_to_ptrofftype (len);
+
return fold_build2 (POINTER_PLUS_EXPR, TREE_TYPE (start), start, len);
}
@@ -1553,6 +1556,27 @@ maybe_create_ssa_name (location_t loc, tree base, gimple_stmt_iterator *iter,
return gimple_assign_lhs (g);
}
+/* LEN can already have necessary size and precision;
+ in that case, do not create a new variable. */
+
+tree
+maybe_cast_to_ptrmode (location_t loc, tree len, gimple_stmt_iterator *iter,
+ bool before_p)
+{
+ if (ptrofftype_p (len))
+ return len;
+ gimple g
+ = gimple_build_assign_with_ops (NOP_EXPR,
+ make_ssa_name (pointer_sized_int_node, NULL),
+ len, NULL);
+ gimple_set_location (g, loc);
+ if (before_p)
+ gsi_insert_before (iter, g, GSI_SAME_STMT);
+ else
+ gsi_insert_after (iter, g, GSI_NEW_STMT);
+ return gimple_assign_lhs (g);
+}
+
/* Instrument the memory access instruction BASE. Insert new
statements before or after ITER.
@@ -1598,7 +1622,10 @@ build_check_stmt (location_t loc, tree base, tree len,
base = maybe_create_ssa_name (loc, base, &gsi, before_p);
if (len)
- len = unshare_expr (len);
+ {
+ len = unshare_expr (len);
+ len = maybe_cast_to_ptrmode (loc, len, iter, before_p);
+ }
else
{
gcc_assert (size_in_bytes != -1);
@@ -1804,6 +1831,7 @@ instrument_mem_region_access (tree base, tree len,
static bool
instrument_strlen_call (gimple_stmt_iterator *iter)
{
+ gimple g;
gimple call = gsi_stmt (*iter);
gcc_assert (is_gimple_call (call));
@@ -1812,6 +1840,8 @@ instrument_strlen_call (gimple_stmt_iterator *iter)
&& DECL_BUILT_IN_CLASS (callee) == BUILT_IN_NORMAL
&& DECL_FUNCTION_CODE (callee) == BUILT_IN_STRLEN);
+ location_t loc = gimple_location (call);
+
tree len = gimple_call_lhs (call);
if (len == NULL)
/* Some passes might clear the return value of the strlen call;
@@ -1820,28 +1850,28 @@ instrument_strlen_call (gimple_stmt_iterator *iter)
return false;
gcc_assert (INTEGRAL_TYPE_P (TREE_TYPE (len)));
- location_t loc = gimple_location (call);
+ len = maybe_cast_to_ptrmode (loc, len, iter, /*before_p*/false);
+
tree str_arg = gimple_call_arg (call, 0);
bool start_instrumented = has_mem_ref_been_instrumented (str_arg, 1);
tree cptr_type = build_pointer_type (char_type_node);
- gimple str_arg_ssa =
- gimple_build_assign_with_ops (NOP_EXPR,
- make_ssa_name (cptr_type, NULL),
- str_arg, NULL);
- gimple_set_location (str_arg_ssa, loc);
- gsi_insert_before (iter, str_arg_ssa, GSI_SAME_STMT);
-
- build_check_stmt (loc, gimple_assign_lhs (str_arg_ssa), NULL_TREE, 1, iter,
+ g = gimple_build_assign_with_ops (NOP_EXPR,
+ make_ssa_name (cptr_type, NULL),
+ str_arg, NULL);
+ gimple_set_location (g, loc);
+ gsi_insert_before (iter, g, GSI_SAME_STMT);
+ str_arg = gimple_assign_lhs (g);
+
+ build_check_stmt (loc, str_arg, NULL_TREE, 1, iter,
/*is_non_zero_len*/true, /*before_p=*/true,
/*is_store=*/false, /*is_scalar_access*/true, /*align*/0,
start_instrumented, start_instrumented);
- gimple g =
- gimple_build_assign_with_ops (POINTER_PLUS_EXPR,
- make_ssa_name (cptr_type, NULL),
- gimple_assign_lhs (str_arg_ssa),
- len);
+ g = gimple_build_assign_with_ops (POINTER_PLUS_EXPR,
+ make_ssa_name (cptr_type, NULL),
+ str_arg,
+ len);
gimple_set_location (g, loc);
gsi_insert_after (iter, g, GSI_NEW_STMT);
@@ -2470,9 +2500,6 @@ asan_expand_check_ifn (gimple_stmt_iterator *iter, bool use_calls)
HOST_WIDE_INT real_size_in_bytes = size_in_bytes == -1 ? 1 : size_in_bytes;
- tree uintptr_type
- = build_nonstandard_integer_type (TYPE_PRECISION (TREE_TYPE (base)), 1);
-
tree shadow_ptr_type = shadow_ptr_types[real_size_in_bytes == 16 ? 1 : 0];
tree shadow_type = TREE_TYPE (shadow_ptr_type);
@@ -2566,14 +2593,14 @@ asan_expand_check_ifn (gimple_stmt_iterator *iter, bool use_calls)
if (size_in_bytes == -1 && !end_instrumented)
{
g = gimple_build_assign_with_ops (MINUS_EXPR,
- make_ssa_name (uintptr_type, NULL),
+ make_ssa_name (pointer_sized_int_node, NULL),
len,
- build_int_cst (uintptr_type, 1));
+ build_int_cst (pointer_sized_int_node, 1));
gimple_set_location (g, loc);
gsi_insert_after (&gsi, g, GSI_NEW_STMT);
tree last = gimple_assign_lhs (g);
g = gimple_build_assign_with_ops (PLUS_EXPR,
- make_ssa_name (uintptr_type, NULL),
+ make_ssa_name (pointer_sized_int_node, NULL),
base_addr,
last);
gimple_set_location (g, loc);
diff --git a/gcc/testsuite/c-c++-common/asan/pr62140-1.c b/gcc/testsuite/c-c++-common/asan/pr62140-1.c
new file mode 100644
index 0000000..f0b026d
--- /dev/null
+++ b/gcc/testsuite/c-c++-common/asan/pr62140-1.c
@@ -0,0 +1,10 @@
+/* { dg-do compile } */
+/* { dg-options "-w -fpermissive" } */
+
+int memcmp (const void *p, const void *q, int len);
+
+int f (int *p, int *q, int len)
+{
+ return memcmp (p, q, len);
+}
+
diff --git a/gcc/testsuite/c-c++-common/asan/pr62140-2.c b/gcc/testsuite/c-c++-common/asan/pr62140-2.c
new file mode 100644
index 0000000..0bb2563
--- /dev/null
+++ b/gcc/testsuite/c-c++-common/asan/pr62140-2.c
@@ -0,0 +1,11 @@
+/* { dg-do compile } */
+/* { dg-options "-w -fpermissive" } */
+
+int strlen (const char *p);
+
+int f (char *p)
+{
+ int x = strlen (p);
+ return x;
+}
+