NSInvocation arguments set without retainArguments
ID |
objectivec.correctness.nsinvocation_arg_lifetime |
Severity |
low |
Remediation Complexity |
trivial |
Remediation Risk |
low |
Remediation Effort |
low |
Resource |
Resource Management |
Language |
Objective-C |
Description
Reports a setArgument:atIndex: call on an NSInvocation in a method that never sends retainArguments, and that never invokes the invocation itself. The region is the method, bounded by its own closing brace, so a retainArguments in the method above or below does not count, and the order of the two calls within the method does not matter.
Rationale
NSInvocation copies the bytes of each argument but does not retain the objects they point at, so an invocation stored for later holds pointers whose owners may already be gone by the time it runs. The result is a use-after-free that depends on when the autorelease pool drains, so it survives testing and fails under memory pressure or on a background queue.
The following code illustrates the pattern detected by this rule:
@implementation Scheduler
- (void)scheduleUpdateWithName:(NSString *)name {
NSInvocation *invocation = [NSInvocation invocationWithMethodSignature:self.signature];
[invocation setTarget:self.worker];
[invocation setSelector:@selector(applyName:)];
// FLAGGED: NSInvocation arguments set without retainArguments
[invocation setArgument:&name atIndex:2];
self.pending = invocation;
}
@end