Fix handling of nvlist array
This commit is contained in:
parent
069142f4c2
commit
e5c63d9d41
2 changed files with 32 additions and 18 deletions
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
|
Loading…
Reference in a new issue