commit a9451a79bcdcab69856a38d228bec8986c0b0b2a Author: Yury Gribov Date: Fri Aug 29 16:43:42 2014 +0400 2014-09-29 Yury Gribov 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= 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 + +#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 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);