table: fix Pit::find leak of NameTreeEntry

refs #3619

Change-Id: If1043a08c9f4f8bb53cad77d2b6f21991553e1cc
diff --git a/daemon/table/pit.cpp b/daemon/table/pit.cpp
index 7286cbe..5db1ce2 100644
--- a/daemon/table/pit.cpp
+++ b/daemon/table/pit.cpp
@@ -60,14 +60,26 @@
 std::pair<shared_ptr<pit::Entry>, bool>
 Pit::findOrInsert(const Interest& interest, bool allowInsert)
 {
-  // ensure NameTree entry exists
+  // determine which NameTree entry should the PIT entry be attached onto
   const Name& name = interest.getName();
   bool isEndWithDigest = name.size() > 0 && name[-1].isImplicitSha256Digest();
-  shared_ptr<name_tree::Entry> nte = m_nameTree.lookup(isEndWithDigest ? name.getPrefix(-1) : name);
-  BOOST_ASSERT(nte != nullptr);
-  size_t nteNameLen = nte->getPrefix().size();
+  const Name& nteName = isEndWithDigest ? name.getPrefix(-1) : name;
+
+  // ensure NameTree entry exists
+  shared_ptr<name_tree::Entry> nte;
+  if (allowInsert) {
+    nte = m_nameTree.lookup(nteName);
+    BOOST_ASSERT(nte != nullptr);
+  }
+  else {
+    nte = m_nameTree.findExactMatch(nteName);
+    if (nte == nullptr) {
+      return {nullptr, true};
+    }
+  }
 
   // check if PIT entry already exists
+  size_t nteNameLen = nteName.size();
   const std::vector<shared_ptr<pit::Entry>>& pitEntries = nte->getPitEntries();
   auto it = std::find_if(pitEntries.begin(), pitEntries.end(),
     [&interest, nteNameLen] (const shared_ptr<pit::Entry>& entry) -> bool {
@@ -84,12 +96,13 @@
   }
 
   if (!allowInsert) {
+    BOOST_ASSERT(!nte->isEmpty()); // nte shouldn't be created in this call
     return {nullptr, true};
   }
 
   auto entry = make_shared<pit::Entry>(interest);
   nte->insertPitEntry(entry);
-  m_nItems++;
+  ++m_nItems;
   return {entry, true};
 }
 
diff --git a/tests/daemon/table/pit.t.cpp b/tests/daemon/table/pit.t.cpp
index 80e31d3..0418f7e 100644
--- a/tests/daemon/table/pit.t.cpp
+++ b/tests/daemon/table/pit.t.cpp
@@ -197,6 +197,25 @@
 BOOST_AUTO_TEST_SUITE_END() // PitEntry
 
 
+BOOST_AUTO_TEST_CASE(Find)
+{
+  shared_ptr<Interest> interest1 = makeInterest("/6hNwxJjw");
+  shared_ptr<Interest> interest2 = makeInterest("/v65zqxm4d");
+
+  NameTree nameTree(16);
+  Pit pit(nameTree);
+
+  pit.insert(*interest1);
+  shared_ptr<pit::Entry> found1a = pit.find(*interest1);
+  shared_ptr<pit::Entry> found1b = pit.find(*interest1);
+  BOOST_CHECK(found1a != nullptr);
+  BOOST_CHECK(found1a == found1b);
+
+  shared_ptr<pit::Entry> found2 = pit.find(*interest2);
+  BOOST_CHECK(found2 == nullptr);
+  BOOST_CHECK(nameTree.findExactMatch(interest2->getName()) == nullptr);
+}
+
 BOOST_AUTO_TEST_CASE(Insert)
 {
   Name name1("ndn:/5vzBNnMst");