diff mbox

[PATCHv3,PING] Enable -fsanitize-recover for KASan

Message ID 54299507.7090800@samsung.com
State New
Headers show

Commit Message

Yury Gribov Sept. 29, 2014, 5:21 p.m. UTC
Hi all,

>> This patch enables -fsanitize-recover for KASan by default. This causes
>> KASan to continue execution after error in case of inline
>> instrumentation. This feature is needed because
>> - reports during early bootstrap won't even be printed
>> - needed to run all tests w/o rebooting machine for every test
>> - needed for interactive work on desktop

This is the third version of patch which renames -fsanitize-recover to 
-fubsan-recover and introduces -fasan-recover (enabled by default for 
KASan). It also moves flag handling to finish_options per Jakub's request.

Bootstrapped and regtested on x64.

-Y

Comments

Jakub Jelinek Sept. 29, 2014, 5:43 p.m. UTC | #1
On Mon, Sep 29, 2014 at 09:21:11PM +0400, Yury Gribov wrote:
> >>This patch enables -fsanitize-recover for KASan by default. This causes
> >>KASan to continue execution after error in case of inline
> >>instrumentation. This feature is needed because
> >>- reports during early bootstrap won't even be printed
> >>- needed to run all tests w/o rebooting machine for every test
> >>- needed for interactive work on desktop
> 
> This is the third version of patch which renames -fsanitize-recover to
> -fubsan-recover and introduces -fasan-recover (enabled by default for
> KASan). It also moves flag handling to finish_options per Jakub's request.

As the -fsanitize-recover option comes from clang originally, I think
this needs coordination with them (whether clang will also rename the
option), and certainly keep -fsanitize-recover as a non-documented
compat option alias for -fubsan-recover.
So, can you please talk to the clang folks about it?

	Jakub
Konstantin Serebryany Sept. 29, 2014, 9:20 p.m. UTC | #2
+Alexey Samsonov

On Mon, Sep 29, 2014 at 10:43 AM, Jakub Jelinek <jakub@redhat.com> wrote:
> On Mon, Sep 29, 2014 at 09:21:11PM +0400, Yury Gribov wrote:
>> >>This patch enables -fsanitize-recover for KASan by default. This causes
>> >>KASan to continue execution after error in case of inline
>> >>instrumentation. This feature is needed because
>> >>- reports during early bootstrap won't even be printed
>> >>- needed to run all tests w/o rebooting machine for every test
>> >>- needed for interactive work on desktop
>>
>> This is the third version of patch which renames -fsanitize-recover to
>> -fubsan-recover and introduces -fasan-recover (enabled by default for
>> KASan). It also moves flag handling to finish_options per Jakub's request.
>
> As the -fsanitize-recover option comes from clang originally, I think
> this needs coordination with them (whether clang will also rename the
> option), and certainly keep -fsanitize-recover as a non-documented
> compat option alias for -fubsan-recover.
> So, can you please talk to the clang folks about it?
>
>         Jakub
Alexey Samsonov Sept. 29, 2014, 10:37 p.m. UTC | #3
(resending in plain-text mode)

-fasan-recover doesn't look like a good idea - for instance, in Clang,
we never use "?san"
in flag names, preferring -fsanitize-whatever. What's the rationale
behind splitting
-fsanitize-recover in two flags (ASan- and UBSan- specific)?
Is there no way to keep a single -f(no-)sanitize-recover for that
purpose? Now it works
only for UBSan checks, but we may extend it to another sanitizers as well.

On Mon, Sep 29, 2014 at 2:20 PM, Konstantin Serebryany
<konstantin.s.serebryany@gmail.com> wrote:
> +Alexey Samsonov
>
> On Mon, Sep 29, 2014 at 10:43 AM, Jakub Jelinek <jakub@redhat.com> wrote:
>> On Mon, Sep 29, 2014 at 09:21:11PM +0400, Yury Gribov wrote:
>>> >>This patch enables -fsanitize-recover for KASan by default. This causes
>>> >>KASan to continue execution after error in case of inline
>>> >>instrumentation. This feature is needed because
>>> >>- reports during early bootstrap won't even be printed
>>> >>- needed to run all tests w/o rebooting machine for every test
>>> >>- needed for interactive work on desktop
>>>
>>> This is the third version of patch which renames -fsanitize-recover to
>>> -fubsan-recover and introduces -fasan-recover (enabled by default for
>>> KASan). It also moves flag handling to finish_options per Jakub's request.
>>
>> As the -fsanitize-recover option comes from clang originally, I think
>> this needs coordination with them (whether clang will also rename the
>> option), and certainly keep -fsanitize-recover as a non-documented
>> compat option alias for -fubsan-recover.
>> So, can you please talk to the clang folks about it?
>>
>>         Jakub
Jakub Jelinek Sept. 29, 2014, 11:17 p.m. UTC | #4
On Mon, Sep 29, 2014 at 03:36:20PM -0700, Alexey Samsonov wrote:
> -fasan-recover doesn't look like a good idea - for instance, in Clang, we
> never use "?san"
> in flag names, preferring -fsanitize-whatever. What's the rationale behind
> splitting
> -fsanitize-recover in two flags (ASan- and UBSan- specific)?
> Is there no way to keep a single -f(no-)sanitize-recover for that purpose?
> Now it works
> only for UBSan checks, but we may extend it to another sanitizers as well.

The problem is that if we start using it for ASan, it needs to have a
different default, because ASan wants to abort by default, while UBSan
recover by default.  -fsanitize=kernel-address w (KASan) wants to recover
by default.  So, the option is either to never support recover for
-fsanitize=address, for ubsan keep -fsanitize-recover (by default) as is
and for kasan use that same switch, or have separate flags.

	Jakub
Alexey Samsonov Sept. 29, 2014, 11:26 p.m. UTC | #5
On Mon, Sep 29, 2014 at 4:17 PM, Jakub Jelinek <jakub@redhat.com> wrote:
> On Mon, Sep 29, 2014 at 03:36:20PM -0700, Alexey Samsonov wrote:
>> -fasan-recover doesn't look like a good idea - for instance, in Clang, we
>> never use "?san"
>> in flag names, preferring -fsanitize-whatever. What's the rationale behind
>> splitting
>> -fsanitize-recover in two flags (ASan- and UBSan- specific)?
>> Is there no way to keep a single -f(no-)sanitize-recover for that purpose?
>> Now it works
>> only for UBSan checks, but we may extend it to another sanitizers as well.
>
> The problem is that if we start using it for ASan, it needs to have a
> different default, because ASan wants to abort by default, while UBSan
> recover by default.  -fsanitize=kernel-address w (KASan) wants to recover
> by default.  So, the option is either to never support recover for
> -fsanitize=address, for ubsan keep -fsanitize-recover (by default) as is
> and for kasan use that same switch, or have separate flags.
>
>         Jakub

I don't think we ever going to support recovery for regular ASan
(Kostya, correct me if I'm wrong).
I see no problem in enabling -fsanitize-recover by default for
-fsanitize=undefined and
-fsanitize=kernel-address. We can, potentially, extend
-fsanitize-recover flag to take the same values as -fsanitize= one,
so that one can specify which sanitizers are recoverable, and which
are not, but I'd try to make this a last resort - this is too complex.
Konstantin Serebryany Sept. 30, 2014, 12:24 a.m. UTC | #6
On Mon, Sep 29, 2014 at 4:26 PM, Alexey Samsonov <samsonov@google.com> wrote:
> On Mon, Sep 29, 2014 at 4:17 PM, Jakub Jelinek <jakub@redhat.com> wrote:
>> On Mon, Sep 29, 2014 at 03:36:20PM -0700, Alexey Samsonov wrote:
>>> -fasan-recover doesn't look like a good idea - for instance, in Clang, we
>>> never use "?san"
>>> in flag names, preferring -fsanitize-whatever. What's the rationale behind
>>> splitting
>>> -fsanitize-recover in two flags (ASan- and UBSan- specific)?
>>> Is there no way to keep a single -f(no-)sanitize-recover for that purpose?
>>> Now it works
>>> only for UBSan checks, but we may extend it to another sanitizers as well.
>>
>> The problem is that if we start using it for ASan, it needs to have a
>> different default, because ASan wants to abort by default, while UBSan
>> recover by default.  -fsanitize=kernel-address w (KASan) wants to recover
>> by default.  So, the option is either to never support recover for
>> -fsanitize=address, for ubsan keep -fsanitize-recover (by default) as is
>> and for kasan use that same switch, or have separate flags.
>>
>>         Jakub
>
> I don't think we ever going to support recovery for regular ASan
> (Kostya, correct me if I'm wrong).

I hope so too.
Another point is that with asan-instrumentation-with-call-threshold=0
(instrumentation with callbacks)
we can and probably will allow to recover from errors (glibc demands that),
but that does not require any compile-time flag.


> I see no problem in enabling -fsanitize-recover by default for
> -fsanitize=undefined and

This becomes more interesting when we use asan and ubsan together.
Which default setting is stronger? :)

> -fsanitize=kernel-address. We can, potentially, extend
> -fsanitize-recover flag to take the same values as -fsanitize= one,
> so that one can specify which sanitizers are recoverable, and which
> are not, but I'd try to make this a last resort - this is too complex.
>
> --
> Alexey Samsonov, Mountain View, CA
Alexey Samsonov Sept. 30, 2014, 1:05 a.m. UTC | #7
On Mon, Sep 29, 2014 at 5:24 PM, Konstantin Serebryany
<konstantin.s.serebryany@gmail.com> wrote:
>
> On Mon, Sep 29, 2014 at 4:26 PM, Alexey Samsonov <samsonov@google.com> wrote:
> > On Mon, Sep 29, 2014 at 4:17 PM, Jakub Jelinek <jakub@redhat.com> wrote:
> >> On Mon, Sep 29, 2014 at 03:36:20PM -0700, Alexey Samsonov wrote:
> >>> -fasan-recover doesn't look like a good idea - for instance, in Clang, we
> >>> never use "?san"
> >>> in flag names, preferring -fsanitize-whatever. What's the rationale behind
> >>> splitting
> >>> -fsanitize-recover in two flags (ASan- and UBSan- specific)?
> >>> Is there no way to keep a single -f(no-)sanitize-recover for that purpose?
> >>> Now it works
> >>> only for UBSan checks, but we may extend it to another sanitizers as well.
> >>
> >> The problem is that if we start using it for ASan, it needs to have a
> >> different default, because ASan wants to abort by default, while UBSan
> >> recover by default.  -fsanitize=kernel-address w (KASan) wants to recover
> >> by default.  So, the option is either to never support recover for
> >> -fsanitize=address, for ubsan keep -fsanitize-recover (by default) as is
> >> and for kasan use that same switch, or have separate flags.
> >>
> >>         Jakub
> >
> > I don't think we ever going to support recovery for regular ASan
> > (Kostya, correct me if I'm wrong).
>
> I hope so too.
> Another point is that with asan-instrumentation-with-call-threshold=0
> (instrumentation with callbacks)
> we can and probably will allow to recover from errors (glibc demands that),
> but that does not require any compile-time flag.


So, if we switch to instrumentation to callbacks (which are not
necessarily noreturn),
-fsanitize-recover is the thing we plan to support?

>
>
>
> > I see no problem in enabling -fsanitize-recover by default for
> > -fsanitize=undefined and
>
> This becomes more interesting when we use asan and ubsan together.
> Which default setting is stronger? :)

We can preserve the default behavior for each tool (no recovery for
ASan, recovery for UBSan)
unless recovery mode is explicitly specified.

>
> > -fsanitize=kernel-address. We can, potentially, extend
> > -fsanitize-recover flag to take the same values as -fsanitize= one,
> > so that one can specify which sanitizers are recoverable, and which
> > are not, but I'd try to make this a last resort - this is too complex.
> >
> > --
> > Alexey Samsonov, Mountain View, CA
Konstantin Serebryany Sept. 30, 2014, 1:48 a.m. UTC | #8
On Mon, Sep 29, 2014 at 6:05 PM, Alexey Samsonov <samsonov@google.com> wrote:
> On Mon, Sep 29, 2014 at 5:24 PM, Konstantin Serebryany
> <konstantin.s.serebryany@gmail.com> wrote:
>>
>> On Mon, Sep 29, 2014 at 4:26 PM, Alexey Samsonov <samsonov@google.com> wrote:
>> > On Mon, Sep 29, 2014 at 4:17 PM, Jakub Jelinek <jakub@redhat.com> wrote:
>> >> On Mon, Sep 29, 2014 at 03:36:20PM -0700, Alexey Samsonov wrote:
>> >>> -fasan-recover doesn't look like a good idea - for instance, in Clang, we
>> >>> never use "?san"
>> >>> in flag names, preferring -fsanitize-whatever. What's the rationale behind
>> >>> splitting
>> >>> -fsanitize-recover in two flags (ASan- and UBSan- specific)?
>> >>> Is there no way to keep a single -f(no-)sanitize-recover for that purpose?
>> >>> Now it works
>> >>> only for UBSan checks, but we may extend it to another sanitizers as well.
>> >>
>> >> The problem is that if we start using it for ASan, it needs to have a
>> >> different default, because ASan wants to abort by default, while UBSan
>> >> recover by default.  -fsanitize=kernel-address w (KASan) wants to recover
>> >> by default.  So, the option is either to never support recover for
>> >> -fsanitize=address, for ubsan keep -fsanitize-recover (by default) as is
>> >> and for kasan use that same switch, or have separate flags.
>> >>
>> >>         Jakub
>> >
>> > I don't think we ever going to support recovery for regular ASan
>> > (Kostya, correct me if I'm wrong).
>>
>> I hope so too.
>> Another point is that with asan-instrumentation-with-call-threshold=0
>> (instrumentation with callbacks)
>> we can and probably will allow to recover from errors (glibc demands that),
>> but that does not require any compile-time flag.
>
>
> So, if we switch to instrumentation to callbacks (which are not
> necessarily noreturn),
> -fsanitize-recover is the thing we plan to support?

Yes, but this will not involve any additional compile-time flag

>
>>
>>
>>
>> > I see no problem in enabling -fsanitize-recover by default for
>> > -fsanitize=undefined and
>>
>> This becomes more interesting when we use asan and ubsan together.
>> Which default setting is stronger? :)
>
> We can preserve the default behavior for each tool (no recovery for
> ASan, recovery for UBSan)
> unless recovery mode is explicitly specified.
>
>>
>> > -fsanitize=kernel-address. We can, potentially, extend
>> > -fsanitize-recover flag to take the same values as -fsanitize= one,
>> > so that one can specify which sanitizers are recoverable, and which
>> > are not, but I'd try to make this a last resort - this is too complex.
>> >
>> > --
>> > Alexey Samsonov, Mountain View, CA
>
>
>
>
> --
> Alexey Samsonov, Mountain View, CA
Jakub Jelinek Sept. 30, 2014, 5:40 a.m. UTC | #9
On Mon, Sep 29, 2014 at 05:24:02PM -0700, Konstantin Serebryany wrote:
> > I don't think we ever going to support recovery for regular ASan
> > (Kostya, correct me if I'm wrong).
> 
> I hope so too.
> Another point is that with asan-instrumentation-with-call-threshold=0
> (instrumentation with callbacks)

The normal (non-recovery) callbacks are __attribute__((noreturn)) for
performance reasons, and you do need different callbacks and different
generated code if you want to recover (after the callback you need jump
back to a basic block after the conditional jump).
So, in that case you would need -fsanitize-recover=address.

> > I see no problem in enabling -fsanitize-recover by default for
> > -fsanitize=undefined and
> 
> This becomes more interesting when we use asan and ubsan together.

That is fairly common case.

	Jakub
Yury Gribov Sept. 30, 2014, 6:56 a.m. UTC | #10
On 09/30/2014 04:24 AM, Konstantin Serebryany wrote:
> On Mon, Sep 29, 2014 at 4:26 PM, Alexey Samsonov <samsonov@google.com> wrote:
>> I don't think we ever going to support recovery for regular ASan
>> (Kostya, correct me if I'm wrong).
>
> I hope so too.
> Another point is that with asan-instrumentation-with-call-threshold=0
> (instrumentation with callbacks)
> we can and probably will allow to recover from errors (glibc demands that),
> but that does not require any compile-time flag.

I don't know details but are you absolutely sure that you won't want to 
do inline instrumentation of glibc in the future? This would then 
require -fasan-recover.

-Y
Yury Gribov Sept. 30, 2014, 7:07 a.m. UTC | #11
On 09/30/2014 09:40 AM, Jakub Jelinek wrote:
> On Mon, Sep 29, 2014 at 05:24:02PM -0700, Konstantin Serebryany wrote:
>>> I don't think we ever going to support recovery for regular ASan
>>> (Kostya, correct me if I'm wrong).
>>
>> I hope so too.
>> Another point is that with asan-instrumentation-with-call-threshold=0
>> (instrumentation with callbacks)
>
> The normal (non-recovery) callbacks are __attribute__((noreturn)) for
> performance reasons, and you do need different callbacks and different
> generated code if you want to recover (after the callback you need jump
> back to a basic block after the conditional jump).
> So, in that case you would need -fsanitize-recover=address.
>
>>> I see no problem in enabling -fsanitize-recover by default for
>>> -fsanitize=undefined and
>>
>> This becomes more interesting when we use asan and ubsan together.
>
> That is fairly common case.

I think we can summarize:
* the current option -fsanitize-recover is misleading; it's really 
-fubsan-recover
* we need a way to selectively enable/disable recovery for different 
sanitizers

The most promininet solution seems to be
* allow -fsanitize-recover=tgt1,tgt2 syntax
* -fsanitize-recover wo options would still mean UBSan recovery

The question is what to do with -fno-sanitize-recover then.

-Y
Yury Gribov Sept. 30, 2014, 7:14 a.m. UTC | #12
On 09/30/2014 10:56 AM, Yury Gribov wrote:
> On 09/30/2014 04:24 AM, Konstantin Serebryany wrote:
>> On Mon, Sep 29, 2014 at 4:26 PM, Alexey Samsonov <samsonov@google.com>
>> wrote:
>>> I don't think we ever going to support recovery for regular ASan
>>> (Kostya, correct me if I'm wrong).
>>
>> I hope so too.
>> Another point is that with asan-instrumentation-with-call-threshold=0
>> (instrumentation with callbacks)
>> we can and probably will allow to recover from errors (glibc demands
>> that),
>> but that does not require any compile-time flag.
>
> I don't know details but are you absolutely sure that you won't want to
> do inline instrumentation of glibc in the future? This would then
> require -fasan-recover.

FYI in kernel we had exactly this situation: outline instrumentation 
allowed us to hide recovery inside callbacks but then turned out to be 
too slow so we are now switching back to inline instrumentation (which 
requires -fasan-recovery).

-Y
Alexey Samsonov Sept. 30, 2014, 5:26 p.m. UTC | #13
On Tue, Sep 30, 2014 at 12:07 AM, Yury Gribov <y.gribov@samsung.com> wrote:
> On 09/30/2014 09:40 AM, Jakub Jelinek wrote:
>>
>> On Mon, Sep 29, 2014 at 05:24:02PM -0700, Konstantin Serebryany wrote:
>>>>
>>>> I don't think we ever going to support recovery for regular ASan
>>>> (Kostya, correct me if I'm wrong).
>>>
>>>
>>> I hope so too.
>>> Another point is that with asan-instrumentation-with-call-threshold=0
>>> (instrumentation with callbacks)
>>
>>
>> The normal (non-recovery) callbacks are __attribute__((noreturn)) for
>> performance reasons, and you do need different callbacks and different
>> generated code if you want to recover (after the callback you need jump
>> back to a basic block after the conditional jump).
>> So, in that case you would need -fsanitize-recover=address.
>>
>>>> I see no problem in enabling -fsanitize-recover by default for
>>>> -fsanitize=undefined and
>>>
>>>
>>> This becomes more interesting when we use asan and ubsan together.
>>
>>
>> That is fairly common case.
>
>
> I think we can summarize:
> * the current option -fsanitize-recover is misleading; it's really
> -fubsan-recover
> * we need a way to selectively enable/disable recovery for different
> sanitizers
>
> The most promininet solution seems to be
> * allow -fsanitize-recover=tgt1,tgt2 syntax
> * -fsanitize-recover wo options would still mean UBSan recovery
>
> The question is what to do with -fno-sanitize-recover then.

We can make -f(no-)?sanitize-recover= flags accept the same values as
-f(no-)?sanitize= flags. In this case,

"-fsanitize-recover" will be a deprecated alias of
"-fsanitize-recover=undefined", and
"-fno-sanitize-recover" will be a deprecated alias of
"-fno-sanitize-recover=undefined".
If a user provides "-fsanitize-recover=address", we can instruct the
instrumentation pass to
use recoverable instrumentation.

>
> -Y
>
Jakub Jelinek Sept. 30, 2014, 5:33 p.m. UTC | #14
On Tue, Sep 30, 2014 at 10:26:39AM -0700, Alexey Samsonov wrote:
> > I think we can summarize:
> > * the current option -fsanitize-recover is misleading; it's really
> > -fubsan-recover
> > * we need a way to selectively enable/disable recovery for different
> > sanitizers
> >
> > The most promininet solution seems to be
> > * allow -fsanitize-recover=tgt1,tgt2 syntax
> > * -fsanitize-recover wo options would still mean UBSan recovery
> >
> > The question is what to do with -fno-sanitize-recover then.
> 
> We can make -f(no-)?sanitize-recover= flags accept the same values as
> -f(no-)?sanitize= flags. In this case,
> 
> "-fsanitize-recover" will be a deprecated alias of
> "-fsanitize-recover=undefined", and
> "-fno-sanitize-recover" will be a deprecated alias of
> "-fno-sanitize-recover=undefined".
> If a user provides "-fsanitize-recover=address", we can instruct the
> instrumentation pass to
> use recoverable instrumentation.

Would we accept -fsanitize-recover=undefined -fno-sanitize-recover=signed-integer-overflow
as recovering everything but signed integer overflows, i.e. the decision
whether to recover a particular call would check similar bitmask as
is checked whether to sanitize something at all?

	Jakub
Alexey Samsonov Sept. 30, 2014, 5:36 p.m. UTC | #15
On Tue, Sep 30, 2014 at 10:33 AM, Jakub Jelinek <jakub@redhat.com> wrote:
> On Tue, Sep 30, 2014 at 10:26:39AM -0700, Alexey Samsonov wrote:
>> > I think we can summarize:
>> > * the current option -fsanitize-recover is misleading; it's really
>> > -fubsan-recover
>> > * we need a way to selectively enable/disable recovery for different
>> > sanitizers
>> >
>> > The most promininet solution seems to be
>> > * allow -fsanitize-recover=tgt1,tgt2 syntax
>> > * -fsanitize-recover wo options would still mean UBSan recovery
>> >
>> > The question is what to do with -fno-sanitize-recover then.
>>
>> We can make -f(no-)?sanitize-recover= flags accept the same values as
>> -f(no-)?sanitize= flags. In this case,
>>
>> "-fsanitize-recover" will be a deprecated alias of
>> "-fsanitize-recover=undefined", and
>> "-fno-sanitize-recover" will be a deprecated alias of
>> "-fno-sanitize-recover=undefined".
>> If a user provides "-fsanitize-recover=address", we can instruct the
>> instrumentation pass to
>> use recoverable instrumentation.
>
> Would we accept -fsanitize-recover=undefined -fno-sanitize-recover=signed-integer-overflow
> as recovering everything but signed integer overflows, i.e. the decision
> whether to recover a particular call would check similar bitmask as
> is checked whether to sanitize something at all?

Yes, the logic for creating a set of recoverable sanitizers should be
the same as the logic for creating a set of enabled sanitizers.
Jakub Jelinek Sept. 30, 2014, 5:39 p.m. UTC | #16
On Tue, Sep 30, 2014 at 10:36:34AM -0700, Alexey Samsonov wrote:
> > Would we accept -fsanitize-recover=undefined -fno-sanitize-recover=signed-integer-overflow
> > as recovering everything but signed integer overflows, i.e. the decision
> > whether to recover a particular call would check similar bitmask as
> > is checked whether to sanitize something at all?
> 
> Yes, the logic for creating a set of recoverable sanitizers should be
> the same as the logic for creating a set of enabled sanitizers.

LGTM, will hack it up soon in GCC then.

	Jakub
Alexey Samsonov Oct. 1, 2014, 11:21 p.m. UTC | #17
Speaking of plain -f(no-)sanitize-recover - it would probably be
better to change the semantics of this flag,
so that "-f(no-)?sanitize-recover" means "enable(disable) recovery for
all sanitizers enabled at this point".
That is, it would be pretty much like -Werror flag.

For example,
"-fsanitize=undefined -fsanitize=address -fno-sanitize-recover"
would mean "run UBSan and ASan and don't recover from errors".

On Tue, Sep 30, 2014 at 10:39 AM, Jakub Jelinek <jakub@redhat.com> wrote:
> On Tue, Sep 30, 2014 at 10:36:34AM -0700, Alexey Samsonov wrote:
>> > Would we accept -fsanitize-recover=undefined -fno-sanitize-recover=signed-integer-overflow
>> > as recovering everything but signed integer overflows, i.e. the decision
>> > whether to recover a particular call would check similar bitmask as
>> > is checked whether to sanitize something at all?
>>
>> Yes, the logic for creating a set of recoverable sanitizers should be
>> the same as the logic for creating a set of enabled sanitizers.
>
> LGTM, will hack it up soon in GCC then.
>
>         Jakub
Jakub Jelinek Oct. 2, 2014, 5:58 a.m. UTC | #18
On Wed, Oct 01, 2014 at 04:21:29PM -0700, Alexey Samsonov wrote:
> Speaking of plain -f(no-)sanitize-recover - it would probably be
> better to change the semantics of this flag,
> so that "-f(no-)?sanitize-recover" means "enable(disable) recovery for
> all sanitizers enabled at this point".
> That is, it would be pretty much like -Werror flag.
> 
> For example,
> "-fsanitize=undefined -fsanitize=address -fno-sanitize-recover"
> would mean "run UBSan and ASan and don't recover from errors".

That would change behavior, e.g. for
-fsanitize=undefined,address -fsanitize-recover
would suddenly enable recovery from asan errors while previously
they wouldn't be recovering.

GCC has not shipped with the -fsanitize-recover flag yet (we have just
vendor backport of it), so if you don't mind changing behavior for clang
users, I can live with that.  Would the default still be
-fsanitize-recover=undefined,kernel-address -fno-sanitize-recover=address ?

	Jakub
Alexey Samsonov Oct. 3, 2014, 6:54 p.m. UTC | #19
On Wed, Oct 1, 2014 at 10:58 PM, Jakub Jelinek <jakub@redhat.com> wrote:
> On Wed, Oct 01, 2014 at 04:21:29PM -0700, Alexey Samsonov wrote:
>> Speaking of plain -f(no-)sanitize-recover - it would probably be
>> better to change the semantics of this flag,
>> so that "-f(no-)?sanitize-recover" means "enable(disable) recovery for
>> all sanitizers enabled at this point".
>> That is, it would be pretty much like -Werror flag.
>>
>> For example,
>> "-fsanitize=undefined -fsanitize=address -fno-sanitize-recover"
>> would mean "run UBSan and ASan and don't recover from errors".
>
> That would change behavior, e.g. for
> -fsanitize=undefined,address -fsanitize-recover
> would suddenly enable recovery from asan errors while previously
> they wouldn't be recovering.
>
> GCC has not shipped with the -fsanitize-recover flag yet (we have just
> vendor backport of it), so if you don't mind changing behavior for clang
> users, I can live with that.

Yes, I think so. -fsanitize-recover was not documented in Clang user manual.

>  Would the default still be
> -fsanitize-recover=undefined,kernel-address -fno-sanitize-recover=address ?

Yes.
diff mbox

Patch

commit a9451a79bcdcab69856a38d228bec8986c0b0b2a
Author: Yury Gribov <y.gribov@samsung.com>
Date:   Fri Aug 29 16:43:42 2014 +0400

    2014-09-29  Yury Gribov  <y.gribov@samsung.com>
    
    gcc/
    	* asan.c (report_error_func): Optionally call recoverable
    	routines.
    	(asan_expand_check_ifn): Ditto.
    	(check_func): Fix formatting.
    	* common.opt (fasan-recover): New option.
    	(fubsan-recover): Rename.
    	* doc/invoke.texi (-fasan-recover): Document new option.
    	* sanitizer.def: New builtins.
    	* opts.c (common_handle_option): Move default initialization to
    	(finish_options): Here. Also initialize flag_asan_recover.
    	* flag-types.h (SANITIZE_UNDEFINED_NONDEFAULT): Rename.
    	* builtins.def: Ditto.
    	* gcc.c (sanitize_spec_function): Ditto.
    	* opts.c (common_handle_option): Ditto.
    	* ubsan.c (ubsan_expand_bounds_ifn): Rename flag.
    	(ubsan_expand_null_ifn): Ditto.
    	(ubsan_build_overflow_builtin): Ditto.
    	(instrument_bool_enum_load): Ditto.
    	(ubsan_instrument_float_cast): Ditto.
    	(instrument_nonnull_arg): Ditto.
    	(instrument_nonnull_return): Ditto.
    
    gcc/c-family/
    
    	* c-ubsan.c (ubsan_instrument_division): Rename flag_sanitize_recover
    	to flag_ubsan_recover.
    	(ubsan_instrument_shift): Ditto.
    	(ubsan_instrument_vla): Ditto.
    
    gcc/testsuite/
    	* c-c++-common/asan/recovery-1.c: New test.
    	* c-c++-common/ubsan/align-1.c: Rename flag.
    	* c-c++-common/ubsan/align-3.c: Ditto.
    	* c-c++-common/ubsan/bounds-1.c: Ditto.
    	* c-c++-common/ubsan/div-by-zero-7.c: Ditto.
    	* c-c++-common/ubsan/float-cast-overflow-10.c: Ditto.
    	* c-c++-common/ubsan/float-cast-overflow-7.c: Ditto.
    	* c-c++-common/ubsan/float-cast-overflow-8.c: Ditto.
    	* c-c++-common/ubsan/float-cast-overflow-9.c: Ditto.
    	* c-c++-common/ubsan/nonnull-2.c: Ditto.
    	* c-c++-common/ubsan/nonnull-3.c: Ditto.
    	* c-c++-common/ubsan/overflow-1.c: Ditto.
    	* c-c++-common/ubsan/overflow-add-1.c: Ditto.
    	* c-c++-common/ubsan/overflow-add-3.c: Ditto.
    	* c-c++-common/ubsan/overflow-mul-1.c: Ditto.
    	* c-c++-common/ubsan/overflow-mul-3.c: Ditto.
    	* c-c++-common/ubsan/overflow-negate-2.c: Ditto.
    	* c-c++-common/ubsan/overflow-sub-1.c: Ditto.
    	* c-c++-common/ubsan/pr59503.c: Ditto.
    	* c-c++-common/ubsan/pr60613-1.c: Ditto.
    	* c-c++-common/ubsan/save-expr-1.c: Ditto.
    	* c-c++-common/ubsan/shift-3.c: Ditto.
    	* c-c++-common/ubsan/shift-6.c: Ditto.
    	* c-c++-common/ubsan/undefined-1.c: Ditto.
    	* c-c++-common/ubsan/vla-2.c: Ditto.
    	* c-c++-common/ubsan/vla-3.c: Ditto.
    	* c-c++-common/ubsan/vla-4.c: Ditto.
    	* g++.dg/ubsan/cxx11-shift-1.C: Ditto.
    	* g++.dg/ubsan/return-2.C: Ditto.
    
    Conflicts:
    
    	gcc/doc/invoke.texi

diff --git a/gcc/asan.c b/gcc/asan.c
index 63f99f5..fb7a660 100644
--- a/gcc/asan.c
+++ b/gcc/asan.c
@@ -1376,22 +1376,36 @@  asan_protect_global (tree decl)
    IS_STORE is either 1 (for a store) or 0 (for a load).  */
 
 static tree
-report_error_func (bool is_store, HOST_WIDE_INT size_in_bytes, int *nargs)
-{
-  static enum built_in_function report[2][6]
-    = { { BUILT_IN_ASAN_REPORT_LOAD1, BUILT_IN_ASAN_REPORT_LOAD2,
-	  BUILT_IN_ASAN_REPORT_LOAD4, BUILT_IN_ASAN_REPORT_LOAD8,
-	  BUILT_IN_ASAN_REPORT_LOAD16, BUILT_IN_ASAN_REPORT_LOAD_N },
-	{ BUILT_IN_ASAN_REPORT_STORE1, BUILT_IN_ASAN_REPORT_STORE2,
-	  BUILT_IN_ASAN_REPORT_STORE4, BUILT_IN_ASAN_REPORT_STORE8,
-	  BUILT_IN_ASAN_REPORT_STORE16, BUILT_IN_ASAN_REPORT_STORE_N } };
+report_error_func (bool is_store, bool recover_p, HOST_WIDE_INT size_in_bytes,
+		   int *nargs)
+{
+  static enum built_in_function report[2][2][6]
+    = { { { BUILT_IN_ASAN_REPORT_LOAD1, BUILT_IN_ASAN_REPORT_LOAD2,
+	    BUILT_IN_ASAN_REPORT_LOAD4, BUILT_IN_ASAN_REPORT_LOAD8,
+	    BUILT_IN_ASAN_REPORT_LOAD16, BUILT_IN_ASAN_REPORT_LOAD_N },
+	  { BUILT_IN_ASAN_REPORT_STORE1, BUILT_IN_ASAN_REPORT_STORE2,
+	    BUILT_IN_ASAN_REPORT_STORE4, BUILT_IN_ASAN_REPORT_STORE8,
+	    BUILT_IN_ASAN_REPORT_STORE16, BUILT_IN_ASAN_REPORT_STORE_N } },
+	{ { BUILT_IN_ASAN_REPORT_RECOVER_LOAD1,
+	    BUILT_IN_ASAN_REPORT_RECOVER_LOAD2,
+	    BUILT_IN_ASAN_REPORT_RECOVER_LOAD4,
+	    BUILT_IN_ASAN_REPORT_RECOVER_LOAD8,
+	    BUILT_IN_ASAN_REPORT_RECOVER_LOAD16,
+	    BUILT_IN_ASAN_REPORT_RECOVER_LOAD_N },
+	  { BUILT_IN_ASAN_REPORT_RECOVER_STORE1,
+	    BUILT_IN_ASAN_REPORT_RECOVER_STORE2,
+	    BUILT_IN_ASAN_REPORT_RECOVER_STORE4,
+	    BUILT_IN_ASAN_REPORT_RECOVER_STORE8,
+	    BUILT_IN_ASAN_REPORT_RECOVER_STORE16,
+	    BUILT_IN_ASAN_REPORT_RECOVER_STORE_N } } };
   if (size_in_bytes == -1)
     {
       *nargs = 2;
-      return builtin_decl_implicit (report[is_store][5]);
+      return builtin_decl_implicit (report[recover_p][is_store][5]);
     }
   *nargs = 1;
-  return builtin_decl_implicit (report[is_store][exact_log2 (size_in_bytes)]);
+  int size_log2 = exact_log2 (size_in_bytes);
+  return builtin_decl_implicit (report[recover_p][is_store][size_log2]);
 }
 
 /* Construct a function tree for __asan_{load,store}{1,2,4,8,16,_n}.
@@ -1402,11 +1416,11 @@  check_func (bool is_store, int size_in_bytes, int *nargs)
 {
   static enum built_in_function check[2][6]
     = { { BUILT_IN_ASAN_LOAD1, BUILT_IN_ASAN_LOAD2,
-      BUILT_IN_ASAN_LOAD4, BUILT_IN_ASAN_LOAD8,
-      BUILT_IN_ASAN_LOAD16, BUILT_IN_ASAN_LOADN },
+	  BUILT_IN_ASAN_LOAD4, BUILT_IN_ASAN_LOAD8,
+	  BUILT_IN_ASAN_LOAD16, BUILT_IN_ASAN_LOADN },
 	{ BUILT_IN_ASAN_STORE1, BUILT_IN_ASAN_STORE2,
-      BUILT_IN_ASAN_STORE4, BUILT_IN_ASAN_STORE8,
-      BUILT_IN_ASAN_STORE16, BUILT_IN_ASAN_STOREN } };
+	  BUILT_IN_ASAN_STORE4, BUILT_IN_ASAN_STORE8,
+	  BUILT_IN_ASAN_STORE16, BUILT_IN_ASAN_STOREN } };
   if (size_in_bytes == -1)
     {
       *nargs = 2;
@@ -2586,9 +2600,10 @@  asan_expand_check_ifn (gimple_stmt_iterator *iter, bool use_calls)
   /* Get an iterator on the point where we can add the condition
      statement for the instrumentation.  */
   basic_block then_bb, else_bb;
+  bool create_then_fallthru_edge = flag_asan_recover != 0;
   gsi = create_cond_insert_point (&gsi, /*before_p*/false,
 				  /*then_more_likely_p=*/false,
-				  /*create_then_fallthru_edge=*/false,
+				  create_then_fallthru_edge,
 				  &then_bb,
 				  &else_bb);
 
@@ -2697,7 +2712,9 @@  asan_expand_check_ifn (gimple_stmt_iterator *iter, bool use_calls)
   /* Generate call to the run-time library (e.g. __asan_report_load8).  */
   gsi = gsi_start_bb (then_bb);
   int nargs;
-  tree fun = report_error_func (is_store, size_in_bytes, &nargs);
+  tree fun = report_error_func (is_store,
+				/*recover_p*/flag_asan_recover != 0,
+				size_in_bytes, &nargs);
   g = gimple_build_call (fun, nargs, base_addr, len);
   gimple_set_location (g, loc);
   gsi_insert_after (&gsi, g, GSI_NEW_STMT);
diff --git a/gcc/builtins.def b/gcc/builtins.def
index cd823a3..58b0b0e 100644
--- a/gcc/builtins.def
+++ b/gcc/builtins.def
@@ -176,7 +176,8 @@  along with GCC; see the file COPYING3.  If not see
   DEF_BUILTIN (ENUM, "__builtin_" NAME, BUILT_IN_NORMAL, TYPE, TYPE,    \
 	       true, true, true, ATTRS, true, \
 	      (flag_sanitize & (SANITIZE_ADDRESS | SANITIZE_THREAD \
-				| SANITIZE_UNDEFINED | SANITIZE_NONDEFAULT)))
+				| SANITIZE_UNDEFINED \
+				| SANITIZE_UNDEFINED_NONDEFAULT)))
 
 #undef DEF_CILKPLUS_BUILTIN
 #define DEF_CILKPLUS_BUILTIN(ENUM, NAME, TYPE, ATTRS)  \
diff --git a/gcc/c-family/c-ubsan.c b/gcc/c-family/c-ubsan.c
index 3539c68..900afd9 100644
--- a/gcc/c-family/c-ubsan.c
+++ b/gcc/c-family/c-ubsan.c
@@ -104,7 +104,7 @@  ubsan_instrument_division (location_t loc, tree op0, tree op1)
 				     NULL_TREE);
       data = build_fold_addr_expr_loc (loc, data);
       enum built_in_function bcode
-	= flag_sanitize_recover
+	= flag_ubsan_recover
 	  ? BUILT_IN_UBSAN_HANDLE_DIVREM_OVERFLOW
 	  : BUILT_IN_UBSAN_HANDLE_DIVREM_OVERFLOW_ABORT;
       tt = builtin_decl_explicit (bcode);
@@ -199,7 +199,7 @@  ubsan_instrument_shift (location_t loc, enum tree_code code,
       data = build_fold_addr_expr_loc (loc, data);
 
       enum built_in_function bcode
-	= flag_sanitize_recover
+	= flag_ubsan_recover
 	  ? BUILT_IN_UBSAN_HANDLE_SHIFT_OUT_OF_BOUNDS
 	  : BUILT_IN_UBSAN_HANDLE_SHIFT_OUT_OF_BOUNDS_ABORT;
       tt = builtin_decl_explicit (bcode);
@@ -229,7 +229,7 @@  ubsan_instrument_vla (location_t loc, tree size)
 				     NULL_TREE);
       data = build_fold_addr_expr_loc (loc, data);
       enum built_in_function bcode
-	= flag_sanitize_recover
+	= flag_ubsan_recover
 	  ? BUILT_IN_UBSAN_HANDLE_VLA_BOUND_NOT_POSITIVE
 	  : BUILT_IN_UBSAN_HANDLE_VLA_BOUND_NOT_POSITIVE_ABORT;
       tt = builtin_decl_explicit (bcode);
diff --git a/gcc/common.opt b/gcc/common.opt
index 90f6bd4..e9710e5 100644
--- a/gcc/common.opt
+++ b/gcc/common.opt
@@ -883,9 +883,13 @@  fasan-shadow-offset=
 Common Joined RejectNegative Var(common_deferred_options) Defer
 -fasan-shadow-offset=<string>	Use custom shadow memory offset.
 
-fsanitize-recover
-Common Report Var(flag_sanitize_recover) Init(1)
-After diagnosing undefined behavior attempt to continue execution
+fasan-recover
+Common Report Var(flag_asan_recover) Init(-1)
+After diagnosing memory error attempt to continue execution
+
+fubsan-recover
+Common Report Var(flag_ubsan_recover) Init(1)
+After diagnosing UBSan error attempt to continue execution
 
 fsanitize-undefined-trap-on-error
 Common Report Var(flag_sanitize_undefined_trap_on_error) Init(0)
diff --git a/gcc/doc/invoke.texi b/gcc/doc/invoke.texi
index d9bd1f7..c166ee6 100644
--- a/gcc/doc/invoke.texi
+++ b/gcc/doc/invoke.texi
@@ -296,7 +296,7 @@  Objective-C and Objective-C++ Dialects}.
 @item Debugging Options
 @xref{Debugging Options,,Options for Debugging Your Program or GCC}.
 @gccoptlist{-d@var{letters}  -dumpspecs  -dumpmachine  -dumpversion @gol
--fsanitize=@var{style} -fsanitize-recover @gol
+-fsanitize=@var{style} -fasan-recover -fubsan-recover @gol
 -fasan-shadow-offset=@var{string} -fsanitize-undefined-trap-on-error @gol
 -fdbg-cnt-list -fdbg-cnt=@var{counter-value-list} @gol
 -fdisable-ipa-@var{pass_name} @gol
@@ -5616,15 +5616,24 @@  This option forces GCC to use custom shadow offset in AddressSanitizer checks.
 It is useful for experimenting with different shadow memory layouts in
 kernel AddressSanitizer.
 
-@item -fsanitize-recover
-@opindex fsanitize-recover
+@item -fasan-recover
+@opindex fasan-recover
+By default @option{-fsanitize=kernel-address} sanitization 
+attempts to continue running after reporting memory error.
+This means multiple errors can be reported in a single Linux
+run.  The @option{-fno-asan-recover} can be used to alter
+this behavior, only the first detected error will be reported and
+kernel will panic afterwards.
+
+@item -fubsan-recover
+@opindex fubsan-recover
 By default @option{-fsanitize=undefined} sanitization (and its suboptions
 except for @option{-fsanitize=unreachable} and @option{-fsanitize=return})
 after reporting undefined behavior attempts to continue running the
 program as if no undefined behavior happened.  This means multiple undefined
 behavior runtime errors can be reported in a single program run, and the exit
 code of the program may indicate success even when undefined behavior
-has been reported.  The @option{-fno-sanitize-recover} can be used to alter
+has been reported.  The @option{-fno-ubsan-recover} can be used to alter
 this behavior, only the first detected undefined behavior will be reported
 and program will exit after that with non-zero exit code.
 
diff --git a/gcc/flag-types.h b/gcc/flag-types.h
index d0818e5..c9a6e17 100644
--- a/gcc/flag-types.h
+++ b/gcc/flag-types.h
@@ -242,7 +242,7 @@  enum sanitize_code {
 		       | SANITIZE_BOUNDS | SANITIZE_ALIGNMENT
 		       | SANITIZE_NONNULL_ATTRIBUTE
 		       | SANITIZE_RETURNS_NONNULL_ATTRIBUTE,
-  SANITIZE_NONDEFAULT = SANITIZE_FLOAT_DIVIDE | SANITIZE_FLOAT_CAST
+  SANITIZE_UNDEFINED_NONDEFAULT = SANITIZE_FLOAT_DIVIDE | SANITIZE_FLOAT_CAST
 };
 
 /* flag_vtable_verify initialization levels. */
diff --git a/gcc/gcc.c b/gcc/gcc.c
index 47c4e28..f97cdb1 100644
--- a/gcc/gcc.c
+++ b/gcc/gcc.c
@@ -8557,7 +8557,8 @@  sanitize_spec_function (int argc, const char **argv)
   if (strcmp (argv[0], "thread") == 0)
     return (flag_sanitize & SANITIZE_THREAD) ? "" : NULL;
   if (strcmp (argv[0], "undefined") == 0)
-    return ((flag_sanitize & (SANITIZE_UNDEFINED | SANITIZE_NONDEFAULT))
+    return ((flag_sanitize & (SANITIZE_UNDEFINED
+			      | SANITIZE_UNDEFINED_NONDEFAULT))
 	    && !flag_sanitize_undefined_trap_on_error) ? "" : NULL;
   if (strcmp (argv[0], "leak") == 0)
     return ((flag_sanitize
diff --git a/gcc/opts.c b/gcc/opts.c
index 774a599..54c3349 100644
--- a/gcc/opts.c
+++ b/gcc/opts.c
@@ -876,19 +876,50 @@  finish_options (struct gcc_options *opts, struct gcc_options *opts_set,
   if (opts->x_dwarf_split_debug_info)
     opts->x_debug_generate_pub_sections = 2;
 
-  /* Userspace and kernel ASan conflict with each other and with TSan.  */
-
+  /* Userspace and kernel ASan conflict with each other.  */
   if ((flag_sanitize & SANITIZE_USER_ADDRESS)
       && (flag_sanitize & SANITIZE_KERNEL_ADDRESS))
     error_at (loc,
-              "-fsanitize=address is incompatible with "
-              "-fsanitize=kernel-address");
+	      "-fsanitize=address is incompatible with "
+	      "-fsanitize=kernel-address");
 
-  if ((flag_sanitize & SANITIZE_ADDRESS)
-      && (flag_sanitize & SANITIZE_THREAD))
+  /* And with TSan.  */
+  if ((flag_sanitize & SANITIZE_ADDRESS) && (flag_sanitize & SANITIZE_THREAD))
     error_at (loc,
-              "-fsanitize=address and -fsanitize=kernel-address "
-              "are incompatible with -fsanitize=thread");
+	      "-fsanitize=address and -fsanitize=kernel-address "
+	      "are incompatible with -fsanitize=thread");
+
+  /* When instrumenting the pointers, we don't want to remove
+     the null pointer checks.  */
+  if (flag_sanitize & (SANITIZE_NULL | SANITIZE_NONNULL_ATTRIBUTE
+		       | SANITIZE_RETURNS_NONNULL_ATTRIBUTE))
+    opts->x_flag_delete_null_pointer_checks = 0;
+
+  /* Kernel ASan does not yet support all features.  */
+  if (flag_sanitize & SANITIZE_KERNEL_ADDRESS)
+    {
+      maybe_set_param_value (PARAM_ASAN_INSTRUMENTATION_WITH_CALL_THRESHOLD, 0,
+			     opts->x_param_values,
+			     opts_set->x_param_values);
+      maybe_set_param_value (PARAM_ASAN_GLOBALS, 0,
+			     opts->x_param_values,
+			     opts_set->x_param_values);
+      maybe_set_param_value (PARAM_ASAN_STACK, 0,
+			     opts->x_param_values,
+			     opts_set->x_param_values);
+      maybe_set_param_value (PARAM_ASAN_USE_AFTER_RETURN, 0,
+			     opts->x_param_values,
+			     opts_set->x_param_values);
+    }
+
+  /* KASan enables recovery by default.  */
+  if (opts->x_flag_asan_recover == -1)
+    opts->x_flag_asan_recover = !!(flag_sanitize & SANITIZE_KERNEL_ADDRESS);
+
+  /* Userspace ASan does not support recovery.  */
+  if (opts->x_flag_asan_recover && (flag_sanitize & SANITIZE_USER_ADDRESS))
+    warning_at (loc, 0,
+	      "-fsanitize=address does not support -fasan-recover");
 }
 
 #define LEFT_COLUMN	27
@@ -1545,30 +1576,6 @@  common_handle_option (struct gcc_options *opts,
 	    p = comma + 1;
 	  }
 
-	/* When instrumenting the pointers, we don't want to remove
-	   the null pointer checks.  */
-	if (flag_sanitize & (SANITIZE_NULL | SANITIZE_NONNULL_ATTRIBUTE
-			     | SANITIZE_RETURNS_NONNULL_ATTRIBUTE))
-	  opts->x_flag_delete_null_pointer_checks = 0;
-
-	/* Kernel ASan implies normal ASan but does not yet support
-	   all features.  */
-	if (flag_sanitize & SANITIZE_KERNEL_ADDRESS)
-	  {
-	    maybe_set_param_value (PARAM_ASAN_INSTRUMENTATION_WITH_CALL_THRESHOLD, 0,
-				   opts->x_param_values,
-				   opts_set->x_param_values);
-	    maybe_set_param_value (PARAM_ASAN_GLOBALS, 0,
-				   opts->x_param_values,
-				   opts_set->x_param_values);
-	    maybe_set_param_value (PARAM_ASAN_STACK, 0,
-				   opts->x_param_values,
-				   opts_set->x_param_values);
-	    maybe_set_param_value (PARAM_ASAN_USE_AFTER_RETURN, 0,
-				   opts->x_param_values,
-				   opts_set->x_param_values);
-	  }
-
 	break;
       }
 
diff --git a/gcc/sanitizer.def b/gcc/sanitizer.def
index 722311a..e00237e 100644
--- a/gcc/sanitizer.def
+++ b/gcc/sanitizer.def
@@ -57,6 +57,44 @@  DEF_SANITIZER_BUILTIN(BUILT_IN_ASAN_REPORT_STORE16, "__asan_report_store16",
 DEF_SANITIZER_BUILTIN(BUILT_IN_ASAN_REPORT_STORE_N, "__asan_report_store_n",
 		      BT_FN_VOID_PTR_PTRMODE,
 		      ATTR_TMPURE_NORETURN_NOTHROW_LEAF_LIST)
+DEF_SANITIZER_BUILTIN(BUILT_IN_ASAN_REPORT_RECOVER_LOAD1,
+		      "__asan_report_recover_load1",
+		      BT_FN_VOID_PTR, ATTR_TMPURE_NOTHROW_LEAF_LIST)
+DEF_SANITIZER_BUILTIN(BUILT_IN_ASAN_REPORT_RECOVER_LOAD2,
+		      "__asan_report_recover_load2",
+		      BT_FN_VOID_PTR, ATTR_TMPURE_NOTHROW_LEAF_LIST)
+DEF_SANITIZER_BUILTIN(BUILT_IN_ASAN_REPORT_RECOVER_LOAD4,
+		      "__asan_report_recover_load4",
+		      BT_FN_VOID_PTR, ATTR_TMPURE_NOTHROW_LEAF_LIST)
+DEF_SANITIZER_BUILTIN(BUILT_IN_ASAN_REPORT_RECOVER_LOAD8,
+		      "__asan_report_recover_load8",
+		      BT_FN_VOID_PTR, ATTR_TMPURE_NOTHROW_LEAF_LIST)
+DEF_SANITIZER_BUILTIN(BUILT_IN_ASAN_REPORT_RECOVER_LOAD16,
+		      "__asan_report_recover_load16",
+		      BT_FN_VOID_PTR, ATTR_TMPURE_NOTHROW_LEAF_LIST)
+DEF_SANITIZER_BUILTIN(BUILT_IN_ASAN_REPORT_RECOVER_LOAD_N,
+		      "__asan_report_recover_load_n",
+		      BT_FN_VOID_PTR_PTRMODE,
+		      ATTR_TMPURE_NOTHROW_LEAF_LIST)
+DEF_SANITIZER_BUILTIN(BUILT_IN_ASAN_REPORT_RECOVER_STORE1,
+		      "__asan_report_recover_store1",
+		      BT_FN_VOID_PTR, ATTR_TMPURE_NOTHROW_LEAF_LIST)
+DEF_SANITIZER_BUILTIN(BUILT_IN_ASAN_REPORT_RECOVER_STORE2,
+		      "__asan_report_recover_store2",
+		      BT_FN_VOID_PTR, ATTR_TMPURE_NOTHROW_LEAF_LIST)
+DEF_SANITIZER_BUILTIN(BUILT_IN_ASAN_REPORT_RECOVER_STORE4,
+		      "__asan_report_recover_store4",
+		      BT_FN_VOID_PTR, ATTR_TMPURE_NOTHROW_LEAF_LIST)
+DEF_SANITIZER_BUILTIN(BUILT_IN_ASAN_REPORT_RECOVER_STORE8,
+		      "__asan_report_recover_store8",
+		      BT_FN_VOID_PTR, ATTR_TMPURE_NOTHROW_LEAF_LIST)
+DEF_SANITIZER_BUILTIN(BUILT_IN_ASAN_REPORT_RECOVER_STORE16,
+		      "__asan_report_recover_store16",
+		      BT_FN_VOID_PTR, ATTR_TMPURE_NOTHROW_LEAF_LIST)
+DEF_SANITIZER_BUILTIN(BUILT_IN_ASAN_REPORT_RECOVER_STORE_N,
+		      "__asan_report_recover_store_n",
+		      BT_FN_VOID_PTR_PTRMODE,
+		      ATTR_TMPURE_NOTHROW_LEAF_LIST)
 DEF_SANITIZER_BUILTIN(BUILT_IN_ASAN_LOAD1, "__asan_load1",
 		      BT_FN_VOID_PTR, ATTR_TMPURE_NOTHROW_LEAF_LIST)
 DEF_SANITIZER_BUILTIN(BUILT_IN_ASAN_LOAD2, "__asan_load2",
diff --git a/gcc/testsuite/c-c++-common/asan/recovery-1.c b/gcc/testsuite/c-c++-common/asan/recovery-1.c
new file mode 100644
index 0000000..b037bde
--- /dev/null
+++ b/gcc/testsuite/c-c++-common/asan/recovery-1.c
@@ -0,0 +1,36 @@ 
+/* { dg-do run } */
+/* { dg-options "-w -fasan-recover" } */
+
+#include <sanitizer/asan_interface.h>
+
+#define NREPORTS 5
+
+static int counter = NREPORTS;
+
+#ifdef __cplusplus
+extern "C"
+#endif
+void __attribute__((used))
+__asan_report_recover_store4 (void *p)
+{
+  --counter;
+}
+ 
+void __attribute__((noinline, noclone))
+foo (int *p)
+{
+  *p = 0;
+}
+
+int
+main ()
+{
+  int x, i;
+  __asan_poison_memory_region (&x, sizeof (x));
+  for (i = 0; i < NREPORTS; ++i)
+    foo (&x);
+  if (counter != 0)
+    __builtin_abort ();
+  return 0;
+}
+
diff --git a/gcc/testsuite/c-c++-common/ubsan/align-1.c b/gcc/testsuite/c-c++-common/ubsan/align-1.c
index 2e40e83..878f969 100644
--- a/gcc/testsuite/c-c++-common/ubsan/align-1.c
+++ b/gcc/testsuite/c-c++-common/ubsan/align-1.c
@@ -1,5 +1,5 @@ 
 /* { dg-do run } */
-/* { dg-options "-fsanitize=undefined -fno-sanitize-recover" } */
+/* { dg-options "-fsanitize=undefined -fno-ubsan-recover" } */
 
 struct S { int a; char b; long long c; short d[10]; };
 struct T { char a; long long b; };
diff --git a/gcc/testsuite/c-c++-common/ubsan/align-3.c b/gcc/testsuite/c-c++-common/ubsan/align-3.c
index a509fa9..6fbece5 100644
--- a/gcc/testsuite/c-c++-common/ubsan/align-3.c
+++ b/gcc/testsuite/c-c++-common/ubsan/align-3.c
@@ -1,5 +1,5 @@ 
 /* { dg-do run } */
-/* { dg-options "-fsanitize=undefined -fno-sanitize-recover" } */
+/* { dg-options "-fsanitize=undefined -fno-ubsan-recover" } */
 
 int c;
 
diff --git a/gcc/testsuite/c-c++-common/ubsan/bounds-1.c b/gcc/testsuite/c-c++-common/ubsan/bounds-1.c
index aa192d3..ec831f3 100644
--- a/gcc/testsuite/c-c++-common/ubsan/bounds-1.c
+++ b/gcc/testsuite/c-c++-common/ubsan/bounds-1.c
@@ -1,5 +1,5 @@ 
 /* { dg-do run } */
-/* { dg-options "-fsanitize=bounds -fno-sanitize-recover -Wall" } */
+/* { dg-options "-fsanitize=bounds -fno-ubsan-recover -Wall" } */
 
 /* Don't fail on valid uses.  */
 
diff --git a/gcc/testsuite/c-c++-common/ubsan/div-by-zero-7.c b/gcc/testsuite/c-c++-common/ubsan/div-by-zero-7.c
index b65a0bc..c1a0a3e 100644
--- a/gcc/testsuite/c-c++-common/ubsan/div-by-zero-7.c
+++ b/gcc/testsuite/c-c++-common/ubsan/div-by-zero-7.c
@@ -1,5 +1,5 @@ 
 /* { dg-do run } */
-/* { dg-options "-fsanitize=integer-divide-by-zero -Wno-div-by-zero -fno-sanitize-recover" } */
+/* { dg-options "-fsanitize=integer-divide-by-zero -Wno-div-by-zero -fno-ubsan-recover" } */
 /* { dg-shouldfail "ubsan" } */
 
 #include <stdio.h>
diff --git a/gcc/testsuite/c-c++-common/ubsan/float-cast-overflow-10.c b/gcc/testsuite/c-c++-common/ubsan/float-cast-overflow-10.c
index e95f194..1697a6e 100644
--- a/gcc/testsuite/c-c++-common/ubsan/float-cast-overflow-10.c
+++ b/gcc/testsuite/c-c++-common/ubsan/float-cast-overflow-10.c
@@ -1,6 +1,6 @@ 
 /* { dg-do run { target dfp } } */
 /* { dg-skip-if "" { ! run_expensive_tests } { "*" } { "-O2" } } */
-/* { dg-options "-fsanitize=float-cast-overflow -fsanitize-recover" } */
+/* { dg-options "-fsanitize=float-cast-overflow -fubsan-recover" } */
 /* { dg-additional-options "-DUSE_INT128" { target int128 } } */
 /* FIXME: When _DecimalXX <-> {signed, unsigned} __int128 conversions are
    supported, -DBROKEN_DECIMAL_INT128 can be removed.  */
diff --git a/gcc/testsuite/c-c++-common/ubsan/float-cast-overflow-7.c b/gcc/testsuite/c-c++-common/ubsan/float-cast-overflow-7.c
index 3223d5e..68e0c73 100644
--- a/gcc/testsuite/c-c++-common/ubsan/float-cast-overflow-7.c
+++ b/gcc/testsuite/c-c++-common/ubsan/float-cast-overflow-7.c
@@ -1,6 +1,6 @@ 
 /* { dg-do run } */
 /* { dg-skip-if "" { ! run_expensive_tests } { "*" } { "-O2" } } */
-/* { dg-options "-fsanitize=float-cast-overflow -fno-sanitize-recover" } */
+/* { dg-options "-fsanitize=float-cast-overflow -fno-ubsan-recover" } */
 /* FIXME: When _DecimalXX <-> {signed, unsigned} __int128 conversions are
    supported, -DBROKEN_DECIMAL_INT128 can be removed.  */
 /* { dg-additional-options "-DUSE_DFP -DBROKEN_DECIMAL_INT128" { target dfp } } */
diff --git a/gcc/testsuite/c-c++-common/ubsan/float-cast-overflow-8.c b/gcc/testsuite/c-c++-common/ubsan/float-cast-overflow-8.c
index 5414a0b..d1a1c24 100644
--- a/gcc/testsuite/c-c++-common/ubsan/float-cast-overflow-8.c
+++ b/gcc/testsuite/c-c++-common/ubsan/float-cast-overflow-8.c
@@ -1,6 +1,6 @@ 
 /* { dg-do run } */
 /* { dg-skip-if "" { ! run_expensive_tests } { "*" } { "-O2" } } */
-/* { dg-options "-fsanitize=float-cast-overflow -fsanitize-recover -DUSE_FLT_DBL_LDBL" } */
+/* { dg-options "-fsanitize=float-cast-overflow -fubsan-recover -DUSE_FLT_DBL_LDBL" } */
 /* { dg-additional-options "-DUSE_INT128" { target int128 } } */
 
 #include "float-cast-overflow-7.h"
diff --git a/gcc/testsuite/c-c++-common/ubsan/float-cast-overflow-9.c b/gcc/testsuite/c-c++-common/ubsan/float-cast-overflow-9.c
index cadef31..502b11f 100644
--- a/gcc/testsuite/c-c++-common/ubsan/float-cast-overflow-9.c
+++ b/gcc/testsuite/c-c++-common/ubsan/float-cast-overflow-9.c
@@ -1,6 +1,6 @@ 
 /* { dg-do run { target { i?86-*-linux* x86_64-*-linux* } } } */
 /* { dg-skip-if "" { ! run_expensive_tests } { "*" } { "-O2" } } */
-/* { dg-options "-fsanitize=float-cast-overflow -fsanitize-recover -DUSE_FLOAT80 -DUSE_FLOAT128" } */
+/* { dg-options "-fsanitize=float-cast-overflow -fubsan-recover -DUSE_FLOAT80 -DUSE_FLOAT128" } */
 /* { dg-additional-options "-DUSE_INT128" { target int128 } } */
 
 #include "float-cast-overflow-8.c"
diff --git a/gcc/testsuite/c-c++-common/ubsan/nonnull-2.c b/gcc/testsuite/c-c++-common/ubsan/nonnull-2.c
index 49a5cf2..c414dfc 100644
--- a/gcc/testsuite/c-c++-common/ubsan/nonnull-2.c
+++ b/gcc/testsuite/c-c++-common/ubsan/nonnull-2.c
@@ -1,6 +1,6 @@ 
 /* { dg-do run } */
 /* { dg-shouldfail "ubsan" } */
-/* { dg-options "-fsanitize=undefined -fno-sanitize-recover" } */
+/* { dg-options "-fsanitize=undefined -fno-ubsan-recover" } */
 
 int q, r;
 void *a, *b, *c = (void *) &q, *d, *e, *f = (void *) &q, *g, *h;
diff --git a/gcc/testsuite/c-c++-common/ubsan/nonnull-3.c b/gcc/testsuite/c-c++-common/ubsan/nonnull-3.c
index 80018c2..7194594 100644
--- a/gcc/testsuite/c-c++-common/ubsan/nonnull-3.c
+++ b/gcc/testsuite/c-c++-common/ubsan/nonnull-3.c
@@ -1,6 +1,6 @@ 
 /* { dg-do run } */
 /* { dg-shouldfail "ubsan" } */
-/* { dg-options "-fsanitize=undefined -fno-sanitize-recover" } */
+/* { dg-options "-fsanitize=undefined -fno-ubsan-recover" } */
 
 int q, r;
 void *a, *b, *c = (void *) &q, *d, *e, *f = (void *) &q, *g, *h;
diff --git a/gcc/testsuite/c-c++-common/ubsan/overflow-1.c b/gcc/testsuite/c-c++-common/ubsan/overflow-1.c
index b0ef259..da0a8a0 100644
--- a/gcc/testsuite/c-c++-common/ubsan/overflow-1.c
+++ b/gcc/testsuite/c-c++-common/ubsan/overflow-1.c
@@ -1,5 +1,5 @@ 
 /* { dg-do run } */
-/* { dg-options "-fsanitize=signed-integer-overflow -fno-sanitize-recover" } */
+/* { dg-options "-fsanitize=signed-integer-overflow -fno-ubsan-recover" } */
 
 #ifndef ASM1
 # define ASM1(a) /* Nothing */
diff --git a/gcc/testsuite/c-c++-common/ubsan/overflow-add-1.c b/gcc/testsuite/c-c++-common/ubsan/overflow-add-1.c
index b009f5b..d16f7ab 100644
--- a/gcc/testsuite/c-c++-common/ubsan/overflow-add-1.c
+++ b/gcc/testsuite/c-c++-common/ubsan/overflow-add-1.c
@@ -1,5 +1,5 @@ 
 /* { dg-do run } */
-/* { dg-options "-fsanitize=signed-integer-overflow -Wno-unused-variable -fno-sanitize-recover" } */
+/* { dg-options "-fsanitize=signed-integer-overflow -Wno-unused-variable -fno-ubsan-recover" } */
 
 #define SCHAR_MAX __SCHAR_MAX__
 #define SHRT_MAX __SHRT_MAX__
diff --git a/gcc/testsuite/c-c++-common/ubsan/overflow-add-3.c b/gcc/testsuite/c-c++-common/ubsan/overflow-add-3.c
index 6475d10..9cd5793 100644
--- a/gcc/testsuite/c-c++-common/ubsan/overflow-add-3.c
+++ b/gcc/testsuite/c-c++-common/ubsan/overflow-add-3.c
@@ -1,5 +1,5 @@ 
 /* { dg-do run } */
-/* { dg-options "-fsanitize=signed-integer-overflow -Wno-unused-variable -fno-sanitize-recover" } */
+/* { dg-options "-fsanitize=signed-integer-overflow -Wno-unused-variable -fno-ubsan-recover" } */
 /* { dg-shouldfail "ubsan" } */
 
 #define INT_MAX __INT_MAX__
diff --git a/gcc/testsuite/c-c++-common/ubsan/overflow-mul-1.c b/gcc/testsuite/c-c++-common/ubsan/overflow-mul-1.c
index 22ea639..eb08b89 100644
--- a/gcc/testsuite/c-c++-common/ubsan/overflow-mul-1.c
+++ b/gcc/testsuite/c-c++-common/ubsan/overflow-mul-1.c
@@ -1,5 +1,5 @@ 
 /* { dg-do run } */
-/* { dg-options "-fsanitize=signed-integer-overflow -Wno-unused-variable -fno-sanitize-recover" } */
+/* { dg-options "-fsanitize=signed-integer-overflow -Wno-unused-variable -fno-ubsan-recover" } */
 
 #define SCHAR_MAX __SCHAR_MAX__
 #define SHRT_MAX __SHRT_MAX__
diff --git a/gcc/testsuite/c-c++-common/ubsan/overflow-mul-3.c b/gcc/testsuite/c-c++-common/ubsan/overflow-mul-3.c
index 896c0bc..ac74579 100644
--- a/gcc/testsuite/c-c++-common/ubsan/overflow-mul-3.c
+++ b/gcc/testsuite/c-c++-common/ubsan/overflow-mul-3.c
@@ -1,5 +1,5 @@ 
 /* { dg-do run } */
-/* { dg-options "-fsanitize=signed-integer-overflow -fno-sanitize-recover" } */
+/* { dg-options "-fsanitize=signed-integer-overflow -fno-ubsan-recover" } */
 
 __attribute__((noinline, noclone)) long long
 mul (long long x, long long y)
diff --git a/gcc/testsuite/c-c++-common/ubsan/overflow-negate-2.c b/gcc/testsuite/c-c++-common/ubsan/overflow-negate-2.c
index 8b5ffa5..5665137 100644
--- a/gcc/testsuite/c-c++-common/ubsan/overflow-negate-2.c
+++ b/gcc/testsuite/c-c++-common/ubsan/overflow-negate-2.c
@@ -1,5 +1,5 @@ 
 /* { dg-do run } */
-/* { dg-options "-fsanitize=signed-integer-overflow -Wno-unused-variable -fno-sanitize-recover" } */
+/* { dg-options "-fsanitize=signed-integer-overflow -Wno-unused-variable -fno-ubsan-recover" } */
 
 #define SCHAR_MIN (-__SCHAR_MAX__ - 1)
 #define SHRT_MIN (-__SHRT_MAX__ - 1)
diff --git a/gcc/testsuite/c-c++-common/ubsan/overflow-sub-1.c b/gcc/testsuite/c-c++-common/ubsan/overflow-sub-1.c
index 2b10f9e..2734766 100644
--- a/gcc/testsuite/c-c++-common/ubsan/overflow-sub-1.c
+++ b/gcc/testsuite/c-c++-common/ubsan/overflow-sub-1.c
@@ -1,5 +1,5 @@ 
 /* { dg-do run } */
-/* { dg-options "-fsanitize=signed-integer-overflow -Wno-unused-variable -fno-sanitize-recover" } */
+/* { dg-options "-fsanitize=signed-integer-overflow -Wno-unused-variable -fno-ubsan-recover" } */
 
 #define SCHAR_MAX __SCHAR_MAX__
 #define SCHAR_MIN (-__SCHAR_MAX__ - 1)
diff --git a/gcc/testsuite/c-c++-common/ubsan/pr59503.c b/gcc/testsuite/c-c++-common/ubsan/pr59503.c
index 81447d7..8ae0a9d 100644
--- a/gcc/testsuite/c-c++-common/ubsan/pr59503.c
+++ b/gcc/testsuite/c-c++-common/ubsan/pr59503.c
@@ -1,5 +1,5 @@ 
 /* { dg-do run } */
-/* { dg-options "-fsanitize=signed-integer-overflow -fno-sanitize-recover" } */
+/* { dg-options "-fsanitize=signed-integer-overflow -fno-ubsan-recover" } */
 
 int
 main (void)
diff --git a/gcc/testsuite/c-c++-common/ubsan/pr60613-1.c b/gcc/testsuite/c-c++-common/ubsan/pr60613-1.c
index 4c0810b..ce94d8b 100644
--- a/gcc/testsuite/c-c++-common/ubsan/pr60613-1.c
+++ b/gcc/testsuite/c-c++-common/ubsan/pr60613-1.c
@@ -1,6 +1,6 @@ 
 /* PR sanitizer/60613 */
 /* { dg-do run } */
-/* { dg-options "-fsanitize=undefined -fno-sanitize-recover" } */
+/* { dg-options "-fsanitize=undefined -fno-ubsan-recover" } */
 
 long long y;
 
diff --git a/gcc/testsuite/c-c++-common/ubsan/save-expr-1.c b/gcc/testsuite/c-c++-common/ubsan/save-expr-1.c
index 89ac58c..b808bed 100644
--- a/gcc/testsuite/c-c++-common/ubsan/save-expr-1.c
+++ b/gcc/testsuite/c-c++-common/ubsan/save-expr-1.c
@@ -1,5 +1,5 @@ 
 /* { dg-do compile } */
-/* { dg-options "-fsanitize=shift -Wall -Werror -O -fno-sanitize-recover" } */
+/* { dg-options "-fsanitize=shift -Wall -Werror -O -fno-ubsan-recover" } */
 
 static int x;
 int
diff --git a/gcc/testsuite/c-c++-common/ubsan/shift-3.c b/gcc/testsuite/c-c++-common/ubsan/shift-3.c
index 67f1b69..4cba6fb 100644
--- a/gcc/testsuite/c-c++-common/ubsan/shift-3.c
+++ b/gcc/testsuite/c-c++-common/ubsan/shift-3.c
@@ -1,5 +1,5 @@ 
 /* { dg-do run } */
-/* { dg-options "-fsanitize=shift -w -fno-sanitize-recover" } */
+/* { dg-options "-fsanitize=shift -w -fno-ubsan-recover" } */
 
 int
 main (void)
diff --git a/gcc/testsuite/c-c++-common/ubsan/shift-6.c b/gcc/testsuite/c-c++-common/ubsan/shift-6.c
index e26e684..ce44de4 100644
--- a/gcc/testsuite/c-c++-common/ubsan/shift-6.c
+++ b/gcc/testsuite/c-c++-common/ubsan/shift-6.c
@@ -1,6 +1,6 @@ 
 /* PR sanitizer/58413 */
 /* { dg-do run { target int32plus } } */
-/* { dg-options "-fsanitize=shift -w -fno-sanitize-recover" } */
+/* { dg-options "-fsanitize=shift -w -fno-ubsan-recover" } */
 
 int x = 7;
 int
diff --git a/gcc/testsuite/c-c++-common/ubsan/undefined-1.c b/gcc/testsuite/c-c++-common/ubsan/undefined-1.c
index 201818d..1da4413 100644
--- a/gcc/testsuite/c-c++-common/ubsan/undefined-1.c
+++ b/gcc/testsuite/c-c++-common/ubsan/undefined-1.c
@@ -1,5 +1,5 @@ 
 /* { dg-do run } */
-/* { dg-options "-fsanitize=undefined -fno-sanitize-recover" } */
+/* { dg-options "-fsanitize=undefined -fno-ubsan-recover" } */
 
 int
 foo (int x, int y)
diff --git a/gcc/testsuite/c-c++-common/ubsan/vla-2.c b/gcc/testsuite/c-c++-common/ubsan/vla-2.c
index c767042..c714950 100644
--- a/gcc/testsuite/c-c++-common/ubsan/vla-2.c
+++ b/gcc/testsuite/c-c++-common/ubsan/vla-2.c
@@ -1,5 +1,5 @@ 
 /* { dg-do run } */
-/* { dg-options "-fsanitize=vla-bound -Wall -Wno-unused-variable -fno-sanitize-recover" } */
+/* { dg-options "-fsanitize=vla-bound -Wall -Wno-unused-variable -fno-ubsan-recover" } */
 
 int
 main (void)
diff --git a/gcc/testsuite/c-c++-common/ubsan/vla-3.c b/gcc/testsuite/c-c++-common/ubsan/vla-3.c
index 06c6939..9355d24 100644
--- a/gcc/testsuite/c-c++-common/ubsan/vla-3.c
+++ b/gcc/testsuite/c-c++-common/ubsan/vla-3.c
@@ -1,5 +1,5 @@ 
 /* { dg-do run } */
-/* { dg-options "-fsanitize=vla-bound -fno-sanitize-recover" } */
+/* { dg-options "-fsanitize=vla-bound -fno-ubsan-recover" } */
 
 /* Don't instrument the arrays here.  */
 int
diff --git a/gcc/testsuite/c-c++-common/ubsan/vla-4.c b/gcc/testsuite/c-c++-common/ubsan/vla-4.c
index d47f26b..d87f5ad 100644
--- a/gcc/testsuite/c-c++-common/ubsan/vla-4.c
+++ b/gcc/testsuite/c-c++-common/ubsan/vla-4.c
@@ -1,5 +1,5 @@ 
 /* { dg-do run } */
-/* { dg-options "-fsanitize=vla-bound -fno-sanitize-recover" } */
+/* { dg-options "-fsanitize=vla-bound -fno-ubsan-recover" } */
 
 int
 main (void)
diff --git a/gcc/testsuite/g++.dg/ubsan/cxx11-shift-1.C b/gcc/testsuite/g++.dg/ubsan/cxx11-shift-1.C
index 23a7b15..67f1f3d 100644
--- a/gcc/testsuite/g++.dg/ubsan/cxx11-shift-1.C
+++ b/gcc/testsuite/g++.dg/ubsan/cxx11-shift-1.C
@@ -1,5 +1,5 @@ 
 /* { dg-do run } */
-/* { dg-options "-fsanitize=shift -w -fno-sanitize-recover -std=c++11" } */
+/* { dg-options "-fsanitize=shift -w -fno-ubsan-recover -std=c++11" } */
 
 int
 main (void)
diff --git a/gcc/testsuite/g++.dg/ubsan/return-2.C b/gcc/testsuite/g++.dg/ubsan/return-2.C
index a182999..4f1fdb0 100644
--- a/gcc/testsuite/g++.dg/ubsan/return-2.C
+++ b/gcc/testsuite/g++.dg/ubsan/return-2.C
@@ -1,5 +1,5 @@ 
 // { dg-do run }
-// { dg-options "-fsanitize=return -fno-sanitize-recover" }
+// { dg-options "-fsanitize=return -fno-ubsan-recover" }
 
 struct S { S (); ~S (); };
 
diff --git a/gcc/ubsan.c b/gcc/ubsan.c
index e3128ad..bf0d3b2 100644
--- a/gcc/ubsan.c
+++ b/gcc/ubsan.c
@@ -630,7 +630,7 @@  ubsan_expand_bounds_ifn (gimple_stmt_iterator *gsi)
 			     NULL_TREE, NULL_TREE);
       data = build_fold_addr_expr_loc (loc, data);
       enum built_in_function bcode
-	= flag_sanitize_recover
+	= flag_ubsan_recover
 	  ? BUILT_IN_UBSAN_HANDLE_OUT_OF_BOUNDS
 	  : BUILT_IN_UBSAN_HANDLE_OUT_OF_BOUNDS_ABORT;
       tree fn = builtin_decl_explicit (bcode);
@@ -733,7 +733,7 @@  ubsan_expand_null_ifn (gimple_stmt_iterator *gsip)
   else
     {
       enum built_in_function bcode
-	= flag_sanitize_recover
+	= flag_ubsan_recover
 	  ? BUILT_IN_UBSAN_HANDLE_TYPE_MISMATCH
 	  : BUILT_IN_UBSAN_HANDLE_TYPE_MISMATCH_ABORT;
       tree fn = builtin_decl_implicit (bcode);
@@ -886,22 +886,22 @@  ubsan_build_overflow_builtin (tree_code code, location_t loc, tree lhstype,
   switch (code)
     {
     case PLUS_EXPR:
-      fn_code = flag_sanitize_recover
+      fn_code = flag_ubsan_recover
 		? BUILT_IN_UBSAN_HANDLE_ADD_OVERFLOW
 		: BUILT_IN_UBSAN_HANDLE_ADD_OVERFLOW_ABORT;
       break;
     case MINUS_EXPR:
-      fn_code = flag_sanitize_recover
+      fn_code = flag_ubsan_recover
 		? BUILT_IN_UBSAN_HANDLE_SUB_OVERFLOW
 		: BUILT_IN_UBSAN_HANDLE_SUB_OVERFLOW_ABORT;
       break;
     case MULT_EXPR:
-      fn_code = flag_sanitize_recover
+      fn_code = flag_ubsan_recover
 		? BUILT_IN_UBSAN_HANDLE_MUL_OVERFLOW
 		: BUILT_IN_UBSAN_HANDLE_MUL_OVERFLOW_ABORT;
       break;
     case NEGATE_EXPR:
-      fn_code = flag_sanitize_recover
+      fn_code = flag_ubsan_recover
 		? BUILT_IN_UBSAN_HANDLE_NEGATE_OVERFLOW
 		: BUILT_IN_UBSAN_HANDLE_NEGATE_OVERFLOW_ABORT;
       break;
@@ -1078,7 +1078,7 @@  instrument_bool_enum_load (gimple_stmt_iterator *gsi)
 				     NULL_TREE);
       data = build_fold_addr_expr_loc (loc, data);
       enum built_in_function bcode
-	= flag_sanitize_recover
+	= flag_ubsan_recover
 	  ? BUILT_IN_UBSAN_HANDLE_LOAD_INVALID_VALUE
 	  : BUILT_IN_UBSAN_HANDLE_LOAD_INVALID_VALUE_ABORT;
       tree fn = builtin_decl_explicit (bcode);
@@ -1200,7 +1200,7 @@  ubsan_instrument_float_cast (location_t loc, tree type, tree expr)
 				     ubsan_type_descriptor (type), NULL_TREE,
 				     NULL_TREE);
       enum built_in_function bcode
-	= flag_sanitize_recover
+	= flag_ubsan_recover
 	  ? BUILT_IN_UBSAN_HANDLE_FLOAT_CAST_OVERFLOW
 	  : BUILT_IN_UBSAN_HANDLE_FLOAT_CAST_OVERFLOW_ABORT;
       fn = builtin_decl_explicit (bcode);
@@ -1266,7 +1266,7 @@  instrument_nonnull_arg (gimple_stmt_iterator *gsi)
 					     NULL_TREE);
 	      data = build_fold_addr_expr_loc (loc[0], data);
 	      enum built_in_function bcode
-		= flag_sanitize_recover
+		= flag_ubsan_recover
 		  ? BUILT_IN_UBSAN_HANDLE_NONNULL_ARG
 		  : BUILT_IN_UBSAN_HANDLE_NONNULL_ARG_ABORT;
 	      tree fn = builtin_decl_explicit (bcode);
@@ -1318,7 +1318,7 @@  instrument_nonnull_return (gimple_stmt_iterator *gsi)
 					 2, loc, NULL_TREE, NULL_TREE);
 	  data = build_fold_addr_expr_loc (loc[0], data);
 	  enum built_in_function bcode
-	    = flag_sanitize_recover
+	    = flag_ubsan_recover
 	      ? BUILT_IN_UBSAN_HANDLE_NONNULL_RETURN
 	      : BUILT_IN_UBSAN_HANDLE_NONNULL_RETURN_ABORT;
 	  tree fn = builtin_decl_explicit (bcode);