Array declared with no size or a zero size
ID |
objectivec.maintainability.flexible_array_member |
Severity |
info |
Remediation Complexity |
hard |
Remediation Risk |
medium |
Remediation Effort |
medium |
Resource |
Memory Layout |
Language |
Objective-C |
Description
Reports an array declared with empty brackets or a zero length - uint8_t payload[];, char body[0]; - which as the trailing member of a struct is a C99 flexible array member. An extern declaration, whose size lives in another translation unit, is not reported.
Rationale
A flexible array member makes the struct’s size a lie. sizeof counts everything except the trailing data, so any instance created on the stack, copied by assignment, compared with memcmp, or stored by value in a collection silently drops the payload, and only a deliberate malloc(sizeof(struct) + n) produces a usable one. In Objective-C code that wraps the struct - handing it to NSData, NSValue or an archiver - the framework has only sizeof to go on, so the payload disappears at exactly the boundary where a reader assumes the whole object travelled. The member must also be last, and nothing in the declaration enforces that.
The following code illustrates the pattern detected by this rule:
struct XYPacket {
uint32_t length;
uint16_t type;
// FLAGGED: Array declared with no size or a zero size
uint8_t payload[];
};
Remediation
Hold the variable-length part in an NSData or NSMutableData alongside a fixed-size header struct, so the length travels with the bytes and reference counting owns them. Where the struct has to keep its wire layout, replace the flexible member with an explicit length field plus a pointer, and confirm at every allocation site that the extra room is accounted for.