Index: uspace/lib/cpp/include/__bits/adt/hash_table.hpp
===================================================================
--- uspace/lib/cpp/include/__bits/adt/hash_table.hpp	(revision 2e328c3f22289158f5d1889f4bacef60637d7da6)
+++ uspace/lib/cpp/include/__bits/adt/hash_table.hpp	(revision 07eaeea80811a92c527a173e4f9c1d293e9803f9)
@@ -212,4 +212,7 @@
             iterator erase(const_iterator it)
             {
+                if (it == cend())
+                    return end();
+
                 auto node = it.node();
                 auto idx = it.idx();
@@ -234,5 +237,8 @@
                 delete node;
 
-                return res;
+                if (empty())
+                    return end();
+                else
+                    return res;
             }
 
@@ -282,5 +288,5 @@
                     current = current->next;
                 }
-                while (current != head);
+                while (current && current != head);
 
                 return end();
Index: uspace/lib/cpp/include/__bits/adt/hash_table_bucket.hpp
===================================================================
--- uspace/lib/cpp/include/__bits/adt/hash_table_bucket.hpp	(revision 2e328c3f22289158f5d1889f4bacef60637d7da6)
+++ uspace/lib/cpp/include/__bits/adt/hash_table_bucket.hpp	(revision 07eaeea80811a92c527a173e4f9c1d293e9803f9)
@@ -92,5 +92,5 @@
                 delete tmp;
             }
-            while (current != head);
+            while (current && current != head);
 
             head = nullptr;
Index: uspace/lib/cpp/include/__bits/adt/hash_table_policies.hpp
===================================================================
--- uspace/lib/cpp/include/__bits/adt/hash_table_policies.hpp	(revision 2e328c3f22289158f5d1889f4bacef60637d7da6)
+++ uspace/lib/cpp/include/__bits/adt/hash_table_policies.hpp	(revision 07eaeea80811a92c527a173e4f9c1d293e9803f9)
@@ -47,233 +47,8 @@
         {
             auto idx = table.get_bucket_idx_(key);
-            return make_tuple(
-                &table.table_[idx],
-                table.table_[idx].head,
-                idx
-            );
-        }
-
-        template<class Table, class Key>
-        static typename Table::size_type erase(Table& table, const Key& key)
-        {
-            auto idx = table.get_bucket_idx_(key);
             auto head = table.table_[idx].head;
-            auto current = head;
-
-            if (!current)
-                return 0;
-
-            do
-            {
-                if (table.keys_equal(key, current->value))
-                {
-                    --table.size_;
-
-                    if (current == head)
-                    {
-                        if (current->next != head)
-                            table.table_[idx].head = current->next;
-                        else
-                            table.table_[idx].head = nullptr;
-                    }
-
-                    current->unlink();
-                    delete current;
-
-                    return 1;
-                }
-                else
-                    current = current->next;
-            }
-            while (current != head);
-
-            return 0;
-        }
-
-        template<class Table, class Key>
-        static pair<
-            typename Table::iterator,
-            typename Table::iterator
-        > equal_range(Table& table, const Key& key)
-        {
-            auto it = table.find(key);
-            return make_pair(it, ++it);
-        }
-
-        template<class Table, class Key>
-        static pair<
-            typename Table::const_iterator,
-            typename Table::const_iterator
-        > equal_range_const(const Table& table, const Key& key)
-        { // Note: We cannot overload by return type, so we use a different name.
-            auto it = table.find(key);
-            return make_pair(it, ++it);
-        }
-
-        /**
-         * Note: We have to duplicate code for emplace, insert(const&)
-         *       and insert(&&) here, because the node (which makes distinction
-         *       between the arguments) is only created if the value isn't
-         *       in the table already.
-         */
-
-        template<class Table, class... Args>
-        static pair<
-            typename Table::iterator, bool
-        > emplace(Table& table, Args&&... args)
-        {
-            using value_type = typename Table::value_type;
-            using node_type  = typename Table::node_type;
-            using iterator   = typename Table::iterator;
-
-            table.increment_size();
-
-            auto val = value_type{forward<Args>(args)...};
-            const auto& key = table.get_key(val);
-            auto [bucket, target, idx] = table.find_insertion_spot(key);
-
-            if (!bucket)
-                return make_pair(table.end(), false);
-
-            if (target && table.keys_equal(key, target->value))
-            {
-                table.decrement_size();
-
-                return make_pair(
-                    iterator{
-                        table.table(), idx, table.bucket_count(),
-                        target
-                    },
-                    false
-                );
-            }
-            else
-            {
-                auto node = new node_type{move(val)};
-                bucket->prepend(node);
-
-                return make_pair(iterator{
-                    table.table(), idx,
-                    table.bucket_count(),
-                    node
-                }, true);
-            }
-        }
-
-        template<class Table, class Value>
-        static pair<
-            typename Table::iterator, bool
-        > insert(Table& table, const Value& val)
-        {
-            using node_type  = typename Table::node_type;
-            using iterator   = typename Table::iterator;
-
-            table.increment_size();
-
-            const auto& key = table.get_key(val);
-            auto [bucket, target, idx] = table.find_insertion_spot(key);
-
-            if (!bucket)
-                return make_pair(table.end(), false);
-
-            if (target && table.keys_equal(key, target->value))
-            {
-                table.decrement_size();
-
-                return make_pair(
-                    iterator{
-                        table.table(), idx, table.bucket_count(),
-                        target
-                    },
-                    false
-                );
-            }
-            else
-            {
-                auto node = new node_type{val};
-                bucket->prepend(node);
-
-                return make_pair(iterator{
-                    table.table(), idx,
-                    table.bucket_count(),
-                    node
-                }, true);
-            }
-        }
-
-        template<class Table, class Value>
-        static pair<
-            typename Table::iterator, bool
-        > insert(Table& table, Value&& val)
-        {
-            using value_type = typename Table::value_type;
-            using node_type  = typename Table::node_type;
-            using iterator   = typename Table::iterator;
-
-            table.increment_size();
-
-            const auto& key = table.get_key(val);
-            auto [bucket, target, idx] = table.find_insertion_spot(key);
-
-            if (!bucket)
-                return make_pair(table.end(), false);
-
-            if (target && table.keys_equal(key, target->value))
-            {
-                table.decrement_size();
-
-                return make_pair(
-                    iterator{
-                        table.table(), idx, table.bucket_count(),
-                        target
-                    },
-                    false
-                );
-            }
-            else
-            {
-                auto node = new node_type{forward<value_type>(val)};
-                bucket->prepend(node);
-
-                return make_pair(iterator{
-                    table.table(), idx,
-                    table.bucket_count(),
-                    node
-                }, true);
-            }
-        }
-    };
-
-    struct hash_multi_policy
-    {
-        template<class Table, class Key>
-        static typename Table::size_type count(const Table& table, const Key& key)
-        {
-            auto head = table.table_[table.get_bucket_idx_(key)].head;
-            if (!head)
-                return 0;
-
-            auto current = head;
-            typename Table::size_type res = 0;
-            do
-            {
-                if (table.keys_equal(key, current->value))
-                    ++res;
-
-                current = current->next;
-            }
-            while (current != head);
-
-            return res;
-        }
-
-        template<class Table, class Key>
-        static typename Table::place_type find_insertion_spot(const Table& table, const Key& key)
-        {
-            auto idx = table.get_bucket_idx_(key);
-            auto head = table.table_[idx].head;
 
             if (head)
-            {
+            { // Check if the key is present.
                 auto current = head;
                 do
@@ -289,5 +64,5 @@
 
                     current = current->next;
-                } while (current != head);
+                } while (current && current != head);
             }
 
@@ -305,5 +80,251 @@
             auto head = table.table_[idx].head;
             auto current = head;
+
+            if (!current)
+                return 0;
+
+            do
+            {
+                if (table.keys_equal(key, current->value))
+                {
+                    --table.size_;
+
+                    if (current == head)
+                    {
+                        if (current->next != head)
+                            table.table_[idx].head = current->next;
+                        else
+                            table.table_[idx].head = nullptr;
+                    }
+
+                    current->unlink();
+                    delete current;
+
+                    return 1;
+                }
+                else
+                    current = current->next;
+            }
+            while (current && current != head);
+
+            return 0;
+        }
+
+        template<class Table, class Key>
+        static pair<
+            typename Table::iterator,
+            typename Table::iterator
+        > equal_range(Table& table, const Key& key)
+        {
+            auto it = table.find(key);
+            return make_pair(it, ++it);
+        }
+
+        template<class Table, class Key>
+        static pair<
+            typename Table::const_iterator,
+            typename Table::const_iterator
+        > equal_range_const(const Table& table, const Key& key)
+        { // Note: We cannot overload by return type, so we use a different name.
+            auto it = table.find(key);
+            return make_pair(it, ++it);
+        }
+
+        /**
+         * Note: We have to duplicate code for emplace, insert(const&)
+         *       and insert(&&) here, because the node (which makes distinction
+         *       between the arguments) is only created if the value isn't
+         *       in the table already.
+         */
+
+        template<class Table, class... Args>
+        static pair<
+            typename Table::iterator, bool
+        > emplace(Table& table, Args&&... args)
+        {
+            using value_type = typename Table::value_type;
+            using node_type  = typename Table::node_type;
+            using iterator   = typename Table::iterator;
+
+            table.increment_size();
+
+            auto val = value_type{forward<Args>(args)...};
+            const auto& key = table.get_key(val);
+            auto [bucket, target, idx] = table.find_insertion_spot(key);
+
+            if (!bucket)
+                return make_pair(table.end(), false);
+
+            if (target && table.keys_equal(key, target->value))
+            {
+                table.decrement_size();
+
+                return make_pair(
+                    iterator{
+                        table.table(), idx, table.bucket_count(),
+                        target
+                    },
+                    false
+                );
+            }
+            else
+            {
+                auto node = new node_type{move(val)};
+                bucket->prepend(node);
+
+                return make_pair(iterator{
+                    table.table(), idx,
+                    table.bucket_count(),
+                    node
+                }, true);
+            }
+        }
+
+        template<class Table, class Value>
+        static pair<
+            typename Table::iterator, bool
+        > insert(Table& table, const Value& val)
+        {
+            using node_type  = typename Table::node_type;
+            using iterator   = typename Table::iterator;
+
+            table.increment_size();
+
+            const auto& key = table.get_key(val);
+            auto [bucket, target, idx] = table.find_insertion_spot(key);
+
+            if (!bucket)
+                return make_pair(table.end(), false);
+
+            if (target && table.keys_equal(key, target->value))
+            {
+                table.decrement_size();
+
+                return make_pair(
+                    iterator{
+                        table.table(), idx, table.bucket_count(),
+                        target
+                    },
+                    false
+                );
+            }
+            else
+            {
+                auto node = new node_type{val};
+                bucket->prepend(node);
+
+                return make_pair(iterator{
+                    table.table(), idx,
+                    table.bucket_count(),
+                    node
+                }, true);
+            }
+        }
+
+        template<class Table, class Value>
+        static pair<
+            typename Table::iterator, bool
+        > insert(Table& table, Value&& val)
+        {
+            using value_type = typename Table::value_type;
+            using node_type  = typename Table::node_type;
+            using iterator   = typename Table::iterator;
+
+            table.increment_size();
+
+            const auto& key = table.get_key(val);
+            auto [bucket, target, idx] = table.find_insertion_spot(key);
+
+            if (!bucket)
+                return make_pair(table.end(), false);
+
+            if (target && table.keys_equal(key, target->value))
+            {
+                table.decrement_size();
+
+                return make_pair(
+                    iterator{
+                        table.table(), idx, table.bucket_count(),
+                        target
+                    },
+                    false
+                );
+            }
+            else
+            {
+                auto node = new node_type{forward<value_type>(val)};
+                bucket->prepend(node);
+
+                return make_pair(iterator{
+                    table.table(), idx,
+                    table.bucket_count(),
+                    node
+                }, true);
+            }
+        }
+    };
+
+    struct hash_multi_policy
+    {
+        template<class Table, class Key>
+        static typename Table::size_type count(const Table& table, const Key& key)
+        {
+            auto head = table.table_[table.get_bucket_idx_(key)].head;
+            if (!head)
+                return 0;
+
+            auto current = head;
+            typename Table::size_type res = 0;
+            do
+            {
+                if (table.keys_equal(key, current->value))
+                    ++res;
+
+                current = current->next;
+            }
+            while (current && current != head);
+
+            return res;
+        }
+
+        template<class Table, class Key>
+        static typename Table::place_type find_insertion_spot(const Table& table, const Key& key)
+        {
+            auto idx = table.get_bucket_idx_(key);
+            auto head = table.table_[idx].head;
+
+            if (head)
+            {
+                auto current = head;
+                do
+                {
+                    if (table.keys_equal(key, current->value))
+                    {
+                        return make_tuple(
+                            &table.table_[idx],
+                            current,
+                            idx
+                        );
+                    }
+
+                    current = current->next;
+                } while (current && current != head);
+            }
+
+            return make_tuple(
+                &table.table_[idx],
+                table.table_[idx].head,
+                idx
+            );
+        }
+
+        template<class Table, class Key>
+        static typename Table::size_type erase(Table& table, const Key& key)
+        {
+            auto idx = table.get_bucket_idx_(key);
+            auto head = table.table_[idx].head;
+            auto current = head;
             table.table_[idx].head = nullptr;
+            decltype(head) last = nullptr;
 
             if (!current)
@@ -321,16 +342,23 @@
                 auto tmp = current;
                 current = current->next;
-
+                tmp->unlink();
+
+                --table.size_;
                 if (!table.keys_equal(key, tmp->value))
-                    table.table_[idx].append(tmp);
+                {
+                    if (!last)
+                        table.table_[idx].head = tmp;
+                    else
+                        last->append(tmp);
+                    last = tmp;
+                }
                 else
                 {
                     ++res;
-                    --table.size_;
 
                     delete tmp;
                 }
             }
-            while (current != head);
+            while (current && current != head);
 
             return res;
@@ -351,5 +379,5 @@
             {
                 ++last;
-            } while (table.keys_equal(key, *last));
+            } while (last != table.end() && table.keys_equal(key, *last));
 
             return make_pair(first, last);
@@ -370,5 +398,5 @@
             {
                 ++last;
-            } while (table.keys_equal(key, *last));
+            } while (last != table.end() && table.keys_equal(key, *last));
 
             return make_pair(first, last);
@@ -417,5 +445,5 @@
 
             if (!bucket)
-                table.end();
+                return table.end();
 
             if (target && table.keys_equal(key, target->value))
Index: uspace/lib/cpp/include/__bits/adt/list_node.hpp
===================================================================
--- uspace/lib/cpp/include/__bits/adt/list_node.hpp	(revision 2e328c3f22289158f5d1889f4bacef60637d7da6)
+++ uspace/lib/cpp/include/__bits/adt/list_node.hpp	(revision 07eaeea80811a92c527a173e4f9c1d293e9803f9)
@@ -64,4 +64,7 @@
         void append(list_node* node)
         {
+            if (!node)
+                return;
+
             node->next = next;
             node->prev = this;
@@ -72,4 +75,7 @@
         void prepend(list_node* node)
         {
+            if (!node)
+                return;
+
             node->next = this;
             node->prev = prev;
