Merge branch 'hotfix/#803-etl-unordered_map-buffer-overflow' into development

This commit is contained in:
John Wellbelove 2024-01-25 16:35:56 +00:00
commit 1d6a068e0a
8 changed files with 181 additions and 24 deletions

View File

@ -1569,20 +1569,41 @@ namespace etl
///\return <b>true</b> if the arrays are equal, otherwise <b>false</b>
///\ingroup unordered_map
//***************************************************************************
template <typename TKey, typename T, typename TKeyCompare>
bool operator ==(const etl::iunordered_map<TKey, T, TKeyCompare>& lhs, const etl::iunordered_map<TKey, T, TKeyCompare>& rhs)
template <typename TKey, typename T, typename THash, typename TKeyEqual>
bool operator ==(const etl::iunordered_map<TKey, T, THash, TKeyEqual>& lhs,
const etl::iunordered_map<TKey, T, THash, TKeyEqual>& rhs)
{
const bool sizes_match = (lhs.size() == rhs.size());
bool elements_match = true;
typedef typename etl::iunordered_map<TKey, T, THash, TKeyEqual>::const_iterator itr_t;
if (sizes_match)
{
for (size_t i = 0; (i < lhs.bucket_count()) && elements_match; ++i)
itr_t l_begin = lhs.begin();
itr_t l_end = lhs.end();
while ((l_begin != l_end) && elements_match)
{
if (!etl::is_permutation(lhs.begin(i), lhs.end(i), rhs.begin(i)))
const TKey key = l_begin->first;
const T l_value = l_begin->second;
// See if the lhs key exists in the rhs.
ETL_OR_STD::pair<itr_t, itr_t> range = rhs.equal_range(key);
if (range.first != rhs.end())
{
// See if the values match
const T r_value = range.first->second;
elements_match = (r_value == l_value);
}
else
{
elements_match = false;
}
++l_begin;
}
}
@ -1596,8 +1617,9 @@ namespace etl
///\return <b>true</b> if the arrays are not equal, otherwise <b>false</b>
///\ingroup unordered_map
//***************************************************************************
template <typename TKey, typename T, typename TKeyCompare>
bool operator !=(const etl::iunordered_map<TKey, T, TKeyCompare>& lhs, const etl::iunordered_map<TKey, T, TKeyCompare>& rhs)
template <typename TKey, typename T, typename THash, typename TKeyEqual>
bool operator !=(const etl::iunordered_map<TKey, T, THash, TKeyEqual>& lhs,
const etl::iunordered_map<TKey, T, THash, TKeyEqual>& rhs)
{
return !(lhs == rhs);
}

View File

@ -1423,20 +1423,48 @@ namespace etl
///\return <b>true</b> if the arrays are equal, otherwise <b>false</b>
///\ingroup unordered_multimap
//***************************************************************************
template <typename TKey, typename TMapped, typename TKeyCompare>
bool operator ==(const etl::iunordered_multimap<TKey, TMapped, TKeyCompare>& lhs, const etl::iunordered_multimap<TKey, TMapped, TKeyCompare>& rhs)
template <typename TKey, typename T, typename THash, typename TKeyEqual>
bool operator ==(const etl::iunordered_multimap<TKey, T, THash, TKeyEqual>& lhs,
const etl::iunordered_multimap<TKey, T, THash, TKeyEqual>& rhs)
{
const bool sizes_match = (lhs.size() == rhs.size());
bool elements_match = true;
typedef typename etl::iunordered_multimap<TKey, T, THash, TKeyEqual>::const_iterator itr_t;
if (sizes_match)
{
for (size_t i = 0; (i < lhs.bucket_count()) && elements_match; ++i)
itr_t l_begin = lhs.begin();
itr_t l_end = lhs.end();
while ((l_begin != l_end) && elements_match)
{
if (!etl::is_permutation(lhs.begin(i), lhs.end(i), rhs.begin(i)))
const TKey key = l_begin->first;
const T l_value = l_begin->second;
// See if the lhs keys exist in the rhs.
ETL_OR_STD::pair<itr_t, itr_t> l_range = lhs.equal_range(key);
ETL_OR_STD::pair<itr_t, itr_t> r_range = rhs.equal_range(key);
if (r_range.first != rhs.end())
{
bool distance_match = (etl::distance(l_range.first, l_range.second) == etl::distance(r_range.first, r_range.second));
if (distance_match)
{
elements_match = etl::is_permutation(l_range.first, l_range.second, r_range.first, r_range.second);
}
else
{
elements_match = false;
}
}
else
{
elements_match = false;
}
++l_begin;
}
}
@ -1450,8 +1478,9 @@ namespace etl
///\return <b>true</b> if the arrays are not equal, otherwise <b>false</b>
///\ingroup unordered_multimap
//***************************************************************************
template <typename TKey, typename TMapped, typename TKeyCompare>
bool operator !=(const etl::iunordered_multimap<TKey, TMapped, TKeyCompare>& lhs, const etl::iunordered_multimap<TKey, TMapped, TKeyCompare>& rhs)
template <typename TKey, typename T, typename THash, typename TKeyEqual>
bool operator !=(const etl::iunordered_multimap<TKey, T, THash, TKeyEqual>& lhs,
const etl::iunordered_multimap<TKey, T, THash, TKeyEqual>& rhs)
{
return !(lhs == rhs);
}

View File

@ -1401,20 +1401,47 @@ namespace etl
///\return <b>true</b> if the arrays are equal, otherwise <b>false</b>
///\ingroup unordered_multiset
//***************************************************************************
template <typename TKey, typename TMapped, typename TKeyCompare>
bool operator ==(const etl::iunordered_multiset<TKey, TMapped, TKeyCompare>& lhs, const etl::iunordered_multiset<TKey, TMapped, TKeyCompare>& rhs)
template <typename TKey, typename THash = etl::hash<TKey>, typename TKeyEqual>
bool operator ==(const etl::iunordered_multiset<TKey, THash, TKeyEqual>& lhs,
const etl::iunordered_multiset<TKey, THash, TKeyEqual>& rhs)
{
const bool sizes_match = (lhs.size() == rhs.size());
bool elements_match = true;
typedef typename etl::iunordered_multiset<TKey, THash, TKeyEqual>::const_iterator itr_t;
if (sizes_match)
{
for (size_t i = 0; (i < lhs.bucket_count()) && elements_match; ++i)
itr_t l_begin = lhs.begin();
itr_t l_end = lhs.end();
while ((l_begin != l_end) && elements_match)
{
if (!etl::is_permutation(lhs.begin(i), lhs.end(i), rhs.begin(i)))
const TKey l_value = *l_begin;
// See if the lhs keys exist in the rhs.
ETL_OR_STD::pair<itr_t, itr_t> l_range = lhs.equal_range(l_value);
ETL_OR_STD::pair<itr_t, itr_t> r_range = rhs.equal_range(l_value);
if (r_range.first != rhs.end())
{
bool distance_match = (etl::distance(l_range.first, l_range.second) == etl::distance(r_range.first, r_range.second));
if (distance_match)
{
elements_match = etl::is_permutation(l_range.first, l_range.second, r_range.first, r_range.second);
}
else
{
elements_match = false;
}
}
else
{
elements_match = false;
}
++l_begin;
}
}
@ -1428,8 +1455,9 @@ namespace etl
///\return <b>true</b> if the arrays are not equal, otherwise <b>false</b>
///\ingroup unordered_multiset
//***************************************************************************
template <typename TKey, typename TMapped, typename TKeyCompare>
bool operator !=(const etl::iunordered_multiset<TKey, TMapped, TKeyCompare>& lhs, const etl::iunordered_multiset<TKey, TMapped, TKeyCompare>& rhs)
template <typename TKey, typename THash = etl::hash<TKey>, typename TKeyEqual>
bool operator !=(const etl::iunordered_multiset<TKey, THash, TKeyEqual>& lhs,
const etl::iunordered_multiset<TKey, THash, TKeyEqual>& rhs)
{
return !(lhs == rhs);
}

View File

@ -1427,20 +1427,40 @@ namespace etl
///\return <b>true</b> if the sets are equal, otherwise <b>false</b>
///\ingroup unordered_set
//***************************************************************************
template <typename TKey, typename TMapped, typename TKeyCompare>
bool operator ==(const etl::iunordered_set<TKey, TMapped, TKeyCompare>& lhs, const etl::iunordered_set<TKey, TMapped, TKeyCompare>& rhs)
template <typename TKey, typename THash, typename TKeyEqual>
bool operator ==(const etl::iunordered_set<TKey, THash, TKeyEqual>& lhs,
const etl::iunordered_set<TKey, THash, TKeyEqual>& rhs)
{
const bool sizes_match = (lhs.size() == rhs.size());
bool elements_match = true;
typedef typename etl::iunordered_set<TKey, THash, TKeyEqual>::const_iterator itr_t;
if (sizes_match)
{
for (size_t i = 0; (i < lhs.bucket_count()) && elements_match; ++i)
itr_t l_begin = lhs.begin();
itr_t l_end = lhs.end();
while ((l_begin != l_end) && elements_match)
{
if (!etl::is_permutation(lhs.begin(i), lhs.end(i), rhs.begin(i)))
const TKey l_value = *l_begin;
// See if the lhs key exists in the rhs.
ETL_OR_STD::pair<itr_t, itr_t> range = rhs.equal_range(l_value);
if (range.first != rhs.end())
{
// See if the values match
const TKey r_value = *(range.first);
elements_match = (r_value == l_value);
}
else
{
elements_match = false;
}
++l_begin;
}
}
@ -1454,8 +1474,9 @@ namespace etl
///\return <b>true</b> if the sets are not equal, otherwise <b>false</b>
///\ingroup unordered_set
//***************************************************************************
template <typename TKey, typename TMapped, typename TKeyCompare>
bool operator !=(const etl::iunordered_set<TKey, TMapped, TKeyCompare>& lhs, const etl::iunordered_set<TKey, TMapped, TKeyCompare>& rhs)
template <typename TKey, typename THash, typename TKeyEqual>
bool operator !=(const etl::iunordered_set<TKey, THash, TKeyEqual>& lhs,
const etl::iunordered_set<TKey, THash, TKeyEqual>& rhs)
{
return !(lhs == rhs);
}

View File

@ -1193,5 +1193,19 @@ namespace
using Map = etl::unordered_map<int, int, 1, 1>;
CHECK((!std::is_same<typename Map::const_iterator::value_type, typename Map::iterator::value_type>::value));
}
//*************************************************************************
TEST(test_iterator_value_types_bug_803)
{
using Map1 = etl::unordered_map<std::string, NDC, SIZE, 5>;
using Map2 = etl::unordered_map<std::string, NDC, 2 * SIZE, 10>;
Map1 map1(initial_data.begin(), initial_data.end());
Map2 map2a(initial_data.begin(), initial_data.end());
Map2 map2b(different_data.begin(), different_data.end());
CHECK_TRUE(map1 == map2a);
CHECK_FALSE(map1 == map2b);
}
};
}

View File

@ -1030,6 +1030,7 @@ namespace
CHECK((!std::is_same<typename Map::const_iterator::value_type, typename Map::iterator::value_type>::value));
}
//*************************************************************************
TEST(test_parameterized_eq)
{
constexpr std::size_t MODULO = 4;
@ -1053,5 +1054,19 @@ namespace
CHECK_EQUAL(std::distance(range.first, range.second), 3);
}
}
//*************************************************************************
TEST(test_iterator_value_types_bug_803)
{
using Map1 = etl::unordered_multimap<std::string, NDC, SIZE, 5>;
using Map2 = etl::unordered_multimap<std::string, NDC, 2 * SIZE, 10>;
Map1 map1(initial_data.begin(), initial_data.end());
Map2 map2a(initial_data.begin(), initial_data.end());
Map2 map2b(different_data.begin(), different_data.end());
CHECK_TRUE(map1 == map2a);
CHECK_FALSE(map1 == map2b);
}
};
}

View File

@ -929,5 +929,19 @@ namespace
CHECK_EQUAL(std::distance(range.first, range.second), 3);
}
}
//*************************************************************************
TEST(test_iterator_value_types_bug_803)
{
using Set1 = etl::unordered_multiset<NDC, SIZE, 5>;
using Set2 = etl::unordered_multiset<NDC, 2 * SIZE, 10>;
Set1 set1(initial_data.begin(), initial_data.end());
Set2 set2a(initial_data.begin(), initial_data.end());
Set2 set2b(different_data.begin(), different_data.end());
CHECK_TRUE(set1 == set2a);
CHECK_FALSE(set1 == set2b);
}
};
}

View File

@ -895,5 +895,19 @@ namespace
using Set = etl::unordered_set<int, 1, 1>;
CHECK((!std::is_same<typename Set::const_iterator::value_type, typename Set::iterator::value_type>::value));
}
//*************************************************************************
TEST(test_iterator_value_types_bug_803)
{
using Set1 = etl::unordered_set<NDC, SIZE, 5>;
using Set2 = etl::unordered_set<NDC, 2 * SIZE, 10>;
Set1 set1(initial_data.begin(), initial_data.end());
Set2 set2a(initial_data.begin(), initial_data.end());
Set2 set2b(different_data.begin(), different_data.end());
CHECK_TRUE(set1 == set2a);
CHECK_FALSE(set1 == set2b);
}
};
}