[libc++] Fix type confusion in hash_{,multi}map
The type `__gnu_cxx::hash_{,multi}map` creates objects of type
`std::pair<Key, Value>` and returns pointers to them of type
`std::pair<const Key, Value>`. If either `Key` or `Value` are
non-standard-layout, this is UB, and is furthermore considered by
pointer field protection to be a type confusion, which leads to a
program crash. Fix it by using the correct type for the pair's storage
and using const_cast to form a pointer to the key in the one place where
that is needed.
Reviewers: ldionne
Reviewed By: ldionne
Pull Request: https://github.com/llvm/llvm-project/pull/183223
This commit is contained in:
committed by
GitHub
parent
c3d69eda36
commit
30084d7476
@@ -426,12 +426,10 @@ public:
|
||||
typedef const value_type& const_reference;
|
||||
|
||||
private:
|
||||
typedef std::pair<key_type, mapped_type> __value_type;
|
||||
typedef __hash_map_hasher<__value_type, hasher> __hasher;
|
||||
typedef __hash_map_equal<__value_type, key_equal> __key_equal;
|
||||
typedef std::__rebind_alloc<std::allocator_traits<allocator_type>, __value_type> __allocator_type;
|
||||
typedef __hash_map_hasher<value_type, hasher> __hasher;
|
||||
typedef __hash_map_equal<value_type, key_equal> __key_equal;
|
||||
|
||||
typedef std::__hash_table<__value_type, __hasher, __key_equal, __allocator_type> __table;
|
||||
typedef std::__hash_table<value_type, __hasher, __key_equal, allocator_type> __table;
|
||||
|
||||
__table __table_;
|
||||
|
||||
@@ -577,7 +575,7 @@ typename hash_map<_Key, _Tp, _Hash, _Pred, _Alloc>::__node_holder
|
||||
hash_map<_Key, _Tp, _Hash, _Pred, _Alloc>::__construct_node(const key_type& __k) {
|
||||
__node_allocator& __na = __table_.__node_alloc();
|
||||
__node_holder __h(__node_traits::allocate(__na, 1), _Dp(__na));
|
||||
__node_traits::construct(__na, std::addressof(__h->__get_value().first), __k);
|
||||
__node_traits::construct(__na, const_cast<_Key*>(std::addressof(__h->__get_value().first)), __k);
|
||||
__h.get_deleter().__first_constructed = true;
|
||||
__node_traits::construct(__na, std::addressof(__h->__get_value().second));
|
||||
__h.get_deleter().__second_constructed = true;
|
||||
@@ -647,12 +645,10 @@ public:
|
||||
typedef const value_type& const_reference;
|
||||
|
||||
private:
|
||||
typedef std::pair<key_type, mapped_type> __value_type;
|
||||
typedef __hash_map_hasher<__value_type, hasher> __hasher;
|
||||
typedef __hash_map_equal<__value_type, key_equal> __key_equal;
|
||||
typedef std::__rebind_alloc<std::allocator_traits<allocator_type>, __value_type> __allocator_type;
|
||||
typedef __hash_map_hasher<value_type, hasher> __hasher;
|
||||
typedef __hash_map_equal<value_type, key_equal> __key_equal;
|
||||
|
||||
typedef std::__hash_table<__value_type, __hasher, __key_equal, __allocator_type> __table;
|
||||
typedef std::__hash_table<value_type, __hasher, __key_equal, allocator_type> __table;
|
||||
|
||||
__table __table_;
|
||||
|
||||
|
||||
@@ -0,0 +1,16 @@
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
||||
// See https://llvm.org/LICENSE.txt for license information.
|
||||
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
// ADDITIONAL_COMPILE_FLAGS: -Wno-deprecated
|
||||
#include <ext/hash_map>
|
||||
|
||||
int main(int, char**) {
|
||||
__gnu_cxx::hash_map<const char*, std::string> m;
|
||||
auto it = m.insert(std::make_pair("foo", "bar")).first;
|
||||
return it->first == nullptr;
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
||||
// See https://llvm.org/LICENSE.txt for license information.
|
||||
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
// ADDITIONAL_COMPILE_FLAGS: -Wno-deprecated
|
||||
#include <ext/hash_map>
|
||||
|
||||
int main(int, char**) {
|
||||
__gnu_cxx::hash_multimap<const char*, std::string> m;
|
||||
auto it = m.insert(std::make_pair("foo", "bar"));
|
||||
return it->first == nullptr;
|
||||
}
|
||||
Reference in New Issue
Block a user