]> git.ipfire.org Git - thirdparty/grub.git/commitdiff
Fix handling of nvlist array
authorVladimir 'phcoder' Serbinenko <phcoder@gmail.com>
Sun, 5 Dec 2010 17:13:32 +0000 (18:13 +0100)
committerVladimir 'phcoder' Serbinenko <phcoder@gmail.com>
Sun, 5 Dec 2010 17:13:32 +0000 (18:13 +0100)
grub-core/fs/zfs/zfs.c
grub-core/fs/zfs/zfsinfo.c

index bf955a930947b9a949cfc98d94285e86e2652faa..670326a421e23c5b6db0f68b59d42b9f9c3a6d8b 100644 (file)
@@ -1812,13 +1812,28 @@ grub_zfs_nvlist_lookup_nvlist_array_get_nelm (char *nvlist, char *name)
   grub_size_t nelm, size;
   int found;
 
-  found = nvlist_find_value (nvlist, name, DATA_TYPE_NVLIST, &nvpair,
+  found = nvlist_find_value (nvlist, name, DATA_TYPE_NVLIST_ARRAY, &nvpair,
                             &size, &nelm);
   if (! found)
     return -1;
   return nelm;
 }
 
+static int
+get_nvlist_size (char *beg, char *limit)
+{
+  char *ptr;
+  grub_uint32_t encode_size;
+  
+  ptr = beg + 8;
+
+  while (ptr < limit
+        && (encode_size = grub_be_to_cpu32 (*(grub_uint32_t *) ptr)))
+    ptr += encode_size;        /* goto the next nvpair */
+  ptr += 8;      
+  return (ptr > limit) ? -1 : (ptr - beg);
+}
+
 char *
 grub_zfs_nvlist_lookup_nvlist_array (char *nvlist, char *name,
                                     grub_size_t index)
@@ -1829,8 +1844,9 @@ grub_zfs_nvlist_lookup_nvlist_array (char *nvlist, char *name,
   grub_size_t size;
   unsigned i;
   grub_size_t nelm;
+  int elemsize = 0;
 
-  found = nvlist_find_value (nvlist, name, DATA_TYPE_NVLIST, &nvpair,
+  found = nvlist_find_value (nvlist, name, DATA_TYPE_NVLIST_ARRAY, &nvpair,
                             &size, &nelm);
   if (!found)
     return 0;
@@ -1844,33 +1860,31 @@ grub_zfs_nvlist_lookup_nvlist_array (char *nvlist, char *name,
 
   for (i = 0; i < index; i++)
     {
-      grub_uint32_t encode_size;
-
-      /* skip the header, nvl_version, and nvl_nvflag */
-      nvpairptr = nvpairptr + 4 * 2;
-
-      while (nvpairptr < nvpair + size
-            && (encode_size = grub_be_to_cpu32 (*(grub_uint32_t *) nvpairptr)))
-       nvlist += encode_size;  /* goto the next nvpair */
+      int r;
+      r = get_nvlist_size (nvpairptr, nvpair + size);
 
-      nvlist = nvlist + 4 * 2; /* skip the ending 2 zeros - 8 bytes */
+      if (r < 0)
+       {
+         grub_error (GRUB_ERR_BAD_FS, "incorrect nvlist array");
+         return NULL;
+       }
+      nvpairptr += r;
     }
 
-  if (nvpairptr >= nvpair + size
-      || nvpairptr + grub_be_to_cpu32 (*(grub_uint32_t *) (nvpairptr + 4 * 2))
-      >= nvpair + size)
+  elemsize = get_nvlist_size (nvpairptr, nvpair + size);
+
+  if (elemsize < 0)
     {
       grub_error (GRUB_ERR_BAD_FS, "incorrect nvlist array");
       return 0;
     }
 
-  ret = grub_zalloc (grub_be_to_cpu32 (*(grub_uint32_t *) (nvpairptr + 4 * 2))
-                    + 3 * sizeof (grub_uint32_t));
+  ret = grub_zalloc (elemsize + sizeof (grub_uint32_t));
   if (!ret)
     return 0;
   grub_memcpy (ret, nvlist, sizeof (grub_uint32_t));
 
-  grub_memcpy (ret + sizeof (grub_uint32_t), nvpairptr, size);
+  grub_memcpy (ret + sizeof (grub_uint32_t), nvpairptr, elemsize);
   return ret;
 }
 
index 33065892a347e93d3941c0adb8e52513cee7a4b9..735b8e9834a6222daed0e5e694eb161eeb4beef4 100644 (file)
@@ -139,7 +139,6 @@ print_vdev_info (char *nvlist, int tab)
        }
       grub_printf ("Mirror VDEV with %d children\n", nelm);
       print_state (nvlist, tab);
-
       for (i = 0; i < nelm; i++)
        {
          char *child;
@@ -159,6 +158,7 @@ print_vdev_info (char *nvlist, int tab)
 
          grub_free (child);
        }
+      return GRUB_ERR_NONE;
     }
 
   print_tabs (tab);