-
-
Notifications
You must be signed in to change notification settings - Fork 33.2k
Description
struct tracemalloc_traceback
is a flexible array struct, which is declared here:
cpython/Include/internal/pycore_tracemalloc.h
Lines 57 to 64 in fcbe6ec
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)
Lines 49 to 53 in fcbe6ec
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.
cpython/Include/internal/pycore_tracemalloc.h
Lines 104 to 106 in fcbe6ec
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 [email protected] 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.