]> git.puffer.fish Git - mirror/frr.git/commitdiff
lib: Fix nondeterministic command matches in rare cases
authorQuentin Young <qlyoung@cumulusnetworks.com>
Tue, 15 Nov 2016 22:15:18 +0000 (22:15 +0000)
committerQuentin Young <qlyoung@cumulusnetworks.com>
Tue, 15 Nov 2016 22:15:18 +0000 (22:15 +0000)
When a user erroneously defines two commands which can
match the same input and at least one of the tokens defined
last in the command is a selector or option, the matcher
does not detect an ambiguous match and matches the command
installed first (leftmost in the graph).

Fix is to do a full walkthrough of the follow set when
matching the final token in a command to check that there
is exactly one possible match, and to throw an ambiguity
error otherwise.

Signed-off-by: Quentin Young <qlyoung@cumulusnetworks.com>
lib/command_match.c

index 82090be732a4511d803d3baef61e263b11c31e3d..06a50656b607bc300184c45174708afb699cef1e 100644 (file)
@@ -240,6 +240,11 @@ command_match_r (struct graph_node *start, vector vline, unsigned int n)
           struct cmd_token *tok = gn->data;
           if (tok->type == END_TKN)
             {
+              if (currbest) // there is more than one END_TKN in the follow set
+              {
+                ambiguous = 1;
+                break;
+              }
               currbest = list_new();
               // node should have one child node with the element
               struct graph_node *leaf = vector_slot (gn->to, 0);
@@ -251,9 +256,10 @@ command_match_r (struct graph_node *start, vector vline, unsigned int n)
               struct cmd_element *el = leaf->data;
               listnode_add (currbest, el);
               currbest->del = (void (*)(void *)) &del_cmd_token;
-              break;
+              // do not break immediately; continue walking through the follow set
+              // to ensure that there is exactly one END_TKN
             }
-          else continue;
+          continue;
         }
 
       // else recurse on candidate child node