[Lldb-commits] [lldb] r339669 - Fix: ConstString::GetConstCStringAndSetMangledCounterPart() should update the value if the key exists already

Stefan Granitz via lldb-commits lldb-commits at lists.llvm.org
Tue Aug 14 04:07:18 PDT 2018


Author: stefan.graenitz
Date: Tue Aug 14 04:07:18 2018
New Revision: 339669

URL: http://llvm.org/viewvc/llvm-project?rev=339669&view=rev
Log:
Fix: ConstString::GetConstCStringAndSetMangledCounterPart() should update the value if the key exists already

Summary:
This issue came up because it caused problems in our unit tests. The StringPool did connect counterparts only once and silently ignored the values passed in subsequent calls.
The simplest solution for the unit tests would be silent overwrite. In practice, however, it seems useful to assert that we never overwrite a different mangled counterpart.
If we ever have mangled counterparts for other languages than C++, this makes it more likely to notice collisions.

I added an assertion that allows the following cases:
* inserting a new value
* overwriting the empty string
* overwriting with an identical value

I fixed the unit tests, which used "random" strings and thus produced collisions.
It would be even better if there was a way to reset or isolate the StringPool, but that's a different story.

Reviewers: jingham, friss, labath

Subscribers: lldb-commits

Differential Revision: https://reviews.llvm.org/D50536

Modified:
    lldb/trunk/source/Utility/ConstString.cpp
    lldb/trunk/unittests/Utility/ConstStringTest.cpp

Modified: lldb/trunk/source/Utility/ConstString.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Utility/ConstString.cpp?rev=339669&r1=339668&r2=339669&view=diff
==============================================================================
--- lldb/trunk/source/Utility/ConstString.cpp (original)
+++ lldb/trunk/source/Utility/ConstString.cpp Tue Aug 14 04:07:18 2018
@@ -119,11 +119,16 @@ public:
       const uint8_t h = hash(demangled);
       llvm::sys::SmartScopedWriter<false> wlock(m_string_pools[h].m_mutex);
 
-      // Make string pool entry with the mangled counterpart already set
-      StringPoolEntryType &entry =
-          *m_string_pools[h]
-               .m_string_map.insert(std::make_pair(demangled, mangled_ccstr))
-               .first;
+      // Make or update string pool entry with the mangled counterpart
+      StringPool &map = m_string_pools[h].m_string_map;
+      StringPoolEntryType &entry = *map.try_emplace(demangled).first;
+
+      assert((entry.second == nullptr || entry.second == mangled_ccstr ||
+              strlen(entry.second) == 0) &&
+             "The demangled string must have a unique counterpart or otherwise "
+             "it must be empty");
+
+      entry.second = mangled_ccstr;
 
       // Extract the const version of the demangled_cstr
       demangled_ccstr = entry.getKeyData();

Modified: lldb/trunk/unittests/Utility/ConstStringTest.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/unittests/Utility/ConstStringTest.cpp?rev=339669&r1=339668&r2=339669&view=diff
==============================================================================
--- lldb/trunk/unittests/Utility/ConstStringTest.cpp (original)
+++ lldb/trunk/unittests/Utility/ConstStringTest.cpp Tue Aug 14 04:07:18 2018
@@ -18,25 +18,45 @@ TEST(ConstStringTest, format_provider) {
 }
 
 TEST(ConstStringTest, MangledCounterpart) {
-  ConstString foo("foo");
+  ConstString uvw("uvw");
   ConstString counterpart;
-  EXPECT_FALSE(foo.GetMangledCounterpart(counterpart));
+  EXPECT_FALSE(uvw.GetMangledCounterpart(counterpart));
   EXPECT_EQ("", counterpart.GetStringRef());
 
-  ConstString bar;
-  bar.SetStringWithMangledCounterpart("bar", foo);
-  EXPECT_EQ("bar", bar.GetStringRef());
+  ConstString xyz;
+  xyz.SetStringWithMangledCounterpart("xyz", uvw);
+  EXPECT_EQ("xyz", xyz.GetStringRef());
 
-  EXPECT_TRUE(bar.GetMangledCounterpart(counterpart));
-  EXPECT_EQ("foo", counterpart.GetStringRef());
+  EXPECT_TRUE(xyz.GetMangledCounterpart(counterpart));
+  EXPECT_EQ("uvw", counterpart.GetStringRef());
 
-  EXPECT_TRUE(foo.GetMangledCounterpart(counterpart));
-  EXPECT_EQ("bar", counterpart.GetStringRef());
+  EXPECT_TRUE(uvw.GetMangledCounterpart(counterpart));
+  EXPECT_EQ("xyz", counterpart.GetStringRef());
+}
+
+TEST(ConstStringTest, UpdateMangledCounterpart) {
+  { // Add counterpart
+    ConstString some1;
+    some1.SetStringWithMangledCounterpart("some", ConstString(""));
+  }
+  { // Overwrite empty string
+    ConstString some2;
+    some2.SetStringWithMangledCounterpart("some", ConstString("one"));
+  }
+  { // Overwrite with identical value
+    ConstString some2;
+    some2.SetStringWithMangledCounterpart("some", ConstString("one"));
+  }
+  { // Check counterpart is set
+    ConstString counterpart;
+    EXPECT_TRUE(ConstString("some").GetMangledCounterpart(counterpart));
+    EXPECT_EQ("one", counterpart.GetStringRef());
+  }
 }
 
 TEST(ConstStringTest, FromMidOfBufferStringRef) {
   // StringRef's into bigger buffer: no null termination
-  const char *buffer = "foobarbaz";
+  const char *buffer = "abcdefghi";
   llvm::StringRef foo_ref(buffer, 3);
   llvm::StringRef bar_ref(buffer + 3, 3);
 
@@ -44,14 +64,14 @@ TEST(ConstStringTest, FromMidOfBufferStr
 
   ConstString bar;
   bar.SetStringWithMangledCounterpart(bar_ref, foo);
-  EXPECT_EQ("bar", bar.GetStringRef());
+  EXPECT_EQ("def", bar.GetStringRef());
 
   ConstString counterpart;
   EXPECT_TRUE(bar.GetMangledCounterpart(counterpart));
-  EXPECT_EQ("foo", counterpart.GetStringRef());
+  EXPECT_EQ("abc", counterpart.GetStringRef());
 
   EXPECT_TRUE(foo.GetMangledCounterpart(counterpart));
-  EXPECT_EQ("bar", counterpart.GetStringRef());
+  EXPECT_EQ("def", counterpart.GetStringRef());
 }
 
 TEST(ConstStringTest, NullAndEmptyStates) {




More information about the lldb-commits mailing list