unix-fns.c revision 368f3b070e8cb657a65bfa443d60256676d269e7
1// RUN: %clang_cc1 -triple x86_64-apple-darwin10 -analyze -analyzer-checker=core,unix.API,osx.API %s -analyzer-store=region -analyzer-output=plist -analyzer-ipa=inlining -analyzer-eagerly-assume -analyzer-config faux-bodies=true -fblocks -verify -o %t.plist 2// RUN: FileCheck --input-file=%t.plist %s 3 4struct _opaque_pthread_once_t { 5 long __sig; 6 char __opaque[8]; 7}; 8typedef struct _opaque_pthread_once_t __darwin_pthread_once_t; 9typedef __darwin_pthread_once_t pthread_once_t; 10int pthread_once(pthread_once_t *, void (*)(void)); 11typedef long unsigned int __darwin_size_t; 12typedef __darwin_size_t size_t; 13void *calloc(size_t, size_t); 14void *malloc(size_t); 15void *realloc(void *, size_t); 16void *reallocf(void *, size_t); 17void *alloca(size_t); 18void *valloc(size_t); 19 20typedef union { 21 struct _os_object_s *_os_obj; 22 struct dispatch_object_s *_do; 23 struct dispatch_continuation_s *_dc; 24 struct dispatch_queue_s *_dq; 25 struct dispatch_queue_attr_s *_dqa; 26 struct dispatch_group_s *_dg; 27 struct dispatch_source_s *_ds; 28 struct dispatch_source_attr_s *_dsa; 29 struct dispatch_semaphore_s *_dsema; 30 struct dispatch_data_s *_ddata; 31 struct dispatch_io_s *_dchannel; 32 struct dispatch_operation_s *_doperation; 33 struct dispatch_disk_s *_ddisk; 34} dispatch_object_t __attribute__((__transparent_union__)); 35 36typedef void (^dispatch_block_t)(void); 37typedef long dispatch_once_t; 38typedef struct dispatch_queue_s *dispatch_queue_t; 39void dispatch_once(dispatch_once_t *predicate, dispatch_block_t block); 40void dispatch_sync(dispatch_queue_t queue, dispatch_block_t block); 41 42#ifndef O_CREAT 43#define O_CREAT 0x0200 44#define O_RDONLY 0x0000 45#endif 46int open(const char *, int, ...); 47int close(int fildes); 48 49void test_open(const char *path) { 50 int fd; 51 fd = open(path, O_RDONLY); // no-warning 52 if (!fd) 53 close(fd); 54 55 fd = open(path, O_CREAT); // expected-warning{{Call to 'open' requires a third argument when the 'O_CREAT' flag is set}} 56 if (!fd) 57 close(fd); 58} 59 60void test_dispatch_once() { 61 dispatch_once_t pred = 0; 62 do { if (__builtin_expect(*(&pred), ~0l) != ~0l) dispatch_once((&pred), (^() {})); } while (0); // expected-warning{{Call to 'dispatch_once' uses the local variable 'pred' for the predicate value}} 63} 64void test_dispatch_once_neg() { 65 static dispatch_once_t pred = 0; 66 do { if (__builtin_expect(*(&pred), ~0l) != ~0l) dispatch_once((&pred), (^() {})); } while (0); // no-warning 67} 68 69void test_pthread_once_aux(); 70 71void test_pthread_once() { 72 pthread_once_t pred = {0x30B1BCBA, {0}}; 73 pthread_once(&pred, test_pthread_once_aux); // expected-warning{{Call to 'pthread_once' uses the local variable 'pred' for the "control" value}} 74} 75void test_pthread_once_neg() { 76 static pthread_once_t pred = {0x30B1BCBA, {0}}; 77 pthread_once(&pred, test_pthread_once_aux); // no-warning 78} 79 80// PR 2899 - warn of zero-sized allocations to malloc(). 81void pr2899() { 82 char* foo = malloc(0); // expected-warning{{Call to 'malloc' has an allocation size of 0 bytes}} 83 for (unsigned i = 0; i < 100; i++) { 84 foo[i] = 0; 85 } 86} 87void pr2899_nowarn(size_t size) { 88 char* foo = malloc(size); // no-warning 89 for (unsigned i = 0; i < 100; i++) { 90 foo[i] = 0; 91 } 92} 93void test_calloc(void) { 94 char *foo = calloc(0, 42); // expected-warning{{Call to 'calloc' has an allocation size of 0 bytes}} 95 for (unsigned i = 0; i < 100; i++) { 96 foo[i] = 0; 97 } 98} 99void test_calloc2(void) { 100 char *foo = calloc(42, 0); // expected-warning{{Call to 'calloc' has an allocation size of 0 bytes}} 101 for (unsigned i = 0; i < 100; i++) { 102 foo[i] = 0; 103 } 104} 105void test_calloc_nowarn(size_t nmemb, size_t size) { 106 char *foo = calloc(nmemb, size); // no-warning 107 for (unsigned i = 0; i < 100; i++) { 108 foo[i] = 0; 109 } 110} 111void test_realloc(char *ptr) { 112 char *foo = realloc(ptr, 0); // expected-warning{{Call to 'realloc' has an allocation size of 0 bytes}} 113 for (unsigned i = 0; i < 100; i++) { 114 foo[i] = 0; 115 } 116} 117void test_reallocf(char *ptr) { 118 char *foo = reallocf(ptr, 0); // expected-warning{{Call to 'reallocf' has an allocation size of 0 bytes}} 119 for (unsigned i = 0; i < 100; i++) { 120 foo[i] = 0; 121 } 122} 123void test_realloc_nowarn(char *ptr, size_t size) { 124 char *foo = realloc(ptr, size); // no-warning 125 for (unsigned i = 0; i < 100; i++) { 126 foo[i] = 0; 127 } 128} 129void test_reallocf_nowarn(char *ptr, size_t size) { 130 char *foo = reallocf(ptr, size); // no-warning 131 for (unsigned i = 0; i < 100; i++) { 132 foo[i] = 0; 133 } 134} 135void test_alloca() { 136 char *foo = alloca(0); // expected-warning{{Call to 'alloca' has an allocation size of 0 bytes}} 137 for(unsigned i = 0; i < 100; i++) { 138 foo[i] = 0; 139 } 140} 141void test_alloca_nowarn(size_t sz) { 142 char *foo = alloca(sz); // no-warning 143 for(unsigned i = 0; i < 100; i++) { 144 foo[i] = 0; 145 } 146} 147void test_builtin_alloca() { 148 char *foo2 = __builtin_alloca(0); // expected-warning{{Call to 'alloca' has an allocation size of 0 bytes}} 149 for(unsigned i = 0; i < 100; i++) { 150 foo2[i] = 0; 151 } 152} 153void test_builtin_alloca_nowarn(size_t sz) { 154 char *foo2 = __builtin_alloca(sz); // no-warning 155 for(unsigned i = 0; i < 100; i++) { 156 foo2[i] = 0; 157 } 158} 159void test_valloc() { 160 char *foo = valloc(0); // expected-warning{{Call to 'valloc' has an allocation size of 0 bytes}} 161 for(unsigned i = 0; i < 100; i++) { 162 foo[i] = 0; 163 } 164} 165void test_valloc_nowarn(size_t sz) { 166 char *foo = valloc(sz); // no-warning 167 for(unsigned i = 0; i < 100; i++) { 168 foo[i] = 0; 169 } 170} 171 172// Test dispatch_once being a macro that wraps a call to _dispatch_once, which in turn 173// calls the real dispatch_once. 174 175static inline void _dispatch_once(dispatch_once_t *predicate, dispatch_block_t block) 176{ 177 dispatch_once(predicate, block); 178} 179 180#define dispatch_once _dispatch_once 181 182void test_dispatch_once_in_macro() { 183 dispatch_once_t pred = 0; 184 dispatch_once(&pred, ^(){}); // expected-warning {{Call to 'dispatch_once' uses the local variable 'pred' for the predicate value}} 185} 186 187// Test inlining of dispatch_sync. 188void test_dispatch_sync(dispatch_queue_t queue, int *q) { 189 int *p = 0; 190 dispatch_sync(queue, ^(void){ 191 if (q) { 192 *p = 1; // expected-warning {{null pointer}} 193 } 194 }); 195} 196 197// Test inlining if dispatch_once. 198void test_inline_dispatch_once() { 199 static dispatch_once_t pred; 200 int *p = 0; 201 dispatch_once(&pred, ^(void) { 202 *p = 1; // expected-warning {{null}} 203 }); 204} 205 206