[objc] Refactor modeling of CoreFoundation and CoreGraphics libraries

Summary:
The diff is very big but it's mostly removing code. It was inspired by the fact that we were getting Dead Store FPs because we were modeling some functions from CoreFoundation and CoreGraphics directly as alloc in the frontend, which caused the parameters of the function to be seen as dead. See the new test.

To deal with this, if we are going to skip the function, we model it as malloc instead. Given how many models we had for those "model as malloc" functions, I removed them to rely solely on the new mechanism.

The modeling of malloc and release was still based on the old retain count implementation, even though all we do here is a malloc/free kind of analysis. I also changed
that to be actually malloc/free which removed many Assert false in the tests. CFRelease is not exactly free though, and it's possible to use the variable afterwards. So used a custom free builtin that only cares about removing the Memory attribute and focuses on minimizing Memory Leaks FPs.

Otherwise we were translating CFBridgingRelease as a special cast, and this wasn't working. To simplify this as well, I removed all the code for the special cast, and just modeled CFBridgingRelease and CFAutorelease also as free_cf, to avoid Memory Leak false positives. I also treated the cast __bridge_transfer as a free_cf model. This means we stopped trying to report Memory Leaks on those objects.

The modeling of CoreGraph release functions was done in the frontend, but seemed simpler to also simplify that code and model all the relevant functions.

Reviewed By: sblackshear

Differential Revision: D6397150

fbshipit-source-id: b1dc636
master
Dulma Churchill 7 years ago committed by Facebook Github Bot
parent 5588f5e1ea
commit 68beca1523

@ -1,12 +1,11 @@
/*
* Copyright (c) 2015 - present Facebook, Inc.
* Copyright (c) 2017 - present Facebook, Inc.
* All rights reserved.
*
* This source code is licensed under the BSD style license found in the
* LICENSE file in the root directory of this source tree. An additional grant
* of patent rights can be found in the PATENTS file in the same directory.
*/
#import <Foundation/Foundation.h>
CFTypeRef CFMakeCollectable(CFTypeRef cf) { return cf; }
void CFRelease(CFTypeRef item) { __free_cf(item); }

@ -1,55 +0,0 @@
/*
* Copyright (c) 2015 - present Facebook, Inc.
* All rights reserved.
*
* This source code is licensed under the BSD style license found in the
* LICENSE file in the root directory of this source tree. An additional grant
* of patent rights can be found in the PATENTS file in the same directory.
*/
#import <AddressBook/AddressBook.h>
#import <Foundation/Foundation.h>
CFArrayRef __cf_alloc(CFArrayRef);
CFArrayRef __cf_non_null_alloc(CFArrayRef);
CFArrayRef CFArrayCreate(CFAllocatorRef allocator,
const void** values,
CFIndex numValues,
const CFArrayCallBacks* callBacks) {
CFArrayRef c;
return __cf_alloc(c);
}
CFArrayRef CFNetworkCopyProxiesForURL(CFURLRef url,
CFDictionaryRef proxySettings) {
CFArrayRef c;
return __cf_alloc(c);
}
CFArrayRef CFStringCreateArrayWithFindResults(
CFAllocatorRef alloc,
CFStringRef theString,
CFStringRef stringToFind,
CFRange rangeToSearch,
CFStringCompareFlags compareOptions) {
CFArrayRef c;
return __cf_alloc(c);
}
CFArrayRef CFPreferencesCopyKeyList(CFStringRef applicationID,
CFStringRef userName,
CFStringRef hostName) {
CFArrayRef c;
return __cf_non_null_alloc(c);
}
CFArrayRef CNCopySupportedInterfaces(void) {
CFArrayRef c;
return __cf_non_null_alloc(c);
}
CFArrayRef ABAddressBookCopyArrayOfAllPeople(ABAddressBookRef addressBook) {
CFArrayRef c;
return __cf_non_null_alloc(c);
}

@ -1,21 +0,0 @@
/*
* Copyright (c) 2015 - present Facebook, Inc.
* All rights reserved.
*
* This source code is licensed under the BSD style license found in the
* LICENSE file in the root directory of this source tree. An additional grant
* of patent rights can be found in the PATENTS file in the same directory.
*/
#import <Foundation/Foundation.h>
CFBinaryHeapRef __cf_alloc(CFBinaryHeapRef);
CFBinaryHeapRef CFBinaryHeapCreate(
CFAllocatorRef allocator,
CFIndex capacity,
const CFBinaryHeapCallBacks* callBacks,
const CFBinaryHeapCompareContext* compareContext) {
CFBinaryHeapRef c;
return __cf_alloc(c);
}

@ -1,50 +0,0 @@
/*
* Copyright (c) 2015 - present Facebook, Inc.
* All rights reserved.
*
* This source code is licensed under the BSD style license found in the
* LICENSE file in the root directory of this source tree. An additional grant
* of patent rights can be found in the PATENTS file in the same directory.
*/
#import <CoreMedia/CoreMedia.h>
#import <Foundation/Foundation.h>
#import <ImageIO/ImageIO.h>
CFDictionaryRef __cf_non_null_alloc(CFDictionaryRef);
CFDictionaryRef __cf_alloc(CFDictionaryRef);
CFDictionaryRef CFDictionaryCreate(
CFAllocatorRef allocator,
const void** keys,
const void** values,
CFIndex numValues,
const CFDictionaryKeyCallBacks* keyCallBacks,
const CFDictionaryValueCallBacks* valueCallBacks) {
CFDictionaryRef c;
return __cf_alloc(c);
}
CFDictionaryRef CFDictionaryCreateCopy(CFAllocatorRef allocator,
CFDictionaryRef theDict) {
CFDictionaryRef c;
return __cf_alloc(c);
}
CFDictionaryRef CMCopyDictionaryOfAttachments(CFAllocatorRef allocator,
CMAttachmentBearerRef target,
CMAttachmentMode attachmentMode) {
CFDictionaryRef c;
return __cf_alloc(c);
}
CFDictionaryRef CFHTTPMessageCopyAllHeaderFields(CFHTTPMessageRef message) {
CFDictionaryRef c;
return __cf_alloc(c);
}
CFDictionaryRef CMTimeCopyAsDictionary(CMTime time, CFAllocatorRef allocator) {
CFDictionaryRef c;
return __cf_alloc(c);
}

@ -1,23 +0,0 @@
/*
* Copyright (c) 2015 - present Facebook, Inc.
* All rights reserved.
*
* This source code is licensed under the BSD style license found in the
* LICENSE file in the root directory of this source tree. An additional grant
* of patent rights can be found in the PATENTS file in the same directory.
*/
#import <Foundation/Foundation.h>
CFErrorRef __cf_alloc(CFErrorRef);
CFErrorRef __cf_non_null_alloc(CFErrorRef);
CFErrorRef CFReadStreamCopyError(CFReadStreamRef stream) {
CFErrorRef c;
return __cf_alloc(c);
}
CFErrorRef CFWriteStreamCopyError(CFWriteStreamRef stream) {
CFErrorRef c;
return __cf_alloc(c);
}

@ -1,40 +0,0 @@
/*
* Copyright (c) 2015 - present Facebook, Inc.
* All rights reserved.
*
* This source code is licensed under the BSD style license found in the
* LICENSE file in the root directory of this source tree. An additional grant
* of patent rights can be found in the PATENTS file in the same directory.
*/
#import <Foundation/Foundation.h>
CFHTTPMessageRef __cf_alloc(CFHTTPMessageRef);
CFHTTPMessageRef CFHTTPMessageCreateCopy(CFAllocatorRef alloc,
CFHTTPMessageRef message) {
CFHTTPMessageRef c;
return __cf_alloc(c);
}
CFHTTPMessageRef CFHTTPMessageCreateEmpty(CFAllocatorRef alloc,
Boolean isRequest) {
CFHTTPMessageRef c;
return __cf_alloc(c);
}
CFHTTPMessageRef CFHTTPMessageCreateRequest(CFAllocatorRef alloc,
CFStringRef requestMethod,
CFURLRef url,
CFStringRef httpVersion) {
CFHTTPMessageRef c;
return __cf_alloc(c);
}
CFHTTPMessageRef CFHTTPMessageCreateResponse(CFAllocatorRef alloc,
CFIndex statusCode,
CFStringRef statusDescription,
CFStringRef httpVersion) {
CFHTTPMessageRef c;
return __cf_alloc(c);
}

@ -1,19 +0,0 @@
/*
* Copyright (c) 2015 - present Facebook, Inc.
* All rights reserved.
*
* This source code is licensed under the BSD style license found in the
* LICENSE file in the root directory of this source tree. An additional grant
* of patent rights can be found in the PATENTS file in the same directory.
*/
#import <Foundation/Foundation.h>
CFLocaleRef __cf_alloc(CFLocaleRef);
CFLocaleRef __cf_non_null_alloc(CFLocaleRef);
CFLocaleRef CFLocaleCreate(CFAllocatorRef allocator,
CFStringRef localeIdentifier) {
CFLocaleRef c;
return __cf_alloc(c);
}

@ -1,20 +0,0 @@
/*
* Copyright (c) 2015 - present Facebook, Inc.
* All rights reserved.
*
* This source code is licensed under the BSD style license found in the
* LICENSE file in the root directory of this source tree. An additional grant
* of patent rights can be found in the PATENTS file in the same directory.
*/
#import <Foundation/Foundation.h>
CFMutableArrayRef __cf_alloc(CFMutableArrayRef);
CFMutableArrayRef __cf_non_null_alloc(CFMutableArrayRef);
CFMutableArrayRef CFArrayCreateMutable(CFAllocatorRef allocator,
CFIndex capacity,
const CFArrayCallBacks* callBacks) {
CFMutableArrayRef c;
return __cf_alloc(c);
}

@ -1,25 +0,0 @@
/*
* Copyright (c) 2015 - present Facebook, Inc.
* All rights reserved.
*
* This source code is licensed under the BSD style license found in the
* LICENSE file in the root directory of this source tree. An additional grant
* of patent rights can be found in the PATENTS file in the same directory.
*/
#import <CoreMedia/CoreMedia.h>
#import <ImageIO/ImageIO.h>
CFMutableDictionaryRef __cf_non_null_alloc(CFMutableDictionaryRef);
CFMutableDictionaryRef __cf_alloc(CFMutableDictionaryRef);
CFMutableDictionaryRef CFDictionaryCreateMutable(
CFAllocatorRef allocator,
CFIndex capacity,
const CFDictionaryKeyCallBacks* keyCallBacks,
const CFDictionaryValueCallBacks* valueCallBacks) {
CFMutableDictionaryRef c;
return __cf_alloc(c);
}

@ -1,20 +0,0 @@
/*
* Copyright (c) 2015 - present Facebook, Inc.
* All rights reserved.
*
* This source code is licensed under the BSD style license found in the
* LICENSE file in the root directory of this source tree. An additional grant
* of patent rights can be found in the PATENTS file in the same directory.
*/
#import <Foundation/Foundation.h>
CFMutableSetRef __cf_alloc(CFMutableSetRef);
CFMutableSetRef __cf_non_null_alloc(CFMutableSetRef);
CFMutableSetRef CFSetCreateMutable(CFAllocatorRef allocator,
CFIndex capacity,
const CFSetCallBacks* callBacks) {
CFMutableSetRef c;
return __cf_alloc(c);
}

@ -1,19 +0,0 @@
/*
* Copyright (c) 2015 - present Facebook, Inc.
* All rights reserved.
*
* This source code is licensed under the BSD style license found in the
* LICENSE file in the root directory of this source tree. An additional grant
* of patent rights can be found in the PATENTS file in the same directory.
*/
#import <Foundation/Foundation.h>
CFNumberRef __cf_alloc(CFNumberRef);
CFNumberRef CFNumberCreate(CFAllocatorRef allocator,
CFNumberType theType,
const void* valuePtr) {
CFNumberRef c;
return __cf_alloc(c);
}

@ -1,23 +0,0 @@
/*
* Copyright (c) 2015 - present Facebook, Inc.
* All rights reserved.
*
* This source code is licensed under the BSD style license found in the
* LICENSE file in the root directory of this source tree. An additional grant
* of patent rights can be found in the PATENTS file in the same directory.
*/
#import <Foundation/Foundation.h>
CFSocketRef __cf_alloc(CFSocketRef);
CFSocketRef CFSocketCreate(CFAllocatorRef allocator,
SInt32 protocolFamily,
SInt32 socketType,
SInt32 protocol,
CFOptionFlags callBackTypes,
CFSocketCallBack callout,
const CFSocketContext* context) {
CFSocketRef c;
return __cf_alloc(c);
}

@ -1,32 +0,0 @@
/*
* Copyright (c) 2015 - present Facebook, Inc.
* All rights reserved.
*
* This source code is licensed under the BSD style license found in the
* LICENSE file in the root directory of this source tree. An additional grant
* of patent rights can be found in the PATENTS file in the same directory.
*/
#import <Foundation/Foundation.h>
#import <stdlib.h>
CFStringRef __cf_alloc(CFStringRef);
void __get_array_length(const UInt8*);
CFStringRef CFStringCreateWithBytesNoCopy(CFAllocatorRef alloc,
const UInt8* bytes,
CFIndex numBytes,
CFStringEncoding encoding,
Boolean isExternalRepresentation,
CFAllocatorRef contentsDeallocator) {
CFStringRef c;
CFStringRef s = __cf_alloc(c);
if (s) {
if (bytes) {
__get_array_length(bytes);
free(bytes);
}
}
return s;
}

@ -1,19 +0,0 @@
/*
* Copyright (c) 2015 - present Facebook, Inc.
* All rights reserved.
*
* This source code is licensed under the BSD style license found in the
* LICENSE file in the root directory of this source tree. An additional grant
* of patent rights can be found in the PATENTS file in the same directory.
*/
#import <CoreText/CTFont.h>
CTFontRef __cf_alloc(CTFontRef);
CTFontRef CTFontCreateWithName(CFStringRef name,
CGFloat size,
const CGAffineTransform* matrix) {
CTFontRef c;
return __cf_alloc(c);
}

@ -1,18 +0,0 @@
/*
* Copyright (c) 2015 - present Facebook, Inc.
* All rights reserved.
*
* This source code is licensed under the BSD style license found in the
* LICENSE file in the root directory of this source tree. An additional grant
* of patent rights can be found in the PATENTS file in the same directory.
*/
#import <CoreText/CTFramesetter.h>
CTFramesetterRef __cf_alloc(CTFramesetterRef);
CTFramesetterRef CTFramesetterCreateWithAttributedString(
CFAttributedStringRef string) {
CTFramesetterRef c;
return __cf_alloc(c);
}

@ -1,20 +0,0 @@
/*
* Copyright (c) 2015 - present Facebook, Inc.
* All rights reserved.
*
* This source code is licensed under the BSD style license found in the
* LICENSE file in the root directory of this source tree. An additional grant
* of patent rights can be found in the PATENTS file in the same directory.
*/
#import <CoreText/CoreText.h>
#import <Foundation/Foundation.h>
CTParagraphStyleRef __cf_alloc(CTParagraphStyleRef);
CTParagraphStyleRef __cf_non_null_alloc(CTParagraphStyleRef);
CTParagraphStyleRef CTParagraphStyleCreate(
const CTParagraphStyleSetting* settings, size_t settingCount) {
CTParagraphStyleRef c;
return __cf_alloc(c);
}

@ -1,20 +0,0 @@
/*
* Copyright (c) 2015 - present Facebook, Inc.
* All rights reserved.
*
* This source code is licensed under the BSD style license found in the
* LICENSE file in the root directory of this source tree. An additional grant
* of patent rights can be found in the PATENTS file in the same directory.
*/
#import <Security/Security.h>
SecCertificateRef __cf_alloc(SecCertificateRef);
SecCertificateRef __cf_non_null_alloc(SecCertificateRef);
SecCertificateRef SecCertificateCreateWithData(CFAllocatorRef allocator,
CFDataRef data) {
SecCertificateRef c;
return __cf_alloc(c);
}

@ -1,20 +0,0 @@
/*
* Copyright (c) 2015 - present Facebook, Inc.
* All rights reserved.
*
* This source code is licensed under the BSD style license found in the
* LICENSE file in the root directory of this source tree. An additional grant
* of patent rights can be found in the PATENTS file in the same directory.
*/
#import <Security/SecKey.h>
#import <Security/SecTrust.h>
SecKeyRef __cf_alloc(SecKeyRef);
SecPolicyRef __cf_non_null_alloc(SecPolicyRef);
SecKeyRef SecTrustCopyPublicKey(SecTrustRef trust) {
SecKeyRef c;
return __cf_alloc(c);
}

@ -0,0 +1,72 @@
/*
* Copyright (c) 2017 - present Facebook, Inc.
* All rights reserved.
*
* This source code is licensed under the BSD style license found in the
* LICENSE file in the root directory of this source tree. An additional grant
* of patent rights can be found in the PATENTS file in the same directory.
*/
void __free_cf(void* item);
void* CFAutorelease(void* item) { __free_cf(item); }
void* CFBridgingRelease(void* item) { __free_cf(item); }
void CGAffineTransformRelease(void* item) { __free_cf(item); }
void CGBaseRelease(void* item) { __free_cf(item); }
void CGBitmapContextRelease(void* item) { __free_cf(item); }
void CGColorRelease(void* item) { __free_cf(item); }
void CGColorSpaceRelease(void* item) { __free_cf(item); }
void CGContextRelease(void* item) { __free_cf(item); }
void CGDataConsumerRelease(void* item) { __free_cf(item); }
void CGDataProviderRelease(void* item) { __free_cf(item); }
void CGErrorRelease(void* item) { __free_cf(item); }
void CGFontRelease(void* item) { __free_cf(item); }
void CGFunctionRelease(void* item) { __free_cf(item); }
void CGGeometryRelease(void* item) { __free_cf(item); }
void CGGradientRelease(void* item) { __free_cf(item); }
void CGImageRelease(void* item) { __free_cf(item); }
void CGLayerRelease(void* item) { __free_cf(item); }
void CGPathRelease(void* item) { __free_cf(item); }
void CGPatternRelease(void* item) { __free_cf(item); }
void CGPDFArrayRelease(void* item) { __free_cf(item); }
void CGPDFContentStreamRelease(void* item) { __free_cf(item); }
void CGPDFContextRelease(void* item) { __free_cf(item); }
void CGPDFDictionaryRelease(void* item) { __free_cf(item); }
void CGPDFDocumentRelease(void* item) { __free_cf(item); }
void CGPDFObjectRelease(void* item) { __free_cf(item); }
void CGPDFOperatorTableRelease(void* item) { __free_cf(item); }
void CGPDFPageRelease(void* item) { __free_cf(item); }
void CGPDFScannerRelease(void* item) { __free_cf(item); }
void CGPDFStreamRelease(void* item) { __free_cf(item); }
void CGPDFStringRelease(void* item) { __free_cf(item); }
void CGShadingRelease(void* item) { __free_cf(item); }

@ -1,36 +0,0 @@
/*
* Copyright (c) 2015 - present Facebook, Inc.
* All rights reserved.
*
* This source code is licensed under the BSD style license found in the
* LICENSE file in the root directory of this source tree. An additional grant
* of patent rights can be found in the PATENTS file in the same directory.
*/
#import <CoreGraphics/CoreGraphics.h>
CGColorRef __cf_non_null_alloc(CGColorRef);
void __objc_release_cf(CGColorRef);
void CGColorRelease(CGColorRef color) {
if (color)
__objc_release_cf(color);
}
// FB own code
CGColorRef FBColorCreateWithGray(CGFloat gray, CGFloat a) {
CGColorRef c;
return __cf_non_null_alloc(c);
}
CGColorRef FBColorCreateWithRGBA(uint8_t r, uint8_t g, uint8_t b, CGFloat a) {
CGColorRef c;
return __cf_non_null_alloc(c);
}
CGColorRef FBColorCreateWithRGB(uint8_t r, uint8_t g, uint8_t b) {
CGColorRef c;
return __cf_non_null_alloc(c);
}

@ -1,29 +0,0 @@
/*
* Copyright (c) 2015 - present Facebook, Inc.
* All rights reserved.
*
* This source code is licensed under the BSD style license found in the
* LICENSE file in the root directory of this source tree. An additional grant
* of patent rights can be found in the PATENTS file in the same directory.
*/
#import <CoreGraphics/CoreGraphics.h>
void __objc_release_cf(CGColorSpaceRef);
void CGColorSpaceRelease(CGColorSpaceRef space) {
if (space)
__objc_release_cf(space);
}
CGColorSpaceRef __cf_alloc(CGColorSpaceRef);
CGColorSpaceRef CGColorSpaceCreateDeviceRGB(void) {
CGColorSpaceRef c;
return __cf_alloc(c);
}
CGColorSpaceRef CGColorSpaceCreateDeviceGray(void) {
CGColorSpaceRef c;
return __cf_alloc(c);
}

@ -1,32 +0,0 @@
/*
* Copyright (c) 2015 - present Facebook, Inc.
* All rights reserved.
*
* This source code is licensed under the BSD style license found in the
* LICENSE file in the root directory of this source tree. An additional grant
* of patent rights can be found in the PATENTS file in the same directory.
*/
#import <CoreGraphics/CoreGraphics.h>
#import <ImageIO/ImageIO.h>
#import <QuartzCore/QuartzCore.h>
void __objc_release_cf(CGContextRef);
void CGContextRelease(CGContextRef c) {
if (c)
__objc_release_cf(c);
}
CGContextRef __cf_alloc(CGContextRef);
CGContextRef CGBitmapContextCreate(void* data,
size_t width,
size_t height,
size_t bitsPerComponent,
size_t bytesPerRow,
CGColorSpaceRef space,
CGBitmapInfo bitmapInfo) {
CGContextRef c;
return __cf_alloc(c);
}

@ -1,17 +0,0 @@
/*
* Copyright (c) 2015 - present Facebook, Inc.
* All rights reserved.
*
* This source code is licensed under the BSD style license found in the
* LICENSE file in the root directory of this source tree. An additional grant
* of patent rights can be found in the PATENTS file in the same directory.
*/
#import <CoreGraphics/CoreGraphics.h>
void __objc_release_cf(CGDataConsumerRef);
void CGDataConsumerRelease(CGDataConsumerRef consumer) {
if (consumer)
__objc_release_cf(consumer);
}

@ -1,27 +0,0 @@
/*
* Copyright (c) 2015 - present Facebook, Inc.
* All rights reserved.
*
* This source code is licensed under the BSD style license found in the
* LICENSE file in the root directory of this source tree. An additional grant
* of patent rights can be found in the PATENTS file in the same directory.
*/
#import <CoreGraphics/CoreGraphics.h>
void __objc_release_cf(CGDataProviderRef);
void CGDataProviderRelease(CGDataProviderRef provider) {
if (provider)
__objc_release_cf(provider);
}
CGDataProviderRef __cf_alloc(CGDataProviderRef);
CGDataProviderRef __cf_non_null_alloc(CGDataProviderRef);
CGDataProviderRef CGDataProviderCreateWithURL(CFURLRef url) {
CGDataProviderRef c;
return __cf_alloc(c);
}

@ -1,24 +0,0 @@
/*
* Copyright (c) 2015 - present Facebook, Inc.
* All rights reserved.
*
* This source code is licensed under the BSD style license found in the
* LICENSE file in the root directory of this source tree. An additional grant
* of patent rights can be found in the PATENTS file in the same directory.
*/
#import <CoreGraphics/CoreGraphics.h>
void __objc_release_cf(CGFontRef);
CGFontRef __cf_alloc(CGFontRef);
void CGFontRelease(CGFontRef font) {
if (font)
__objc_release_cf(font);
}
CGFontRef CGFontCreateWithDataProvider(CGDataProviderRef provider) {
CGFontRef c;
return __cf_alloc(c);
}

@ -1,17 +0,0 @@
/*
* Copyright (c) 2015 - present Facebook, Inc.
* All rights reserved.
*
* This source code is licensed under the BSD style license found in the
* LICENSE file in the root directory of this source tree. An additional grant
* of patent rights can be found in the PATENTS file in the same directory.
*/
#import <CoreGraphics/CoreGraphics.h>
void __objc_release_cf(CGFunctionRef);
void CGFunctionRelease(CGFunctionRef function) {
if (function)
__objc_release_cf(function);
}

@ -1,19 +0,0 @@
/*
* Copyright (c) 2015 - present Facebook, Inc.
* All rights reserved.
*
* This source code is licensed under the BSD style license found in the
* LICENSE file in the root directory of this source tree. An additional grant
* of patent rights can be found in the PATENTS file in the same directory.
*/
#import <CoreGraphics/CoreGraphics.h>
void __objc_release_cf(CGGradientRef);
void CGGradientRelease(CGGradientRef gradient) {
if (gradient)
__objc_release_cf(gradient);
}
CGGradientRef __cf_non_null_alloc(CGGradientRef);

@ -1,30 +0,0 @@
/*
* Copyright (c) 2015 - present Facebook, Inc.
* All rights reserved.
*
* This source code is licensed under the BSD style license found in the
* LICENSE file in the root directory of this source tree. An additional grant
* of patent rights can be found in the PATENTS file in the same directory.
*/
#import <CoreGraphics/CoreGraphics.h>
#import <ImageIO/ImageIO.h>
CGImageRef __cf_non_null_alloc(CGImageRef);
CGImageRef __cf_alloc(CGImageRef);
void __objc_release_cf(CGImageRef);
void CGImageRelease(CGImageRef image) {
if (image)
__objc_release_cf(image);
}
CGImageRef CGBitmapContextCreateImage(CGContextRef context) {
CGImageRef c;
return __cf_alloc(c);
}
CGImageRef CGImageCreateWithImageInRect(CGImageRef image, CGRect rect) {
CGImageRef c;
return __cf_alloc(c);
}

@ -1,27 +0,0 @@
/*
* Copyright (c) 2015 - present Facebook, Inc.
* All rights reserved.
*
* This source code is licensed under the BSD style license found in the
* LICENSE file in the root directory of this source tree. An additional grant
* of patent rights can be found in the PATENTS file in the same directory.
*/
#import <CoreGraphics/CoreGraphics.h>
#import <ImageIO/ImageIO.h>
CGImageSourceRef __cf_non_null_alloc(CGImageSourceRef);
CGImageSourceRef __cf_alloc(CGImageSourceRef);
void __objc_release_cf(CGImageSourceRef);
CGImageSourceRef CGImageSourceCreateWithURL(CFURLRef url,
CFDictionaryRef options) {
CGImageSourceRef c;
return __cf_alloc(c);
}
void CGImageSourceRelease(CGImageSourceRef image) {
if (image)
__objc_release_cf(image);
}

@ -1,17 +0,0 @@
/*
* Copyright (c) 2015 - present Facebook, Inc.
* All rights reserved.
*
* This source code is licensed under the BSD style license found in the
* LICENSE file in the root directory of this source tree. An additional grant
* of patent rights can be found in the PATENTS file in the same directory.
*/
#import <CoreGraphics/CoreGraphics.h>
void __objc_release_cf(CGLayerRef);
void CGLayerRelease(CGLayerRef layer) {
if (layer)
__objc_release_cf(layer);
}

@ -1,17 +0,0 @@
/*
* Copyright (c) 2015 - present Facebook, Inc.
* All rights reserved.
*
* This source code is licensed under the BSD style license found in the
* LICENSE file in the root directory of this source tree. An additional grant
* of patent rights can be found in the PATENTS file in the same directory.
*/
#import <CoreGraphics/CoreGraphics.h>
void __objc_release_cf(CGPDFContentStreamRef);
void CGPDFContentStreamRelease(CGPDFContentStreamRef cs) {
if (cs)
__objc_release_cf(cs);
}

@ -1,17 +0,0 @@
/*
* Copyright (c) 2015 - present Facebook, Inc.
* All rights reserved.
*
* This source code is licensed under the BSD style license found in the
* LICENSE file in the root directory of this source tree. An additional grant
* of patent rights can be found in the PATENTS file in the same directory.
*/
#import <CoreGraphics/CoreGraphics.h>
void __objc_release_cf(CGPDFDocumentRef);
void CGPDFDocumentRelease(CGPDFDocumentRef document) {
if (document)
__objc_release_cf(document);
}

@ -1,17 +0,0 @@
/*
* Copyright (c) 2015 - present Facebook, Inc.
* All rights reserved.
*
* This source code is licensed under the BSD style license found in the
* LICENSE file in the root directory of this source tree. An additional grant
* of patent rights can be found in the PATENTS file in the same directory.
*/
#import <CoreGraphics/CoreGraphics.h>
void __objc_release_cf(CGPDFOperatorTableRef);
void CGPDFOperatorTableRelease(CGPDFOperatorTableRef table) {
if (table)
__objc_release_cf(table);
}

@ -1,17 +0,0 @@
/*
* Copyright (c) 2015 - present Facebook, Inc.
* All rights reserved.
*
* This source code is licensed under the BSD style license found in the
* LICENSE file in the root directory of this source tree. An additional grant
* of patent rights can be found in the PATENTS file in the same directory.
*/
#import <CoreGraphics/CoreGraphics.h>
void __objc_release_cf(CGPDFPageRef);
void CGPDFPageRelease(CGPDFPageRef page) {
if (page)
__objc_release_cf(page);
}

@ -1,17 +0,0 @@
/*
* Copyright (c) 2015 - present Facebook, Inc.
* All rights reserved.
*
* This source code is licensed under the BSD style license found in the
* LICENSE file in the root directory of this source tree. An additional grant
* of patent rights can be found in the PATENTS file in the same directory.
*/
#import <CoreGraphics/CoreGraphics.h>
void __objc_release_cf(CGPDFScannerRef);
void CGPDFScannerRelease(CGPDFScannerRef scanner) {
if (scanner)
__objc_release_cf(scanner);
}

@ -1,20 +0,0 @@
/*
* Copyright (c) 2015 - present Facebook, Inc.
* All rights reserved.
*
* This source code is licensed under the BSD style license found in the
* LICENSE file in the root directory of this source tree. An additional grant
* of patent rights can be found in the PATENTS file in the same directory.
*/
#import <CoreGraphics/CoreGraphics.h>
#import <Foundation/Foundation.h>
CGPathRef __cf_non_null_alloc(CGPathRef);
void __objc_release_cf(CGPathRef);
void CGPathRelease(CGPathRef path) {
if (path)
__objc_release_cf(path);
}

@ -1,17 +0,0 @@
/*
* Copyright (c) 2015 - present Facebook, Inc.
* All rights reserved.
*
* This source code is licensed under the BSD style license found in the
* LICENSE file in the root directory of this source tree. An additional grant
* of patent rights can be found in the PATENTS file in the same directory.
*/
#import <CoreGraphics/CoreGraphics.h>
void __objc_release_cf(CGPatternRef);
void CGPatternRelease(CGPatternRef pattern) {
if (pattern)
__objc_release_cf(pattern);
}

@ -1,17 +0,0 @@
/*
* Copyright (c) 2015 - present Facebook, Inc.
* All rights reserved.
*
* This source code is licensed under the BSD style license found in the
* LICENSE file in the root directory of this source tree. An additional grant
* of patent rights can be found in the PATENTS file in the same directory.
*/
#import <CoreGraphics/CoreGraphics.h>
void __objc_release_cf(CGShadingRef);
void CGShadingRelease(CGShadingRef shading) {
if (shading)
__objc_release_cf(shading);
}

@ -38,6 +38,8 @@ module type S = sig
val __exit : t
val __free_cf : t
val __get_array_length : t
val __get_hidden_field : t
@ -59,18 +61,10 @@ module type S = sig
val __new_array : t
val __objc_alloc : t
val __objc_alloc_no_fail : t
val __objc_cast : t
val __objc_dictionary_literal : t
val __objc_release_cf : t
val __objc_retain_cf : t
val __placement_delete : t
val __placement_new : t

@ -56,6 +56,8 @@ let __delete_locked_attribute = create_procname "__delete_locked_attribute"
let __exit = create_procname "_exit"
let __free_cf = create_procname "__free_cf"
let __get_array_length = create_procname "__get_array_length"
let __get_hidden_field = create_procname "__get_hidden_field"
@ -86,16 +88,6 @@ let __objc_dictionary_literal =
create_objc_class_method "NSDictionary" "dictionaryWithObjects:forKeys:count:"
let __objc_release = create_procname "__objc_release"
let __objc_release_autorelease_pool = create_procname "__objc_release_autorelease_pool"
let __objc_release_cf = create_procname "__objc_release_cf"
let __objc_retain = create_procname "__objc_retain"
let __objc_retain_cf = create_procname "__objc_retain_cf"
let __placement_delete = create_procname "__placement_delete"
let __placement_new = create_procname "__placement_new"

@ -166,16 +166,6 @@ module Core_foundation_model = struct
let create = "Create"
let cf_retain = "CFRetain"
let cf_release = "CFRelease"
let upper_release = "Release"
let ref = "Ref"
let cf_type = "CFTypeRef"
type core_lib = Core_foundation | Core_graphics
let core_lib_to_type_list lib =
@ -212,25 +202,10 @@ module Core_foundation_model = struct
is_core_lib_type typ
&& (String.is_substring ~substring:create funct || String.is_substring ~substring:copy funct)
let function_arg_is_cftype typ = String.is_substring ~substring:cf_type typ
let is_core_lib_retain typ funct = function_arg_is_cftype typ && String.equal funct cf_retain
let is_core_lib_release typ funct = function_arg_is_cftype typ && String.equal funct cf_release
let is_core_graphics_release typ funct =
let f lib =
String.equal funct (lib ^ upper_release) && String.is_substring ~substring:(lib ^ ref) typ
in
List.exists ~f core_graphics_types
(*
let function_arg_is_core_pgraphics typ =
let res = (String.is_substring ~substring:cf_type typ) in
res
*)
end
let is_core_lib_type typ = Core_foundation_model.is_core_lib_type typ
let is_malloc_model return_type pname =
Core_foundation_model.is_core_lib_create return_type (Typ.Procname.to_string pname)

@ -13,15 +13,11 @@ open! IStd
for which there are particular rules for memory management. *)
module Core_foundation_model : sig
val is_core_lib_release : string -> string -> bool
val is_core_lib_create : Typ.t -> string -> bool
val is_core_lib_retain : string -> string -> bool
val is_core_graphics_release : string -> string -> bool
val is_objc_memory_model_controlled : string -> bool
end
val is_core_lib_type : Typ.t -> bool
val is_malloc_model : Typ.t -> Typ.Procname.t -> bool

@ -480,70 +480,6 @@ let execute___set_hidden_field {Builtin.tenv; pdesc; prop_; path; args} : Builti
raise (Exceptions.Wrong_argument_number __POS__)
(* Update the objective-c hidden counter by applying the operation op and the operand delta.*)
(* Eg. op=+/- delta is an integer *)
let execute___objc_counter_update ~mask_errors op delta
{Builtin.pdesc; tenv; prop_; path; args; loc} : Builtin.ret_typ =
match args with
| [(lexp, (({Typ.desc= Tstruct _} as typ) | {desc= Tptr (({desc= Tstruct _} as typ), _)}))] ->
(* Assumes that lexp is a temp n$1 that has the value of the object. *)
(* This is the case as a call f(o) it's translates as n$1=*&o; f(n$1) *)
(* n$2 = *n$1.hidden *)
let tmp = Ident.create_fresh Ident.knormal in
let hidden_field = Exp.Lfield (lexp, Typ.Fieldname.hidden, typ) in
let counter_to_tmp = Sil.Load (tmp, hidden_field, typ, loc) in
(* *n$1.hidden = (n$2 +/- delta) *)
let update_counter =
Sil.Store (hidden_field, typ, BinOp (op, Var tmp, Const (Cint delta)), loc)
in
let update_counter_instrs =
[counter_to_tmp; update_counter; Sil.Remove_temps ([tmp], loc)]
in
SymExec.instrs ~mask_errors tenv pdesc update_counter_instrs [(prop_, path)]
| [(_, typ)] ->
L.d_str ("Trying to update hidden field of non-struct value. Type: " ^ Typ.to_string typ) ;
assert false
| _ ->
raise (Exceptions.Wrong_argument_number __POS__)
(* Given a list of args checks if the first is the flag indicating whether is a call to
retain/release for which we have to suppress NPE report or not. If the flag is present it is
removed from the list of args. *)
let get_suppress_npe_flag args =
match args with
| (Exp.Const Const.Cint i, {Typ.desc= Tint Typ.IBool}) :: args' when IntLit.isone i ->
(false, args') (* this is a CFRelease/CFRetain *)
| _ ->
(true, args)
let execute___objc_retain_impl ({Builtin.tenv; prop_; args; ret_id} as builtin_args)
: Builtin.ret_typ =
let mask_errors, args' = get_suppress_npe_flag args in
match args' with
| [(lexp, _)] ->
let prop = return_result tenv lexp prop_ ret_id in
execute___objc_counter_update ~mask_errors Binop.PlusA IntLit.one
{builtin_args with Builtin.prop_= prop; args= args'}
| _ ->
raise (Exceptions.Wrong_argument_number __POS__)
let execute___objc_retain_cf builtin_args : Builtin.ret_typ =
execute___objc_retain_impl builtin_args
let execute___objc_release_impl ({Builtin.args} as builtin_args) : Builtin.ret_typ =
let mask_errors, args' = get_suppress_npe_flag args in
execute___objc_counter_update ~mask_errors Binop.MinusA IntLit.one
{builtin_args with Builtin.args= args'}
let execute___objc_release_cf builtin_args : Builtin.ret_typ =
execute___objc_release_impl builtin_args
let set_attr tenv pdesc prop path exp attr =
let pname = Procdesc.get_proc_name pdesc in
let n_lexp, prop = check_arith_norm_exp tenv pname exp prop in
@ -584,33 +520,6 @@ let execute___set_wont_leak_attribute builtin_args : Builtin.ret_typ =
execute___set_attr PredSymb.Awont_leak builtin_args
let execute___objc_cast {Builtin.tenv; pdesc; prop_; path; ret_id; args} : Builtin.ret_typ =
match args with
| [(val1_, _); (texp2_, _)]
-> (
let pname = Procdesc.get_proc_name pdesc in
let val1, prop__ = check_arith_norm_exp tenv pname val1_ prop_ in
let texp2, prop = check_arith_norm_exp tenv pname texp2_ prop__ in
match
List.find
~f:(function Sil.Hpointsto (e1, _, _) -> Exp.equal e1 val1 | _ -> false)
prop.Prop.sigma
|> Option.map ~f:(fun hpred ->
match (hpred, texp2) with
| Sil.Hpointsto (val1, _, _), Exp.Sizeof _ ->
let prop' = replace_ptsto_texp tenv prop val1 texp2 in
[(return_result tenv val1 prop' ret_id, path)]
| _ ->
[(return_result tenv val1 prop ret_id, path)] )
with
| Some res ->
res
| None ->
[(return_result tenv val1 prop ret_id, path)] )
| _ ->
raise (Exceptions.Wrong_argument_number __POS__)
let execute_abort {Builtin.proc_name} : Builtin.ret_typ =
raise
(Exceptions.Precondition_not_found
@ -619,24 +528,26 @@ let execute_abort {Builtin.proc_name} : Builtin.ret_typ =
let execute_exit {Builtin.prop_; path} : Builtin.ret_typ = SymExec.diverge prop_ path
let execute_free_ tenv mk loc acc iter =
let execute_free_ tenv mk ?(mark_as_freed= true) loc acc iter =
match Prop.prop_iter_current tenv iter with
| Sil.Hpointsto (lexp, _, _), [] ->
let prop = Prop.prop_iter_remove_curr_then_to_prop tenv iter in
let pname = PredSymb.mem_dealloc_pname mk in
let ra =
{ PredSymb.ra_kind= PredSymb.Rrelease
; PredSymb.ra_res= PredSymb.Rmemory mk
; PredSymb.ra_pname= pname
; PredSymb.ra_loc= loc
; PredSymb.ra_vpath= None }
in
(* mark value as freed *)
let p_res =
Attribute.add_or_replace_check_changed tenv Tabulation.check_attr_dealloc_mismatch prop
(Apred (Aresource ra, [lexp]))
in
p_res :: acc
if mark_as_freed then
let pname = PredSymb.mem_dealloc_pname mk in
let ra =
{ PredSymb.ra_kind= PredSymb.Rrelease
; PredSymb.ra_res= PredSymb.Rmemory mk
; PredSymb.ra_pname= pname
; PredSymb.ra_loc= loc
; PredSymb.ra_vpath= None }
in
(* mark value as freed *)
let p_res =
Attribute.add_or_replace_check_changed tenv Tabulation.check_attr_dealloc_mismatch prop
(Apred (Aresource ra, [lexp]))
in
p_res :: acc
else prop :: acc
| Sil.Hpointsto _, _ :: _ ->
assert false (* alignment error *)
| _ ->
@ -645,7 +556,7 @@ let execute_free_ tenv mk loc acc iter =
(* should not happen *)
let execute_free_nonzero_ mk pdesc tenv instr prop lexp typ loc =
let execute_free_nonzero_ mk ?(mark_as_freed= true) pdesc tenv instr prop lexp typ loc =
try
match Prover.is_root tenv prop lexp lexp with
| None ->
@ -653,7 +564,9 @@ let execute_free_nonzero_ mk pdesc tenv instr prop lexp typ loc =
assert false
| Some _ ->
let prop_list =
List.fold ~f:(execute_free_ tenv mk loc) ~init:[]
List.fold
~f:(execute_free_ tenv mk ~mark_as_freed loc)
~init:[]
(Rearrange.rearrange pdesc tenv lexp typ prop loc)
in
List.rev prop_list
@ -670,7 +583,8 @@ let execute_free_nonzero_ mk pdesc tenv instr prop lexp typ loc =
raise (Exceptions.Array_of_pointsto __POS__) )
let execute_free mk {Builtin.pdesc; instr; tenv; prop_; path; args; loc} : Builtin.ret_typ =
let execute_free mk ?(mark_as_freed= true) {Builtin.pdesc; instr; tenv; prop_; path; args; loc}
: Builtin.ret_typ =
match args with
| [(lexp, typ)] ->
let pname = Procdesc.get_proc_name pdesc in
@ -688,7 +602,7 @@ let execute_free mk {Builtin.pdesc; instr; tenv; prop_; path; args; loc} : Built
@ (* model: if 0 then skip else execute_free_nonzero_ *)
List.concat_map
~f:(fun p ->
execute_free_nonzero_ mk pdesc tenv instr p
execute_free_nonzero_ mk ~mark_as_freed pdesc tenv instr p
(Prop.exp_normalize_prop tenv p lexp)
typ loc)
prop_nonzero
@ -698,6 +612,13 @@ let execute_free mk {Builtin.pdesc; instr; tenv; prop_; path; args; loc} : Built
raise (Exceptions.Wrong_argument_number __POS__)
(* This is for objects of CoreFoundation and CoreGraphics that ned to be released.
However, we want to treat them a bit differently to standard free; in particular we
don't want to flag Use_after_free because they can be used after CFRelease. The main purpose
of this builtin is to remove the memory attribute so that we don't report Memory Leaks.
This should behave correctly most of the time. *)
let execute_free_cf mk = execute_free mk ~mark_as_freed:false
let execute_alloc mk can_return_null {Builtin.pdesc; tenv; prop_; path; ret_id; args; loc}
: Builtin.ret_typ =
let pname = Procdesc.get_proc_name pdesc in
@ -1026,6 +947,8 @@ let __delete_locked_attribute =
let __exit = Builtin.register BuiltinDecl.__exit execute_exit
let __free_cf = Builtin.register BuiltinDecl.__free_cf (execute_free_cf PredSymb.Mmalloc)
(* return the length of the array passed as a parameter *)
let __get_array_length = Builtin.register BuiltinDecl.__get_array_length execute___get_array_length
@ -1055,23 +978,15 @@ let __new_array =
Builtin.register BuiltinDecl.__new_array (execute_alloc PredSymb.Mnew_array false)
let __objc_alloc = Builtin.register BuiltinDecl.__objc_alloc (execute_alloc PredSymb.Mobjc true)
(* like __objc_alloc, but does not return nil *)
let __objc_alloc_no_fail =
Builtin.register BuiltinDecl.__objc_alloc_no_fail (execute_alloc PredSymb.Mobjc false)
let __objc_cast = Builtin.register BuiltinDecl.__objc_cast execute___objc_cast
let __objc_dictionary_literal =
Builtin.register BuiltinDecl.__objc_dictionary_literal execute___objc_dictionary_literal
let __objc_release_cf = Builtin.register BuiltinDecl.__objc_release_cf execute___objc_release_cf
let __objc_retain_cf = Builtin.register BuiltinDecl.__objc_retain_cf execute___objc_retain_cf
let __placement_delete = Builtin.register BuiltinDecl.__placement_delete execute_skip
let __placement_new = Builtin.register BuiltinDecl.__placement_new execute_return_first_argument

@ -1286,53 +1286,43 @@ let rec sym_exec tenv current_pdesc instr_ (prop_: Prop.normal Prop.t) path
~f:(fun summary -> is_some (reason_to_skip summary))
~default:true resolved_summary_opt
then
(* If it's an ObjC getter or setter, call the builtin rather than skipping *)
let attrs_opt =
let attr_opt = Option.map ~f:Procdesc.get_attributes callee_pdesc_opt in
match (attr_opt, resolved_pname) with
| Some attrs, Typ.Procname.ObjC_Cpp _ ->
Some attrs
| None, Typ.Procname.ObjC_Cpp _ ->
Attributes.load resolved_pname
| _ ->
None
in
let objc_property_accessor_ret_typ_opt =
match attrs_opt with
| Some attrs -> (
match attrs.ProcAttributes.objc_accessor with
| Some objc_accessor ->
Some (objc_accessor, attrs.ProcAttributes.ret_type)
| None ->
None )
let ret_annots =
match resolved_summary_opt with
| Some summ ->
let ret_annots, _ =
(Specs.get_attributes summ).ProcAttributes.method_annotation
in
ret_annots
| None ->
None
load_ret_annots resolved_pname
in
match objc_property_accessor_ret_typ_opt with
| Some (objc_property_accessor, ret_typ) ->
handle_objc_instance_method_call n_actual_params n_actual_params prop tenv
ret_id current_pdesc callee_pname loc path
(sym_exec_objc_accessor objc_property_accessor ret_typ)
| None ->
let ret_annots =
match resolved_summary_opt with
| Some summ ->
let ret_annots, _ =
(Specs.get_attributes summ).ProcAttributes.method_annotation
in
ret_annots
| None ->
load_ret_annots resolved_pname
in
let is_objc_instance_method =
match attrs_opt with
| Some attrs ->
let attrs_opt = Option.map ~f:Procdesc.get_attributes callee_pdesc_opt in
match attrs_opt with
| Some attrs
-> (
let ret_type = attrs.ProcAttributes.ret_type in
let model_as_malloc = Objc_models.is_malloc_model ret_type callee_pname in
match (attrs.ProcAttributes.objc_accessor, model_as_malloc) with
| Some objc_accessor, _ ->
(* If it's an ObjC getter or setter, call the builtin rather than skipping *)
handle_objc_instance_method_call n_actual_params n_actual_params prop
tenv ret_id current_pdesc callee_pname loc path
(sym_exec_objc_accessor objc_accessor ret_type)
| None, true ->
(* If it's an alloc model, call alloc rather than skipping *)
sym_exec_alloc_model callee_pname ret_type tenv ret_id current_pdesc loc
prop path
| None, false ->
let is_objc_instance_method =
attrs.ProcAttributes.is_objc_instance_method
| None ->
false
in
skip_call ~is_objc_instance_method ~reason:"function or method not found"
prop path resolved_pname ret_annots loc ret_id ret_typ_opt n_actual_params
in
skip_call ~is_objc_instance_method ~reason:"function or method not found"
prop path resolved_pname ret_annots loc ret_id ret_typ_opt
n_actual_params )
| None ->
skip_call ~is_objc_instance_method:false
~reason:"function or method not found" prop path resolved_pname ret_annots
loc ret_id ret_typ_opt n_actual_params
else
proc_call
(Option.value_exn resolved_summary_opt)
@ -1717,6 +1707,21 @@ and sym_exec_objc_accessor property_accesor ret_typ tenv ret_id pdesc _ loc args
f_accessor ret_typ tenv ret_id pdesc cur_pname loc args prop |> List.map ~f:(fun p -> (p, path))
and sym_exec_alloc_model pname ret_typ tenv ret_id pdesc loc prop path : Builtin.ret_typ =
let alloc_source_function_arg = (Exp.Const (Const.Cfun pname), Typ.mk Tvoid) in
let args =
let sizeof_exp =
Exp.Sizeof {typ= ret_typ; nbytes= None; dynamic_length= None; subtype= Subtype.exact}
in
let exp = (sizeof_exp, Typ.mk (Tint Typ.IULong)) in
[exp; alloc_source_function_arg]
in
let alloc_fun = Exp.Const (Const.Cfun BuiltinDecl.malloc_no_fail) in
let alloc_instr = Sil.Call (ret_id, alloc_fun, args, loc, CallFlags.default) in
L.d_strln "No spec found, method should be model as alloc, executing alloc... " ;
instrs tenv pdesc [alloc_instr] [(prop, path)]
(** Perform symbolic execution for a function call *)
and proc_call callee_summary
{Builtin.pdesc; tenv; prop_= pre; path; ret_id; args= actual_pars; loc} =

@ -60,9 +60,6 @@ val get_decl_from_typ_ptr : Clang_ast_t.type_ptr -> Clang_ast_t.decl option
val name_of_typedef_type_info : Clang_ast_t.typedef_type_info -> QualifiedCppName.t
val name_opt_of_typedef_qual_type : Clang_ast_t.qual_type -> QualifiedCppName.t option
(** returns name of typedef if qual_type points to Typedef, None otherwise *)
val string_of_qual_type : Clang_ast_t.qual_type -> string
val make_name_decl : string -> Clang_ast_t.named_decl_info

@ -434,7 +434,7 @@ module CTrans_funct (F : CModule_type.CFrontend) : CModule_type.CTranslation = s
{empty_res_trans with root_nodes= [root_node']; leaf_nodes= trans_state.succ_nodes}
let get_builtin_pname_opt trans_unit_ctx qual_name decl_opt (qual_type: Clang_ast_t.qual_type) =
let get_builtin_pname_opt trans_unit_ctx qual_name decl_opt =
let get_annotate_attr_arg decl =
let open Clang_ast_t in
let decl_info = Clang_ast_proj.get_decl_tuple decl in
@ -458,10 +458,6 @@ module CTrans_funct (F : CModule_type.CFrontend) : CModule_type.CTranslation = s
Some (Typ.Procname.from_string_c_fun attr)
| _ when CTrans_models.is_modeled_builtin name ->
Some (Typ.Procname.from_string_c_fun (CFrontend_config.infer ^ name))
| _ when CTrans_models.is_release_builtin name qual_type.qt_type_ptr ->
Some BuiltinDecl.__objc_release_cf
| _ when CTrans_models.is_retain_builtin name qual_type.qt_type_ptr ->
Some BuiltinDecl.__objc_retain_cf
| _
when String.equal name CFrontend_config.malloc
&& CGeneral_utils.is_objc_extension trans_unit_ctx ->
@ -479,9 +475,7 @@ module CTrans_funct (F : CModule_type.CFrontend) : CModule_type.CTranslation = s
let qual_name = CAst_utils.get_qualified_name name_info in
let typ = CType_decl.qual_type_to_sil_type context.tenv qual_type in
let pname =
match
get_builtin_pname_opt context.translation_unit_context qual_name decl_opt qual_type
with
match get_builtin_pname_opt context.translation_unit_context qual_name decl_opt with
| Some builtin_pname ->
builtin_pname
| None ->
@ -599,9 +593,7 @@ module CTrans_funct (F : CModule_type.CFrontend) : CModule_type.CTranslation = s
(* use qualified method name for builtin matching, but use unqualified name elsewhere *)
let qual_method_name = CAst_utils.get_qualified_name name_info in
let pname =
match
get_builtin_pname_opt context.translation_unit_context qual_method_name decl_opt qual_type
with
match get_builtin_pname_opt context.translation_unit_context qual_method_name decl_opt with
| Some builtin_pname ->
builtin_pname
| None ->
@ -979,16 +971,11 @@ module CTrans_funct (F : CModule_type.CFrontend) : CModule_type.CTranslation = s
in
match
Option.bind callee_pname_opt
~f:
(CTrans_utils.builtin_trans trans_state_pri sil_loc si function_type
result_trans_subexprs)
~f:(CTrans_utils.builtin_trans trans_state_pri sil_loc result_trans_subexprs)
with
| Some builtin ->
builtin
| None ->
let is_cf_retain_release =
Option.value_map ~f:CTrans_models.is_cf_retain_release ~default:false callee_pname_opt
in
let act_params =
let params = List.tl_exn (collect_exprs result_trans_subexprs) in
if Int.equal (List.length params) (List.length params_stmt) then params
@ -1001,23 +988,11 @@ module CTrans_funct (F : CModule_type.CFrontend) : CModule_type.CTranslation = s
(Pp.seq (Pp.to_string ~f:Clang_ast_j.string_of_stmt))
params_stmt
in
let act_params =
if is_cf_retain_release then
(Exp.Const (Const.Cint IntLit.one), Typ.mk (Tint Typ.IBool)) :: act_params
else act_params
in
let res_trans_call =
let cast_trans_fun = cast_trans act_params sil_loc function_type in
match Option.bind callee_pname_opt ~f:cast_trans_fun with
| Some (instr, cast_exp) ->
{empty_res_trans with instrs= [instr]; exps= [(cast_exp, function_type)]}
| _ ->
let is_call_to_block = objc_exp_of_type_block fun_exp_stmt in
let call_flags =
{CallFlags.default with CallFlags.cf_is_objc_block= is_call_to_block}
in
create_call_instr trans_state function_type sil_fe act_params sil_loc call_flags
~is_objc_method:false
let is_call_to_block = objc_exp_of_type_block fun_exp_stmt in
let call_flags = {CallFlags.default with CallFlags.cf_is_objc_block= is_call_to_block} in
create_call_instr trans_state function_type sil_fe act_params sil_loc call_flags
~is_objc_method:false
in
let nname = "Call " ^ Exp.to_string sil_fe in
let all_res_trans = result_trans_subexprs @ [res_trans_call] in
@ -2358,13 +2333,7 @@ module CTrans_funct (F : CModule_type.CFrontend) : CModule_type.CTranslation = s
in
let cast_kind = cast_expr_info.Clang_ast_t.cei_cast_kind in
(* This gives the differnece among cast operations kind*)
let is_objc_bridged_cast_expr _ stmt =
match stmt with Clang_ast_t.ObjCBridgedCastExpr _ -> true | _ -> false
in
let is_objc_bridged = CAst_utils.exists_eventually_st is_objc_bridged_cast_expr () stmt in
let cast_inst, cast_exp =
cast_operation trans_state cast_kind res_trans_stmt.exps typ sil_loc is_objc_bridged
in
let cast_inst, cast_exp = cast_operation cast_kind res_trans_stmt.exps typ sil_loc in
{res_trans_stmt with instrs= res_trans_stmt.instrs @ cast_inst; exps= [cast_exp]}
@ -2959,14 +2928,6 @@ module CTrans_funct (F : CModule_type.CFrontend) : CModule_type.CTranslation = s
{res_trans_to_parent with exps= res_trans_call.exps}
and objCBridgedCastExpr_trans trans_state stmts expr_info =
let stmt = extract_stmt_from_singleton stmts "" in
let tenv = trans_state.context.CContext.tenv in
let typ = CType_decl.get_type_from_expr_info expr_info tenv in
let trans_state' = {trans_state with obj_bridged_cast_typ= Some typ} in
instruction trans_state' stmt
and binaryOperator_trans_with_cond trans_state stmt_info stmt_list expr_info binop_info =
let open Clang_ast_t in
match binop_info.boi_kind with
@ -3111,8 +3072,7 @@ module CTrans_funct (F : CModule_type.CFrontend) : CModule_type.CTranslation = s
pseudoObjectExpr_trans trans_state stmt_list
| UnaryExprOrTypeTraitExpr (_, _, expr_info, ei) ->
unaryExprOrTypeTraitExpr_trans trans_state expr_info ei
| ObjCBridgedCastExpr (_, stmt_list, expr_info, _, _) ->
objCBridgedCastExpr_trans trans_state stmt_list expr_info
| ObjCBridgedCastExpr (stmt_info, stmt_list, expr_info, cast_kind, _)
| ImplicitCastExpr (stmt_info, stmt_list, expr_info, cast_kind)
| CStyleCastExpr (stmt_info, stmt_list, expr_info, cast_kind, _)
| CXXReinterpretCastExpr (stmt_info, stmt_list, expr_info, cast_kind, _, _)
@ -3459,8 +3419,7 @@ module CTrans_funct (F : CModule_type.CFrontend) : CModule_type.CTranslation = s
; continuation= None
; priority= Free
; var_exp_typ= None
; opaque_exp= None
; obj_bridged_cast_typ= None }
; opaque_exp= None }
in
let res_trans_stmt = instruction trans_state stmt in
fst (CTrans_utils.extract_exp_from_list res_trans_stmt.exps warning)
@ -3473,8 +3432,7 @@ module CTrans_funct (F : CModule_type.CFrontend) : CModule_type.CTranslation = s
; continuation= None
; priority= Free
; var_exp_typ= None
; opaque_exp= None
; obj_bridged_cast_typ= None }
; opaque_exp= None }
in
let procname = Procdesc.get_proc_name context.CContext.procdesc in
let is_destructor = Typ.Procname.is_destructor procname in

@ -11,25 +11,14 @@ open! IStd
open Objc_models
let is_modelled_static_function name =
let modelled_functions = ["_dispatch_once"] in
let modelled_functions = ["_dispatch_once"; "CFAutorelease"; "CFBridgingRelease"] in
List.mem ~equal:String.equal modelled_functions name
let class_equal class_typename class_name = String.equal (Typ.Name.name class_typename) class_name
let is_cf_non_null_alloc pname =
String.equal (Typ.Procname.to_string pname) CFrontend_config.cf_non_null_alloc
let is_alloc pname = String.equal (Typ.Procname.to_string pname) CFrontend_config.cf_alloc
let class_equal class_typename class_name = String.equal (Typ.Name.name class_typename) class_name
let is_alloc_model typ pname =
if Specs.summary_exists pname then false
else
let funct = Typ.Procname.to_string pname in
(* if (Core_foundation_model.is_core_lib_create typ funct) then
print_endline ("\nCore Foundation create not modelled "
^(Typ.to_string typ)^" "^(funct));*)
Core_foundation_model.is_core_lib_create typ funct
Core_foundation_model.is_core_lib_create typ (Typ.Procname.to_string pname)
let is_builtin_expect pname =
@ -50,54 +39,12 @@ let is_replace_with_deref_first_arg pname =
String.equal (Typ.Procname.to_string pname) CFrontend_config.replace_with_deref_first_arg_attr
let is_retain_predefined_model typ pname =
let funct = Typ.Procname.to_string pname in
Core_foundation_model.is_core_lib_retain typ funct
let is_release_predefined_model typ pname =
let funct = Typ.Procname.to_string pname in
Core_foundation_model.is_core_lib_release typ funct
|| Core_foundation_model.is_core_graphics_release typ funct
let is_modeled_builtin funct = String.equal funct CFrontend_config.builtin_memset_chk
let is_modeled_attribute attr_name =
List.mem ~equal:String.equal CFrontend_config.modeled_function_attributes attr_name
let get_first_param_typedef_string_opt type_ptr =
match CAst_utils.get_desugared_type type_ptr with
| Some Clang_ast_t.FunctionProtoType (_, _, {pti_params_type= [param_ptr]}) ->
CAst_utils.name_opt_of_typedef_qual_type param_ptr
|> Option.map ~f:QualifiedCppName.to_qual_string
| _ ->
None
let is_release_builtin funct fun_type =
let pn = Typ.Procname.from_string_c_fun funct in
if Specs.summary_exists pn then false
else
match get_first_param_typedef_string_opt fun_type with
| Some typ ->
is_release_predefined_model typ pn
| _ ->
false
let is_retain_builtin funct fun_type =
let pn = Typ.Procname.from_string_c_fun funct in
if Specs.summary_exists pn then false
else
match get_first_param_typedef_string_opt fun_type with
| Some typ ->
is_retain_predefined_model typ pn
| _ ->
false
let is_assert_log_s funct =
String.equal funct CFrontend_config.assert_rtn || String.equal funct CFrontend_config.assert_fail
|| String.equal funct CFrontend_config.fbAssertWithSignalAndLogFunctionHelper
@ -111,19 +58,6 @@ let is_handleFailureInMethod funct =
|| String.equal funct CFrontend_config.handleFailureInFunction
let is_toll_free_bridging pn =
let funct = Typ.Procname.to_string pn in
String.equal funct CFrontend_config.cf_bridging_release
|| String.equal funct CFrontend_config.cf_bridging_retain
|| String.equal funct CFrontend_config.cf_autorelease
|| String.equal funct CFrontend_config.ns_make_collectable
let is_cf_retain_release pn =
Typ.Procname.equal pn BuiltinDecl.__objc_retain_cf
|| Typ.Procname.equal pn BuiltinDecl.__objc_release_cf
(** If the function is a builtin model, return the model, otherwise return the function *)
let is_assert_log pname =
match pname with

@ -11,10 +11,6 @@ open! IStd
val is_modelled_static_function : string -> bool
val is_cf_non_null_alloc : Typ.Procname.t -> bool
val is_alloc : Typ.Procname.t -> bool
val is_alloc_model : Typ.t -> Typ.Procname.t -> bool
val is_builtin_expect : Typ.Procname.t -> bool
@ -33,16 +29,8 @@ val is_handleFailureInMethod : string -> bool
val is_modeled_builtin : string -> bool
val is_release_builtin : string -> Clang_ast_t.type_ptr -> bool
val is_retain_builtin : string -> Clang_ast_t.type_ptr -> bool
val is_modeled_attribute : string -> bool
val is_toll_free_bridging : Typ.Procname.t -> bool
val is_cf_retain_release : Typ.Procname.t -> bool
val get_predefined_model_method_signature :
Typ.Name.t -> string
-> (Typ.Name.t -> string -> Typ.Procname.objc_cpp_method_kind -> Typ.Procname.t)

@ -164,8 +164,7 @@ type trans_state =
; (* current continuation *)
priority: priority_node
; var_exp_typ: (Exp.t * Typ.t) option
; opaque_exp: (Exp.t * Typ.t) option
; obj_bridged_cast_typ: Typ.t option }
; opaque_exp: (Exp.t * Typ.t) option }
(* A translation result. It is returned by the translation function. *)
type trans_result =
@ -370,7 +369,7 @@ module Scope = struct
end
(** This function handles ObjC new/alloc and C++ new calls *)
let create_alloc_instrs ~alloc_builtin ?alloc_source_function ?size_exp sil_loc function_type =
let create_alloc_instrs ~alloc_builtin ?size_exp sil_loc function_type =
let function_type, function_type_np =
match function_type.Typ.desc with
| Tptr (styp, Typ.Pk_pointer)
@ -381,13 +380,6 @@ let create_alloc_instrs ~alloc_builtin ?alloc_source_function ?size_exp sil_loc
| _ ->
(CType.add_pointer_to_typ function_type, function_type)
in
let alloc_source_function_arg =
match alloc_source_function with
| Some procname ->
[(Exp.Const (Const.Cfun procname), Typ.mk Tvoid)]
| None ->
[]
in
let ret_id = Ident.create_fresh Ident.knormal in
let args =
let sizeof_exp_ =
@ -401,7 +393,7 @@ let create_alloc_instrs ~alloc_builtin ?alloc_source_function ?size_exp sil_loc
sizeof_exp_
in
let exp = (sizeof_exp, Typ.mk (Tint Typ.IULong)) in
exp :: alloc_source_function_arg
[exp]
in
let ret_id_typ = Some (ret_id, function_type) in
let stmt_call =
@ -410,10 +402,8 @@ let create_alloc_instrs ~alloc_builtin ?alloc_source_function ?size_exp sil_loc
(function_type, [stmt_call], Exp.Var ret_id)
let alloc_trans trans_state ~alloc_builtin ?alloc_source_function loc stmt_info function_type =
let function_type, instrs, exp =
create_alloc_instrs ~alloc_builtin ?alloc_source_function loc function_type
in
let alloc_trans trans_state ~alloc_builtin loc stmt_info function_type =
let function_type, instrs, exp = create_alloc_instrs ~alloc_builtin loc function_type in
let res_trans_tmp = {empty_res_trans with instrs} in
let res_trans =
let nname = "Call alloc" in
@ -477,27 +467,12 @@ let cpp_new_trans sil_loc function_type size_exp =
{empty_res_trans with instrs= stmt_call; exps= [(exp, function_type)]}
let create_cast_instrs exp cast_from_typ cast_to_typ sil_loc =
let ret_id = Ident.create_fresh Ident.knormal in
let ret_id_typ = Some (ret_id, cast_to_typ) in
let typ = CType.remove_pointer_to_typ cast_to_typ in
let sizeof_exp = Exp.Sizeof {typ; nbytes= None; dynamic_length= None; subtype= Subtype.exact} in
let pname = BuiltinDecl.__objc_cast in
let args = [(exp, cast_from_typ); (sizeof_exp, Typ.mk (Tint Typ.IULong))] in
let create_call_to_free_cf sil_loc exp typ =
let pname = BuiltinDecl.__free_cf in
let stmt_call =
Sil.Call (ret_id_typ, Exp.Const (Const.Cfun pname), args, sil_loc, CallFlags.default)
Sil.Call (None, Exp.Const (Const.Cfun pname), [(exp, typ)], sil_loc, CallFlags.default)
in
(stmt_call, Exp.Var ret_id)
let cast_trans exps sil_loc function_type pname =
if CTrans_models.is_toll_free_bridging pname then
match exps with
| [(exp, typ)] ->
Some (create_cast_instrs exp typ function_type sil_loc)
| _ ->
assert false
else None
stmt_call
let dereference_var_sil (exp, typ) sil_loc =
@ -516,9 +491,8 @@ let dereference_value_from_result sil_loc trans_result ~strip_pointer =
{trans_result with instrs= trans_result.instrs @ cast_inst; exps= [(cast_exp, cast_typ)]}
let cast_operation trans_state cast_kind exps cast_typ sil_loc is_objc_bridged =
let cast_operation cast_kind exps cast_typ sil_loc =
let exp, typ = extract_exp_from_list exps "" in
let is_objc_bridged = Option.is_some trans_state.obj_bridged_cast_typ || is_objc_bridged in
match cast_kind with
| `NoOp | `DerivedToBase | `UncheckedDerivedToBase ->
(* These casts ignore change of type *)
@ -526,12 +500,9 @@ let cast_operation trans_state cast_kind exps cast_typ sil_loc is_objc_bridged =
| `BitCast | `IntegralCast | `IntegralToBoolean ->
(* This is treated as a nop by returning the same expressions exps*)
([], (exp, cast_typ))
| (`CPointerToObjCPointerCast | `ARCProduceObject | `ARCConsumeObject) when is_objc_bridged ->
(* Translation of __bridge_transfer or __bridge_retained *)
let objc_cast_typ =
match trans_state.obj_bridged_cast_typ with Some typ -> typ | None -> cast_typ
in
let instr, exp = create_cast_instrs exp typ objc_cast_typ sil_loc in
| `CPointerToObjCPointerCast when Objc_models.is_core_lib_type typ ->
(* Translation of __bridge_transfer *)
let instr = create_call_to_free_cf sil_loc exp typ in
([instr], (exp, cast_typ))
| `LValueToRValue ->
(* Takes an LValue and allow it to use it as RValue. *)
@ -600,16 +571,8 @@ let trans_replace_with_deref_first_arg sil_loc params_trans_res ~cxx_method_call
dereference_value_from_result sil_loc first_arg_res_trans ~strip_pointer:true
let builtin_trans trans_state loc stmt_info function_type params_trans_res pname =
if CTrans_models.is_cf_non_null_alloc pname || CTrans_models.is_alloc_model function_type pname
then
Some
(alloc_trans trans_state ~alloc_builtin:BuiltinDecl.__objc_alloc_no_fail
~alloc_source_function:pname loc stmt_info function_type)
else if CTrans_models.is_alloc pname then
Some
(alloc_trans trans_state ~alloc_builtin:BuiltinDecl.__objc_alloc loc stmt_info function_type)
else if CTrans_models.is_assert_log pname then Some (trans_assertion trans_state loc)
let builtin_trans trans_state loc params_trans_res pname =
if CTrans_models.is_assert_log pname then Some (trans_assertion trans_state loc)
else if CTrans_models.is_builtin_expect pname then trans_builtin_expect params_trans_res
else if CTrans_models.is_replace_with_deref_first_arg pname then
Some (trans_replace_with_deref_first_arg loc params_trans_res ~cxx_method_call:false)

@ -25,8 +25,7 @@ type trans_state =
; continuation: continuation option
; priority: priority_node
; var_exp_typ: (Exp.t * Typ.t) option
; opaque_exp: (Exp.t * Typ.t) option
; obj_bridged_cast_typ: Typ.t option }
; opaque_exp: (Exp.t * Typ.t) option }
type trans_result =
{ root_nodes: Procdesc.Node.t list
@ -76,7 +75,7 @@ val dereference_value_from_result :
expression assigned to it *)
val cast_operation :
trans_state -> Clang_ast_t.cast_kind -> (Exp.t * Typ.t) list -> Typ.t -> Location.t -> bool
Clang_ast_t.cast_kind -> (Exp.t * Typ.t) list -> Typ.t -> Location.t
-> Sil.instr list * (Exp.t * Typ.t)
val trans_assertion : trans_state -> Location.t -> trans_result
@ -88,15 +87,14 @@ val contains_opaque_value_expr : Clang_ast_t.stmt -> bool
val get_decl_ref_info : Clang_ast_t.stmt -> Clang_ast_t.decl_ref
val builtin_trans :
trans_state -> Location.t -> Clang_ast_t.stmt_info -> Typ.t -> trans_result list
-> Typ.Procname.t -> trans_result option
trans_state -> Location.t -> trans_result list -> Typ.Procname.t -> trans_result option
val cxx_method_builtin_trans :
trans_state -> Location.t -> trans_result list -> Typ.Procname.t -> trans_result option
val alloc_trans :
trans_state -> alloc_builtin:Typ.Procname.t -> ?alloc_source_function:Typ.Procname.t
-> Location.t -> Clang_ast_t.stmt_info -> Typ.t -> trans_result
trans_state -> alloc_builtin:Typ.Procname.t -> Location.t -> Clang_ast_t.stmt_info -> Typ.t
-> trans_result
val new_or_alloc_trans :
trans_state -> Location.t -> Clang_ast_t.stmt_info -> Clang_ast_t.qual_type -> Typ.Name.t option
@ -104,9 +102,6 @@ val new_or_alloc_trans :
val cpp_new_trans : Location.t -> Typ.t -> Exp.t option -> trans_result
val cast_trans :
(Exp.t * Typ.t) list -> Location.t -> Typ.t -> Typ.Procname.t -> (Sil.instr * Exp.t) option
val dereference_var_sil : Exp.t * Typ.t -> Location.t -> Sil.instr list * Exp.t
(** Module for creating cfg nodes and other utility functions related to them. *)

@ -73,14 +73,9 @@ codetoanalyze/objc/errors/subtyping/KindOfClassExample.m, shouldThrowDivideByZer
codetoanalyze/objc/errors/subtyping/KindOfClassExample.m, shouldThrowDivideByZero2, 2, DIVIDE_BY_ZERO, [start of procedure shouldThrowDivideByZero2(),start of procedure init,return from a call to Base_init,start of procedure returnsZero2(),Condition is false,return from a call to returnsZero2]
codetoanalyze/objc/errors/subtyping/KindOfClassExample.m, shouldThrowDivideByZero3, 3, DIVIDE_BY_ZERO, [start of procedure shouldThrowDivideByZero3(),start of procedure init,return from a call to Derived_init,Condition is true]
codetoanalyze/objc/errors/variadic_methods/premature_nil_termination.m, PrematureNilTermA_nilInArrayWithObjects, 5, PREMATURE_NIL_TERMINATION_ARGUMENT, [start of procedure nilInArrayWithObjects]
codetoanalyze/objc/shared/memory_leaks_benchmark/TollBridgeExample.m, TollBridgeExample_brideRetained, 2, MEMORY_LEAK, [start of procedure brideRetained]
codetoanalyze/objc/shared/memory_leaks_benchmark/TollBridgeExample.m, TollBridgeExample_bridge, 2, MEMORY_LEAK, [start of procedure bridge]
codetoanalyze/objc/errors/memory_leaks_benchmark/NSData_models_tests.m, NSData_models_tests_macForIV:, 2, MEMORY_LEAK, [start of procedure macForIV:]
codetoanalyze/objc/errors/memory_leaks_benchmark/NSString_models_tests.m, StringInitA_hexStringValue, 11, MEMORY_LEAK, [start of procedure hexStringValue,Skipping CFStringCreateWithBytesNoCopy(): function or method not found,Condition is false]
codetoanalyze/objc/errors/npe/Fraction.m, test_virtual_call, 7, NULL_DEREFERENCE, [start of procedure test_virtual_call(),start of procedure setNumerator:,return from a call to Fraction_setNumerator:,start of procedure getNumerator,return from a call to Fraction_getNumerator,Condition is true]
codetoanalyze/objc/errors/npe/NPD_core_foundation.m, NullDeref_createCloseCrossGlyphNoLeak:, 5, Assert_failure, [start of procedure createCloseCrossGlyphNoLeak:,Skipping CGRectGetHeight(): function or method not found]
codetoanalyze/objc/errors/npe/NPD_core_foundation.m, NullDeref_layoutSubviews, 4, Assert_failure, [start of procedure layoutSubviews]
codetoanalyze/objc/errors/npe/NPD_core_foundation.m, NullDeref_measureFrameSizeForTextNoLeak, 4, Assert_failure, [start of procedure measureFrameSizeForTextNoLeak,Condition is true]
codetoanalyze/objc/errors/npe/NPD_core_foundation.m, NullDeref_test2, 2, Assert_failure, [start of procedure test2]
codetoanalyze/objc/errors/npe/Npe_with_equal_names.m, EqualNamesTest, 3, NULL_DEREFERENCE, [start of procedure EqualNamesTest(),start of procedure meth,return from a call to EqualNamesA_meth]
codetoanalyze/objc/errors/npe/block.m, BlockA_doSomethingThenCallback:, 2, PARAMETER_NOT_NULL_CHECKED, [start of procedure doSomethingThenCallback:]
codetoanalyze/objc/errors/npe/block.m, BlockA_foo, 5, NULL_DEREFERENCE, [start of procedure foo]
@ -102,13 +97,9 @@ codetoanalyze/objc/shared/block/dispatch.m, DispatchA_dispatch_a_block_variable_
codetoanalyze/objc/shared/memory_leaks_benchmark/MemoryLeakExample.m, MemoryLeakExample_blockCapturedVarLeak, 3, MEMORY_LEAK, [start of procedure blockCapturedVarLeak]
codetoanalyze/objc/shared/memory_leaks_benchmark/MemoryLeakExample.m, MemoryLeakExample_blockFreeNoLeakTODO, 3, MEMORY_LEAK, [start of procedure blockFreeNoLeakTODO]
codetoanalyze/objc/shared/memory_leaks_benchmark/MemoryLeakExample.m, MemoryLeakExample_createCloseCrossGlyph:, 2, MEMORY_LEAK, [start of procedure createCloseCrossGlyph:,Skipping CGRectGetHeight(): function or method not found]
codetoanalyze/objc/shared/memory_leaks_benchmark/MemoryLeakExample.m, MemoryLeakExample_createCloseCrossGlyphNoLeak:, 5, Assert_failure, [start of procedure createCloseCrossGlyphNoLeak:,Skipping CGRectGetHeight(): function or method not found]
codetoanalyze/objc/shared/memory_leaks_benchmark/MemoryLeakExample.m, MemoryLeakExample_measureFrameSizeForText, 1, MEMORY_LEAK, [start of procedure measureFrameSizeForText]
codetoanalyze/objc/shared/memory_leaks_benchmark/MemoryLeakExample.m, MemoryLeakExample_measureFrameSizeForTextNoLeak, 3, Assert_failure, [start of procedure measureFrameSizeForTextNoLeak]
codetoanalyze/objc/shared/memory_leaks_benchmark/MemoryLeakExample.m, MemoryLeakExample_regularLeak, 3, MEMORY_LEAK, [start of procedure regularLeak]
codetoanalyze/objc/shared/memory_leaks_benchmark/MemoryLeakExample.m, MemoryLeakExample_test, 3, MEMORY_LEAK, [start of procedure test,Skipping setShadowPath:: function or method not found]
codetoanalyze/objc/shared/memory_leaks_benchmark/MemoryLeakExample.m, MemoryLeakExample_test, 3, MEMORY_LEAK, [start of procedure test,Skipping bounds: function or method not found,Skipping setShadowPath:: function or method not found]
codetoanalyze/objc/shared/memory_leaks_benchmark/MemoryLeakExample.m, MemoryLeakExample_test1:, 1, MEMORY_LEAK, [start of procedure test1:]
codetoanalyze/objc/shared/memory_leaks_benchmark/MemoryLeakExample.m, MemoryLeakExample_test1NoLeak, 2, Assert_failure, [start of procedure test1NoLeak]
codetoanalyze/objc/shared/memory_leaks_benchmark/MemoryLeakExample.m, MemoryLeakExample_test2:, 1, MEMORY_LEAK, [start of procedure test2:]
codetoanalyze/objc/shared/memory_leaks_benchmark/MemoryLeakExample.m, MemoryLeakExample_test2NoLeak, 2, Assert_failure, [start of procedure test2NoLeak]
codetoanalyze/objc/shared/npe/Available_expr.m, Available_expr_test_no_bug, 3, NULL_DEREFERENCE, [start of procedure test_no_bug,Condition is true]

@ -0,0 +1,17 @@
/*
* Copyright (c) 2017 - present Facebook, Inc.
* All rights reserved.
*
* This source code is licensed under the BSD style license found in the
* LICENSE file in the root directory of this source tree. An additional grant
* of patent rights can be found in the PATENTS file in the same directory.
*/
#import <Foundation/Foundation.h>
static NSDictionary* dictionaryRepresentationFromCFPreferences(
NSString* preferencesID) {
CFStringRef ID = (__bridge CFStringRef)preferencesID;
return (__bridge_transfer NSDictionary*)CFPreferencesCopyMultiple(
NULL, ID, kCFPreferencesCurrentUser, kCFPreferencesAnyHost);
}

@ -7,7 +7,7 @@ digraph iCFG {
"measureFrameSizeForText#MemoryLeakExample#class.f59bd9e59cef3fd16475487a380b3804_2" [label="2: Exit MemoryLeakExample_measureFrameSizeForText \n " color=yellow style=filled]
"measureFrameSizeForText#MemoryLeakExample#class.f59bd9e59cef3fd16475487a380b3804_3" [label="3: Call alloc \n n$14=_fun___objc_alloc_no_fail(sizeof(t=__CFAttributedString):unsigned long,_fun_CFAttributedStringCreateMutable:void) [line 35, column 3]\n " shape="box"]
"measureFrameSizeForText#MemoryLeakExample#class.f59bd9e59cef3fd16475487a380b3804_3" [label="3: Call _fun_CFAttributedStringCreateMutable \n n$14=_fun_CFAttributedStringCreateMutable(null:__CFAllocator const *,0:long) [line 35, column 3]\n " shape="box"]
"measureFrameSizeForText#MemoryLeakExample#class.f59bd9e59cef3fd16475487a380b3804_3" -> "measureFrameSizeForText#MemoryLeakExample#class.f59bd9e59cef3fd16475487a380b3804_2" ;
@ -18,11 +18,11 @@ digraph iCFG {
"measureFrameSizeForTextNoLeak#MemoryLeakExample#class.9443bec011166230e1709abbe3c930d4_2" [label="2: Exit MemoryLeakExample_measureFrameSizeForTextNoLeak \n " color=yellow style=filled]
"measureFrameSizeForTextNoLeak#MemoryLeakExample#class.9443bec011166230e1709abbe3c930d4_3" [label="3: Call _fun___objc_release_cf \n n$15=*&maString:__CFAttributedString* [line 41, column 13]\n _fun___objc_release_cf(1:_Bool,n$15:void const *) [line 41, column 3]\n " shape="box"]
"measureFrameSizeForTextNoLeak#MemoryLeakExample#class.9443bec011166230e1709abbe3c930d4_3" [label="3: Call _fun_CFRelease \n n$15=*&maString:__CFAttributedString* [line 41, column 13]\n _fun_CFRelease(n$15:void const *) [line 41, column 3]\n " shape="box"]
"measureFrameSizeForTextNoLeak#MemoryLeakExample#class.9443bec011166230e1709abbe3c930d4_3" -> "measureFrameSizeForTextNoLeak#MemoryLeakExample#class.9443bec011166230e1709abbe3c930d4_2" ;
"measureFrameSizeForTextNoLeak#MemoryLeakExample#class.9443bec011166230e1709abbe3c930d4_4" [label="4: DeclStmt \n n$16=_fun___objc_alloc_no_fail(sizeof(t=__CFAttributedString):unsigned long,_fun_CFAttributedStringCreateMutable:void) [line 40, column 7]\n *&maString:__CFAttributedString*=n$16 [line 39, column 3]\n " shape="box"]
"measureFrameSizeForTextNoLeak#MemoryLeakExample#class.9443bec011166230e1709abbe3c930d4_4" [label="4: DeclStmt \n n$16=_fun_CFAttributedStringCreateMutable(null:__CFAllocator const *,0:long) [line 40, column 7]\n *&maString:__CFAttributedString*=n$16 [line 39, column 3]\n " shape="box"]
"measureFrameSizeForTextNoLeak#MemoryLeakExample#class.9443bec011166230e1709abbe3c930d4_4" -> "measureFrameSizeForTextNoLeak#MemoryLeakExample#class.9443bec011166230e1709abbe3c930d4_3" ;
@ -33,7 +33,7 @@ digraph iCFG {
"test1NoLeak#MemoryLeakExample#class.7e0d9640dbd86a21622e801793707bd9_2" [label="2: Exit MemoryLeakExample_test1NoLeak \n " color=yellow style=filled]
"test1NoLeak#MemoryLeakExample#class.7e0d9640dbd86a21622e801793707bd9_3" [label="3: Call _fun___objc_release_cf \n n$19=*&framesetter:__CTFramesetter const * [line 50, column 13]\n _fun___objc_release_cf(1:_Bool,n$19:void const *) [line 50, column 3]\n " shape="box"]
"test1NoLeak#MemoryLeakExample#class.7e0d9640dbd86a21622e801793707bd9_3" [label="3: Call _fun_CFRelease \n n$19=*&framesetter:__CTFramesetter const * [line 50, column 13]\n _fun_CFRelease(n$19:void const *) [line 50, column 3]\n " shape="box"]
"test1NoLeak#MemoryLeakExample#class.7e0d9640dbd86a21622e801793707bd9_3" -> "test1NoLeak#MemoryLeakExample#class.7e0d9640dbd86a21622e801793707bd9_2" ;
@ -48,7 +48,7 @@ digraph iCFG {
"test2NoLeak#MemoryLeakExample#class.69cf0c35f7df26deefa723cac655894d_2" [label="2: Exit MemoryLeakExample_test2NoLeak \n " color=yellow style=filled]
"test2NoLeak#MemoryLeakExample#class.69cf0c35f7df26deefa723cac655894d_3" [label="3: Call _fun___objc_release_cf \n n$30=*&allowedPublicKey:__SecKey* [line 72, column 13]\n _fun___objc_release_cf(1:_Bool,n$30:void const *) [line 72, column 3]\n " shape="box"]
"test2NoLeak#MemoryLeakExample#class.69cf0c35f7df26deefa723cac655894d_3" [label="3: Call _fun_CFRelease \n n$30=*&allowedPublicKey:__SecKey* [line 72, column 13]\n _fun_CFRelease(n$30:void const *) [line 72, column 3]\n " shape="box"]
"test2NoLeak#MemoryLeakExample#class.69cf0c35f7df26deefa723cac655894d_3" -> "test2NoLeak#MemoryLeakExample#class.69cf0c35f7df26deefa723cac655894d_2" ;
@ -78,7 +78,7 @@ digraph iCFG {
"createCloseCrossGlyph:#MemoryLeakExample#class.b78475cbe035b221b50538a8aad3c9cf_2" [label="2: Exit MemoryLeakExample_createCloseCrossGlyph: \n " color=yellow style=filled]
"createCloseCrossGlyph:#MemoryLeakExample#class.b78475cbe035b221b50538a8aad3c9cf_3" [label="3: Call alloc \n n$21=_fun___objc_alloc_no_fail(sizeof(t=CGPath):unsigned long,_fun_CGPathCreateMutable:void) [line 55, column 3]\n " shape="box"]
"createCloseCrossGlyph:#MemoryLeakExample#class.b78475cbe035b221b50538a8aad3c9cf_3" [label="3: Call _fun_CGPathCreateMutable \n n$21=_fun_CGPathCreateMutable() [line 55, column 3]\n " shape="box"]
"createCloseCrossGlyph:#MemoryLeakExample#class.b78475cbe035b221b50538a8aad3c9cf_3" -> "createCloseCrossGlyph:#MemoryLeakExample#class.b78475cbe035b221b50538a8aad3c9cf_2" ;
@ -93,11 +93,11 @@ digraph iCFG {
"createCloseCrossGlyphNoLeak:#MemoryLeakExample#class.0954bcd442044fd9788af38303a3790b_2" [label="2: Exit MemoryLeakExample_createCloseCrossGlyphNoLeak: \n " color=yellow style=filled]
"createCloseCrossGlyphNoLeak:#MemoryLeakExample#class.0954bcd442044fd9788af38303a3790b_3" [label="3: Call _fun___objc_release_cf \n n$24=*&path1:CGPath* [line 63, column 13]\n _fun___objc_release_cf(1:_Bool,n$24:void const *) [line 63, column 3]\n " shape="box"]
"createCloseCrossGlyphNoLeak:#MemoryLeakExample#class.0954bcd442044fd9788af38303a3790b_3" [label="3: Call _fun_CFRelease \n n$24=*&path1:CGPath* [line 63, column 13]\n _fun_CFRelease(n$24:void const *) [line 63, column 3]\n " shape="box"]
"createCloseCrossGlyphNoLeak:#MemoryLeakExample#class.0954bcd442044fd9788af38303a3790b_3" -> "createCloseCrossGlyphNoLeak:#MemoryLeakExample#class.0954bcd442044fd9788af38303a3790b_2" ;
"createCloseCrossGlyphNoLeak:#MemoryLeakExample#class.0954bcd442044fd9788af38303a3790b_4" [label="4: DeclStmt \n n$25=_fun___objc_alloc_no_fail(sizeof(t=CGPath):unsigned long,_fun_CGPathCreateMutable:void) [line 62, column 28]\n *&path1:CGPath*=n$25 [line 62, column 3]\n " shape="box"]
"createCloseCrossGlyphNoLeak:#MemoryLeakExample#class.0954bcd442044fd9788af38303a3790b_4" [label="4: DeclStmt \n n$25=_fun_CGPathCreateMutable() [line 62, column 28]\n *&path1:CGPath*=n$25 [line 62, column 3]\n " shape="box"]
"createCloseCrossGlyphNoLeak:#MemoryLeakExample#class.0954bcd442044fd9788af38303a3790b_4" -> "createCloseCrossGlyphNoLeak:#MemoryLeakExample#class.0954bcd442044fd9788af38303a3790b_3" ;
@ -120,7 +120,7 @@ digraph iCFG {
"layoutSubviews#MemoryLeakExample#instance.2b3151f18431bcdbc08267ea4ff96f53_4" -> "layoutSubviews#MemoryLeakExample#instance.2b3151f18431bcdbc08267ea4ff96f53_3" ;
"layoutSubviews#MemoryLeakExample#instance.2b3151f18431bcdbc08267ea4ff96f53_5" [label="5: DeclStmt \n n$4=_fun___objc_alloc_no_fail(sizeof(t=CGPath const ):unsigned long,_fun_CGPathCreateWithRect:void) [line 22, column 7]\n *&shadowPath:CGPath const *=n$4 [line 21, column 3]\n " shape="box"]
"layoutSubviews#MemoryLeakExample#instance.2b3151f18431bcdbc08267ea4ff96f53_5" [label="5: DeclStmt \n n$2=*&attachmentContainerView:UIView* [line 22, column 28]\n n$3=_fun_UIView_bounds(n$2:UIView*) [line 22, column 52]\n n$4=_fun_CGPathCreateWithRect(n$3:CGRect,null:CGAffineTransform const *) [line 22, column 7]\n *&shadowPath:CGPath const *=n$4 [line 21, column 3]\n " shape="box"]
"layoutSubviews#MemoryLeakExample#instance.2b3151f18431bcdbc08267ea4ff96f53_5" -> "layoutSubviews#MemoryLeakExample#instance.2b3151f18431bcdbc08267ea4ff96f53_4" ;
@ -139,7 +139,7 @@ digraph iCFG {
"test#MemoryLeakExample#instance.cbb708bfe735ac5e5777524359299e00_3" -> "test#MemoryLeakExample#instance.cbb708bfe735ac5e5777524359299e00_2" ;
"test#MemoryLeakExample#instance.cbb708bfe735ac5e5777524359299e00_4" [label="4: DeclStmt \n n$13=_fun___objc_alloc_no_fail(sizeof(t=CGPath const ):unsigned long,_fun_CGPathCreateWithRect:void) [line 30, column 7]\n *&shadowPath:CGPath const *=n$13 [line 29, column 3]\n " shape="box"]
"test#MemoryLeakExample#instance.cbb708bfe735ac5e5777524359299e00_4" [label="4: DeclStmt \n n$10=*&self:MemoryLeakExample* [line 30, column 28]\n n$11=_fun_MemoryLeakExample_backgroundCoveringView(n$10:MemoryLeakExample*) [line 30, column 33]\n n$12=_fun_UIView_bounds(n$11:UIView*) [line 30, column 56]\n n$13=_fun_CGPathCreateWithRect(n$12:CGRect,null:CGAffineTransform const *) [line 30, column 7]\n *&shadowPath:CGPath const *=n$13 [line 29, column 3]\n " shape="box"]
"test#MemoryLeakExample#instance.cbb708bfe735ac5e5777524359299e00_4" -> "test#MemoryLeakExample#instance.cbb708bfe735ac5e5777524359299e00_3" ;

@ -7,7 +7,7 @@ digraph iCFG {
"cfautorelease_test.2ccea2233b65cd3828a2d5e2571ad69b_2" [label="2: Exit cfautorelease_test \n " color=yellow style=filled]
"cfautorelease_test.2ccea2233b65cd3828a2d5e2571ad69b_3" [label="3: Return Stmt \n n$0=_fun___builtin___CFStringMakeConstantString(\"Icon\":char const *) [line 41, column 45]\n n$1=_fun_CTFontCreateWithName(n$0:__CFString const *,17.000000:double,null:CGAffineTransform const *) [line 41, column 24]\n n$2=_fun___objc_cast(n$1:void const *,sizeof(t=void const ):unsigned long) [line 41, column 10]\n *&return:__CTFont const *=n$2 [line 41, column 3]\n " shape="box"]
"cfautorelease_test.2ccea2233b65cd3828a2d5e2571ad69b_3" [label="3: Return Stmt \n n$0=_fun___builtin___CFStringMakeConstantString(\"Icon\":char const *) [line 41, column 45]\n n$1=_fun_CTFontCreateWithName(n$0:__CFString const *,17.000000:double,null:CGAffineTransform const *) [line 41, column 24]\n n$2=_fun_CFAutorelease(n$1:void const *) [line 41, column 10]\n *&return:__CTFont const *=n$2 [line 41, column 3]\n " shape="box"]
"cfautorelease_test.2ccea2233b65cd3828a2d5e2571ad69b_3" -> "cfautorelease_test.2ccea2233b65cd3828a2d5e2571ad69b_2" ;
@ -33,7 +33,7 @@ digraph iCFG {
"bridgeTransfer#TollBridgeExample#instance.d0065913beb197e891ef0d8a0bb81b38_2" [label="2: Exit TollBridgeExample_bridgeTransfer \n " color=yellow style=filled]
"bridgeTransfer#TollBridgeExample#instance.d0065913beb197e891ef0d8a0bb81b38_3" [label="3: DeclStmt \n n$0=*&nameRef:__CFLocale const * [line 21, column 46]\n *&a:NSLocale*=n$0 [line 21, column 3]\n " shape="box"]
"bridgeTransfer#TollBridgeExample#instance.d0065913beb197e891ef0d8a0bb81b38_3" [label="3: DeclStmt \n n$0=*&nameRef:__CFLocale const * [line 21, column 46]\n _fun___free_cf(n$0:__CFLocale const *) [line 21, column 17]\n *&a:NSLocale*=n$0 [line 21, column 3]\n " shape="box"]
"bridgeTransfer#TollBridgeExample#instance.d0065913beb197e891ef0d8a0bb81b38_3" -> "bridgeTransfer#TollBridgeExample#instance.d0065913beb197e891ef0d8a0bb81b38_2" ;
@ -48,7 +48,7 @@ digraph iCFG {
"bridge#TollBridgeExample#instance.fadd5a014118113c960fa1a6e3ff27ba_2" [label="2: Exit TollBridgeExample_bridge \n " color=yellow style=filled]
"bridge#TollBridgeExample#instance.fadd5a014118113c960fa1a6e3ff27ba_3" [label="3: DeclStmt \n n$2=*&nameRef:__CFLocale const * [line 26, column 37]\n *&a:NSLocale*=n$2 [line 26, column 3]\n " shape="box"]
"bridge#TollBridgeExample#instance.fadd5a014118113c960fa1a6e3ff27ba_3" [label="3: DeclStmt \n n$2=*&nameRef:__CFLocale const * [line 26, column 37]\n _fun___free_cf(n$2:__CFLocale const *) [line 26, column 17]\n *&a:NSLocale*=n$2 [line 26, column 3]\n " shape="box"]
"bridge#TollBridgeExample#instance.fadd5a014118113c960fa1a6e3ff27ba_3" -> "bridge#TollBridgeExample#instance.fadd5a014118113c960fa1a6e3ff27ba_2" ;
@ -78,7 +78,7 @@ digraph iCFG {
"_readHTTPHeader#TollBridgeExample#instance.3d37ce88cf13750e89ba404865a70554_2" [label="2: Exit TollBridgeExample__readHTTPHeader \n " color=yellow style=filled]
"_readHTTPHeader#TollBridgeExample#instance.3d37ce88cf13750e89ba404865a70554_3" [label="3: Call _fun_CFBridgingRelease \n n$6=*&ref:__CFDictionary const * [line 37, column 21]\n n$7=_fun___objc_cast(n$6:void const *,sizeof(t=objc_object):unsigned long) [line 37, column 3]\n " shape="box"]
"_readHTTPHeader#TollBridgeExample#instance.3d37ce88cf13750e89ba404865a70554_3" [label="3: Call _fun_CFBridgingRelease \n n$6=*&ref:__CFDictionary const * [line 37, column 21]\n n$7=_fun_CFBridgingRelease(n$6:void const *) [line 37, column 3]\n " shape="box"]
"_readHTTPHeader#TollBridgeExample#instance.3d37ce88cf13750e89ba404865a70554_3" -> "_readHTTPHeader#TollBridgeExample#instance.3d37ce88cf13750e89ba404865a70554_2" ;

Loading…
Cancel
Save