Fix handling of nvlist array

This commit is contained in:
Vladimir 'phcoder' Serbinenko 2010-12-05 18:13:32 +01:00
parent 069142f4c2
commit e5c63d9d41
2 changed files with 32 additions and 18 deletions

View 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;
int r;
r = get_nvlist_size (nvpairptr, nvpair + 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 */
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;
}

View 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);