table: fix Fib::removeNextHopFromAllEntries invalidating NameTree iterator

refs #2177

Change-Id: I19b8234d94b804273404176d6751a91f082653b7
diff --git a/daemon/table/fib.cpp b/daemon/table/fib.cpp
index 99a1bf9..c28a695 100644
--- a/daemon/table/fib.cpp
+++ b/daemon/table/fib.cpp
@@ -143,26 +143,21 @@
 void
 Fib::removeNextHopFromAllEntries(shared_ptr<Face> face)
 {
-  shared_ptr<fib::Entry> toErase;
+  std::list<fib::Entry*> toErase;
 
   auto&& enumerable = m_nameTree.fullEnumerate(&predicate_NameTreeEntry_hasFibEntry);
   for (const name_tree::Entry& nte : enumerable) {
-    if (toErase != nullptr) {
-      this->erase(*toErase);
-      toErase.reset();
-    }
-
     shared_ptr<fib::Entry> entry = nte.getFibEntry();
     entry->removeNextHop(face);
     if (!entry->hasNextHops()) {
-      toErase = entry;
-      // entry needs to be erased, but we must wait until next iteration
-      // to erase it because otherwise it would invalidate the iterator
+      toErase.push_back(entry.get());
+      // entry needs to be erased, but we must wait until the enumeration ends,
+      // because otherwise NameTree iterator would be invalidated
     }
   }
 
-  if (toErase != nullptr) {
-    this->erase(*toErase);
+  for (fib::Entry* entry : toErase) {
+    this->erase(*entry);
   }
 }
 
diff --git a/tests/daemon/table/fib.cpp b/tests/daemon/table/fib.cpp
index 35fcd3e..d75088b 100644
--- a/tests/daemon/table/fib.cpp
+++ b/tests/daemon/table/fib.cpp
@@ -264,6 +264,22 @@
   BOOST_CHECK_EQUAL(entry->getPrefix(), nameEmpty);
 }
 
+BOOST_AUTO_TEST_CASE(RemoveNextHopFromManyEntries)
+{
+  NameTree nameTree(16);
+  Fib fib(nameTree);
+  shared_ptr<Face> face1 = make_shared<DummyFace>();
+
+  for (uint64_t i = 0; i < 300; ++i) {
+    shared_ptr<fib::Entry> entry = fib.insert(Name("/P").appendVersion(i)).first;
+    entry->addNextHop(face1, 0);
+  }
+  BOOST_CHECK_EQUAL(fib.size(), 300);
+
+  fib.removeNextHopFromAllEntries(face1);
+  BOOST_CHECK_EQUAL(fib.size(), 0);
+}
+
 void
 validateFindExactMatch(const Fib& fib, const Name& target)
 {