-
Notifications
You must be signed in to change notification settings - Fork 8.2k
flex array: Replace 0 length arrays #95134
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
| union { | ||
| uint8_t resv[0]; | ||
| } __packed; | ||
| FLEXIBLE_ARRAY_DECLARE(uint8_t, resv); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I have concern (not verified) that __packed has been removed by the introduction of FLEXIBLE_ARRAY_DECLARE. Is this truly equivalent?
I see prior PRs have already change some in subsys/bluetooth/controller/ll_sw/pdu.h file.
Can we have a __packed variant of this "workaround" define, like FLEXIBLE_ARRAY_DECLARE_PACKED?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Out of curiosity, did __packed for an array of size 0 really do anything?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
And even if it wasn't of size 0, since the elements are byte aligned, I don't think __packed would do anything at all.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
__packed struct or union when nested need __packed individually every time; besides themselves being packed, the parent struct or union which has __packed still need to include them without which the members are machine word aligned/sized (please run a sample on Cortex-M0 nRF51 and you will hit hardfaults based on how linking has been unlucky... i.e. increasing/decreasing buffer counts will misalign these structs).
This file is not the best example, as the union has only one zero length byte array.
But here :
zephyr/subsys/bluetooth/controller/ll_sw/nordic/lll/pdu_vendor.h
Lines 17 to 25 in e028ecf
| struct pdu_data_vnd_octet3 { | |
| union { | |
| uint8_t resv[OCTET3_LEN]; /* nRF specific octet3 required for NRF_CCM use */ | |
| #if !defined(CONFIG_BT_CTLR_DATA_LENGTH_CLEAR) | |
| struct pdu_cte_info cte_info; /* BT 5.1 Core spec. CTEInfo storage */ | |
| #endif /* !CONFIG_BT_CTLR_DATA_LENGTH_CLEAR */ | |
| } __packed; | |
| } __packed; |
The union needs __packed so that it take 1 byte and not 4 bytes in size.
It is best to have a FLEXIBLE_ARRAY_DECLARE_PACKED for code that had __packed for the union inside other __packed union/structs... and also where FLEXIBLE_ARRAY_DECLARE added new union/struct into __packed structs/unions. Hence to also correct the other PR that made changes to as here: 1a56b90
There is also zero length array alignment requirements for nRF51: 701d524
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think this example is wrong. With/without packed you will get 4 bytes if CONFIG_BT_CTLR_DATA_LENGTH_CLEAR is not defined. And since this union is the only element of the structure pdu_data_vnd_octet3 that is packed you will get 1 byte size when CONFIG_BT_CTLR_DATA_LENGTH_CLEAR is defined.
If you noticed, I have just changed for this specific use case where the union.
I am wondering if I am missing something here though. Did you get any memory alignment issue ? Printing the struct sizes I get exactly the same thing and the alignment should be correct.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ok... I did a quick diff of .lst file of a sample for BBC microbit board (adding CONFIG_OUTPUT_DISASSEMBLY=y), with and without 56e2b01, and I see no difference. I am ok for now.
| union { | ||
| uint8_t resv[0]; | ||
| } __packed; | ||
| FLEXIBLE_ARRAY_DECLARE(uint8_t, resv); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
__packed struct or union when nested need __packed individually every time; besides themselves being packed, the parent struct or union which has __packed still need to include them without which the members are machine word aligned/sized (please run a sample on Cortex-M0 nRF51 and you will hit hardfaults based on how linking has been unlucky... i.e. increasing/decreasing buffer counts will misalign these structs).
This file is not the best example, as the union has only one zero length byte array.
But here :
zephyr/subsys/bluetooth/controller/ll_sw/nordic/lll/pdu_vendor.h
Lines 17 to 25 in e028ecf
| struct pdu_data_vnd_octet3 { | |
| union { | |
| uint8_t resv[OCTET3_LEN]; /* nRF specific octet3 required for NRF_CCM use */ | |
| #if !defined(CONFIG_BT_CTLR_DATA_LENGTH_CLEAR) | |
| struct pdu_cte_info cte_info; /* BT 5.1 Core spec. CTEInfo storage */ | |
| #endif /* !CONFIG_BT_CTLR_DATA_LENGTH_CLEAR */ | |
| } __packed; | |
| } __packed; |
The union needs __packed so that it take 1 byte and not 4 bytes in size.
It is best to have a FLEXIBLE_ARRAY_DECLARE_PACKED for code that had __packed for the union inside other __packed union/structs... and also where FLEXIBLE_ARRAY_DECLARE added new union/struct into __packed structs/unions. Hence to also correct the other PR that made changes to as here: 1a56b90
There is also zero length array alignment requirements for nRF51: 701d524
| #define BTP_OTS_READ_SUPPORTED_COMMANDS 0x01 | ||
| struct btp_ots_read_supported_commands_rp { | ||
| uint8_t data[0]; | ||
| FLEXIBLE_ARRAY_DECLARE(uint8_t, data); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Did you use a script to do data[0] changes?
Below name[0] is not using FLEXIBLE_ARRAY_DECLARE :-)
Please revert to using uint8_t data[]; instead.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
IIRC C++ does not allow empty structs (i.e. struct with only uint8_t data[];, so that's why we need to use FLEXIBLE_ARRAY_DECLARE if a struct only contains a flexible array
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
IIRC C++ does not allow empty structs
@Thalley this is not documented in FLEXIBLE_ARRAY_DECLARE as a workaround for.
* Since C99, flexible arrays are part of the C standard, but for historical
* reasons many places still use an older GNU extension that is declare
* zero length arrays.
*
* Although zero length arrays are flexible arrays, we can't blindly
* replace [0] with [] because of some syntax limitations. This macro
* workaround these limitations.
@ceolin I am not happy polluting the source with workarounds (more of Zephyr macro magics to make code convoluted, and "steep learning curve" when it comes to Zephyr code base), as clearly the documentation conveys that the macro is a workaround.
Well, for many reasons, redesigns/refactoring increasing CPU usages, compiler instruction re-ordering, bugs included, nRF51 support is broken over the times now (#74345).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@cvinayak I see your point, unfortunately I don't see a better way to do it, at least not while we are supporting C++. Also, this macro is needed when using flexible arrays in unions.
There is always a risk of introducing issues for sure, but there are many benefits as well. Doing these changes I found some places where flexible arrays were not in the end of the structure and more importantly it will allow us to enable new compilation options to check some type out-of-bound accesses that is the majority cause of security issues.
|
Convinced for now, that the changes (did not check this particular PR changes, but only with 56e2b01) do not show any difference in generated code for a bbc microbit board sample with the Bluetooth Controller. @thedjnK Cool experiment as part of this PR: #95191 My request changes can be dismissed (when conflicts are resolved in this PR). |
0 length array is a GNU extension. Use proper C99 flexible array. Signed-off-by: Flavio Ceolin <[email protected]>
0 length array is a GNU extension. Use proper C99 flexible array. Signed-off-by: Flavio Ceolin <[email protected]>
0 length array is a GNU extension. Use proper C99 flexible array. Signed-off-by: Flavio Ceolin <[email protected]>
0 length array is a GNU extension. Use proper C99 flexible array. Signed-off-by: Flavio Ceolin <[email protected]>
0 length array is a GNU extension. Use proper C99 flexible array. Signed-off-by: Flavio Ceolin <[email protected]>
0 length array is a GNU extension. Use proper C99 flexible array. Signed-off-by: Flavio Ceolin <[email protected]>
0 length array is a GNU extension. Use proper C99 flexible array. Signed-off-by: Flavio Ceolin <[email protected]>
e028ecf to
0df79cf
Compare
|



Replace 0 length arrays declaration with proper C99 flexible arrays.