]> git.puffer.fish Git - matthieu/frr.git/commitdiff
lib: parser: fix memory management
authorDavid Lamparter <equinox@opensourcerouting.org>
Wed, 25 Jan 2017 01:27:29 +0000 (02:27 +0100)
committerDavid Lamparter <equinox@opensourcerouting.org>
Wed, 25 Jan 2017 01:27:29 +0000 (02:27 +0100)
command.c had:
DEFINE_MTYPE_STATIC(LIB, CMD_TOKENS, "Command desc")
while command_match.c had:
DEFINE_MTYPE_STATIC(LIB, CMD_TOKENS, "Command Tokens")

... which means that there are 2 distinct MTYPE_CMD_TOKENS.
(The description text being different does not matter, even with the
same text it'd be 2 distinct types.)

command_match.c allocates token->arg in command_match_r() while
command.c frees it in del_cmd_token().  Therefore with each command
being executed, the allocation count goes up on one, down on the other.

=> clean up parser allocation counting.  Also, use separate MTYPEs for
the different fields in struct cmd_token.

Fixes: #108 / ee9216cf ("lib, ripngd: clean up merge leftovers")
Signed-off-by: David Lamparter <equinox@opensourcerouting.org>
Cc: Quentin Young <qlyoung@cumulusnetworks.com>
lib/command.c
lib/command.h
lib/command_match.c
lib/command_parse.y

index b5dae5f28e13bec5216cfaf0d193da1cad60c82c..781f627bb554b24f8aa947c8eef1904fc60427b0 100644 (file)
 
 DEFINE_MTYPE(       LIB, HOST,       "Host config")
 DEFINE_MTYPE(       LIB, STRVEC,     "String vector")
-DEFINE_MTYPE_STATIC(LIB, CMD_TOKENS, "Command desc")
+DEFINE_MTYPE_STATIC(LIB, CMD_TOKENS, "Command Tokens")
+DEFINE_MTYPE_STATIC(LIB, CMD_DESC,   "Command Token Text")
+DEFINE_MTYPE_STATIC(LIB, CMD_TEXT,   "Command Token Help")
+DEFINE_MTYPE(       LIB, CMD_ARG,    "Command Argument")
 
 /* Command vector which includes some level of command lists. Normally
    each daemon maintains each own cmdvec. */
@@ -2405,13 +2408,14 @@ cmd_init (int terminal)
 }
 
 struct cmd_token *
-new_cmd_token (enum cmd_token_type type, u_char attr, char *text, char *desc)
+new_cmd_token (enum cmd_token_type type, u_char attr,
+               const char *text, const char *desc)
 {
   struct cmd_token *token = XCALLOC (MTYPE_CMD_TOKENS, sizeof (struct cmd_token));
   token->type = type;
   token->attr = attr;
-  token->text = text;
-  token->desc = desc;
+  token->text = text ? XSTRDUP (MTYPE_CMD_TEXT, text) : NULL;
+  token->desc = desc ? XSTRDUP (MTYPE_CMD_DESC, desc) : NULL;
   token->arg  = NULL;
   token->allowrepeat = false;
 
@@ -2424,11 +2428,11 @@ del_cmd_token (struct cmd_token *token)
   if (!token) return;
 
   if (token->text)
-    XFREE (MTYPE_CMD_TOKENS, token->text);
+    XFREE (MTYPE_CMD_TEXT, token->text);
   if (token->desc)
-    XFREE (MTYPE_CMD_TOKENS, token->desc);
+    XFREE (MTYPE_CMD_DESC, token->desc);
   if (token->arg)
-    XFREE (MTYPE_CMD_TOKENS, token->arg);
+    XFREE (MTYPE_CMD_ARG, token->arg);
 
   XFREE (MTYPE_CMD_TOKENS, token);
 }
@@ -2439,9 +2443,9 @@ copy_cmd_token (struct cmd_token *token)
   struct cmd_token *copy = new_cmd_token (token->type, token->attr, NULL, NULL);
   copy->max   = token->max;
   copy->min   = token->min;
-  copy->text  = token->text ? XSTRDUP (MTYPE_CMD_TOKENS, token->text) : NULL;
-  copy->desc  = token->desc ? XSTRDUP (MTYPE_CMD_TOKENS, token->desc) : NULL;
-  copy->arg   = token->arg  ? XSTRDUP (MTYPE_CMD_TOKENS, token->arg) : NULL;
+  copy->text  = token->text ? XSTRDUP (MTYPE_CMD_TEXT, token->text) : NULL;
+  copy->desc  = token->desc ? XSTRDUP (MTYPE_CMD_DESC, token->desc) : NULL;
+  copy->arg   = token->arg  ? XSTRDUP (MTYPE_CMD_ARG, token->arg) : NULL;
 
   return copy;
 }
index 1e1698fc7d123908f65365a6e7bcddbd643a18b9..1e490cc4cdb2511c47b7c7a4b01aa93dcbb8d6c3 100644 (file)
@@ -31,6 +31,7 @@
 #include "hash.h"
 
 DECLARE_MTYPE(HOST)
+DECLARE_MTYPE(CMD_ARG)
 
 /* for test-commands.c */
 DECLARE_MTYPE(STRVEC)
@@ -420,12 +421,10 @@ extern void cmd_exit (struct vty *vty);
 extern int cmd_list_cmds (struct vty *vty, int do_permute);
 
 /* memory management for cmd_token */
-struct cmd_token *
-new_cmd_token (enum cmd_token_type, u_char attr, char *, char *);
-void
-del_cmd_token (struct cmd_token *);
-struct cmd_token *
-copy_cmd_token (struct cmd_token *);
+extern struct cmd_token *new_cmd_token (enum cmd_token_type, u_char attr,
+                                        const char *text, const char *desc);
+extern void del_cmd_token (struct cmd_token *);
+extern struct cmd_token *copy_cmd_token (struct cmd_token *);
 
 extern void command_parse_format (struct graph *graph, struct cmd_element *cmd);
 
index d228563240075eab177b5ed886e28de5e0c88f8f..aa58313134f553e958091bb0987f83f56b3bd3f7 100644 (file)
@@ -27,7 +27,6 @@
 #include "command_match.h"
 #include "memory.h"
 
-DEFINE_MTYPE_STATIC(LIB, CMD_TOKENS, "Command Tokens")
 DEFINE_MTYPE_STATIC(LIB, CMD_MATCHSTACK, "Command Match Stack")
 
 #define MAXDEPTH 64
@@ -322,7 +321,7 @@ command_match_r (struct graph_node *start, vector vline, unsigned int n,
           // copy token, set arg and prepend to currbest
           struct cmd_token *token = start->data;
           struct cmd_token *copy = copy_cmd_token (token);
-          copy->arg = XSTRDUP (MTYPE_CMD_TOKENS, input_token);
+          copy->arg = XSTRDUP (MTYPE_CMD_ARG, input_token);
           listnode_add_before (currbest, currbest->head, copy);
           matcher_rv = MATCHER_OK;
         }
index c920e11380cdfa0bf118d7ed15aa975d8f3ebfb6..7f98704f90744c25554a29ce79e715eb470aca3c 100644 (file)
   };
 
   /* helper functions for parser */
-  static char *
+  static const char *
   doc_next (struct parser_ctx *ctx);
 
   static struct graph_node *
   static struct graph_node *
   new_token_node (struct parser_ctx *,
                   enum cmd_token_type type,
-                  char *text,
-                  char *doc);
+                  const char *text,
+                  const char *doc);
 
   static void
   terminate_graph (struct parser_ctx *ctx,
@@ -222,7 +222,7 @@ compound_token:
 
 literal_token: WORD
 {
-  $$ = new_token_node (ctx, WORD_TKN, strdup($1), doc_next(ctx));
+  $$ = new_token_node (ctx, WORD_TKN, $1, doc_next(ctx));
   free ($1);
 }
 ;
@@ -230,32 +230,32 @@ literal_token: WORD
 placeholder_token:
   IPV4
 {
-  $$ = new_token_node (ctx, IPV4_TKN, strdup($1), doc_next(ctx));
+  $$ = new_token_node (ctx, IPV4_TKN, $1, doc_next(ctx));
   free ($1);
 }
 | IPV4_PREFIX
 {
-  $$ = new_token_node (ctx, IPV4_PREFIX_TKN, strdup($1), doc_next(ctx));
+  $$ = new_token_node (ctx, IPV4_PREFIX_TKN, $1, doc_next(ctx));
   free ($1);
 }
 | IPV6
 {
-  $$ = new_token_node (ctx, IPV6_TKN, strdup($1), doc_next(ctx));
+  $$ = new_token_node (ctx, IPV6_TKN, $1, doc_next(ctx));
   free ($1);
 }
 | IPV6_PREFIX
 {
-  $$ = new_token_node (ctx, IPV6_PREFIX_TKN, strdup($1), doc_next(ctx));
+  $$ = new_token_node (ctx, IPV6_PREFIX_TKN, $1, doc_next(ctx));
   free ($1);
 }
 | VARIABLE
 {
-  $$ = new_token_node (ctx, VARIABLE_TKN, strdup($1), doc_next(ctx));
+  $$ = new_token_node (ctx, VARIABLE_TKN, $1, doc_next(ctx));
   free ($1);
 }
 | RANGE
 {
-  $$ = new_token_node (ctx, RANGE_TKN, strdup($1), doc_next(ctx));
+  $$ = new_token_node (ctx, RANGE_TKN, $1, doc_next(ctx));
   struct cmd_token *token = $$->data;
 
   // get the numbers out
@@ -462,10 +462,7 @@ terminate_graph (struct parser_ctx *ctx, struct graph_node *finalnode)
   // * -> finalnode -> END_TKN -> cmd_element
   struct cmd_element *element = ctx->el;
   struct graph_node *end_token_node =
-    new_token_node (ctx,
-                    END_TKN,
-                    strdup (CMD_CR_TEXT),
-                    strdup (""));
+    new_token_node (ctx, END_TKN, CMD_CR_TEXT, "");
   struct graph_node *end_element_node =
     graph_new_node (ctx->graph, element, NULL);
 
@@ -476,7 +473,7 @@ terminate_graph (struct parser_ctx *ctx, struct graph_node *finalnode)
   graph_add_edge (end_token_node, end_element_node);
 }
 
-static char *
+static const char *
 doc_next (struct parser_ctx *ctx)
 {
   const char *piece = ctx->docstr ? strsep (&ctx->docstr, "\n") : "";
@@ -486,12 +483,12 @@ doc_next (struct parser_ctx *ctx)
     piece = "";
   }
 
-  return strdup (piece);
+  return piece;
 }
 
 static struct graph_node *
 new_token_node (struct parser_ctx *ctx, enum cmd_token_type type,
-                char *text, char *doc)
+                const char *text, const char *doc)
 {
   struct cmd_token *token = new_cmd_token (type, ctx->el->attr, text, doc);
   return graph_new_node (ctx->graph, token, (void (*)(void *)) &del_cmd_token);