PR12962: Fix a rare use after free when collecting virtual overrides.
The DenseMap reallocates after 64 insertions so this only happened in
large test cases under very specific circumstances.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@157549 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/lib/AST/CXXInheritance.cpp b/lib/AST/CXXInheritance.cpp
index 2186730..7e278ff 100644
--- a/lib/AST/CXXInheritance.cpp
+++ b/lib/AST/CXXInheritance.cpp
@@ -505,12 +505,17 @@
CXXFinalOverriderMap *BaseOverriders = &ComputedBaseOverriders;
if (Base->isVirtual()) {
CXXFinalOverriderMap *&MyVirtualOverriders = VirtualOverriders[BaseDecl];
+ BaseOverriders = MyVirtualOverriders;
if (!MyVirtualOverriders) {
MyVirtualOverriders = new CXXFinalOverriderMap;
+
+ // Collect may cause VirtualOverriders to reallocate, invalidating the
+ // MyVirtualOverriders reference. Set BaseOverriders to the right
+ // value now.
+ BaseOverriders = MyVirtualOverriders;
+
Collect(BaseDecl, true, BaseDecl, *MyVirtualOverriders);
}
-
- BaseOverriders = MyVirtualOverriders;
} else
Collect(BaseDecl, false, InVirtualSubobject, ComputedBaseOverriders);
diff --git a/test/SemaCXX/long-virtual-inheritance-chain.cpp b/test/SemaCXX/long-virtual-inheritance-chain.cpp
new file mode 100644
index 0000000..8599597
--- /dev/null
+++ b/test/SemaCXX/long-virtual-inheritance-chain.cpp
@@ -0,0 +1,53 @@
+// RUN: %clang_cc1 -fsyntax-only %s
+
+class test0 { virtual void f(); };
+class test1 : virtual test0 { virtual void f(); };
+class test2 : virtual test1 { virtual void f(); };
+class test3 : virtual test2 { virtual void f(); };
+class test4 : virtual test3 { virtual void f(); };
+class test5 : virtual test4 { virtual void f(); };
+class test6 : virtual test5 { virtual void f(); };
+class test7 : virtual test6 { virtual void f(); };
+class test8 : virtual test7 { virtual void f(); };
+class test9 : virtual test8 { virtual void f(); };
+class test10 : virtual test9 { virtual void f(); };
+class test11 : virtual test10 { virtual void f(); };
+class test12 : virtual test11 { virtual void f(); };
+class test13 : virtual test12 { virtual void f(); };
+class test14 : virtual test13 { virtual void f(); };
+class test15 : virtual test14 { virtual void f(); };
+class test16 : virtual test15 { virtual void f(); };
+class test17 : virtual test16 { virtual void f(); };
+class test18 : virtual test17 { virtual void f(); };
+class test19 : virtual test18 { virtual void f(); };
+class test20 : virtual test19 { virtual void f(); };
+class test21 : virtual test20 { virtual void f(); };
+class test22 : virtual test21 { virtual void f(); };
+class test23 : virtual test22 { virtual void f(); };
+class test24 : virtual test23 { virtual void f(); };
+class test25 : virtual test24 { virtual void f(); };
+class test26 : virtual test25 { virtual void f(); };
+class test27 : virtual test26 { virtual void f(); };
+class test28 : virtual test27 { virtual void f(); };
+class test29 : virtual test28 { virtual void f(); };
+class test30 : virtual test29 { virtual void f(); };
+class test31 : virtual test30 { virtual void f(); };
+class test32 : virtual test31 { virtual void f(); };
+class test33 : virtual test32 { virtual void f(); };
+class test34 : virtual test33 { virtual void f(); };
+class test35 : virtual test34 { virtual void f(); };
+class test36 : virtual test35 { virtual void f(); };
+class test37 : virtual test36 { virtual void f(); };
+class test38 : virtual test37 { virtual void f(); };
+class test39 : virtual test38 { virtual void f(); };
+class test40 : virtual test39 { virtual void f(); };
+class test41 : virtual test40 { virtual void f(); };
+class test42 : virtual test41 { virtual void f(); };
+class test43 : virtual test42 { virtual void f(); };
+class test44 : virtual test43 { virtual void f(); };
+class test45 : virtual test44 { virtual void f(); };
+class test46 : virtual test45 { virtual void f(); };
+class test47 : virtual test46 { virtual void f(); };
+class test48 : virtual test47 { virtual void f(); };
+class test49 : virtual test48 { virtual void f(); };
+class test50 : virtual test49 { virtual void f(); };