table: limit prefix length in StrategyChoice

refs #4262

Change-Id: Iddebeb555b2f3315515a298f8cded353fb51854d
diff --git a/daemon/table/strategy-choice.cpp b/daemon/table/strategy-choice.cpp
index 01756f5..55db095 100644
--- a/daemon/table/strategy-choice.cpp
+++ b/daemon/table/strategy-choice.cpp
@@ -1,5 +1,5 @@
 /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
-/**
+/*
  * Copyright (c) 2014-2017,  Regents of the University of California,
  *                           Arizona Board of Regents,
  *                           Colorado State University,
@@ -69,6 +69,10 @@
 StrategyChoice::InsertResult
 StrategyChoice::insert(const Name& prefix, const Name& strategyName)
 {
+  if (prefix.size() > NameTree::getMaxDepth()) {
+    return InsertResult::DEPTH_EXCEEDED;
+  }
+
   unique_ptr<Strategy> strategy;
   try {
     strategy = Strategy::create(strategyName, m_forwarder);
@@ -83,7 +87,7 @@
     return InsertResult::NOT_REGISTERED;
   }
 
-  name_tree::Entry& nte = m_nameTree.lookup(prefix);
+  name_tree::Entry& nte = m_nameTree.lookup(prefix, true);
   Entry* entry = nte.getStrategyChoiceEntry();
   Strategy* oldStrategy = nullptr;
   if (entry != nullptr) {
@@ -125,6 +129,9 @@
       return os << "Strategy not registered";
     case StrategyChoice::InsertResult::EXCEPTION:
       return os << "Error instantiating strategy: " << res.m_exceptionMessage;
+    case StrategyChoice::InsertResult::DEPTH_EXCEEDED:
+      return os << "Prefix has too many components (limit is "
+                 << to_string(NameTree::getMaxDepth()) << ")";
   }
   return os;
 }
diff --git a/daemon/table/strategy-choice.hpp b/daemon/table/strategy-choice.hpp
index 4e59716..8cfa93b 100644
--- a/daemon/table/strategy-choice.hpp
+++ b/daemon/table/strategy-choice.hpp
@@ -1,5 +1,5 @@
 /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
-/**
+/*
  * Copyright (c) 2014-2017,  Regents of the University of California,
  *                           Arizona Board of Regents,
  *                           Colorado State University,
@@ -80,14 +80,15 @@
     bool
     isRegistered() const
     {
-      return m_status != NOT_REGISTERED;
+      return m_status == OK || m_status == EXCEPTION;
     }
 
   private:
     enum Status {
       OK,
       NOT_REGISTERED,
-      EXCEPTION
+      EXCEPTION,
+      DEPTH_EXCEEDED
     };
 
     // implicitly constructible from Status
diff --git a/tests/daemon/table/strategy-choice.t.cpp b/tests/daemon/table/strategy-choice.t.cpp
index eeba048..0173af4 100644
--- a/tests/daemon/table/strategy-choice.t.cpp
+++ b/tests/daemon/table/strategy-choice.t.cpp
@@ -1,5 +1,5 @@
 /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
-/**
+/*
  * Copyright (c) 2014-2017,  Regents of the University of California,
  *                           Arizona Board of Regents,
  *                           Colorado State University,
@@ -144,6 +144,21 @@
   BOOST_CHECK(!sc.insert("/D", oneParamUnversioned));
 }
 
+BOOST_AUTO_TEST_CASE(InsertLongName)
+{
+  Name n1;
+  while (n1.size() < NameTree::getMaxDepth()) {
+    n1.append("A");
+  }
+  Name n2 = n1;
+  while (n2.size() < NameTree::getMaxDepth() * 2) {
+    n2.append("B");
+  }
+
+  BOOST_CHECK(sc.insert(n1, strategyNameP));
+  BOOST_CHECK(!sc.insert(n2, strategyNameP));
+}
+
 BOOST_AUTO_TEST_CASE(Get)
 {
   BOOST_CHECK(sc.insert("/", strategyNameP));