81 lines · c
1// RUN: %clang_analyze_cc1 -analyzer-checker=core,unix.Malloc -verify %s2//3 4typedef __SIZE_TYPE__ size_t;5 6typedef enum memory_order {7 memory_order_relaxed = __ATOMIC_RELAXED,8} memory_order;9 10void *calloc(size_t, size_t);11void free(void *);12 13struct SomeData {14 int i;15 _Atomic int ref;16};17 18static struct SomeData *alloc_data(void)19{20 struct SomeData *data = calloc(sizeof(*data), 1);21 22 __c11_atomic_store(&data->ref, 2, memory_order_relaxed);23 return data;24}25 26static void put_data(struct SomeData *data)27{28 if (__c11_atomic_fetch_sub(&data->ref, 1, memory_order_relaxed) == 1)29 free(data);30}31 32static int dec_refcounter(struct SomeData *data)33{34 return __c11_atomic_fetch_sub(&data->ref, 1, memory_order_relaxed) == 1;35}36 37static void put_data_nested(struct SomeData *data)38{39 if (dec_refcounter(data))40 free(data);41}42 43static void put_data_uncond(struct SomeData *data)44{45 free(data);46}47 48static void put_data_unrelated_atomic(struct SomeData *data)49{50 free(data);51 __c11_atomic_fetch_sub(&data->ref, 1, memory_order_relaxed);52}53 54void test_no_uaf(void)55{56 struct SomeData *data = alloc_data();57 put_data(data);58 data->i += 1; // no warning59}60 61void test_no_uaf_nested(void)62{63 struct SomeData *data = alloc_data();64 put_data_nested(data);65 data->i += 1; // no warning66}67 68void test_uaf(void)69{70 struct SomeData *data = alloc_data();71 put_data_uncond(data);72 data->i += 1; // expected-warning{{Use of memory after it is released}}73}74 75void test_no_uaf_atomic_after(void)76{77 struct SomeData *data = alloc_data();78 put_data_unrelated_atomic(data);79 data->i += 1; // expected-warning{{Use of memory after it is released}}80}81