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 3 typedef const struct __CFAllocator * CFAllocatorRef; 4 typedef const struct __CFString * CFStringRef; 5 typedef unsigned char Boolean; 6 typedef signed long CFIndex; 7 extern 8 const CFAllocatorRef kCFAllocatorDefault; 9 typedef const void * (*CFArrayRetainCallBack)(CFAllocatorRef allocator, const void *value); 10 typedef void (*CFArrayReleaseCallBack)(CFAllocatorRef allocator, const void *value); 11 typedef CFStringRef (*CFArrayCopyDescriptionCallBack)(const void *value); 12 typedef Boolean (*CFArrayEqualCallBack)(const void *value1, const void *value2); 13 typedef struct { 14 CFIndex version; 15 CFArrayRetainCallBack retain; 16 CFArrayReleaseCallBack release; 17 CFArrayCopyDescriptionCallBack copyDescription; 18 CFArrayEqualCallBack equal; 19 } CFArrayCallBacks; 20 typedef const struct __CFArray * CFArrayRef; 21 CFArrayRef CFArrayCreate(CFAllocatorRef allocator, const void **values, CFIndex numValues, const CFArrayCallBacks *callBacks); 22 typedef const struct __CFString * CFStringRef; 23 enum { 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 }; 42 typedef CFIndex CFNumberType; 43 typedef const struct __CFNumber * CFNumberRef; 44 typedef CFIndex CFComparisonResult; 45 typedef const struct __CFDictionary * CFDictionaryRef; 46 typedef const void * (*CFDictionaryRetainCallBack)(CFAllocatorRef allocator, const void *value); 47 typedef void (*CFDictionaryReleaseCallBack)(CFAllocatorRef allocator, const void *value); 48 typedef CFStringRef (*CFDictionaryCopyDescriptionCallBack)(const void *value); 49 typedef Boolean (*CFDictionaryEqualCallBack)(const void *value1, const void *value2); 50 typedef Boolean (*CFArrayEqualCallBack)(const void *value1, const void *value2); 51 typedef Boolean (*CFSetEqualCallBack)(const void *value1, const void *value2); 52 typedef const void * (*CFSetRetainCallBack)(CFAllocatorRef allocator, const void *value); 53 typedef void (*CFSetReleaseCallBack)(CFAllocatorRef allocator, const void *value); 54 typedef CFStringRef (*CFSetCopyDescriptionCallBack)(const void *value); 55 typedef struct { 56 CFIndex version; 57 CFSetRetainCallBack retain; 58 CFSetReleaseCallBack release; 59 CFSetCopyDescriptionCallBack copyDescription; 60 CFSetEqualCallBack equal; 61 } CFSetCallBacks; 62 typedef struct { 63 CFIndex version; 64 CFDictionaryRetainCallBack retain; 65 CFDictionaryReleaseCallBack release; 66 CFDictionaryCopyDescriptionCallBack copyDescription; 67 CFDictionaryEqualCallBack equal; 68 } CFDictionaryKeyCallBacks; 69 typedef struct { 70 CFIndex version; 71 CFDictionaryRetainCallBack retain; 72 CFDictionaryReleaseCallBack release; 73 CFDictionaryCopyDescriptionCallBack copyDescription; 74 CFDictionaryEqualCallBack equal; 75 } CFDictionaryValueCallBacks; 76 CFDictionaryRef CFDictionaryCreate(CFAllocatorRef allocator, const void **keys, const void **values, CFIndex numValues, const CFDictionaryKeyCallBacks *keyCallBacks, const CFDictionaryValueCallBacks *valueCallBacks); 77 extern 78 const CFDictionaryValueCallBacks kCFTypeDictionaryValueCallBacks; 79 typedef const struct __CFSet * CFSetRef; 80 extern 81 const CFSetCallBacks kCFTypeSetCallBacks; 82 extern 83 const CFDictionaryKeyCallBacks kCFCopyStringDictionaryKeyCallBacks; 84 extern 85 const void *CFArrayGetValueAtIndex(CFArrayRef theArray, CFIndex idx); 86 extern 87 CFIndex CFArrayGetCount(CFArrayRef theArray); 88 CFDictionaryRef CFDictionaryCreate(CFAllocatorRef allocator, const void **keys, const void **values, CFIndex numValues, const 89 CFDictionaryKeyCallBacks *keyCallBacks, const CFDictionaryValueCallBacks *valueCallBacks); 90 CFNumberRef CFNumberCreate(CFAllocatorRef allocator, CFNumberType theType, const void *valuePtr); 91 extern 92 CFSetRef 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. 98 void 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 111 void 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 132 void 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 140 void 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 154 void 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 161 void 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 168 typedef void* XX[3]; 169 void 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 187 void 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 196 void 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 202 void TestNullArray() { 203 CFArrayGetValueAtIndex(0, 0); 204 } 205