forked from OSchip/llvm-project
				
			tsan: better reporting for virtual-call-after-free
Previously we said that it's a data race, which is confusing if it happens in the same thread. llvm-svn: 219600
This commit is contained in:
		
							parent
							
								
									b205978100
								
							
						
					
					
						commit
						02ff8bb986
					
				| 
						 | 
				
			
			@ -70,6 +70,8 @@ static const char *ReportTypeString(ReportType typ) {
 | 
			
		|||
    return "data race on vptr (ctor/dtor vs virtual call)";
 | 
			
		||||
  if (typ == ReportTypeUseAfterFree)
 | 
			
		||||
    return "heap-use-after-free";
 | 
			
		||||
  if (typ == ReportTypeVptrUseAfterFree)
 | 
			
		||||
    return "heap-use-after-free (virtual call vs free)";
 | 
			
		||||
  if (typ == ReportTypeThreadLeak)
 | 
			
		||||
    return "thread leak";
 | 
			
		||||
  if (typ == ReportTypeMutexDestroyLocked)
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -22,6 +22,7 @@ enum ReportType {
 | 
			
		|||
  ReportTypeRace,
 | 
			
		||||
  ReportTypeVptrRace,
 | 
			
		||||
  ReportTypeUseAfterFree,
 | 
			
		||||
  ReportTypeVptrUseAfterFree,
 | 
			
		||||
  ReportTypeThreadLeak,
 | 
			
		||||
  ReportTypeMutexDestroyLocked,
 | 
			
		||||
  ReportTypeMutexDoubleLock,
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -627,7 +627,9 @@ void ReportRace(ThreadState *thr) {
 | 
			
		|||
  ThreadRegistryLock l0(ctx->thread_registry);
 | 
			
		||||
 | 
			
		||||
  ReportType typ = ReportTypeRace;
 | 
			
		||||
  if (thr->is_vptr_access)
 | 
			
		||||
  if (thr->is_vptr_access && freed)
 | 
			
		||||
    typ = ReportTypeVptrUseAfterFree;
 | 
			
		||||
  else if (thr->is_vptr_access)
 | 
			
		||||
    typ = ReportTypeVptrRace;
 | 
			
		||||
  else if (freed)
 | 
			
		||||
    typ = ReportTypeUseAfterFree;
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -60,6 +60,8 @@ SuppressionType conv(ReportType typ) {
 | 
			
		|||
    return SuppressionRace;
 | 
			
		||||
  else if (typ == ReportTypeUseAfterFree)
 | 
			
		||||
    return SuppressionRace;
 | 
			
		||||
  else if (typ == ReportTypeVptrUseAfterFree)
 | 
			
		||||
    return SuppressionRace;
 | 
			
		||||
  else if (typ == ReportTypeThreadLeak)
 | 
			
		||||
    return SuppressionThread;
 | 
			
		||||
  else if (typ == ReportTypeMutexDestroyLocked)
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -0,0 +1,34 @@
 | 
			
		|||
// RUN: %clangxx_tsan -O1 %s -o %t && %deflake %run %t | FileCheck %s
 | 
			
		||||
#include <pthread.h>
 | 
			
		||||
#include <stdio.h>
 | 
			
		||||
#include <unistd.h>
 | 
			
		||||
 | 
			
		||||
struct A {
 | 
			
		||||
  virtual void F() {
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  virtual ~A() {
 | 
			
		||||
  }
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
struct B : A {
 | 
			
		||||
  virtual void F() {
 | 
			
		||||
  }
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
void *Thread(void *x) {
 | 
			
		||||
  sleep(1);
 | 
			
		||||
  ((A*)x)->F();
 | 
			
		||||
  return 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int main() {
 | 
			
		||||
  A *obj = new B;
 | 
			
		||||
  pthread_t t;
 | 
			
		||||
  pthread_create(&t, 0, Thread, obj);
 | 
			
		||||
  delete obj;
 | 
			
		||||
  pthread_join(t, 0);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// CHECK: WARNING: ThreadSanitizer: heap-use-after-free (virtual call vs free)
 | 
			
		||||
 | 
			
		||||
		Loading…
	
		Reference in New Issue