1// RUN: %clang_cc1 -analyze -analyzer-checker=osx.coreFoundation.containers.PointerSizedValues,osx.coreFoundation.containers.OutOfBounds -analyzer-store=region -triple x86_64-apple-darwin -verify %s 2 3typedef const struct __CFAllocator * CFAllocatorRef; 4typedef const struct __CFString * CFStringRef; 5typedef unsigned char Boolean; 6typedef signed long CFIndex; 7extern 8const CFAllocatorRef kCFAllocatorDefault; 9typedef const void * (*CFArrayRetainCallBack)(CFAllocatorRef allocator, const void *value); 10typedef void (*CFArrayReleaseCallBack)(CFAllocatorRef allocator, const void *value); 11typedef CFStringRef (*CFArrayCopyDescriptionCallBack)(const void *value); 12typedef Boolean (*CFArrayEqualCallBack)(const void *value1, const void *value2); 13typedef struct { 14 CFIndex version; 15 CFArrayRetainCallBack retain; 16 CFArrayReleaseCallBack release; 17 CFArrayCopyDescriptionCallBack copyDescription; 18 CFArrayEqualCallBack equal; 19} CFArrayCallBacks; 20typedef const struct __CFArray * CFArrayRef; 21CFArrayRef CFArrayCreate(CFAllocatorRef allocator, const void **values, CFIndex numValues, const CFArrayCallBacks *callBacks); 22typedef const struct __CFString * CFStringRef; 23enum { 24 kCFNumberSInt8Type = 1, 25 kCFNumberSInt16Type = 2, 26 kCFNumberSInt32Type = 3, 27 kCFNumberSInt64Type = 4, 28 kCFNumberFloat32Type = 5, 29 kCFNumberFloat64Type = 6, 30 kCFNumberCharType = 7, 31 kCFNumberShortType = 8, 32 kCFNumberIntType = 9, 33 kCFNumberLongType = 10, 34 kCFNumberLongLongType = 11, 35 kCFNumberFloatType = 12, 36 kCFNumberDoubleType = 13, 37 kCFNumberCFIndexType = 14, 38 kCFNumberNSIntegerType = 15, 39 kCFNumberCGFloatType = 16, 40 kCFNumberMaxType = 16 41}; 42typedef CFIndex CFNumberType; 43typedef const struct __CFNumber * CFNumberRef; 44typedef CFIndex CFComparisonResult; 45typedef const struct __CFDictionary * CFDictionaryRef; 46typedef const void * (*CFDictionaryRetainCallBack)(CFAllocatorRef allocator, const void *value); 47typedef void (*CFDictionaryReleaseCallBack)(CFAllocatorRef allocator, const void *value); 48typedef CFStringRef (*CFDictionaryCopyDescriptionCallBack)(const void *value); 49typedef Boolean (*CFDictionaryEqualCallBack)(const void *value1, const void *value2); 50typedef Boolean (*CFArrayEqualCallBack)(const void *value1, const void *value2); 51typedef Boolean (*CFSetEqualCallBack)(const void *value1, const void *value2); 52typedef const void * (*CFSetRetainCallBack)(CFAllocatorRef allocator, const void *value); 53typedef void (*CFSetReleaseCallBack)(CFAllocatorRef allocator, const void *value); 54typedef CFStringRef (*CFSetCopyDescriptionCallBack)(const void *value); 55typedef struct { 56 CFIndex version; 57 CFSetRetainCallBack retain; 58 CFSetReleaseCallBack release; 59 CFSetCopyDescriptionCallBack copyDescription; 60 CFSetEqualCallBack equal; 61} CFSetCallBacks; 62typedef struct { 63 CFIndex version; 64 CFDictionaryRetainCallBack retain; 65 CFDictionaryReleaseCallBack release; 66 CFDictionaryCopyDescriptionCallBack copyDescription; 67 CFDictionaryEqualCallBack equal; 68} CFDictionaryKeyCallBacks; 69typedef struct { 70 CFIndex version; 71 CFDictionaryRetainCallBack retain; 72 CFDictionaryReleaseCallBack release; 73 CFDictionaryCopyDescriptionCallBack copyDescription; 74 CFDictionaryEqualCallBack equal; 75} CFDictionaryValueCallBacks; 76CFDictionaryRef CFDictionaryCreate(CFAllocatorRef allocator, const void **keys, const void **values, CFIndex numValues, const CFDictionaryKeyCallBacks *keyCallBacks, const CFDictionaryValueCallBacks *valueCallBacks); 77extern 78const CFDictionaryValueCallBacks kCFTypeDictionaryValueCallBacks; 79typedef const struct __CFSet * CFSetRef; 80extern 81const CFSetCallBacks kCFTypeSetCallBacks; 82extern 83const CFDictionaryKeyCallBacks kCFCopyStringDictionaryKeyCallBacks; 84extern 85const void *CFArrayGetValueAtIndex(CFArrayRef theArray, CFIndex idx); 86extern 87CFIndex CFArrayGetCount(CFArrayRef theArray); 88CFDictionaryRef CFDictionaryCreate(CFAllocatorRef allocator, const void **keys, const void **values, CFIndex numValues, const 89CFDictionaryKeyCallBacks *keyCallBacks, const CFDictionaryValueCallBacks *valueCallBacks); 90CFNumberRef CFNumberCreate(CFAllocatorRef allocator, CFNumberType theType, const void *valuePtr); 91extern 92CFSetRef CFSetCreate(CFAllocatorRef allocator, const void **values, CFIndex numValues, const CFSetCallBacks *callBacks); 93#define CFSTR(cStr) ((CFStringRef) __builtin___CFStringMakeConstantString ("" cStr "")) 94#define NULL __null 95 96// Done with the headers. 97// Test alpha.osx.cocoa.ContainerAPI checker. 98void testContainers(int **xNoWarn, CFIndex count) { 99 int x[] = { 1, 2, 3 }; 100 CFArrayRef foo = CFArrayCreate(kCFAllocatorDefault, (const void **) x, sizeof(x) / sizeof(x[0]), 0);// expected-warning {{The second argument to 'CFArrayCreate' must be a C array of pointer-sized}} 101 102 CFArrayRef fooNoWarn = CFArrayCreate(kCFAllocatorDefault, (const void **) xNoWarn, sizeof(xNoWarn) / sizeof(xNoWarn[0]), 0); // no warning 103 CFArrayRef fooNoWarn2 = CFArrayCreate(kCFAllocatorDefault, 0, sizeof(xNoWarn) / sizeof(xNoWarn[0]), 0);// no warning, passing in 0 104 CFArrayRef fooNoWarn3 = CFArrayCreate(kCFAllocatorDefault, NULL, sizeof(xNoWarn) / sizeof(xNoWarn[0]), 0);// no warning, passing in NULL 105 106 CFSetRef set = CFSetCreate(NULL, (const void **)x, 3, &kCFTypeSetCallBacks); // expected-warning {{The second argument to 'CFSetCreate' must be a C array of pointer-sized values}} 107 CFArrayRef* pairs = new CFArrayRef[count]; 108 CFSetRef fSet = CFSetCreate(kCFAllocatorDefault, (const void**) pairs, count - 1, &kCFTypeSetCallBacks);// no warning 109} 110 111void CreateDict(int *elems) { 112 const short days28 = 28; 113 const short days30 = 30; 114 const short days31 = 31; 115 CFIndex numValues = 6; 116 CFStringRef keys[6]; 117 CFNumberRef values[6]; 118 keys[0] = CFSTR("January"); values[0] = CFNumberCreate(kCFAllocatorDefault, kCFNumberShortType, &days31); 119 keys[1] = CFSTR("February"); values[1] = CFNumberCreate(kCFAllocatorDefault, kCFNumberShortType, &days28); 120 keys[2] = CFSTR("March"); values[2] = CFNumberCreate(kCFAllocatorDefault, kCFNumberShortType, &days31); 121 keys[3] = CFSTR("April"); values[3] = CFNumberCreate(kCFAllocatorDefault, kCFNumberShortType, &days30); 122 keys[4] = CFSTR("May"); values[4] = CFNumberCreate(kCFAllocatorDefault, kCFNumberShortType, &days31); 123 keys[5] = CFSTR("June"); values[5] = CFNumberCreate(kCFAllocatorDefault, kCFNumberShortType, &days30); 124 125 const CFDictionaryKeyCallBacks keyCB = kCFCopyStringDictionaryKeyCallBacks; 126 const CFDictionaryValueCallBacks valCB = kCFTypeDictionaryValueCallBacks; 127 CFDictionaryRef dict1 = CFDictionaryCreate(kCFAllocatorDefault, (const void**)keys, (const void**)values, numValues, &keyCB, &valCB); // no warning 128 CFDictionaryRef dict2 = CFDictionaryCreate(kCFAllocatorDefault, (const void**)elems[0], (const void**)values, numValues, &keyCB, &valCB); //expected-warning {{The second argument to 'CFDictionaryCreate' must be a C array of}} expected-warning {{cast to 'const void **' from smaller integer type 'int'}} 129 CFDictionaryRef dict3 = CFDictionaryCreate(kCFAllocatorDefault, (const void**)keys, (const void**)elems, numValues, &keyCB, &valCB); // expected-warning {{The third argument to 'CFDictionaryCreate' must be a C array of pointer-sized values}} 130} 131 132void OutOfBoundsSymbolicOffByOne(const void ** input, CFIndex S) { 133 CFArrayRef array; 134 array = CFArrayCreate(kCFAllocatorDefault, input, S, 0); 135 const void *s1 = CFArrayGetValueAtIndex(array, 0); // no warning 136 const void *s2 = CFArrayGetValueAtIndex(array, S-1); // no warning 137 const void *s3 = CFArrayGetValueAtIndex(array, S); // expected-warning {{Index is out of bounds}} 138} 139 140void OutOfBoundsConst(const void ** input, CFIndex S) { 141 CFArrayRef array; 142 array = CFArrayCreate(kCFAllocatorDefault, input, 3, 0); 143 const void *s1 = CFArrayGetValueAtIndex(array, 0); // no warning 144 const void *s2 = CFArrayGetValueAtIndex(array, 2); // no warning 145 const void *s3 = CFArrayGetValueAtIndex(array, 5); // expected-warning {{Index is out of bounds}} 146 147 // TODO: The solver is probably not strong enough here. 148 CFIndex sIndex; 149 for (sIndex = 0 ; sIndex <= 5 ; sIndex += 3 ) { 150 const void *s = CFArrayGetValueAtIndex(array, sIndex); 151 } 152} 153 154void OutOfBoundsZiro(const void ** input, CFIndex S) { 155 CFArrayRef array; 156 // The API allows to set the size to 0. Check that we don't undeflow when the size is 0. 157 array = CFArrayCreate(kCFAllocatorDefault, 0, 0, 0); 158 const void *s1 = CFArrayGetValueAtIndex(array, 0); // expected-warning {{Index is out of bounds}} 159} 160 161void TestGetCount(CFArrayRef A, CFIndex sIndex) { 162 CFIndex sCount = CFArrayGetCount(A); 163 if (sCount > sIndex) 164 const void *s1 = CFArrayGetValueAtIndex(A, sIndex); 165 const void *s2 = CFArrayGetValueAtIndex(A, sCount);// expected-warning {{Index is out of bounds}} 166} 167 168typedef void* XX[3]; 169void TestPointerToArray(int *elems, void *p1, void *p2, void *p3, unsigned count, void* fn[], char cp[]) { 170 void* x[] = { p1, p2, p3 }; 171 CFArrayCreate(0, (const void **) &x, count, 0); // no warning 172 173 void* y[] = { p1, p2, p3 }; 174 CFArrayCreate(0, (const void **) y, count, 0); // no warning 175 XX *z = &x; 176 CFArrayCreate(0, (const void **) z, count, 0); // no warning 177 178 CFArrayCreate(0, (const void **) &fn, count, 0); // false negative 179 CFArrayCreate(0, (const void **) fn, count, 0); // no warning 180 CFArrayCreate(0, (const void **) cp, count, 0); // expected-warning {{The second argument to 'CFArrayCreate' must be a C array of pointer-sized}} 181 182 char cc[] = { 0, 2, 3 }; 183 CFArrayCreate(0, (const void **) &cc, count, 0); // expected-warning {{The second argument to 'CFArrayCreate' must be a C array of pointer-sized}} 184 CFArrayCreate(0, (const void **) cc, count, 0); // expected-warning {{The second argument to 'CFArrayCreate' must be a C array of pointer-sized}} 185} 186 187void TestUndef(CFArrayRef A, CFIndex sIndex, void* x[]) { 188 unsigned undefVal; 189 const void *s1 = CFArrayGetValueAtIndex(A, undefVal); 190 191 unsigned undefVal2; 192 CFArrayRef B = CFArrayCreate(0, (const void **) &x, undefVal2, 0); 193 const void *s2 = CFArrayGetValueAtIndex(B, 2); 194} 195 196void TestConst(CFArrayRef A, CFIndex sIndex, void* x[]) { 197 CFArrayRef B = CFArrayCreate(0, (const void **) &x, 4, 0); 198 const void *s1 = CFArrayGetValueAtIndex(B, 2); 199 200} 201 202void TestNullArray() { 203 CFArrayGetValueAtIndex(0, 0); 204} 205