Avoid a use-after-move in `QuicheLinkedHashMap::TryEmplaceInternal`. When `key` is a rvalue, `QuicheLinkedHashMap::TryEmplaceInternal` currently moves it twice: - First time into the map: `map_.try_emplace(std::forward<K>(key))` - Second time into the list: `std::forward_as_tuple(std::forward<K>(key))` This will cause the key in the list to be in the moved-from state => BUG. The fix is to replace the second move by a copy. PiperOrigin-RevId: 965986514
diff --git a/quiche/common/quiche_linked_hash_map.h b/quiche/common/quiche_linked_hash_map.h index 3932844..4d4e630 100644 --- a/quiche/common/quiche_linked_hash_map.h +++ b/quiche/common/quiche_linked_hash_map.h
@@ -231,7 +231,7 @@ auto list_iter = list_.emplace(list_.end(), std::piecewise_construct, - std::forward_as_tuple(std::forward<K>(key)), + std::forward_as_tuple(insert_result.first->first), std::forward_as_tuple(std::forward<Args>(args)...)); insert_result.first->second = list_iter;
diff --git a/quiche/common/quiche_linked_hash_map_test.cc b/quiche/common/quiche_linked_hash_map_test.cc index 98a731a..4bdb23e 100644 --- a/quiche/common/quiche_linked_hash_map_test.cc +++ b/quiche/common/quiche_linked_hash_map_test.cc
@@ -7,6 +7,7 @@ #include "quiche/common/quiche_linked_hash_map.h" #include <memory> +#include <string> #include <tuple> #include <utility> @@ -69,6 +70,16 @@ EXPECT_EQ(234, found->second.x); } +TEST(LinkedHashMapTest, TryEmplaceRvalueKey) { + QuicheLinkedHashMap<std::string, int> m; + std::string key = "hello"; + auto result = m.try_emplace(std::move(key), 42); + EXPECT_TRUE(result.second); + EXPECT_EQ(result.first->first, "hello"); + EXPECT_EQ(m.find("hello")->first, "hello"); + EXPECT_EQ(m.begin()->first, "hello"); +} + TEST(LinkedHashMapTest, ConstKeys) { QuicheLinkedHashMap<int, int> m; m.insert(std::make_pair(1, 2));