Hi,

Below patch fixes some out of memory cases, that I came across when I
was working on lexer rewrite.  This patch is based on
people/bvk/while-loop-support branch, and is also available as
people/bvk/oom-fixes branch.

Let me know your comments.



thanks,
-- 
bvk.chaitanya
=== modified file 'ChangeLog.scripting'
--- ChangeLog.scripting 2009-12-26 05:11:18 +0000
+++ ChangeLog.scripting 2009-12-27 10:26:21 +0000
@@ -1,3 +1,26 @@
+2009-12-27  BVK Chaitanya  <b...@dbook>
+
+       * include/grub/script_sh.h (grub_script_cmd_menuentry): Member
+       sourcecode type is reverted back to pointer to constant.
+       * script/script.c (grub_script_malloc): Fixed it to handle out of
+       memory cases gracefully.
+       (grub_script_add_cmd): Likewise.
+       (grub_script_arg_add): Likewise.
+       (grub_script_add_arglist): Likewise.
+       (grub_script_create_cmdline): Likewise.
+       (grub_script_create_cmdif): Likewise.
+       (grub_script_create_cmdmenu): Likewise, and sourcecode parameter
+       is used as it is.
+       * script/parser.y (arguments1): Added null pointer check to handle
+       out of memory cases.
+       (grubcmd): Likewise.
+       (commands1): Likewise.
+       * script/lexer.c (grub_script_lexer_record_stop): Allocates
+       sourcecode using grub_script_alloc, so that memory is recollected
+       automatically and refactored it to trim the source code.
+       * util/grub-script-check.c (grub_script_execute_menuentry):
+       Freeing sourcecode is now unnecessary, so is removed.
+
 2009-12-26  BVK Chaitanya  <bvk.gro...@gmail.com>
 
        * include/grub/script_sh.h: New function prototypes for

=== modified file 'include/grub/script_sh.h'
--- include/grub/script_sh.h    2009-12-26 05:11:18 +0000
+++ include/grub/script_sh.h    2009-12-27 10:06:47 +0000
@@ -145,7 +145,7 @@
   struct grub_script_arglist *arglist;
 
   /* The sourcecode the entry will be generated from.  */
-  char *sourcecode;
+  const char *sourcecode;
 
   /* Options.  XXX: Not used yet.  */
   int options;

=== modified file 'script/lexer.c'
--- script/lexer.c      2009-12-26 04:07:41 +0000
+++ script/lexer.c      2009-12-27 09:50:59 +0000
@@ -63,29 +63,40 @@
 grub_script_lexer_record_stop (struct grub_parser_param *parser)
 {
   char *ptr;
+  char *result;
   struct grub_lexer_param *lexer = parser->lexerstate;
 
+  auto char *compact (char *start, char *end);
+  char *compact (char *start, char *end)
+  {
+    /* Delete '{' and '}' characters and whitespaces.  */
+    while (*start && grub_isspace (*start)) start++;
+    if (*start == '{') start++;
+    while (*start && grub_isspace (*start)) start++;
+
+    while (*end && grub_isspace (*end)) end--;
+    if (*end == '}') end--;
+    while (*end && grub_isspace (*end)) end--;
+    *end = '\0';
+
+    return start;
+  }
+
   if (!lexer->record || !lexer->recording)
     return 0;
 
-  /* Delete '{' and '}' characters.  */
   /* XXX This is not necessary in BASH.  */
 
-  ptr = lexer->recording + lexer->recordpos - 1;
-  while (*ptr && grub_isspace (*ptr))
-    ptr--;
-  if (*ptr == '}')
-    *ptr = '\0';
-
-  ptr = lexer->recording;
-  while (*ptr && grub_isspace (*ptr))
-    ptr++;
-  if (*ptr == '{')
-    ptr++;
-
+  ptr = compact (lexer->recording, lexer->recording + lexer->recordpos - 1);
   lexer->record = 0;
   lexer->recordpos = 0;
-  return (*ptr ? grub_strdup (ptr) : 0);
+
+  /* This memory would be freed by, grub_script_free.  */
+  result = grub_script_malloc (parser, grub_strlen (ptr) + 1);
+  if (result)
+    grub_strcpy (result, ptr);
+
+  return result;
 }
 
 

=== modified file 'script/parser.y'
--- script/parser.y     2009-12-26 05:11:18 +0000
+++ script/parser.y     2009-12-27 09:45:42 +0000
@@ -158,19 +158,19 @@
 ;
 arguments1: argument arguments0
             {
-             if ($2)
+             if ($1 && $2)
                {
                  $1->next = $2;
                  $1->argcount += $2->argcount;
                  $2->argcount = 0;
                }
              $$ = $1;
-            }      
+            }
 ;
 
 grubcmd: word arguments0
          {
-           if ($2) {
+           if ($1 && $2) {
              $1->next = $2;
              $1->argcount += $2->argcount;
              $2->argcount = 0;
@@ -197,11 +197,15 @@
             struct grub_script_cmd *cmd;
              struct grub_script_cmdblock *cmdblock;
 
-             cmdblock = (struct grub_script_cmdblock *) $1;
-            cmd = cmdblock->cmdlist;
-            while (cmd->next)
-              cmd = cmd->next;
-            cmd->next = $3;
+            if ($1)
+              {
+                cmdblock = (struct grub_script_cmdblock *) $1;
+                cmd = cmdblock->cmdlist;
+                while (cmd->next)
+                  cmd = cmd->next;
+                cmd->next = $3;
+              }
+            $$ = $1;
            }
 ;
 

=== modified file 'script/script.c'
--- script/script.c     2009-12-26 05:11:18 +0000
+++ script/script.c     2009-12-27 10:19:35 +0000
@@ -24,12 +24,10 @@
 
 /* It is not possible to deallocate the memory when a syntax error was
    found.  Because of that it is required to keep track of all memory
-   allocations.  The memory is freed in case of an error, or
-   assigned to the parsed script when parsing was successful.  */
-
-/* XXX */
-
-/* In case of the normal malloc, some additional bytes are allocated
+   allocations.  The memory is freed in case of an error, or assigned
+   to the parsed script when parsing was successful.
+
+   In case of the normal malloc, some additional bytes are allocated
    for this datastructure.  All reserved memory is stored in a linked
    list so it can be easily freed.  The original memory can be found
    from &mem.  */
@@ -46,6 +44,8 @@
   struct grub_script_mem *mem;
   mem = (struct grub_script_mem *) grub_malloc (size + sizeof (*mem)
                                                - sizeof (char));
+  if (!mem)
+    return 0;
 
   grub_dprintf ("scripting", "malloc %p\n", mem);
   mem->next = state->memused;
@@ -115,9 +115,15 @@
 
   argpart =
     (struct grub_script_arg *) grub_script_malloc (state, sizeof (*arg));
+  if (!argpart)
+    return arg;
+
   argpart->type = type;
   len = grub_strlen (str) + 1;
   argpart->str = grub_script_malloc (state, len);
+  if (!argpart->str)
+    return arg; /* argpart is freed later, during grub_script_free.  */
+
   grub_memcpy (argpart->str, str, len);
   argpart->next = 0;
 
@@ -144,6 +150,9 @@
 
   link =
     (struct grub_script_arglist *) grub_script_malloc (state, sizeof (*link));
+  if (!link)
+    return list;
+
   link->next = 0;
   link->arg = arg;
   link->argcount = 0;
@@ -175,6 +184,9 @@
   grub_dprintf ("scripting", "cmdline\n");
 
   cmd = grub_script_malloc (state, sizeof (*cmd));
+  if (!cmd)
+    return 0;
+
   cmd->cmd.exec = grub_script_execute_cmdline;
   cmd->cmd.next = 0;
   cmd->arglist = arglist;
@@ -197,6 +209,9 @@
   grub_dprintf ("scripting", "cmdif\n");
 
   cmd = grub_script_malloc (state, sizeof (*cmd));
+  if (!cmd)
+    return 0;
+
   cmd->cmd.exec = grub_script_execute_cmdif;
   cmd->cmd.next = 0;
   cmd->exec_to_evaluate = exec_to_evaluate;
@@ -262,26 +277,13 @@
                            char *sourcecode, int options)
 {
   struct grub_script_cmd_menuentry *cmd;
-  int i;
-
-  /* Skip leading newlines to make the sourcecode better readable when
-     using the editor.  */
-  while (*sourcecode == '\n')
-    sourcecode++;
-
-  /* Having trailing returns can some some annoying conflicts, remove
-     them.  XXX: Can the parser be improved to handle this?  */
-  for (i = grub_strlen (sourcecode) - 1; i > 0; i--)
-    {
-      if (sourcecode[i] != '\n')
-       break;
-      sourcecode[i] = '\0';
-    }
 
   cmd = grub_script_malloc (state, sizeof (*cmd));
+  if (!cmd)
+    return 0;
+    
   cmd->cmd.exec = grub_script_execute_menuentry;
   cmd->cmd.next = 0;
-  /* XXX: Check if this memory is properly freed.  */
   cmd->sourcecode = sourcecode;
   cmd->arglist = arglist;
   cmd->options = options;
@@ -304,9 +306,10 @@
 
   if (!cmdblock)
     {
-      cmdblock = (struct grub_script_cmdblock *) grub_script_malloc (state,
-                                                                    sizeof
-                                                                    
(*cmdblock));
+      cmdblock = grub_script_malloc (state, sizeof (*cmdblock));
+      if (!cmdblock)
+       return 0;
+
       cmdblock->cmd.exec = grub_script_execute_cmdblock;
       cmdblock->cmd.next = 0;
       cmdblock->cmdlist = cmd;

=== modified file 'util/grub-script-check.c'
--- util/grub-script-check.c    2009-12-26 05:11:18 +0000
+++ util/grub-script-check.c    2009-12-27 10:06:22 +0000
@@ -90,16 +90,8 @@
 }
 
 grub_err_t
-grub_script_execute_menuentry (struct grub_script_cmd *cmd)
+grub_script_execute_menuentry (struct grub_script_cmd *cmd __attribute__ 
((unused)))
 {
-  struct grub_script_cmd_menuentry *menu;
-  menu = (struct grub_script_cmd_menuentry *)cmd;
-
-  if (menu->sourcecode)
-    {
-      grub_free (menu->sourcecode);
-      menu->sourcecode = 0;
-    }
   return 0;
 }
 

_______________________________________________
Grub-devel mailing list
Grub-devel@gnu.org
http://lists.gnu.org/mailman/listinfo/grub-devel

Reply via email to