From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from smtp-out1.suse.de (smtp-out1.suse.de [195.135.220.28]) by sourceware.org (Postfix) with ESMTPS id F10C83858D33 for ; Tue, 28 Feb 2023 09:02:49 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.2 sourceware.org F10C83858D33 Authentication-Results: sourceware.org; dmarc=pass (p=none dis=none) header.from=suse.de Authentication-Results: sourceware.org; spf=pass smtp.mailfrom=suse.de Received: from relay2.suse.de (relay2.suse.de [149.44.160.134]) by smtp-out1.suse.de (Postfix) with ESMTP id 20CFC21A18; Tue, 28 Feb 2023 09:02:48 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=suse.de; s=susede2_rsa; t=1677574968; h=from:from:reply-to:date:date:message-id:message-id:to:to:cc:cc: mime-version:mime-version:content-type:content-type: in-reply-to:in-reply-to:references:references; bh=irJREMoBf+sNp5Tx3vv87VSLwaSd/P5gdv9b8xBmcrY=; b=V5z9Twjuj2whiqoEzDQaTtSRWoD4RmsQf/nndtEL+sLkFACfYytntnMbJ/V1GnJ5hoycd7 DaTsbkTtooVvvSlb/wRR82ag+zW8DeozhRTJ2X7bMvx4erVCwjJzuZYNk0FYCP+Fp+RH3F XW4R7MYrUjuZJjMvsuzJeKSUo0Dslbk= DKIM-Signature: v=1; a=ed25519-sha256; c=relaxed/relaxed; d=suse.de; s=susede2_ed25519; t=1677574968; h=from:from:reply-to:date:date:message-id:message-id:to:to:cc:cc: mime-version:mime-version:content-type:content-type: in-reply-to:in-reply-to:references:references; bh=irJREMoBf+sNp5Tx3vv87VSLwaSd/P5gdv9b8xBmcrY=; b=cdCEL4yHWp54ZjNcMZHoMxwbr1hCBTS1PwdlXllCoMYUvPqJxBD0bYpPdYZFhBIq2zfwP3 ukK94TLR1JEvNMCQ== Received: from wotan.suse.de (wotan.suse.de [10.160.0.1]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by relay2.suse.de (Postfix) with ESMTPS id F0E432C141; Tue, 28 Feb 2023 09:02:47 +0000 (UTC) Date: Tue, 28 Feb 2023 09:02:47 +0000 (UTC) From: Richard Biener To: Jakub Jelinek cc: gcc-patches@gcc.gnu.org Subject: Re: [PATCH] ubsan: Honor -fstrict-flex-arrays= in -fsanitize=bounds [PR108894] In-Reply-To: Message-ID: References: User-Agent: Alpine 2.22 (LSU 394 2020-01-19) MIME-Version: 1.0 Content-Type: text/plain; charset=US-ASCII X-Spam-Status: No, score=-5.0 required=5.0 tests=BAYES_00,DKIM_SIGNED,DKIM_VALID,DKIM_VALID_AU,DKIM_VALID_EF,SPF_HELO_NONE,SPF_PASS,TXREP autolearn=ham autolearn_force=no version=3.4.6 X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) on server2.sourceware.org List-Id: On Tue, 28 Feb 2023, Jakub Jelinek wrote: > Hi! > > While this isn't really a regression, the -fstrict-flex-arrays* > option is new in GCC 13 and so I think we should make -fsanitize=bounds > play with it well from the beginning. > > The current behavior is that -fsanitize=bounds considers all trailing > arrays as flexible member-like arrays and both -fsanitize=bounds and > -fsanitize=bounds-strict because of a bug don't even instrument > [0] arrays at all, not as trailing nor when followed by other members. > > I think -fstrict-flex-arrays* options can be considered as language > mode changing options, by default flexible member-like arrays are > handled like flexible arrays, but that option can change the set of > the arrays which are treated like that. So, -fsanitize=bounds should > change with that on what is considered acceptable and what isn't. > While -fsanitize=bounds-strict should reject them all always to > continue previous behavior. > > The following patch implements that. To support [0] array instrumentation, > I had to change the meaning of the bounds argument to .UBSAN_BOUNDS, > previously it was the TYPE_MAX_VALUE of the domain unless ignore_off_by_one > (used for taking address of the array element rather than accessing it; > in that case 1 is added to the bound argument) and the later lowered checks > were if (index > bound) report_failure (). > The problem with that is that for [0] arrays where (at least for C++) > the max value is all ones, for accesses that condition will be never true; > for addresses of elements it was working (in C++) correctly before. > This patch changes it to add 1 + ignore_off_by_one, so -1 becomes 0 or > 1 for &array_ref and changing the lowering to be if (index >= bound) > report_failure (). Furthermore, as C represents the [0] arrays with > NULL TYPE_MAX_VALUE, I treated those like the C++ ones. > > Bootstrapped/regtested on x86_64-linux and i686-linux, ok for trunk? LGTM. Btw, what does -fsanitize=bounds do for C++ code which lacks flexible arrays? Does it treat all trailing arrays as fixed? Thanks, Richard. > 2023-02-28 Jakub Jelinek > > PR sanitizer/108894 > gcc/ > * ubsan.cc (ubsan_expand_bounds_ifn): Emit index >= bound > comparison rather than index > bound. > * gimple-fold.cc (gimple_fold_call): Use tree_int_cst_lt > rather than tree_int_cst_le for IFN_UBSAN_BOUND comparison. > * doc/invoke.texi (-fsanitize=bounds): Document that whether > flexible array member-like arrays are instrumented or not depends > on -fstrict-flex-arrays* options of strict_flex_array attributes. > (-fsanitize=bounds-strict): Document that flexible array members > are not instrumented. > gcc/c-family/ > * c-common.h (c_strict_flex_array_level_of): Declare. > * c-common.cc (c_strict_flex_array_level_of): New function, > moved and renamed from c-decl.cc's strict_flex_array_level_of. > * c-ubsan.cc (ubsan_instrument_bounds): Fix comment typo. For > C check c_strict_flex_array_level_of whether a trailing array > should be treated as flexible member like. Handle C [0] arrays. > Add 1 + index_off_by_one rather than index_off_by_one to bounds > and use tree_int_cst_lt rather than tree_int_cst_le for idx vs. > bounds comparison. > gcc/c/ > * c-decl.cc (strict_flex_array_level_of): Move to c-common.cc > and rename to c_strict_flex_array_level_of. > (is_flexible_array_member_p): Adjust caller. > gcc/testsuite/ > * gcc.dg/ubsan/bounds-4.c: New test. > * gcc.dg/ubsan/bounds-4a.c: New test. > * gcc.dg/ubsan/bounds-4b.c: New test. > * gcc.dg/ubsan/bounds-4c.c: New test. > * gcc.dg/ubsan/bounds-4d.c: New test. > * g++.dg/ubsan/bounds-1.C: New test. > > --- gcc/ubsan.cc.jj 2023-02-06 09:05:49.001628881 +0100 > +++ gcc/ubsan.cc 2023-02-27 16:46:13.452122423 +0100 > @@ -721,7 +721,7 @@ ubsan_expand_bounds_ifn (gimple_stmt_ite > > gimple_stmt_iterator gsi_orig = *gsi; > > - /* Create condition "if (index > bound)". */ > + /* Create condition "if (index >= bound)". */ > basic_block then_bb, fallthru_bb; > gimple_stmt_iterator cond_insert_point > = create_cond_insert_point (gsi, false, false, true, > @@ -730,7 +730,7 @@ ubsan_expand_bounds_ifn (gimple_stmt_ite > index = force_gimple_operand_gsi (&cond_insert_point, index, > true, NULL_TREE, > false, GSI_NEW_STMT); > - gimple *g = gimple_build_cond (GT_EXPR, index, bound, NULL_TREE, NULL_TREE); > + gimple *g = gimple_build_cond (GE_EXPR, index, bound, NULL_TREE, NULL_TREE); > gimple_set_location (g, loc); > gsi_insert_after (&cond_insert_point, g, GSI_NEW_STMT); > > --- gcc/gimple-fold.cc.jj 2023-02-08 11:57:29.726582589 +0100 > +++ gcc/gimple-fold.cc 2023-02-27 16:45:00.895160752 +0100 > @@ -5624,7 +5624,7 @@ gimple_fold_call (gimple_stmt_iterator * > { > index = fold_convert (TREE_TYPE (bound), index); > if (TREE_CODE (index) == INTEGER_CST > - && tree_int_cst_le (index, bound)) > + && tree_int_cst_lt (index, bound)) > { > replace_call_with_value (gsi, NULL_TREE); > return true; > --- gcc/doc/invoke.texi.jj 2023-02-24 09:58:39.888509771 +0100 > +++ gcc/doc/invoke.texi 2023-02-28 08:32:27.313775696 +0100 > @@ -16831,14 +16831,17 @@ a++; > @item -fsanitize=bounds > This option enables instrumentation of array bounds. Various out of bounds > accesses are detected. Flexible array members, flexible array member-like > -arrays, and initializers of variables with static storage are not instrumented. > +arrays, and initializers of variables with static storage are not > +instrumented, with the exception of flexible array member-like arrays > +for which @code{-fstrict-flex-arrays} or @code{-fstrict-flex-arrays=} > +options or @code{strict_flex_array} attributes say they shouldn't be treated > +like flexible array member-like arrays. > > @opindex fsanitize=bounds-strict > @item -fsanitize=bounds-strict > This option enables strict instrumentation of array bounds. Most out of bounds > -accesses are detected, including flexible array members and flexible array > -member-like arrays. Initializers of variables with static storage are not > -instrumented. > +accesses are detected, including flexible array member-like arrays. > +Initializers of variables with static storage are not instrumented. > > @opindex fsanitize=alignment > @item -fsanitize=alignment > --- gcc/c-family/c-common.h.jj 2023-02-17 12:45:07.524646367 +0100 > +++ gcc/c-family/c-common.h 2023-02-27 15:11:16.737259968 +0100 > @@ -907,6 +907,7 @@ extern tree fold_for_warn (tree); > extern tree c_common_get_narrower (tree, int *); > extern bool get_attribute_operand (tree, unsigned HOST_WIDE_INT *); > extern void c_common_finalize_early_debug (void); > +extern unsigned int c_strict_flex_array_level_of (tree); > extern bool c_option_is_from_cpp_diagnostics (int); > > /* Used by convert_and_check; in front ends. */ > --- gcc/c-family/c-common.cc.jj 2023-01-19 09:58:50.875229150 +0100 > +++ gcc/c-family/c-common.cc 2023-02-27 15:10:56.232547326 +0100 > @@ -9501,4 +9501,33 @@ c_common_finalize_early_debug (void) > (*debug_hooks->early_global_decl) (cnode->decl); > } > > +/* Get the LEVEL of the strict_flex_array for the ARRAY_FIELD based on the > + values of attribute strict_flex_array and the flag_strict_flex_arrays. */ > +unsigned int > +c_strict_flex_array_level_of (tree array_field) > +{ > + gcc_assert (TREE_CODE (array_field) == FIELD_DECL); > + unsigned int strict_flex_array_level = flag_strict_flex_arrays; > + > + tree attr_strict_flex_array > + = lookup_attribute ("strict_flex_array", DECL_ATTRIBUTES (array_field)); > + /* If there is a strict_flex_array attribute attached to the field, > + override the flag_strict_flex_arrays. */ > + if (attr_strict_flex_array) > + { > + /* Get the value of the level first from the attribute. */ > + unsigned HOST_WIDE_INT attr_strict_flex_array_level = 0; > + gcc_assert (TREE_VALUE (attr_strict_flex_array) != NULL_TREE); > + attr_strict_flex_array = TREE_VALUE (attr_strict_flex_array); > + gcc_assert (TREE_VALUE (attr_strict_flex_array) != NULL_TREE); > + attr_strict_flex_array = TREE_VALUE (attr_strict_flex_array); > + gcc_assert (tree_fits_uhwi_p (attr_strict_flex_array)); > + attr_strict_flex_array_level = tree_to_uhwi (attr_strict_flex_array); > + > + /* The attribute has higher priority than flag_struct_flex_array. */ > + strict_flex_array_level = attr_strict_flex_array_level; > + } > + return strict_flex_array_level; > +} > + > #include "gt-c-family-c-common.h" > --- gcc/c-family/c-ubsan.cc.jj 2023-01-16 11:52:15.899736776 +0100 > +++ gcc/c-family/c-ubsan.cc 2023-02-28 08:15:57.579124095 +0100 > @@ -354,7 +354,7 @@ ubsan_instrument_return (location_t loc) > that gets expanded in the sanopt pass, and make an array dimension > of it. ARRAY is the array, *INDEX is an index to the array. > Return NULL_TREE if no instrumentation is emitted. > - IGNORE_OFF_BY_ONE is true if the ARRAY_REF is inside a ADDR_EXPR. */ > + IGNORE_OFF_BY_ONE is true if the ARRAY_REF is inside an ADDR_EXPR. */ > > tree > ubsan_instrument_bounds (location_t loc, tree array, tree *index, > @@ -363,13 +363,25 @@ ubsan_instrument_bounds (location_t loc, > tree type = TREE_TYPE (array); > tree domain = TYPE_DOMAIN (type); > > - if (domain == NULL_TREE || TYPE_MAX_VALUE (domain) == NULL_TREE) > + if (domain == NULL_TREE) > return NULL_TREE; > > tree bound = TYPE_MAX_VALUE (domain); > - if (ignore_off_by_one) > - bound = fold_build2 (PLUS_EXPR, TREE_TYPE (bound), bound, > - build_int_cst (TREE_TYPE (bound), 1)); > + if (!bound) > + { > + /* Handle C [0] arrays, which have TYPE_MAX_VALUE NULL, like > + C++ [0] arrays which have TYPE_MIN_VALUE 0 TYPE_MAX_VALUE -1. */ > + if (!c_dialect_cxx () > + && COMPLETE_TYPE_P (type) > + && integer_zerop (TYPE_SIZE (type))) > + bound = build_int_cst (TREE_TYPE (TYPE_MIN_VALUE (domain)), -1); > + else > + return NULL_TREE; > + } > + > + bound = fold_build2 (PLUS_EXPR, TREE_TYPE (bound), bound, > + build_int_cst (TREE_TYPE (bound), > + 1 + ignore_off_by_one)); > > /* Detect flexible array members and suchlike, unless > -fsanitize=bounds-strict. */ > @@ -392,6 +404,45 @@ ubsan_instrument_bounds (location_t loc, > if (next) > /* Not a last element. Instrument it. */ > break; > + if (TREE_CODE (TREE_TYPE (TREE_OPERAND (cref, 1))) == ARRAY_TYPE > + && !c_dialect_cxx ()) > + { > + unsigned l > + = c_strict_flex_array_level_of (TREE_OPERAND (cref, 1)); > + tree type2 = TREE_TYPE (TREE_OPERAND (cref, 1)); > + if (TYPE_DOMAIN (type2) != NULL_TREE) > + { > + tree max = TYPE_MAX_VALUE (TYPE_DOMAIN (type2)); > + if (max == NULL_TREE) > + { > + /* C [0] */ > + if (COMPLETE_TYPE_P (type2) > + && integer_zerop (TYPE_SIZE (type2)) > + && l == 3) > + next = TREE_OPERAND (cref, 1); > + } > + else if (TREE_CODE (max) == INTEGER_CST) > + { > + if (c_dialect_cxx () > + && integer_all_onesp (max)) > + { > + /* C++ [0] */ > + if (l == 3) > + next = TREE_OPERAND (cref, 1); > + } > + else if (integer_zerop (max)) > + { > + /* C/C++ [1] */ > + if (l >= 2) > + next = TREE_OPERAND (cref, 1); > + } > + else if (l >= 1) > + next = TREE_OPERAND (cref, 1); > + } > + } > + if (next) > + break; > + } > /* Ok, this is the last field of the structure/union. But the > aggregate containing the field must be the last field too, > recursively. */ > @@ -413,7 +464,7 @@ ubsan_instrument_bounds (location_t loc, > if (idx > && TREE_CODE (bound) == INTEGER_CST > && tree_int_cst_sgn (idx) >= 0 > - && tree_int_cst_le (idx, bound)) > + && tree_int_cst_lt (idx, bound)) > return NULL_TREE; > > *index = save_expr (*index); > --- gcc/c/c-decl.cc.jj 2023-02-18 12:38:30.000000000 +0100 > +++ gcc/c/c-decl.cc 2023-02-27 15:09:57.143375989 +0100 > @@ -9050,35 +9050,6 @@ finish_incomplete_vars (tree incomplete_ > } > } > > -/* Get the LEVEL of the strict_flex_array for the ARRAY_FIELD based on the > - values of attribute strict_flex_array and the flag_strict_flex_arrays. */ > -static unsigned int > -strict_flex_array_level_of (tree array_field) > -{ > - gcc_assert (TREE_CODE (array_field) == FIELD_DECL); > - unsigned int strict_flex_array_level = flag_strict_flex_arrays; > - > - tree attr_strict_flex_array > - = lookup_attribute ("strict_flex_array", DECL_ATTRIBUTES (array_field)); > - /* If there is a strict_flex_array attribute attached to the field, > - override the flag_strict_flex_arrays. */ > - if (attr_strict_flex_array) > - { > - /* Get the value of the level first from the attribute. */ > - unsigned HOST_WIDE_INT attr_strict_flex_array_level = 0; > - gcc_assert (TREE_VALUE (attr_strict_flex_array) != NULL_TREE); > - attr_strict_flex_array = TREE_VALUE (attr_strict_flex_array); > - gcc_assert (TREE_VALUE (attr_strict_flex_array) != NULL_TREE); > - attr_strict_flex_array = TREE_VALUE (attr_strict_flex_array); > - gcc_assert (tree_fits_uhwi_p (attr_strict_flex_array)); > - attr_strict_flex_array_level = tree_to_uhwi (attr_strict_flex_array); > - > - /* The attribute has higher priority than flag_struct_flex_array. */ > - strict_flex_array_level = attr_strict_flex_array_level; > - } > - return strict_flex_array_level; > -} > - > /* Determine whether the FIELD_DECL X is a flexible array member according to > the following info: > A. whether the FIELD_DECL X is the last field of the DECL_CONTEXT; > @@ -9105,7 +9076,7 @@ is_flexible_array_member_p (bool is_last > bool is_one_element_array = one_element_array_type_p (TREE_TYPE (x)); > bool is_flexible_array = flexible_array_member_type_p (TREE_TYPE (x)); > > - unsigned int strict_flex_array_level = strict_flex_array_level_of (x); > + unsigned int strict_flex_array_level = c_strict_flex_array_level_of (x); > > switch (strict_flex_array_level) > { > --- gcc/testsuite/gcc.dg/ubsan/bounds-4.c.jj 2023-02-27 17:08:46.193766320 +0100 > +++ gcc/testsuite/gcc.dg/ubsan/bounds-4.c 2023-02-27 17:21:40.489668882 +0100 > @@ -0,0 +1,79 @@ > +/* PR sanitizer/108894 */ > +/* { dg-do run } */ > +/* { dg-options "-fsanitize=bounds -fsanitize-recover=bounds" } */ > +/* { dg-output "index 15 out of bounds for type 'int \\\[15\\\]'\[^\n\r]*(\n|\r\n|\r)" } */ > +/* { dg-output "\[^\n\r]*index 0 out of bounds for type 'int \\\[\\\*\\\]'\[^\n\r]*(\n|\r\n|\r)" } */ > +/* { dg-output "\[^\n\r]*index 16 out of bounds for type 'int \\\[15\\\]'" } */ > + > +struct A { int a; int b[]; }; > +struct B { int a; int b[0]; }; > +struct C { int a; int b[1]; }; > +struct D { int a; int b[2]; }; > +struct E { int a; int b[42]; }; > +struct F { int a; int b[0]; int c[2]; }; > +struct G { int a; int b[15]; int c[2]; }; > + > +__attribute__((noipa)) int > +foo (struct A *a) > +{ > + return a->b[14]; > +} > + > +__attribute__((noipa)) int > +bar (struct B *a) > +{ > + return a->b[0]; > +} > + > +__attribute__((noipa)) int > +baz (struct C *a) > +{ > + return a->b[1]; > +} > + > +__attribute__((noipa)) int > +qux (struct D *a) > +{ > + return a->b[2]; > +} > + > +__attribute__((noipa)) int > +corge (struct E *a) > +{ > + return a->b[14]; > +} > + > +__attribute__((noipa)) int > +freddy (struct F *a) > +{ > + return a->b[0]; > +} > + > +__attribute__((noipa)) int > +garply (struct G *a) > +{ > + return a->b[15]; > +} > + > +__attribute__((noipa)) int > +waldo (struct G *a) > +{ > + return a->b[16]; > +} > + > +int > +main () > +{ > + union { struct A a; struct B b; struct C c; > + struct D d; struct E e; struct F f; } u; > + struct G g; > + u.e.a = 42; > + __builtin_memset (u.e.b, 0, sizeof (u.e.b)); > + __builtin_memset (&g, 0, sizeof (g)); > + int r = garply (&g); > + r += foo (&u.a) + bar (&u.b) + baz (&u.c); > + r += qux (&u.d) + corge (&u.e) + freddy (&u.f); > + r += waldo (&g); > + if (r != 0) > + __builtin_abort (); > +} > --- gcc/testsuite/gcc.dg/ubsan/bounds-4a.c.jj 2023-02-27 17:08:52.797671833 +0100 > +++ gcc/testsuite/gcc.dg/ubsan/bounds-4a.c 2023-02-27 17:25:08.463687314 +0100 > @@ -0,0 +1,8 @@ > +/* PR sanitizer/108894 */ > +/* { dg-do run } */ > +/* { dg-options "-fsanitize=bounds -fsanitize-recover=bounds -fstrict-flex-arrays=0" } */ > +/* { dg-output "index 15 out of bounds for type 'int \\\[15\\\]'\[^\n\r]*(\n|\r\n|\r)" } */ > +/* { dg-output "\[^\n\r]*index 0 out of bounds for type 'int \\\[\\\*\\\]'\[^\n\r]*(\n|\r\n|\r)" } */ > +/* { dg-output "\[^\n\r]*index 16 out of bounds for type 'int \\\[15\\\]'" } */ > + > +#include "bounds-4.c" > --- gcc/testsuite/gcc.dg/ubsan/bounds-4b.c.jj 2023-02-27 17:08:52.797671833 +0100 > +++ gcc/testsuite/gcc.dg/ubsan/bounds-4b.c 2023-02-27 17:29:57.042545420 +0100 > @@ -0,0 +1,9 @@ > +/* PR sanitizer/108894 */ > +/* { dg-do run } */ > +/* { dg-options "-fsanitize=bounds -fsanitize-recover=bounds -fstrict-flex-arrays=1" } */ > +/* { dg-output "index 15 out of bounds for type 'int \\\[15\\\]'\[^\n\r]*(\n|\r\n|\r)" } */ > +/* { dg-output "\[^\n\r]*index 2 out of bounds for type 'int \\\[2\\\]'\[^\n\r]*(\n|\r\n|\r)" } */ > +/* { dg-output "\[^\n\r]*index 0 out of bounds for type 'int \\\[\\\*\\\]'\[^\n\r]*(\n|\r\n|\r)" } */ > +/* { dg-output "\[^\n\r]*index 16 out of bounds for type 'int \\\[15\\\]'" } */ > + > +#include "bounds-4.c" > --- gcc/testsuite/gcc.dg/ubsan/bounds-4c.c.jj 2023-02-27 17:08:52.797671833 +0100 > +++ gcc/testsuite/gcc.dg/ubsan/bounds-4c.c 2023-02-27 17:34:29.094634537 +0100 > @@ -0,0 +1,10 @@ > +/* PR sanitizer/108894 */ > +/* { dg-do run } */ > +/* { dg-options "-fsanitize=bounds -fsanitize-recover=bounds -fstrict-flex-arrays=2" } */ > +/* { dg-output "index 15 out of bounds for type 'int \\\[15\\\]'\[^\n\r]*(\n|\r\n|\r)" } */ > +/* { dg-output "\[^\n\r]*index 1 out of bounds for type 'int \\\[1\\\]'\[^\n\r]*(\n|\r\n|\r)" } */ > +/* { dg-output "\[^\n\r]*index 2 out of bounds for type 'int \\\[2\\\]'\[^\n\r]*(\n|\r\n|\r)" } */ > +/* { dg-output "\[^\n\r]*index 0 out of bounds for type 'int \\\[\\\*\\\]'\[^\n\r]*(\n|\r\n|\r)" } */ > +/* { dg-output "\[^\n\r]*index 16 out of bounds for type 'int \\\[15\\\]'" } */ > + > +#include "bounds-4.c" > --- gcc/testsuite/gcc.dg/ubsan/bounds-4d.c.jj 2023-02-27 17:08:52.797671833 +0100 > +++ gcc/testsuite/gcc.dg/ubsan/bounds-4d.c 2023-02-27 17:35:46.556520992 +0100 > @@ -0,0 +1,11 @@ > +/* PR sanitizer/108894 */ > +/* { dg-do run } */ > +/* { dg-options "-fsanitize=bounds -fsanitize-recover=bounds -fstrict-flex-arrays=3" } */ > +/* { dg-output "index 15 out of bounds for type 'int \\\[15\\\]'\[^\n\r]*(\n|\r\n|\r)" } */ > +/* { dg-output "\[^\n\r]*index 0 out of bounds for type 'int \\\[\\\*\\\]'\[^\n\r]*(\n|\r\n|\r)" } */ > +/* { dg-output "\[^\n\r]*index 1 out of bounds for type 'int \\\[1\\\]'\[^\n\r]*(\n|\r\n|\r)" } */ > +/* { dg-output "\[^\n\r]*index 2 out of bounds for type 'int \\\[2\\\]'\[^\n\r]*(\n|\r\n|\r)" } */ > +/* { dg-output "\[^\n\r]*index 0 out of bounds for type 'int \\\[\\\*\\\]'\[^\n\r]*(\n|\r\n|\r)" } */ > +/* { dg-output "\[^\n\r]*index 16 out of bounds for type 'int \\\[15\\\]'" } */ > + > +#include "bounds-4.c" > --- gcc/testsuite/g++.dg/ubsan/bounds-1.C.jj 2023-02-27 17:37:03.076420982 +0100 > +++ gcc/testsuite/g++.dg/ubsan/bounds-1.C 2023-02-27 17:38:23.717261726 +0100 > @@ -0,0 +1,8 @@ > +// PR sanitizer/108894 > +// { dg-do run } > +// { dg-options "-fsanitize=bounds -fsanitize-recover=bounds" } > +// { dg-output "index 15 out of bounds for type 'int \\\[15\\\]'\[^\n\r]*(\n|\r\n|\r)" } > +// { dg-output "\[^\n\r]*index 0 out of bounds for type 'int \\\[\[0-9x]*\\\]'\[^\n\r]*(\n|\r\n|\r)" } > +// { dg-output "\[^\n\r]*index 16 out of bounds for type 'int \\\[15\\\]'" } > + > +#include "../../gcc.dg/ubsan/bounds-4.c" > > Jakub > > -- Richard Biener SUSE Software Solutions Germany GmbH, Frankenstrasse 146, 90461 Nuernberg, Germany; GF: Ivo Totev, Andrew Myers, Andrew McDonald, Boudien Moerman; HRB 36809 (AG Nuernberg)