can: Replace zero-length array with flexible-array
Subsystems (2)
PATCH 1/1 can: 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")
--- include/linux/can/skb.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
include/linux/can/skb.h +1 -1
@@ -34,7 +34,7 @@struct can_skb_priv {int ifindex;int skbcnt; -struct can_frame cf[0 ]; +struct can_frame cf[]; };static inline struct can_skb_priv *can_skb_prv (struct sk_buff *skb)
Quoted 46 lines · Gustavo A. R. Silva
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] commit76497732932f("cxgb3/l2t: Fix undefined behaviour")Signed-off-by Gustavo A. R. Silva <[email protected]>--- include/linux/can/skb.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)include/linux/can/skb.h +0
-0
include/linux/can/skb.h line 40
Quoted 8 lines
include/linux/can/skb.h +1
-1@@ -34,7 +34,7 @@struct can_skb_priv {int ifindex;int skbcnt; -struct can_frame cf[0 ]; +struct can_frame cf[]; };static inline struct can_skb_priv *can_skb_prv (struct sk_buff *skb)
@Gustavo: Just to be sure:
From the referenced URLs I got the information that the sizeof() operator causes problems when applied to e.g. cf[0].
We don't have this case in our code - but one question remains to me:
We are using the above construct to ensure the padding between the two 'int' values and the struct can_frame which enforces a 64 bit alignment.
This intention is not affected by the patch, right?
Best,
Oliver
Hi Oliver,
Sorry for the late reply. I totally lost track of this thread. :/ Please, see my comments below...
Quoted 61 lines · Oliver Hartkopp
Quoted 45 lines · Gustavo A. R. Silva
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] commit76497732932f("cxgb3/l2t: Fix undefined behaviour")Signed-off-by Gustavo A. R. Silva <[email protected]>---
include/linux/can/skb.h| 2 +-1 file changed, 1 insertion(+), 1 deletion(-)include/linux/can/skb.h +0
-0include/linux/can/skb.h line 40
Quoted 8 lines
include/linux/can/skb.h +1
-1@@ -34,7 +34,7 @@ struct can_skb_priv { int ifindex; int skbcnt; - struct can_frame cf[0]; + struct can_frame cf[]; }; static inline struct can_skb_priv *can_skb_prv(struct sk_buff *skb)Acked-by Oliver Hartkopp <[email protected]>@Gustavo: Just to be sure:
Quoted 8 lines
From the referenced URLs I got the information that the
sizeof()operator causes problems when applied to e.g. cf[0].We don't have this case in our code - but one question remains to me:
We are using the above construct to ensure the padding between the two 'int' values and the struct
can_framewhich enforces a 64 bit alignment.This intention is not affected by the patch, right?
pahole shows exactly the same output either if cf is a zero-length array or a flexible-array member:
$ pahole -C 'can_skb_priv' drivers/net/can/dev.o
struct can_skb_priv {
int ifindex; /* 0 4 */
int skbcnt; /* 4 4 */
struct can_frame cf[] __attribute__((__aligned__(8))); /* 8 0 */
/* size: 8, cachelines: 1, members: 3 */
/* forced alignments: 1 */
/* last cacheline: 8 bytes */
} __attribute__((__aligned__(8)));So, it seems everything should fine. :)
Thanks
--
Gustavo
Oliver Hartkopp
maintainerHi Gustavo,
Quoted 1 line · Gustavo A. R. Silva
Sorry for the late reply. I totally lost track of this thread. :/
NP. At least your workflow seems to work :o)
Quoted 15 lines
pahole shows exactly the same output either if cf is a zero-length array or a flexible-array member:
$ pahole -C 'can_skb_priv' drivers/net/can/dev.ostruct can_skb_priv { int ifindex; /* 0 4 */ int skbcnt; /* 4 4 */ struct can_frame cf[] __attribute__((__aligned__(8))); /* 8 0 */ /* size: 8, cachelines: 1, members: 3 */ /* forced alignments: 1 */ /* last cacheline: 8 bytes */ } __attribute__((__aligned__(8)));
Quoted 1 line
So, it seems everything should fine. :)
Great! Thanks for the info - and how I could have checked it on my own, too.
Best,
Oliver
Quoted 3 lines · Oliver Hartkopp
Great! Thanks for the info - and how I could have checked it on my own, too.
No problem. :)
Thanks
--
Gustavo