From a992a71ed8df5188e9cdb3d2f5f502c2cc2e6417 Mon Sep 17 00:00:00 2001 From: BVK Chaitanya Date: Thu, 10 Jun 2010 20:49:57 +0530 Subject: [PATCH] fix memory issues when used inside loops --- hello/hello.c | 14 ++++---------- include/grub/script_sh.h | 21 ++++++++++++++++++++- script/argv.c | 14 ++++---------- script/execute.c | 2 +- script/parser.y | 14 +++++++------- script/script.c | 17 ++++++----------- 6 files changed, 42 insertions(+), 40 deletions(-) diff --git a/hello/hello.c b/hello/hello.c index 992c99f71..118966291 100644 --- a/hello/hello.c +++ b/hello/hello.c @@ -44,16 +44,9 @@ grub_cmd_hello (grub_extcmd_context_t ctxt, return 1; if (script) - grub_script_free (script); + grub_script_put (script); - script = grub_malloc (sizeof (*script)); - if (! script) - return 1; - - script->cmd = ctxt->script_params[0]->cmd; - script->mem = ctxt->script_params[0]->mem; - ctxt->script_params[0]->cmd = 0; - ctxt->script_params[0]->mem = 0; + script = grub_script_get (ctxt->script_params[0]); } return 0; @@ -71,7 +64,8 @@ GRUB_MOD_INIT(hello) GRUB_MOD_FINI(hello) { if (script) - grub_script_free (script); + grub_script_put (script); + script = 0; grub_unregister_extcmd (cmd); } diff --git a/include/grub/script_sh.h b/include/grub/script_sh.h index a17dcca70..2ada5d474 100644 --- a/include/grub/script_sh.h +++ b/include/grub/script_sh.h @@ -39,6 +39,7 @@ struct grub_script_cmd struct grub_script { + unsigned refcnt; struct grub_script_mem *mem; struct grub_script_cmd *cmd; }; @@ -61,7 +62,7 @@ struct grub_script_arg char *str; /* Parsed block argument. */ - struct grub_script block; + struct grub_script *block; /* Next argument part. */ struct grub_script_arg *next; @@ -227,6 +228,8 @@ struct grub_parser_param struct grub_lexer_param *lexerstate; }; +void grub_script_mem_free (struct grub_script_mem *mem); + void grub_script_argv_free (struct grub_script_argv *argv); int grub_script_argv_next (struct grub_script_argv *argv); int grub_script_argv_append (struct grub_script_argv *argv, const char *s); @@ -354,4 +357,20 @@ grub_err_t grub_script_function_call (grub_script_function_t func, char ** grub_script_execute_arglist_to_argv (struct grub_script_arglist *arglist, int *count); +static inline struct grub_script * +grub_script_get (struct grub_script *script) +{ + script->refcnt++; + return script; +} + +static inline void +grub_script_put (struct grub_script *script) +{ + if (script->refcnt == 0) + grub_script_free (script); + else + script->refcnt--; +} + #endif /* ! GRUB_NORMAL_PARSER_HEADER */ diff --git a/script/argv.c b/script/argv.c index f962556d8..8dd563345 100644 --- a/script/argv.c +++ b/script/argv.c @@ -55,7 +55,8 @@ grub_script_argv_free (struct grub_script_argv *argv) if (argv->scripts) { for (i = 0; i < argv->argc; i++) - grub_script_free (argv->scripts[i]); + if (argv->scripts[i]) + grub_script_put (argv->scripts[i]); grub_free (argv->scripts); } @@ -127,17 +128,10 @@ int grub_script_argv_script_append (struct grub_script_argv *argv, struct grub_script *script) { - struct grub_script *s; - - s = grub_malloc (sizeof (*s)); - if (! s) - return 1; - if (argv->scripts[argv->argc - 1]) - grub_script_free (argv->scripts[argv->argc - 1]); + grub_script_put (argv->scripts[argv->argc - 1]); - *s = *script; - argv->scripts[argv->argc - 1] = s; + argv->scripts[argv->argc - 1] = grub_script_get (script); return 0; } diff --git a/script/execute.c b/script/execute.c index 0ac42cf4a..c6a6c2484 100644 --- a/script/execute.c +++ b/script/execute.c @@ -198,7 +198,7 @@ grub_script_arglist_to_argv (struct grub_script_arglist *arglist, case GRUB_SCRIPT_ARG_TYPE_BLOCK: if (grub_script_argv_append (&result, arg->str) || - grub_script_argv_script_append (&result, &arg->block)) + grub_script_argv_script_append (&result, arg->block)) goto fail; break; diff --git a/script/parser.y b/script/parser.y index d774ca918..1202fef29 100644 --- a/script/parser.y +++ b/script/parser.y @@ -164,11 +164,9 @@ block: "{" if ((p = grub_script_lexer_record_stop (state, $2))) *grub_strrchr (p, '}') = '\0'; - if ((arg = grub_script_arg_add (state, 0, GRUB_SCRIPT_ARG_TYPE_BLOCK, p))) - { - arg->block.cmd = $3; - arg->block.mem = memory; - } + arg = grub_script_arg_add (state, 0, GRUB_SCRIPT_ARG_TYPE_BLOCK, p); + if (! arg || ! (arg->block = grub_script_create ($3, memory))) + grub_script_mem_free (memory); $$ = grub_script_add_arglist (state, 0, arg); grub_script_lexer_deref (state->lexerstate); @@ -256,8 +254,10 @@ function: "function" "name" state->func_mem = grub_script_mem_record_stop (state, state->func_mem); script = grub_script_create ($6, state->func_mem); - if (script) - grub_script_function_create ($2, script); + if (! script) + grub_script_mem_free (state->func_mem); + else + grub_script_function_create ($2, script); grub_script_lexer_deref (state->lexerstate); } diff --git a/script/script.c b/script/script.c index 9017a08e8..b7cbdff1d 100644 --- a/script/script.c +++ b/script/script.c @@ -54,7 +54,7 @@ grub_script_malloc (struct grub_parser_param *state, grub_size_t size) } /* Free all memory described by MEM. */ -static void +void grub_script_mem_free (struct grub_script_mem *mem) { struct grub_script_mem *memfree; @@ -122,8 +122,7 @@ grub_script_arg_add (struct grub_parser_param *state, return arg; argpart->type = type; - argpart->block.mem = 0; - argpart->block.cmd = 0; + argpart->block = 0; len = grub_strlen (str) + 1; argpart->str = grub_script_malloc (state, len); @@ -341,16 +340,12 @@ grub_script_create (struct grub_script_cmd *cmd, struct grub_script_mem *mem) struct grub_script *parsed; parsed = grub_malloc (sizeof (*parsed)); - if (!parsed) - { - grub_script_mem_free (mem); - grub_free (cmd); - - return 0; - } + if (! parsed) + return 0; parsed->mem = mem; parsed->cmd = cmd; + parsed->refcnt = 0; return parsed; } @@ -365,7 +360,7 @@ grub_script_parse (char *script, grub_reader_getline_t getline) struct grub_lexer_param *lexstate; struct grub_parser_param *parsestate; - parsed = grub_malloc (sizeof (*parsed)); + parsed = grub_script_create (0, 0); if (!parsed) return 0;