diff options
Diffstat (limited to 'clang')
5 files changed, 25 insertions, 3 deletions
diff --git a/clang/include/clang/StaticAnalyzer/Core/PathSensitive/CallEvent.h b/clang/include/clang/StaticAnalyzer/Core/PathSensitive/CallEvent.h index d69f50a9a2f..e2baf38e0be 100644 --- a/clang/include/clang/StaticAnalyzer/Core/PathSensitive/CallEvent.h +++ b/clang/include/clang/StaticAnalyzer/Core/PathSensitive/CallEvent.h @@ -885,6 +885,8 @@ public: virtual RuntimeDefinition getRuntimeDefinition() const; + virtual bool argumentsMayEscape() const; + virtual void getInitialStackFrameContents(const StackFrameContext *CalleeCtx, BindingsTy &Bindings) const; diff --git a/clang/lib/StaticAnalyzer/Checkers/MallocChecker.cpp b/clang/lib/StaticAnalyzer/Checkers/MallocChecker.cpp index 82a1aa22579..87d7e89e52e 100644 --- a/clang/lib/StaticAnalyzer/Checkers/MallocChecker.cpp +++ b/clang/lib/StaticAnalyzer/Checkers/MallocChecker.cpp @@ -1907,7 +1907,8 @@ bool MallocChecker::mayFreeAnyEscapedMemoryOrIsModeledExplicitly( // that the pointers get freed by following the container itself. if (FirstSlot.startswith("addPointer") || FirstSlot.startswith("insertPointer") || - FirstSlot.startswith("replacePointer")) { + FirstSlot.startswith("replacePointer") || + FirstSlot.equals("valueWithPointer")) { return true; } diff --git a/clang/lib/StaticAnalyzer/Core/CallEvent.cpp b/clang/lib/StaticAnalyzer/Core/CallEvent.cpp index e0392bd1473..838d273cc0a 100644 --- a/clang/lib/StaticAnalyzer/Core/CallEvent.cpp +++ b/clang/lib/StaticAnalyzer/Core/CallEvent.cpp @@ -886,6 +886,17 @@ RuntimeDefinition ObjCMethodCall::getRuntimeDefinition() const { return RuntimeDefinition(); } +bool ObjCMethodCall::argumentsMayEscape() const { + if (isInSystemHeader() && !isInstanceMessage()) { + Selector Sel = getSelector(); + if (Sel.getNumArgs() == 1 && + Sel.getIdentifierInfoForSlot(0)->isStr("valueWithPointer")) + return true; + } + + return CallEvent::argumentsMayEscape(); +} + void ObjCMethodCall::getInitialStackFrameContents( const StackFrameContext *CalleeCtx, BindingsTy &Bindings) const { diff --git a/clang/test/Analysis/Inputs/system-header-simulator-objc.h b/clang/test/Analysis/Inputs/system-header-simulator-objc.h index 3e1d9555bbd..8a5d3b6403c 100644 --- a/clang/test/Analysis/Inputs/system-header-simulator-objc.h +++ b/clang/test/Analysis/Inputs/system-header-simulator-objc.h @@ -66,8 +66,11 @@ typedef struct { NSFastEnumerationState; @protocol NSFastEnumeration - (NSUInteger)countByEnumeratingWithState:(NSFastEnumerationState *)state objects:(id *)stackbuf count:(NSUInteger)len; @end @class NSString, NSDictionary; -@interface NSValue : NSObject <NSCopying, NSCoding> - (void)getValue:(void *)value; -@end @interface NSNumber : NSValue - (char)charValue; +@interface NSValue : NSObject <NSCopying, NSCoding> ++ (NSValue *)valueWithPointer:(const void *)p; +- (void)getValue:(void *)value; +@end +@interface NSNumber : NSValue - (char)charValue; - (id)initWithInt:(int)value; @end @class NSString; @interface NSArray : NSObject <NSCopying, NSMutableCopying, NSCoding, NSFastEnumeration> - (NSUInteger)count; diff --git a/clang/test/Analysis/malloc.m b/clang/test/Analysis/malloc.m index ad16db52dff..9201c2b75fe 100644 --- a/clang/test/Analysis/malloc.m +++ b/clang/test/Analysis/malloc.m @@ -49,4 +49,9 @@ void _ArrayCreate() { void testNSDataTruePositiveLeak() { char *b = (char *)malloc(12); NSData *d = [[NSData alloc] initWithBytes: b length: 12]; // expected-warning {{Potential leak of memory pointed to by 'b'}} +} + +id wrapInNSValue() { + void *buffer = malloc(4); + return [NSValue valueWithPointer:buffer]; // no-warning }
\ No newline at end of file |