From dbb48b978671394bcb33c9f34656a9aadf40a318 Mon Sep 17 00:00:00 2001 From: Chet Ramey Date: Tue, 4 Jun 2024 12:23:18 -0400 Subject: [PATCH] avoid storing extra copy of function bodies; fix some minor memory leaks --- CWRU/CWRU.chlog | 36 ++++++++++++++++++++++++++++++++++++ builtins/declare.def | 1 + builtins/exec.def | 4 ---- parse.y | 13 +++++++++++-- subst.c | 4 +++- variables.c | 3 +++ 6 files changed, 54 insertions(+), 7 deletions(-) diff --git a/CWRU/CWRU.chlog b/CWRU/CWRU.chlog index b902d7c3..54420f56 100644 --- a/CWRU/CWRU.chlog +++ b/CWRU/CWRU.chlog @@ -9590,3 +9590,39 @@ arrayfunc.c - assign_array_element_internal: if the assignment failed, as tested by ASSIGN_DISALLOWED, free the assoc array key we allocated Report from Grisha Levit + + 6/3 + --- +variables.c + - bind_function_def: don't copy the command tree if we're overwriting + a function definition; after function binding, the function_def + struct never uses the saved command anyway + From a report and patch by Koichi Murase + +parse.y + - make sure to free WORD in coproc WORD COMMAND after creating the + coproc struct + Report and patch from Grisha Levit + +builtins/exec.def + - exec_builtin: we don't need to set args to NULL; if shell_execve + reallocates args to add more items at the front, it has committed + to longjmp back to the top level + Report and patch from Grisha Levit + +subst.c + - expand_word_internal: dispose of the list used for $@ if we're not + splitting and save the space-separated list back to tword->word + Report and patch from Grisha Levit + +parse.y + - read_token: if we try to parse a conditional command and get a syntax + error, make sure to dispose of the partial command we created + Report and patch from Grisha Levit + - read_token: if we try to parse a conditional command and get a syntax + error because we read an unexpected WORD, dispose of the WORD_DESC + before returning -1 + Report and patch from Grisha Levit + - cond_term: if we read a WORD where we expect something else, dispose + of the WORD_DESC before returning COND_ERROR + Report and patch from Grisha Levit diff --git a/builtins/declare.def b/builtins/declare.def index 8065f8d2..b8e1f223 100644 --- a/builtins/declare.def +++ b/builtins/declare.def @@ -156,6 +156,7 @@ declare_find_variable (const char *name, int mkglobal, int chklocal) var = find_variable (name); if (var && local_p (var) && var->context == variable_context) return var; + /* XXX - add check for previous scopes here if wanted 6/4/2024 */ return (find_global_variable (name)); } else diff --git a/builtins/exec.def b/builtins/exec.def index 3ca7c4f8..618882c8 100644 --- a/builtins/exec.def +++ b/builtins/exec.def @@ -230,10 +230,6 @@ exec_builtin (WORD_LIST *list) exit_value = shell_execve (command, args, env); opt = errno; - /* We have to set this to NULL because shell_execve has called realloc() - to stuff more items at the front of the array, which may have caused - the memory to be freed by realloc(). We don't want to free it twice. */ - args = (char **)NULL; if (cleanenv == 0) adjust_shell_level (1); diff --git a/parse.y b/parse.y index 1349480b..eb83af4c 100644 --- a/parse.y +++ b/parse.y @@ -1103,6 +1103,7 @@ coproc: COPROC shell_command { $$ = make_coproc_command ($2->word, $3); $$->flags |= CMD_WANT_SUBSHELL|CMD_COPROC_SUBSHELL; + dispose_word ($2); } | COPROC WORD shell_command redirection_list { @@ -1120,6 +1121,7 @@ coproc: COPROC shell_command tc->redirects = $4; $$ = make_coproc_command ($2->word, $3); $$->flags |= CMD_WANT_SUBSHELL|CMD_COPROC_SUBSHELL; + dispose_word ($2); } | COPROC simple_command { @@ -3518,15 +3520,20 @@ read_token (int command) #if defined (COND_COMMAND) if ((parser_state & (PST_CONDCMD|PST_CONDEXPR)) == PST_CONDCMD) { + COMMAND *cond_command; parser_state &= ~PST_CMDBLTIN; cond_lineno = line_number; parser_state |= PST_CONDEXPR; - yylval.command = parse_cond_command (); + cond_command = parse_cond_command (); if (cond_token != COND_END) { cond_error (); + if (cond_token == WORD) + dispose_word (yylval.word); + dispose_command (cond_command); return (-1); } + yylval.command = cond_command; token_to_read = COND_END; parser_state &= ~(PST_CONDEXPR|PST_CONDCMD); return (COND_CMD); @@ -5042,7 +5049,7 @@ cond_term (void) else if (tok == BANG || (tok == WORD && (yylval.word->word[0] == '!' && yylval.word->word[1] == '\0'))) { if (tok == WORD) - dispose_word (yylval.word); /* not needed */ + dispose_word (yylval.word); /* word not needed */ term = cond_term (); if (term) term->flags ^= CMD_INVERT_RETURN; @@ -5118,6 +5125,8 @@ cond_term (void) else parser_error (line_number, _("conditional binary operator expected")); dispose_cond_node (tleft); + if (tok == WORD) + dispose_word (yylval.word); COND_RETURN_ERROR (); } diff --git a/subst.c b/subst.c index 929fabb2..03205f95 100644 --- a/subst.c +++ b/subst.c @@ -3472,6 +3472,7 @@ do_compound_assignment (const char *name, char *value, int flags) else if (mkglobal && variable_context) { v = chklocal ? find_variable (name) : 0; + /* XXX - if we want to make chklocal search previous scopes, change here 2024/06/04 */ if (v && (local_p (v) == 0 || v->context != variable_context)) v = 0; if (v == 0) @@ -12144,6 +12145,7 @@ finished_with_string: return, we expect to be able to split the results, but the space separation means the right split doesn't happen. */ tword->word = string_list (list); + dispose_words (list); } else tword->word = istring; @@ -12959,7 +12961,7 @@ expand_declaration_argument (WORD_LIST *tlist, WORD_LIST *wcmd) if (tlist->word->flags & W_ASSNGLOBAL) omap['g'] = 1; if (tlist->word->flags & W_CHKLOCAL) - omap['G'] = 1; + omap['G'] = 1; /* internal, undocumented */ /* If we have special handling note the integer attribute and others that transform the value upon assignment. What we do is take all diff --git a/variables.c b/variables.c index a64368e4..e069ae5e 100644 --- a/variables.c +++ b/variables.c @@ -3507,7 +3507,10 @@ bind_function_def (const char *name, FUNCTION_DEF *value, int flags) if (entry && (flags & 1)) { dispose_function_def_contents (entry); + cmd = value->command; + value->command = 0; entry = copy_function_def_contents (value, entry); + value->command = cmd; } else if (entry) return; -- 2.47.2