kern/parser: Fix a memory leak

The getline() function supplied to grub_parser_split_cmdline() returns
a newly allocated buffer and can be called multiple times, but the
returned buffer is never freed.

Signed-off-by: Chris Coulson <chris.coulson@canonical.com>
Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
This commit is contained in:
Chris Coulson authored and Daniel Kiper committed 2021-03-02 15:54:19 +01:00
1 parent b911884dd7
commit c6c426e5ab
1 file changed
+16 -4
+16 -4
View File
@@ -140,6 +140,7 @@ grub_parser_split_cmdline (const char *cmdline,
char buffer[1024]; char buffer[1024];
char *bp = buffer; char *bp = buffer;
char *rd = (char *) cmdline; char *rd = (char *) cmdline;
char *rp = rd;
char varname[200]; char varname[200];
char *vp = varname; char *vp = varname;
char *args; char *args;
@@ -149,10 +150,18 @@ grub_parser_split_cmdline (const char *cmdline,
*argv = NULL; *argv = NULL;
do do
{ {
if (!rd || !*rd) if (rp == NULL || *rp == '\0')
{ {
if (rd != cmdline)
{
grub_free (rd);
rd = rp = NULL;
}
if (getline) if (getline)
getline (&rd, 1, getline_data); {
getline (&rd, 1, getline_data);
rp = rd;
}
else else
break; break;
} }
@@ -160,12 +169,12 @@ grub_parser_split_cmdline (const char *cmdline,
if (!rd) if (!rd)
break; break;
for (; *rd; rd++) for (; *rp != '\0'; rp++)
{ {
grub_parser_state_t newstate; grub_parser_state_t newstate;
char use; char use;
newstate = grub_parser_cmdline_state (state, *rd, &use); newstate = grub_parser_cmdline_state (state, *rp, &use);
/* If a variable was being processed and this character does /* If a variable was being processed and this character does
not describe the variable anymore, write the variable to not describe the variable anymore, write the variable to
@@ -198,6 +207,9 @@ grub_parser_split_cmdline (const char *cmdline,
} }
while (state != GRUB_PARSER_STATE_TEXT && !check_varstate (state)); while (state != GRUB_PARSER_STATE_TEXT && !check_varstate (state));
if (rd != cmdline)
grub_free (rd);
/* A special case for when the last character was part of a /* A special case for when the last character was part of a
variable. */ variable. */
add_var (varname, &bp, &vp, state, GRUB_PARSER_STATE_TEXT); add_var (varname, &bp, &vp, state, GRUB_PARSER_STATE_TEXT);