From patchwork Tue Feb 28 08:26:50 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jakub Jelinek X-Patchwork-Id: 65724 Return-Path: X-Original-To: patchwork@sourceware.org Delivered-To: patchwork@sourceware.org Received: from server2.sourceware.org (localhost [IPv6:::1]) by sourceware.org (Postfix) with ESMTP id 6238B3858410 for ; Tue, 28 Feb 2023 08:27:51 +0000 (GMT) DKIM-Filter: OpenDKIM Filter v2.11.0 sourceware.org 6238B3858410 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gcc.gnu.org; s=default; t=1677572871; bh=d+02y4rSmJ1csdPw1OK2SGAOl0dPYK0QNXsyETyJlQQ=; h=Date:To:Cc:Subject:List-Id:List-Unsubscribe:List-Archive: List-Post:List-Help:List-Subscribe:From:Reply-To:From; b=GW/ZuLx/XZZWxcbvSw7uGorhy0+cbyy+izqX7Yw4ZycjpCUDkR6D5I/uPaQNtJA2T DdNcI44kgBWgwZncsAh4Owp8LGCdSzT03bgu1tifdIGkjuZ2jHdkE5q7ZDAUQT9Be0 UmiB6rArOAAUy+UJ3dJ3QmfyPUKdNb6QkGjOFdc8= X-Original-To: gcc-patches@gcc.gnu.org Delivered-To: gcc-patches@gcc.gnu.org Received: from us-smtp-delivery-124.mimecast.com (us-smtp-delivery-124.mimecast.com [170.10.129.124]) by sourceware.org (Postfix) with ESMTPS id 61B353858D3C for ; Tue, 28 Feb 2023 08:26:59 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.2 sourceware.org 61B353858D3C Received: from mimecast-mx02.redhat.com (mx3-rdu2.redhat.com [66.187.233.73]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id us-mta-609-g0awEM5xPFKZkhMnUHDlUA-1; Tue, 28 Feb 2023 03:26:54 -0500 X-MC-Unique: g0awEM5xPFKZkhMnUHDlUA-1 Received: from smtp.corp.redhat.com (int-mx07.intmail.prod.int.rdu2.redhat.com [10.11.54.7]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mimecast-mx02.redhat.com (Postfix) with ESMTPS id 83EA82810C00; Tue, 28 Feb 2023 08:26:54 +0000 (UTC) Received: from tucnak.zalov.cz (unknown [10.45.224.101]) by smtp.corp.redhat.com (Postfix) with ESMTPS id 2AC50140EBF6; Tue, 28 Feb 2023 08:26:54 +0000 (UTC) Received: from tucnak.zalov.cz (localhost [127.0.0.1]) by tucnak.zalov.cz (8.17.1/8.17.1) with ESMTPS id 31S8QpEu1108318 (version=TLSv1.3 cipher=TLS_AES_256_GCM_SHA384 bits=256 verify=NOT); Tue, 28 Feb 2023 09:26:52 +0100 Received: (from jakub@localhost) by tucnak.zalov.cz (8.17.1/8.17.1/Submit) id 31S8Qpvr1108317; Tue, 28 Feb 2023 09:26:51 +0100 Date: Tue, 28 Feb 2023 09:26:50 +0100 To: Richard Biener Cc: gcc-patches@gcc.gnu.org Subject: [PATCH] ubsan: Honor -fstrict-flex-arrays= in -fsanitize=bounds [PR108894] Message-ID: MIME-Version: 1.0 X-Scanned-By: MIMEDefang 3.1 on 10.11.54.7 X-Mimecast-Spam-Score: 0 X-Mimecast-Originator: redhat.com Content-Disposition: inline X-Spam-Status: No, score=-3.7 required=5.0 tests=BAYES_00, DKIMWL_WL_HIGH, DKIM_SIGNED, DKIM_VALID, DKIM_VALID_AU, DKIM_VALID_EF, RCVD_IN_DNSWL_NONE, RCVD_IN_MSPIKE_H2, SPF_HELO_NONE, SPF_NONE, 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 X-BeenThere: gcc-patches@gcc.gnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: Gcc-patches mailing list List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-Patchwork-Original-From: Jakub Jelinek via Gcc-patches From: Jakub Jelinek Reply-To: Jakub Jelinek Errors-To: gcc-patches-bounces+patchwork=sourceware.org@gcc.gnu.org Sender: "Gcc-patches" 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? 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. Jakub --- 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"