C++: Add tests for std::map and std::unordered_map.

This commit is contained in:
Geoffrey White
2020-09-22 13:21:17 +01:00
parent 71a605b7d9
commit 49f9a76c54
5 changed files with 1671 additions and 160 deletions

View File

@@ -8,6 +8,10 @@ char *source();
void sink(char *);
void sink(const char *);
void sink(std::pair<char *, char *>);
void sink(std::map<char *, char *>);
void sink(std::map<char *, char *>::iterator);
void sink(std::unordered_map<char *, char *>);
void sink(std::unordered_map<char *, char *>::iterator);
void test_pair()
{
@@ -44,9 +48,9 @@ void test_pair()
sink(f); // tainted [NOT DETECTED]
std::pair<char *, char *> g(f);
sink(f.first);
sink(f.second); // tainted [NOT DETECTED]
sink(f); // tainted [NOT DETECTED]
sink(g.first);
sink(g.second); // tainted [NOT DETECTED]
sink(g); // tainted [NOT DETECTED]
std::pair<char *, char *> h;
h = f;
@@ -91,3 +95,304 @@ void test_pair()
sink(m.first.second); // tainted [NOT DETECTED]
sink(m.second);
}
void test_map()
{
// insert
std::map<char *, char *> m1, m2, m3, m4, m5, m6;
sink(m1.insert(std::make_pair("abc", "def")).first);
sink(m2.insert(std::make_pair("abc", source())).first); // tainted [NOT DETECTED]
sink(m3.insert(std::make_pair(source(), "def")).first); // tainted [NOT DETECTED]
sink(m4.insert(m4.begin(), std::pair<char *, char *>("abc", source()))); // tainted [NOT DETECTED]
sink(m5.insert_or_assign("abc", source()).first); // tainted [NOT DETECTED]
sink(m6.insert_or_assign(m6.begin(), "abc", source())); // tainted [NOT DETECTED]
sink(m1);
sink(m2); // tainted [NOT DETECTED]
sink(m3); // tainted [NOT DETECTED]
sink(m4); // tainted [NOT DETECTED]
sink(m5); // tainted [NOT DETECTED]
sink(m6); // tainted [NOT DETECTED]
sink(m1.find("abc"));
sink(m2.find("abc")); // tainted [NOT DETECTED]
sink(m3.find("abc"));
sink(m4.find("abc")); // tainted [NOT DETECTED]
sink(m5.find("abc")); // tainted [NOT DETECTED]
sink(m6.find("abc")); // tainted [NOT DETECTED]
sink(m1.find("def"));
sink(m2.find("def"));
sink(m3.find("def"));
sink(m4.find("def"));
sink(m5.find("def"));
sink(m6.find("def"));
// copy constructors and assignment
std::map<char *, char *> m7(m2);
std::map<char *, char *> m8 = m2;
std::map<char *, char *> m9;
m9 = m2;
sink(m7); // tainted [NOT DETECTED]
sink(m8); // tainted [NOT DETECTED]
sink(m9); // tainted [NOT DETECTED]
sink(m7.find("abc")); // tainted [NOT DETECTED]
sink(m8.find("abc")); // tainted [NOT DETECTED]
sink(m9.find("abc")); // tainted [NOT DETECTED]
// iterators
std::map<char *, char *>::iterator i1, i2, i3;
for (i1 = m1.begin(); i1 != m1.end(); i1++)
{
sink(*i1);
sink(i1->first);
sink(i1->second);
}
for (i2 = m2.begin(); i2 != m2.end(); i2++)
{
sink(*i2); // tainted [NOT DETECTED]
sink(i2->first);
sink(i2->second); // tainted [NOT DETECTED]
}
for (i3 = m3.begin(); i3 != m3.end(); i3++)
{
sink(*i3); // tainted [NOT DETECTED]
sink(i2->first); // tainted [NOT DETECTED]
sink(i2->second);
}
// array-like access
std::map<char *, char *> m10, m11, m12, m13;
sink(m10["abc"] = "def");
sink(m11["abc"] = source()); // tainted
sink(m12.at("abc") = "def");
sink(m13.at("abc") = source()); // tainted
sink(m10["abc"]);
sink(m11["abc"]); // tainted [NOT DETECTED]
sink(m12["abc"]);
sink(m13["abc"]); // tainted [NOT DETECTED]
// ranges
std::map<char *, char *> m14;
m14.insert(std::make_pair("a", "a"));
m14.insert(std::make_pair("b", source()));
m14.insert(std::make_pair("c", source()));
m14.insert(std::make_pair("d", "d"));
sink(m2.lower_bound("b")); // tainted [NOT DETECTED]
sink(m2.upper_bound("b")); // tainted [NOT DETECTED]
sink(m2.equal_range("b").first); // tainted [NOT DETECTED]
sink(m2.equal_range("b").second); // tainted [NOT DETECTED]
sink(m2.upper_bound("c"));
sink(m2.equal_range("c").second);
// swap
std::map<char *, char *> m15, m16, m17, m18;
m15.insert(std::pair<char *, char *>(source(), source()));
m18.insert(std::pair<char *, char *>(source(), source()));
sink(m15); // tainted [NOT DETECTED]
sink(m16);
sink(m17);
sink(m18); // tainted [NOT DETECTED]
m15.swap(m16);
m17.swap(m18);
sink(m15);
sink(m16); // tainted [NOT DETECTED]
sink(m17); // tainted [NOT DETECTED]
sink(m18);
// merge
std::map<char *, char *> m19, m20, m21, m22;
m19.insert(std::pair<char *, char *>(source(), source()));
m20.insert(std::pair<char *, char *>("abc", "def"));
m21.insert(std::pair<char *, char *>("abc", "def"));
m22.insert(std::pair<char *, char *>(source(), source()));
sink(m19); // tainted [NOT DETECTED]
sink(m20);
sink(m21);
sink(m22); // tainted [NOT DETECTED]
m15.merge(m16);
m17.merge(m18);
sink(m19); // tainted [NOT DETECTED]
sink(m20); // tainted [NOT DETECTED]
sink(m21); // tainted [NOT DETECTED]
sink(m22); // tainted [NOT DETECTED]
// erase, clear
std::map<char *, char *> m23;
m23.insert(std::pair<char *, char *>(source(), source()));
m23.insert(std::pair<char *, char *>(source(), source()));
sink(m23); // tainted [NOT DETECTED]
sink(m23.erase(m23.begin())); // tainted [NOT DETECTED]
sink(m23); // tainted [NOT DETECTED]
m23.clear();
sink(m23);
// emplace, emplace_hint
std::map<char *, char *> m24, m25;
sink(m24.emplace("abc", "def").first);
sink(m24);
sink(m24.emplace("abc", source()).first); // tainted [NOT DETECTED]
sink(m24); // tainted [NOT DETECTED]
sink(m25.emplace_hint(m25.begin(), "abc", "def"));
sink(m25);
sink(m25.emplace_hint(m25.begin(), "abc", source())); // tainted [NOT DETECTED]
sink(m25); // tainted [NOT DETECTED]
// try_emplace
std::map<char *, char *> m26, m27;
sink(m26.try_emplace("abc", "def").first);
sink(m26);
sink(m26.try_emplace("abc", source()).first); // tainted [NOT DETECTED]
sink(m26); // tainted [NOT DETECTED]
sink(m27.try_emplace(m27.begin(), "abc", "def"));
sink(m27);
sink(m27.try_emplace(m27.begin(), "abc", source())); // tainted [NOT DETECTED]
sink(m27); // tainted [NOT DETECTED]
}
void test_unordered_map()
{
// insert
std::unordered_map<char *, char *> m1, m2, m3, m4, m5, m6;
sink(m1.insert(std::make_pair("abc", "def")).first);
sink(m2.insert(std::make_pair("abc", source())).first); // tainted [NOT DETECTED]
sink(m3.insert(std::make_pair(source(), "def")).first); // tainted [NOT DETECTED]
sink(m4.insert(m4.begin(), std::pair<char *, char *>("abc", source()))); // tainted [NOT DETECTED]
sink(m5.insert_or_assign("abc", source()).first); // tainted [NOT DETECTED]
sink(m6.insert_or_assign(m6.begin(), "abc", source())); // tainted [NOT DETECTED]
sink(m1);
sink(m2); // tainted [NOT DETECTED]
sink(m3); // tainted [NOT DETECTED]
sink(m4); // tainted [NOT DETECTED]
sink(m5); // tainted [NOT DETECTED]
sink(m6); // tainted [NOT DETECTED]
sink(m1.find("abc"));
sink(m2.find("abc")); // tainted [NOT DETECTED]
sink(m3.find("abc"));
sink(m4.find("abc")); // tainted [NOT DETECTED]
sink(m5.find("abc")); // tainted [NOT DETECTED]
sink(m6.find("abc")); // tainted [NOT DETECTED]
sink(m1.find("def"));
sink(m2.find("def"));
sink(m3.find("def"));
sink(m4.find("def"));
sink(m5.find("def"));
sink(m6.find("def"));
// copy constructors and assignment
std::unordered_map<char *, char *> m7(m2);
std::unordered_map<char *, char *> m8 = m2;
std::unordered_map<char *, char *> m9;
m9 = m2;
sink(m7); // tainted [NOT DETECTED]
sink(m8); // tainted [NOT DETECTED]
sink(m9); // tainted [NOT DETECTED]
sink(m7.find("abc")); // tainted [NOT DETECTED]
sink(m8.find("abc")); // tainted [NOT DETECTED]
sink(m9.find("abc")); // tainted [NOT DETECTED]
// iterators
std::unordered_map<char *, char *>::iterator i1, i2, i3;
for (i1 = m1.begin(); i1 != m1.end(); i1++)
{
sink(*i1);
sink(i1->first);
sink(i1->second);
}
for (i2 = m2.begin(); i2 != m2.end(); i2++)
{
sink(*i2); // tainted [NOT DETECTED]
sink(i2->first);
sink(i2->second); // tainted [NOT DETECTED]
}
for (i3 = m3.begin(); i3 != m3.end(); i3++)
{
sink(*i3); // tainted [NOT DETECTED]
sink(i2->first); // tainted [NOT DETECTED]
sink(i2->second);
}
// array-like access
std::unordered_map<char *, char *> m10, m11, m12, m13;
sink(m10["abc"] = "def");
sink(m11["abc"] = source()); // tainted
sink(m12.at("abc") = "def");
sink(m13.at("abc") = source()); // tainted
sink(m10["abc"]);
sink(m11["abc"]); // tainted [NOT DETECTED]
sink(m12["abc"]);
sink(m13["abc"]); // tainted [NOT DETECTED]
// ranges
std::unordered_map<char *, char *> m14;
m14.insert(std::make_pair("a", "a"));
m14.insert(std::make_pair("b", source()));
m14.insert(std::make_pair("c", source()));
m14.insert(std::make_pair("d", "d"));
sink(m2.equal_range("b").first); // tainted [NOT DETECTED]
sink(m2.equal_range("b").second); // tainted [NOT DETECTED]
sink(m2.equal_range("c").second);
// swap
std::unordered_map<char *, char *> m15, m16, m17, m18;
m15.insert(std::pair<char *, char *>(source(), source()));
m18.insert(std::pair<char *, char *>(source(), source()));
sink(m15); // tainted [NOT DETECTED]
sink(m16);
sink(m17);
sink(m18); // tainted [NOT DETECTED]
m15.swap(m16);
m17.swap(m18);
sink(m15);
sink(m16); // tainted [NOT DETECTED]
sink(m17); // tainted [NOT DETECTED]
sink(m18);
// merge
std::unordered_map<char *, char *> m19, m20, m21, m22;
m19.insert(std::pair<char *, char *>(source(), source()));
m20.insert(std::pair<char *, char *>("abc", "def"));
m21.insert(std::pair<char *, char *>("abc", "def"));
m22.insert(std::pair<char *, char *>(source(), source()));
sink(m19); // tainted [NOT DETECTED]
sink(m20);
sink(m21);
sink(m22); // tainted [NOT DETECTED]
m15.merge(m16);
m17.merge(m18);
sink(m19); // tainted [NOT DETECTED]
sink(m20); // tainted [NOT DETECTED]
sink(m21); // tainted [NOT DETECTED]
sink(m22); // tainted [NOT DETECTED]
// erase, clear
std::unordered_map<char *, char *> m23;
m23.insert(std::pair<char *, char *>(source(), source()));
m23.insert(std::pair<char *, char *>(source(), source()));
sink(m23); // tainted [NOT DETECTED]
sink(m23.erase(m23.begin())); // tainted [NOT DETECTED]
sink(m23); // tainted [NOT DETECTED]
m23.clear();
sink(m23);
// emplace, emplace_hint
std::unordered_map<char *, char *> m24, m25;
sink(m24.emplace("abc", "def").first);
sink(m24);
sink(m24.emplace("abc", source()).first); // tainted [NOT DETECTED]
sink(m24); // tainted [NOT DETECTED]
sink(m25.emplace_hint(m25.begin(), "abc", "def"));
sink(m25);
sink(m25.emplace_hint(m25.begin(), "abc", source())); // tainted [NOT DETECTED]
sink(m25); // tainted [NOT DETECTED]
// try_emplace
std::unordered_map<char *, char *> m26, m27;
sink(m26.try_emplace("abc", "def").first);
sink(m26);
sink(m26.try_emplace("abc", source()).first); // tainted [NOT DETECTED]
sink(m26); // tainted [NOT DETECTED]
sink(m27.try_emplace(m27.begin(), "abc", "def"));
sink(m27);
sink(m27.try_emplace(m27.begin(), "abc", source())); // tainted [NOT DETECTED]
sink(m27); // tainted [NOT DETECTED]
}

View File

@@ -36,6 +36,7 @@ namespace std {
bool operator==(iterator other) const;
bool operator!=(iterator other) const;
reference_type operator*() const;
pointer_type operator->() const;
iterator operator+(int);
iterator operator-(int);
iterator &operator+=(int);
@@ -326,3 +327,137 @@ namespace std {
template <class T1, class T2> pair<T1,T2> make_pair(T1, T2);
}
// --- map ---
namespace std {
template<class T = void> struct less;
template<class Key, class T, class Compare = less<Key>, class Allocator = allocator<pair<const Key, T>>>
class map {
public:
using key_type = Key;
using mapped_type = T;
using value_type = pair<const Key, T>;
using iterator = std::iterator<random_access_iterator_tag, value_type >;
using const_iterator = std::iterator<random_access_iterator_tag, const value_type >;
map() /*: map(Compare()) { }*/;
map(const map& x);
map(map&& x);
~map();
map& operator=(const map& x);
map& operator=(map&& x) /*noexcept(allocator_traits<Allocator>::is_always_equal::value && is_nothrow_move_assignable_v<Compare>)*/;
iterator begin() noexcept;
const_iterator begin() const noexcept;
iterator end() noexcept;
const_iterator end() const noexcept;
T& operator[](const key_type& x);
T& operator[](key_type&& x);
T& at(const key_type& x);
const T& at(const key_type& x) const;
template<class... Args> pair<iterator, bool> emplace(Args&&... args);
template<class... Args> iterator emplace_hint(const_iterator position, Args&&... args);
pair<iterator, bool> insert(const value_type& x);
pair<iterator, bool> insert(value_type&& x);
iterator insert(const_iterator position, const value_type& x);
iterator insert(const_iterator position, value_type&& x);
template<class... Args> pair<iterator, bool> try_emplace(const key_type& k, Args&&... args);
template<class... Args> pair<iterator, bool> try_emplace(key_type&& k, Args&&... args);
template<class... Args> iterator try_emplace(const_iterator hint, const key_type& k, Args&&... args);
template<class... Args> iterator try_emplace(const_iterator hint, key_type&& k, Args&&... args);
template<class M> pair<iterator, bool> insert_or_assign(const key_type& k, M&& obj);
template<class M> pair<iterator, bool> insert_or_assign(key_type&& k, M&& obj);
template<class M> iterator insert_or_assign(const_iterator hint, const key_type& k, M&& obj);
template<class M> iterator insert_or_assign(const_iterator hint, key_type&& k, M&& obj);
iterator erase(iterator position);
iterator erase(const_iterator position);
iterator erase(const_iterator first, const_iterator last);
void swap(map&) /*noexcept(/*==allocator_traits<Allocator>::is_always_equal::value && is_nothrow_swappable_v<Compare>)*/;
void clear() noexcept;
template<class C2> void merge(map<Key, T, C2, Allocator>& source);
template<class C2> void merge(map<Key, T, C2, Allocator>&& source);
iterator find(const key_type& x);
const_iterator find(const key_type& x) const;
iterator lower_bound(const key_type& x);
const_iterator lower_bound(const key_type& x) const;
iterator upper_bound(const key_type& x);
const_iterator upper_bound(const key_type& x) const;
pair<iterator, iterator> equal_range(const key_type& x);
pair<const_iterator, const_iterator> equal_range(const key_type& x) const;
};
template<class T> struct hash;
template<class T = void> struct equal_to;
template<class Key, class T, class Hash = hash<Key>, class Pred = equal_to<Key>, class Allocator = allocator<pair<const Key, T>>>
class unordered_map {
public:
using key_type = Key;
using mapped_type = T;
using value_type = pair<const Key, T>;
using iterator = std::iterator<random_access_iterator_tag, value_type >;
using const_iterator = std::iterator<random_access_iterator_tag, const value_type >;
unordered_map();
unordered_map(const unordered_map&);
unordered_map(unordered_map&&);
~unordered_map();
unordered_map& operator=(const unordered_map&);
unordered_map& operator=(unordered_map&&) /*noexcept(allocator_traits<Allocator>::is_always_equal::value && is_nothrow_move_assignable_v<Hash> && is_nothrow_move_assignable_v<Pred>)*/;
iterator begin() noexcept;
const_iterator begin() const noexcept;
iterator end() noexcept;
const_iterator end() const noexcept;
mapped_type& operator[](const key_type& k);
mapped_type& operator[](key_type&& k);
mapped_type& at(const key_type& k);
const mapped_type& at(const key_type& k) const;
template<class... Args> pair<iterator, bool> emplace(Args&&... args);
template<class... Args> iterator emplace_hint(const_iterator position, Args&&... args);
pair<iterator, bool> insert(const value_type& obj);
pair<iterator, bool> insert(value_type&& obj);
iterator insert(const_iterator hint, const value_type& obj);
iterator insert(const_iterator hint, value_type&& obj);
template<class... Args> pair<iterator, bool> try_emplace(const key_type& k, Args&&... args);
template<class... Args> pair<iterator, bool> try_emplace(key_type&& k, Args&&... args);
template<class... Args> iterator try_emplace(const_iterator hint, const key_type& k, Args&&... args);
template<class... Args> iterator try_emplace(const_iterator hint, key_type&& k, Args&&... args);
template<class M> pair<iterator, bool> insert_or_assign(const key_type& k, M&& obj);
template<class M> pair<iterator, bool> insert_or_assign(key_type&& k, M&& obj);
template<class M> iterator insert_or_assign(const_iterator hint, const key_type& k, M&& obj);
template<class M> iterator insert_or_assign(const_iterator hint, key_type&& k, M&& obj);
iterator erase(iterator position);
iterator erase(const_iterator position);
iterator erase(const_iterator first, const_iterator last);
void swap(unordered_map&) /*noexcept(allocator_traits<Allocator>::is_always_equal::value && is_nothrow_swappable_v<Hash> && is_nothrow_swappable_v<Pred>)*/;
void clear() noexcept;
template<class H2, class P2> void merge(unordered_map<Key, T, H2, P2, Allocator>& source);
template<class H2, class P2> void merge(unordered_map<Key, T, H2, P2, Allocator>&& source);
iterator find(const key_type& k);
const_iterator find(const key_type& k) const;
pair<iterator, iterator> equal_range(const key_type& k);
pair<const_iterator, const_iterator> equal_range(const key_type& k) const;
};
};

View File

@@ -33,8 +33,12 @@
| format.cpp:115:8:115:13 | buffer | format.cpp:114:37:114:50 | call to source |
| format.cpp:157:7:157:22 | access to array | format.cpp:147:12:147:25 | call to source |
| format.cpp:158:7:158:27 | ... + ... | format.cpp:148:16:148:30 | call to source |
| map.cpp:22:9:22:13 | first | map.cpp:21:12:21:17 | call to source |
| map.cpp:28:9:28:14 | second | map.cpp:26:13:26:18 | call to source |
| map.cpp:26:9:26:13 | first | map.cpp:25:12:25:17 | call to source |
| map.cpp:32:9:32:14 | second | map.cpp:30:13:30:18 | call to source |
| map.cpp:165:7:165:27 | ... = ... | map.cpp:165:20:165:25 | call to source |
| map.cpp:167:7:167:30 | ... = ... | map.cpp:167:23:167:28 | call to source |
| map.cpp:317:7:317:27 | ... = ... | map.cpp:317:20:317:25 | call to source |
| map.cpp:319:7:319:30 | ... = ... | map.cpp:319:23:319:28 | call to source |
| movableclass.cpp:44:8:44:9 | s1 | movableclass.cpp:39:21:39:26 | call to source |
| movableclass.cpp:45:8:45:9 | s2 | movableclass.cpp:40:23:40:28 | call to source |
| movableclass.cpp:46:8:46:9 | s3 | movableclass.cpp:42:8:42:13 | call to source |

View File

@@ -42,8 +42,12 @@
| format.cpp:115:8:115:13 | Argument 0 indirection | format.cpp:114:37:114:50 | call to source |
| format.cpp:157:7:157:22 | access to array | format.cpp:147:12:147:25 | call to source |
| format.cpp:158:7:158:27 | ... + ... | format.cpp:148:16:148:30 | call to source |
| map.cpp:22:9:22:13 | first | map.cpp:21:12:21:17 | call to source |
| map.cpp:28:9:28:14 | second | map.cpp:26:13:26:18 | call to source |
| map.cpp:26:9:26:13 | first | map.cpp:25:12:25:17 | call to source |
| map.cpp:32:9:32:14 | second | map.cpp:30:13:30:18 | call to source |
| map.cpp:165:7:165:27 | ... = ... | map.cpp:165:20:165:25 | call to source |
| map.cpp:167:7:167:30 | ... = ... | map.cpp:167:23:167:28 | call to source |
| map.cpp:317:7:317:27 | ... = ... | map.cpp:317:20:317:25 | call to source |
| map.cpp:319:7:319:30 | ... = ... | map.cpp:319:23:319:28 | call to source |
| movableclass.cpp:44:8:44:9 | s1 | movableclass.cpp:39:21:39:26 | call to source |
| movableclass.cpp:45:8:45:9 | s2 | movableclass.cpp:40:23:40:28 | call to source |
| movableclass.cpp:46:8:46:9 | s3 | movableclass.cpp:42:8:42:13 | call to source |