Skip to content

[static-analyzer-output] Flexible array member referenced in the middle of a struct (tracemalloc_traceback) #127635

@Snape3058

Description

@Snape3058

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:

  1. 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;
      |                                  ^~~~~~~~~~~~~~~
  1. 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.

Metadata

Metadata

Assignees

No one assigned

    Labels

    interpreter-core(Objects, Python, Grammar, and Parser dirs)type-bugAn unexpected behavior, bug, or error

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions