[Bug sanitizer/70541] unnoticed invalid dereference when using address sanitizer
m.ostapenko at samsung dot com
gcc-bugzilla@gcc.gnu.org
Tue Apr 5 09:19:00 GMT 2016
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=70541
--- Comment #4 from Maxim Ostapenko <m.ostapenko at samsung dot com> ---
(In reply to Jakub Jelinek from comment #3)
> (In reply to Maxim Ostapenko from comment #1)
> > @@ -2060,7 +2067,20 @@ maybe_instrument_call (gimple_stmt_iterator *iter)
> > return true;
> > }
>
> If the function call returns a struct, then your patch wouldn't instrument
> it.
> You need the bool instrumented = false; already above
> if (gimple_store_p (stmt))
> and set instrumented = true; there instead of gsi_next (iter); return true;
>
> > - return false;
> > + bool instrumented = false;
> > + HOST_WIDE_INT args_num = gimple_call_num_args (stmt);
> > + for (int i = 0; i < args_num; ++i)
> > + {
> > + if (is_arg_deref_p (TREE_CODE (gimple_call_arg (stmt, i))))
>
> I'm not aware of any is_arg_deref_p predicate.
> IMHO you should test:
> if (!is_gimple_reg (gimple_call_arg (stmt, i)))
>
> > + {
> > + instrument_derefs (iter, gimple_call_arg (stmt, i),
> > + gimple_location (stmt), false);
> > + instrumented = true;
> > + }
> > + }
> > + if (instrumented)
> > + gsi_next (iter);
> > + return instrumented;
>
Thanks, looks better now?
diff --git a/gcc/asan.c b/gcc/asan.c
index 47bfdcd..c51e629 100644
--- a/gcc/asan.c
+++ b/gcc/asan.c
@@ -1766,6 +1766,8 @@ instrument_derefs (gimple_stmt_iterator *iter, tree t,
tree type, base;
HOST_WIDE_INT size_in_bytes;
+ if (location == UNKNOWN_LOCATION)
+ location = EXPR_LOCATION (t);
type = TREE_TYPE (t);
switch (TREE_CODE (t))
@@ -2049,6 +2051,7 @@ maybe_instrument_call (gimple_stmt_iterator *iter)
gsi_insert_before (iter, g, GSI_SAME_STMT);
}
+ bool instrumented = false;
if (gimple_store_p (stmt))
{
tree ref_expr = gimple_call_lhs (stmt);
@@ -2056,11 +2059,22 @@ maybe_instrument_call (gimple_stmt_iterator *iter)
gimple_location (stmt),
/*is_store=*/true);
- gsi_next (iter);
- return true;
+ instrumented = true;
}
- return false;
+ HOST_WIDE_INT args_num = gimple_call_num_args (stmt);
+ for (int i = 0; i < args_num; ++i)
+ {
+ if (!is_gimple_reg (gimple_call_arg (stmt, i)))
+ {
+ instrument_derefs (iter, gimple_call_arg (stmt, i),
+ gimple_location (stmt), false);
+ instrumented = true;
+ }
+ }
+ if (instrumented)
+ gsi_next (iter);
+ return instrumented;
}
> As for the location_t thing, the fix would be to do in instrument_derefs
> something like:
> if (location == UNKNOWN_LOCATION)
> location = EXPR_LOCATION (t);
> after the early bail outs.
Hm, even with if (location == UNKNOWN_LOCATION) location = EXPR_LOCATION (t); I
don't see reasonable line in -O2 case:
1 #include <stdio.h>
2 #include <stdlib.h>
3
4 struct Simple {
5 int value;
6 };
7
8 int f(struct Simple simple) {
9 return simple.value;
10 }
11
12 int g(int value) {
13 return value;
14 }
15
16 int main() {
17 struct Simple *psimple = (struct Simple *) malloc(sizeof(struct Simple));
18 psimple->value = 42;
19 free(psimple);
20 printf("%d\n", f(*psimple));
21 return 0;
22 }
$ ./a.out
==29898==ERROR: AddressSanitizer: heap-use-after-free on address 0x60200000eff0
at pc 0x0000004055a6 bp 0x7ffc6b5632c0 sp 0x7ffc6b5632a0
READ of size 4 at 0x60200000eff0 thread T0
#0 0x4055a5 in main /tmp/test2.c:22
#1 0x7f8e6df32ec4 in __libc_start_main
(/lib/x86_64-linux-gnu/libc.so.6+0x21ec4)
#2 0x4055f9 (/tmp/a.out+0x4055f9)
$ cat test2.c.126t.asan1
main ()
{
int simple$value;
struct Simple * psimple;
<bb 2>:
[test2.c:17:18] psimple_3 = malloc (4);
[test2.c:17:18] # DEBUG psimple => psimple_3
[test2.c:19:3] free (psimple_3);
ASAN_CHECK (6, psimple_3, 4, 8);
simple$value_6 = MEM[(struct Simple *)psimple_3];
# DEBUG simple$value => simple$value_6
[test2.c:20:3] printf ([test2.c:20:10] "%d\n", simple$value_6);
return 0;
}
Perhaps we indeed should look at the inliner.
More information about the Gcc-bugs
mailing list