]> git.ipfire.org Git - thirdparty/gcc.git/commit
ubsan: Honor -fstrict-flex-arrays= in -fsanitize=bounds [PR108894]
authorJakub Jelinek <jakub@redhat.com>
Tue, 28 Feb 2023 10:38:46 +0000 (11:38 +0100)
committerJakub Jelinek <jakub@redhat.com>
Tue, 28 Feb 2023 10:38:46 +0000 (11:38 +0100)
commitc7728805a7107444683290cd629d13f089130a0d
treeec08b75320097bdd5f0ce0625918d71d68337420
parent41c02eeb309b3be58683be8f9961f3894b6fb4c7
ubsan: Honor -fstrict-flex-arrays= in -fsanitize=bounds [PR108894]

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.

2023-02-28  Jakub Jelinek  <jakub@redhat.com>

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.
13 files changed:
gcc/c-family/c-common.cc
gcc/c-family/c-common.h
gcc/c-family/c-ubsan.cc
gcc/c/c-decl.cc
gcc/doc/invoke.texi
gcc/gimple-fold.cc
gcc/testsuite/g++.dg/ubsan/bounds-1.C [new file with mode: 0644]
gcc/testsuite/gcc.dg/ubsan/bounds-4.c [new file with mode: 0644]
gcc/testsuite/gcc.dg/ubsan/bounds-4a.c [new file with mode: 0644]
gcc/testsuite/gcc.dg/ubsan/bounds-4b.c [new file with mode: 0644]
gcc/testsuite/gcc.dg/ubsan/bounds-4c.c [new file with mode: 0644]
gcc/testsuite/gcc.dg/ubsan/bounds-4d.c [new file with mode: 0644]
gcc/ubsan.cc