struct tracemalloc_traceback is a flexible array struct, which is declared here:
|
struct tracemalloc_traceback { |
|
Py_uhash_t hash; |
|
/* Number of frames stored */ |
|
uint16_t nframe; |
|
/* Total number of frames the traceback had */ |
|
uint16_t total_nframe; |
|
struct tracemalloc_frame frames[1]; |
|
}; |
and confirmed to be used as a flexible array: (allocation size computation)
|
typedef struct tracemalloc_frame frame_t; |
|
typedef struct tracemalloc_traceback traceback_t; |
|
|
|
#define TRACEBACK_SIZE(NFRAME) \ |
|
(sizeof(traceback_t) + sizeof(frame_t) * (NFRAME - 1)) |
Using this type in the middle of a struct may lead to unexpected behavior if the flexible array field is used accidentally somewhere else.
|
struct tracemalloc_traceback empty_traceback; |
|
|
|
Py_tss_t reentrant_key; |
Suggested fix:
- In the current version, the flexible array field is declared with length
[1]. If it is not on purpose, it can be changed to length unspecified [] to enable the GCC and Clang syntax checker for the flexible array usages.
The expected GCC warning after modifying [1] to []:
In file included from ./Include/internal/pycore_runtime.h:26,
from ./Include/internal/pycore_emscripten_trampoline.h:4,
from ./Include/internal/pycore_object.h:13,
from Python/tracemalloc.c:5:
./Include/internal/pycore_tracemalloc.h:104:34: warning: structure containing a flexible array member is not at the end of another structure [-Wflex-array-member-not-at-end]
104 | struct tracemalloc_traceback empty_traceback;
| ^~~~~~~~~~~~~~~
- As this flexible array field is being used currently, we can define the header and flexible array separately in different structs.
(the solution proposed by Gustavo A. R. Silva gustavoars@kernel.org and currently being used in Linux kernel: https://lpc.events/event/18/contributions/1722/attachments/1591/3303/Wfamnae_lpceu2024.pdf, page 44)
#define define_struct_group(NAME, MEMBERS...) \
union { \
struct { MEMBERS }; \
struct NAME { MEMBERS }; \
}
struct tracemalloc_traceback_FA {
define_struct_group(tracemalloc_traceback,
Py_uhash_t hash;
/* Number of frames stored */
uint16_t nframe;
/* Total number of frames the traceback had */
uint16_t total_nframe;
);
struct tracemalloc_frame frames[1];
};
For the usages of only the header struct, they can still use the name tracemalloc_traceback to reference the struct, which means no modification is needed.
Whereas for other usages that need to reference the flexible array field, they need to use tracemalloc_traceback_FA instead.
Some changes need to be carried out for the later cases.
Linked PRs
struct
tracemalloc_tracebackis a flexible array struct, which is declared here:cpython/Include/internal/pycore_tracemalloc.h
Lines 57 to 64 in fcbe6ec
and confirmed to be used as a flexible array: (allocation size computation)
cpython/Python/tracemalloc.c
Lines 49 to 53 in fcbe6ec
Using this type in the middle of a struct may lead to unexpected behavior if the flexible array field is used accidentally somewhere else.
cpython/Include/internal/pycore_tracemalloc.h
Lines 104 to 106 in fcbe6ec
Suggested fix:
[1]. If it is not on purpose, it can be changed to length unspecified[]to enable the GCC and Clang syntax checker for the flexible array usages.The expected GCC warning after modifying
[1]to[]:(the solution proposed by Gustavo A. R. Silva gustavoars@kernel.org and currently being used in Linux kernel: https://lpc.events/event/18/contributions/1722/attachments/1591/3303/Wfamnae_lpceu2024.pdf, page 44)
For the usages of only the header struct, they can still use the name
tracemalloc_tracebackto reference the struct, which means no modification is needed.Whereas for other usages that need to reference the flexible array field, they need to use
tracemalloc_traceback_FAinstead.Some changes need to be carried out for the later cases.
Linked PRs