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