Bug 59600 - no_sanitize_address mishandled when function is inlined
Summary: no_sanitize_address mishandled when function is inlined
Status: RESOLVED FIXED
Alias: None
Product: gcc
Classification: Unclassified
Component: sanitizer (show other bugs)
Version: 4.8.2
: P3 normal
Target Milestone: 4.9.0
Assignee: Not yet assigned to anyone
URL:
Keywords:
Depends on:
Blocks:
 
Reported: 2013-12-26 01:57 UTC by Paul Eggert
Modified: 2017-07-18 19:43 UTC (History)
4 users (show)

See Also:
Host:
Target:
Build:
Known to work: 4.9.0
Known to fail:
Last reconfirmed:


Attachments
Compile and link with '-fsanitize=address -O2' and run to illustrate the bug (567 bytes, text/x-csrc)
2013-12-26 01:57 UTC, Paul Eggert
Details
Draft patch (381 bytes, patch)
2013-12-26 05:03 UTC, Yury Gribov
Details | Diff
New patch based on Andrew's review (378 bytes, patch)
2013-12-26 07:54 UTC, Yury Gribov
Details | Diff
Patch which inlines based on caller/callee attribute match (875 bytes, patch)
2013-12-27 05:07 UTC, Yury Gribov
Details | Diff

Note You need to log in before you can comment on or make changes to this bug.
Description Paul Eggert 2013-12-26 01:57:35 UTC
Created attachment 31514 [details]
Compile and link with '-fsanitize=address -O2' and run to illustrate the bug

A function declared with __attribute__ ((no_sanitize_address)) will attempt to sanitize its addresses if the function happens to be inlined in another function that lacks the attribute.  This will cause the code to dump core even when it's not supposed to.  I discovered this problem when trying to use address sanitization in Emacs.  To reproduce the problem on an x86-64 platform, compile the attached program with 'gcc -fsanitize=address -O2'.  It will dump core because the commented address is sanitized even though it's in a no_sanitize_address function.  Compiling with -DTHIS_WORKS_AROUND_THE_BUG works around the bug by adding a noinline attribute to the function in question, but user code shouldn't have to do that.
Comment 1 Yury Gribov 2013-12-26 05:03:55 UTC
Created attachment 31515 [details]
Draft patch

Fails for me as well.

Given that Asan runs long after inliner this behavior is expected. Perhaps it makes sense to prohibit inline for unsanitized functions? We'll loose some performance but no_sanitize_address semantics would be more transparent for users.

Here's a crude patch which seems to fix repro and also show no regressions for `make check-c RUNTESTFLAGS=asan.exp'.
Comment 2 Kostya Serebryany 2013-12-26 06:04:27 UTC
We had this problem in clang before 
http://llvm.org/viewvc/llvm-project?view=revision&revision=187967
Comment 3 Andrew Pinski 2013-12-26 07:17:34 UTC
(In reply to Yury Gribov from comment #1)
> Created attachment 31515 [details]
> Draft patch


Why can't you just set DECL_UNINLINABLE on the function decl in handle_no_sanitize_undefined_attribute in c-common.c just like how handle_noinline_attribute handles it?
Comment 4 Andrew Pinski 2013-12-26 07:24:38 UTC
(In reply to Andrew Pinski from comment #3)
> (In reply to Yury Gribov from comment #1)
> > Created attachment 31515 [details]
> > Draft patch
> 
> 
> Why can't you just set DECL_UNINLINABLE on the function decl in
> handle_no_sanitize_undefined_attribute in c-common.c just like how
> handle_noinline_attribute handles it?

Or better yet handle the case where the attributes diff inside function_attribute_inlinable_p so you don't lose that much optimizations only when the attributes differ.
Comment 5 Yury Gribov 2013-12-26 07:54:56 UTC
Created attachment 31516 [details]
New patch based on Andrew's review

(In reply to Andrew Pinski from comment #3)
> Or better yet handle the case where the attributes diff
> inside function_attribute_inlinable_p
> so you don't lose that much optimizations
> only when the attributes differ.

Yup and this would also work for non-C-family frontends.

How about this patch then?
Comment 6 Andrew Pinski 2013-12-26 08:16:29 UTC
Comment on attachment 31516 [details]
New patch based on Andrew's review

No this wrong in two ways. Move the check to before the check of the target attribute table. And second you should compare the current function attribute to fndecl attribute.
Comment 7 Yury Gribov 2013-12-26 10:11:43 UTC
(In reply to Andrew Pinski from comment #6)
> Move the check to before the check of the target
> attribute table.

My bad.

> And second you should compare the current function
> attribute to fndecl attribute.

You mean compare caller's and callee's attributes? Makes a lot of sense but I don't think this info is available at the time function_attribute_inlinable_p is called:

(gdb) b function_attribute_inlinable_p
(gdb) r
(gdb) call debug_generic_stmt(fndecl)
mark_maybe_pointer

(gdb) call debug_generic_stmt(current_function_decl)
mark_maybe_pointer

Perhaps this check should be moved to e.g. expand_call_inline?
Comment 8 Yury Gribov 2013-12-27 05:07:23 UTC
Created attachment 31522 [details]
Patch which inlines based on caller/callee attribute match

(In reply to Yury Gribov from comment #7)
> > And second you should compare the current function
> > attribute to fndecl attribute.
> 
> You mean compare caller's and callee's attributes? Makes a lot of sense but
> I don't think this info is available at the time
> function_attribute_inlinable_p is called:
> 
> ...
> 
> Perhaps this check should be moved to e.g. expand_call_inline?

I'm giving this a try with this new patch. Does it look reasonable for you?
Comment 9 Yury Gribov 2014-02-05 05:23:01 UTC
Author: ygribov
Date: Wed Feb  5 05:22:29 2014
New Revision: 207497

URL: http://gcc.gnu.org/viewcvs?rev=207497&root=gcc&view=rev
Log:
	PR sanitizer/59600

gcc/
	* cif-code.def (ATTRIBUTE_MISMATCH): New CIF code.
	* ipa-inline.c (report_inline_failed_reason): Handle mismatched
	sanitization attributes.
	(can_inline_edge_p): Likewise.
	(sanitize_attrs_match_for_inline_p): New function.

gcc/testsuite/
	* gcc.dg/asan/nosanitize-and-inline.c: : New test.

Added:
    trunk/gcc/testsuite/gcc.dg/asan/nosanitize-and-inline.c
Modified:
    trunk/gcc/ChangeLog
    trunk/gcc/cif-code.def
    trunk/gcc/ipa-inline.c
    trunk/gcc/testsuite/ChangeLog
Comment 10 Yury Gribov 2014-02-05 05:26:28 UTC
Paul, does this work for you?
Comment 11 Paul Eggert 2014-02-05 05:32:55 UTC
It's not easy for me to test the fix, sorry, I don't normally build GCC.  If it works on the test case my guess is that it'll work for Emacs, though.
Comment 12 Yury Gribov 2017-07-18 19:33:41 UTC
Fixed.