Heap block allocated or released with malloc/calloc/realloc/free
ID |
objectivec.correctness.avoid_dynamic_memory |
Severity |
info |
Remediation Complexity |
hard |
Remediation Risk |
high |
Remediation Effort |
high |
Resource |
Resource Management |
Language |
Objective-C |
Description
Reports a call to the C heap allocator - malloc, calloc, realloc or free - in Objective-C code. Object allocation through alloc, new or a Foundation container is not reported.
Rationale
A raw heap block has no owner. Nothing releases it when the enclosing scope exits, nothing zeroes the pointer once it is freed, and ARC - which does exactly that for every object - cannot see it, so the balance between allocation and release is maintained by hand on every path including the error ones. That is the classic source of leaks, double frees and reads through a dangling pointer, and it is a defect class the compiler and the static analyser can only partly rule out. The allocation itself also has unbounded, data-dependent latency and can fail at a point most testing never exercises, which is why the embedded and safety-critical profiles forbid it outright once initialisation is over.
The following code illustrates the pattern detected by this rule:
@implementation SampleBuffer
- (void)fillFromSensor:(NSUInteger)count {
// FLAGGED: Heap block allocated or released with malloc/calloc/realloc/free
int16_t *samples = malloc(count * sizeof(int16_t));
// FLAGGED: Heap block allocated or released with malloc/calloc/realloc/free
int16_t *zeroed = calloc(count, sizeof(int16_t));
// FLAGGED: Heap block allocated or released with malloc/calloc/realloc/free
samples = realloc(samples, (count + 1) * sizeof(int16_t));
[self readInto:samples length:count];
// FLAGGED: Heap block allocated or released with malloc/calloc/realloc/free
free(zeroed);
// FLAGGED: Heap block allocated or released with malloc/calloc/realloc/free
free(samples);
}
@end
Remediation
Use an NSMutableData (or an NSData for read-only bytes) when a byte buffer is needed - it is reference counted, ARC releases it, and mutableBytes still hands out a raw pointer for the C API that needs one. Where the size is a compile-time constant, a stack array is simpler again. Keep malloc/free for a genuine C interop boundary, confine the pair to a single function, and document why the bound on allocations is safe.