qt4_rwlock.vgtest \
qt4_semaphore.stderr.exp \
qt4_semaphore.vgtest \
+ read_after_free.stderr.exp \
+ read_after_free.vgtest \
recursive_mutex.stderr.exp-linux \
recursive_mutex.stderr.exp-darwin \
recursive_mutex.vgtest \
annotate_smart_pointer \
atomic_var \
circular_buffer \
+ read_after_free \
tsan_unittest
endif
--- /dev/null
+#define _GNU_SOURCE 1
+
+#include <assert.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <pthread.h>
+
+static char* s_mem;
+static volatile int s_freed;
+
+static void* thread_func(void* arg)
+{
+ // Busy-wait until pthread_create() has finished.
+ while (s_freed == 0)
+ pthread_yield();
+ free(s_mem);
+ __sync_add_and_fetch(&s_freed, 1);
+ return NULL;
+}
+
+int main(int argc, char** argv)
+{
+ pthread_t tid;
+ int quiet;
+ char result;
+
+ quiet = argc > 1;
+
+ s_mem = malloc(10);
+ if (!quiet)
+ fprintf(stderr, "Pointer to allocated memory: %p\n", s_mem);
+ assert(s_mem);
+ pthread_create(&tid, NULL, thread_func, NULL);
+ __sync_add_and_fetch(&s_freed, 1);
+ // Busy-wait until the memory has been freed.
+ while (s_freed == 1)
+ pthread_yield();
+ // Read-after-free.
+ result = s_mem[0];
+ if (!quiet)
+ fprintf(stderr, "Read-after-free result: %d\n", result);
+ pthread_join(tid, NULL);
+ fprintf(stderr, "Done.\n");
+ return 0;
+}
--- /dev/null
+
+Conflicting load by thread 1 at 0x........ size 1
+ at 0x........: main (read_after_free.c:?)
+Allocation context: unknown.
+
+Done.
+
+ERROR SUMMARY: 1 errors from 1 contexts (suppressed: 0 from 0)