summaryrefslogtreecommitdiffstats
path: root/lib/command_parse.y
diff options
context:
space:
mode:
authorDavid Lamparter <equinox@diac24.net>2019-06-25 13:34:12 +0200
committerDavid Lamparter <equinox@diac24.net>2019-06-25 13:35:21 +0200
commiteb44e1aac0811da16766bdea255ffef93e2a5b23 (patch)
tree4a715b14d03b0002111328000d55f41ee9b814d0 /lib/command_parse.y
parentMerge pull request #4597 from FRRouting/revert-3775-ospf_missing_interface_ha... (diff)
downloadfrr-eb44e1aac0811da16766bdea255ffef93e2a5b23.tar.xz
frr-eb44e1aac0811da16766bdea255ffef93e2a5b23.zip
lib: add a check for {[...]} in DEFUNs
Our command matcher doesn't handle {[...]} correctly; let's warn about it so the DEFUN can be changed to [{...}] (which does work as expected.) Fixes: #4594 Signed-off-by: David Lamparter <equinox@opensourcerouting.org>
Diffstat (limited to 'lib/command_parse.y')
-rw-r--r--lib/command_parse.y36
1 files changed, 36 insertions, 0 deletions
diff --git a/lib/command_parse.y b/lib/command_parse.y
index 1b304a98b..062a4bb30 100644
--- a/lib/command_parse.y
+++ b/lib/command_parse.y
@@ -46,6 +46,7 @@
%code requires {
#include "config.h"
+ #include <stdbool.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
@@ -140,6 +141,8 @@
static void
cleanup (struct parser_ctx *ctx);
+ static void loopcheck(struct parser_ctx *ctx, struct subgraph *sg);
+
#define scanner ctx->scanner
}
@@ -335,6 +338,7 @@ selector: '{' selector_seq_seq '}' varname_token
* just use [{a|b}] if neccessary, that will work perfectly fine, and reason
* #1 is good enough to keep it this way. */
+ loopcheck(ctx, &$$);
cmd_token_varname_set ($2.end->data, $4);
XFREE (MTYPE_LEX, $4);
};
@@ -396,6 +400,38 @@ cmd_graph_parse (struct graph *graph, struct cmd_element *cmd)
/* parser helper functions */
+static bool loopcheck_inner(struct graph_node *start, struct graph_node *node,
+ struct graph_node *end, size_t depth)
+{
+ size_t i;
+ bool ret;
+
+ /* safety check */
+ if (depth++ == 64)
+ return true;
+
+ for (i = 0; i < vector_active(node->to); i++) {
+ struct graph_node *next = vector_slot(node->to, i);
+ struct cmd_token *tok = next->data;
+
+ if (next == end || next == start)
+ return true;
+ if (tok->type < SPECIAL_TKN)
+ continue;
+ ret = loopcheck_inner(start, next, end, depth);
+ if (ret)
+ return true;
+ }
+ return false;
+}
+
+static void loopcheck(struct parser_ctx *ctx, struct subgraph *sg)
+{
+ if (loopcheck_inner(sg->start, sg->start, sg->end, 0))
+ zlog_err("FATAL: '%s': {} contains an empty path! Use [{...}]",
+ ctx->el->string);
+}
+
void
yyerror (CMD_YYLTYPE *loc, struct parser_ctx *ctx, char const *msg)
{