Skip to content

Commit

Permalink
[ubsan] Support varlen arrays at end of struct as [1] or []
Browse files Browse the repository at this point in the history
The --enable-ubsan configure feature complains when we index variable
length arrays at the end of some structs because the arrays size is
defined to be 1. Newer C compilers support declaring these as
variable-sized using [] in the struct member type definition, which also
quiets the UBSAN complaint. Test for this support in configure and use
it if it is supported by the compiler.

Signed-off-by: Coleman Kane <ckane@colemankane.org>
  • Loading branch information
ckane committed Aug 17, 2023
1 parent cae502c commit 095a435
Show file tree
Hide file tree
Showing 6 changed files with 39 additions and 7 deletions.
27 changes: 27 additions & 0 deletions config/zfs-build.m4
Original file line number Diff line number Diff line change
Expand Up @@ -231,6 +231,7 @@ AC_DEFUN([ZFS_AC_CONFIG_ALWAYS], [
ZFS_AC_CONFIG_ALWAYS_CPPCHECK
ZFS_AC_CONFIG_ALWAYS_SHELLCHECK
ZFS_AC_CONFIG_ALWAYS_PARALLEL
ZFS_AC_CONFIG_ALWAYS_CC_VARSIZE_ARRAY_IN_STRUCT
])

AC_DEFUN([ZFS_AC_CONFIG], [
Expand Down Expand Up @@ -630,3 +631,29 @@ AC_DEFUN([ZFS_AC_PACKAGE], [
ZFS_AC_ALIEN
])
])

dnl #
dnl # Test whether C compiler supports variable-length array at the
dnl # end of a struct definition, and if it needs a constant or not
dnl # declaring a size
dnl #
AC_DEFUN([ZFS_AC_CONFIG_ALWAYS_CC_VARSIZE_ARRAY_IN_STRUCT], [
AC_MSG_CHECKING(
[if C compiler handles empty-index var-length array members])
AC_COMPILE_IFELSE([AC_LANG_SOURCE([
struct s {
int a;
int v[];
};
struct s test_array __attribute__((unused));
])], [
AC_MSG_RESULT([yes])
AC_DEFINE([VARLEN_ARRAY_IDX], [],
[Index to use for variable-length array struct members])
], [
AC_MSG_RESULT([no])
AC_DEFINE([VARLEN_ARRAY_IDX], 1,
[Index to use for variable-length array struct members])
])
])
3 changes: 2 additions & 1 deletion include/os/linux/spl/sys/kmem_cache.h
Original file line number Diff line number Diff line change
Expand Up @@ -108,7 +108,8 @@ typedef struct spl_kmem_magazine {
uint32_t skm_refill; /* Batch refill size */
struct spl_kmem_cache *skm_cache; /* Owned by cache */
unsigned int skm_cpu; /* Owned by cpu */
void *skm_objs[0]; /* Object pointers */
/* Object pointers */
void *skm_objs[VARLEN_ARRAY_IDX];
} spl_kmem_magazine_t;

typedef struct spl_kmem_obj {
Expand Down
7 changes: 5 additions & 2 deletions include/sys/sa_impl.h
Original file line number Diff line number Diff line change
Expand Up @@ -177,8 +177,11 @@ typedef struct sa_hdr_phys {
*
*/
uint16_t sa_layout_info;
uint16_t sa_lengths[1]; /* optional sizes for variable length attrs */
/* ... Data follows the lengths. */
uint16_t sa_lengths[VARLEN_ARRAY_IDX];
/*
* optional sizes for variable length attrs
* ... Data follows the lengths.
*/
} sa_hdr_phys_t;

#define SA_HDR_LAYOUT_NUM(hdr) BF32_GET(hdr->sa_layout_info, 0, 10)
Expand Down
5 changes: 3 additions & 2 deletions include/sys/vdev_raidz_impl.h
Original file line number Diff line number Diff line change
Expand Up @@ -130,7 +130,8 @@ typedef struct raidz_row {
uint64_t rr_offset; /* Logical offset for *_io_verify() */
uint64_t rr_size; /* Physical size for *_io_verify() */
#endif
raidz_col_t rr_col[0]; /* Flexible array of I/O columns */
/* Flexible array of I/O columns */
raidz_col_t rr_col[VARLEN_ARRAY_IDX];
} raidz_row_t;

typedef struct raidz_map {
Expand All @@ -139,7 +140,7 @@ typedef struct raidz_map {
int rm_nskip; /* RAIDZ sectors skipped for padding */
int rm_skipstart; /* Column index of padding start */
const raidz_impl_ops_t *rm_ops; /* RAIDZ math operations */
raidz_row_t *rm_row[0]; /* flexible array of rows */
raidz_row_t *rm_row[VARLEN_ARRAY_IDX]; /* flexible array of rows */
} raidz_map_t;


Expand Down
2 changes: 1 addition & 1 deletion include/sys/zap_impl.h
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,7 @@ typedef struct mzap_phys {
uint64_t mz_salt;
uint64_t mz_normflags;
uint64_t mz_pad[5];
mzap_ent_phys_t mz_chunk[1];
mzap_ent_phys_t mz_chunk[VARLEN_ARRAY_IDX];
/* actually variable size depending on block size */
} mzap_phys_t;

Expand Down
2 changes: 1 addition & 1 deletion include/sys/zap_leaf.h
Original file line number Diff line number Diff line change
Expand Up @@ -132,7 +132,7 @@ typedef struct zap_leaf_phys {
* with the ZAP_LEAF_CHUNK() macro.
*/

uint16_t l_hash[1];
uint16_t l_hash[VARLEN_ARRAY_IDX];
} zap_leaf_phys_t;

typedef union zap_leaf_chunk {
Expand Down

0 comments on commit 095a435

Please sign in to comment.