Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

dm: replace zero-length array with flexible-array

The current codebase makes use of the zero-length array language
extension to the C90 standard, but the preferred mechanism to declare
variable-length types such as these ones is a flexible array member[1][2],
introduced in C99:

struct foo {
int stuff;
struct boo array[];
};

By making use of the mechanism above, we will get a compiler warning
in case the flexible array does not occur last in the structure, which
will help us prevent some kind of undefined behavior bugs from being
inadvertently introduced[3] to the codebase from now on.

Also, notice that, dynamic memory allocations won't be affected by
this change:

"Flexible array members have incomplete type, and so the sizeof operator
may not be applied. As a quirk of the original implementation of
zero-length arrays, sizeof evaluates to zero."[1]

sizeof(flexible-array-member) triggers a warning because flexible array
members have incomplete type[1]. There are some instances of code in
which the sizeof operator is being incorrectly/erroneously applied to
zero-length arrays and the result is zero. Such instances may be hiding
some bugs. So, this work (flexible-array member conversions) will also
help to get completely rid of those sorts of issues.

This issue was found with the help of Coccinelle.

[1] https://gcc.gnu.org/onlinedocs/gcc/Zero-Length.html
[2] https://github.com/KSPP/linux/issues/21
[3] commit 76497732932f ("cxgb3/l2t: Fix undefined behaviour")

Signed-off-by: Gustavo A. R. Silva <gustavoars@kernel.org>
Signed-off-by: Mike Snitzer <snitzer@redhat.com>

authored by

Gustavo A. R. Silva and committed by
Mike Snitzer
b18ae8dd bd5c4031

+9 -9
+1 -1
drivers/md/dm-crypt.c
··· 214 214 struct mutex bio_alloc_lock; 215 215 216 216 u8 *authenc_key; /* space for keys in authenc() format (if used) */ 217 - u8 key[0]; 217 + u8 key[]; 218 218 }; 219 219 220 220 #define MIN_IOS 64
+1 -1
drivers/md/dm-integrity.c
··· 92 92 } s; 93 93 __u64 sector; 94 94 } u; 95 - commit_id_t last_bytes[0]; 95 + commit_id_t last_bytes[]; 96 96 /* __u8 tag[0]; */ 97 97 }; 98 98
+1 -1
drivers/md/dm-log-writes.c
··· 127 127 char *data; 128 128 u32 datalen; 129 129 struct list_head list; 130 - struct bio_vec vecs[0]; 130 + struct bio_vec vecs[]; 131 131 }; 132 132 133 133 struct per_bio_data {
+1 -1
drivers/md/dm-raid.c
··· 254 254 int mode; 255 255 } journal_dev; 256 256 257 - struct raid_dev dev[0]; 257 + struct raid_dev dev[]; 258 258 }; 259 259 260 260 static void rs_config_backup(struct raid_set *rs, struct rs_layout *l)
+1 -1
drivers/md/dm-raid1.c
··· 83 83 struct work_struct trigger_event; 84 84 85 85 unsigned nr_mirrors; 86 - struct mirror mirror[0]; 86 + struct mirror mirror[]; 87 87 }; 88 88 89 89 DECLARE_DM_KCOPYD_THROTTLE_WITH_MODULE_PARM(raid1_resync_throttle,
+1 -1
drivers/md/dm-stats.c
··· 56 56 size_t percpu_alloc_size; 57 57 size_t histogram_alloc_size; 58 58 struct dm_stat_percpu *stat_percpu[NR_CPUS]; 59 - struct dm_stat_shared stat_shared[0]; 59 + struct dm_stat_shared stat_shared[]; 60 60 }; 61 61 62 62 #define STAT_PRECISE_TIMESTAMPS 1
+1 -1
drivers/md/dm-stripe.c
··· 41 41 /* Work struct used for triggering events*/ 42 42 struct work_struct trigger_event; 43 43 44 - struct stripe stripe[0]; 44 + struct stripe stripe[]; 45 45 }; 46 46 47 47 /*
+1 -1
drivers/md/dm-switch.c
··· 53 53 /* 54 54 * Array of dm devices to switch between. 55 55 */ 56 - struct switch_path path_list[0]; 56 + struct switch_path path_list[]; 57 57 }; 58 58 59 59 static struct switch_ctx *alloc_switch_ctx(struct dm_target *ti, unsigned nr_paths,
+1 -1
drivers/md/persistent-data/dm-btree-internal.h
··· 38 38 39 39 struct btree_node { 40 40 struct node_header header; 41 - __le64 keys[0]; 41 + __le64 keys[]; 42 42 } __packed; 43 43 44 44