Add compiler option -fstrict-flex-arrays=1

Currently, every trailing array regardless of its declared bound is
exempt from -Warray-bounds, __builtin_object_size/_FORTIFY_SOURCE, and
-fsanitize=bounds.  -fstrict-flex-arrays=1 says that only arrays
declared with bounds [], [0], or [1] can be flexible array
members (which are then mostly exempt from array bounds checking); for
all other arrays, the declared size is taken as is for bounds
checking, which is what we want.

This applies to a large number of structs in the tree, for example

- struct pg_hmac_ctx
- fe_scram_state
- struct XidCache
- struct RelPathStr
...

which can now be checked properly.

Ideally, we'd want to use the maximum level -fstrict-flex-arrays=3,
which would also disqualify flexible array members declared with
bounds [0] or [1].  But we do need the [1] variant in a few cases
because standard C does not allow flexible array members as the only
element in a struct.  Affected are:

- struct RevmapContents
- struct ReplicationSlotCtlData
- union pgresult_data

Also:

- struct sqlda_struct (bound by external API specification)

Turning on -fstrict-flex-arrays=3 for these would conjure undefined
behavior.

One piece of code needs to be adjusted: JsonValueList has an array
declared as [2] (via BASE_JVL_ITEMS) but addresses it as a
flexible-length array in some circumstances.  Change this to an
anonymous union with one branch having the original size [2], to keep
local variables sized the same as before, and one branch of size [1],
which effectively makes this a flexible-array member under
-fstrict-flex-arrays=1.  We can't make it a fully flexible-array
member [], because JsonValueList is also used for a field in the
middle of JsonTablePlanState, which is not allowed in standard C.

There is one structure with a genuine trailing one-element array:

- WordEntryPosVector1

By staying with -fstrict-flex-arrays=1 we would miss out on bounds
checking on that one.

Also provide an attribute macro pg_attribute_strict_flex_array that
allows overriding the strict flex array level for a particular struct.
Use that to annotate WordEntryPosVector1.  Note that clang supports
the command-line option but not the attribute, so we can only use this
to optionally raise the level for some structs, but we can't do the
opposite of having a higher global level and lower it for some
exceptions.

Reviewed-by: Tristan Partin <[email protected]>
Reviewed-by: Greg Burd <[email protected]>
Discussion: 
https://www.postgresql.org/message-id/flat/c79da9e1-965d-4530-9e3e-84b8bde134ec%40eisentraut.org

Branch
------
master

Details
-------
https://git.postgresql.org/pg/commitdiff/a625e153b7d2f0e1c81955d13f2fc8de472bc082

Modified Files
--------------
configure                             | 92 +++++++++++++++++++++++++++++++++++
configure.ac                          |  3 ++
meson.build                           |  2 +
src/backend/utils/adt/jsonpath_exec.c | 16 +++++-
src/include/c.h                       | 19 ++++++++
src/include/tsearch/ts_type.h         |  2 +-
src/tools/pgindent/pgindent           |  1 +
7 files changed, 133 insertions(+), 2 deletions(-)

Reply via email to