Print this page
5679 be_sort_list(): Possible null pointer dereference
@@ -24,10 +24,11 @@
*/
/*
* Copyright 2013 Nexenta Systems, Inc. All rights reserved.
* Copyright 2015 Toomas Soome <tsoome@me.com>
+ * Copyright 2015 Gary Mills
*/
#include <assert.h>
#include <libintl.h>
#include <libnvpair.h>
@@ -65,11 +66,11 @@
static int be_get_zone_node_data(be_node_list_t *, char *);
static int be_get_ds_data(zfs_handle_t *, char *, be_dataset_list_t *,
be_node_list_t *);
static int be_get_ss_data(zfs_handle_t *, char *, be_snapshot_list_t *,
be_node_list_t *);
-static void be_sort_list(be_node_list_t **,
+static int be_sort_list(be_node_list_t **,
int (*)(const void *, const void *));
static int be_qsort_compare_BEs_name(const void *, const void *);
static int be_qsort_compare_BEs_name_rev(const void *, const void *);
static int be_qsort_compare_BEs_date(const void *, const void *);
static int be_qsort_compare_BEs_date_rev(const void *, const void *);
@@ -141,24 +142,25 @@
* Function: be_sort
* Description: Sort BE node list
* Parameters:
* pointer to address of list head
* sort order type
- * Returns:
- * nothing
+ * Return:
+ * BE_SUCCESS - Success
+ * be_errno_t - Failure
* Side effect:
* node list sorted by name
* Scope:
* Public
*/
-void
+int
be_sort(be_node_list_t **be_nodes, int order)
{
int (*compar)(const void *, const void *) = be_qsort_compare_BEs_date;
if (be_nodes == NULL)
- return;
+ return (BE_ERR_INVAL);
switch (order) {
case BE_SORT_UNSPECIFIED:
case BE_SORT_DATE:
compar = be_qsort_compare_BEs_date;
@@ -179,14 +181,14 @@
compar = be_qsort_compare_BEs_space_rev;
break;
default:
be_print_err(gettext("be_sort: invalid sort order %d\n"),
order);
- return;
+ return (BE_ERR_INVAL);
}
- be_sort_list(be_nodes, compar);
+ return (be_sort_list(be_nodes, compar));
}
/* ******************************************************************** */
/* Semi-Private Functions */
/* ******************************************************************** */
@@ -212,10 +214,11 @@
_be_list(char *be_name, be_node_list_t **be_nodes)
{
list_callback_data_t cb = { 0 };
be_transaction_data_t bt = { 0 };
int ret = BE_SUCCESS;
+ int sret;
zpool_handle_t *zphp;
char *rpool = NULL;
struct be_defaults be_defaults;
if (be_nodes == NULL)
@@ -275,13 +278,13 @@
*be_nodes = cb.be_nodes_head;
free(cb.be_name);
- be_sort(be_nodes, BE_SORT_DATE);
+ sret = be_sort(be_nodes, BE_SORT_DATE);
- return (ret);
+ return ((ret == BE_SUCCESS) ? sret : ret);
}
/*
* Function: be_free_list
* Description: Frees up all the data allocated for the list of BEs,
@@ -682,34 +685,44 @@
* Function: be_sort_list
* Description: Sort BE node list
* Parameters:
* pointer to address of list head
* compare function
- * Returns:
- * nothing
+ * Return:
+ * BE_SUCCESS - Success
+ * be_errno_t - Failure
* Side effect:
* node list sorted by name
* Scope:
* Private
*/
-static void
+static int
be_sort_list(be_node_list_t **pstart, int (*compar)(const void *, const void *))
{
+ int ret = BE_SUCCESS;
size_t ibe, nbe;
be_node_list_t *p = NULL;
be_node_list_t **ptrlist = NULL;
+ be_node_list_t **ptrtmp;
- if (pstart == NULL)
- return;
+ if (pstart == NULL) /* Nothing to sort */
+ return (BE_SUCCESS);
/* build array of linked list BE struct pointers */
for (p = *pstart, nbe = 0; p != NULL; nbe++, p = p->be_next_node) {
- ptrlist = realloc(ptrlist,
+ ptrtmp = realloc(ptrlist,
sizeof (be_node_list_t *) * (nbe + 2));
+ if (ptrtmp == NULL) { /* out of memory */
+ be_print_err(gettext("be_sort_list: memory "
+ "allocation failed\n"));
+ ret = BE_ERR_NOMEM;
+ goto free;
+ }
+ ptrlist = ptrtmp;
ptrlist[nbe] = p;
}
- if (nbe == 0)
- return;
+ if (nbe == 0) /* Nothing to sort */
+ return (BE_SUCCESS);
/* in-place list quicksort using qsort(3C) */
if (nbe > 1) /* no sort if less than 2 BEs */
qsort(ptrlist, nbe, sizeof (be_node_list_t *), compar);
ptrlist[nbe] = NULL; /* add linked list terminator */
@@ -725,12 +738,14 @@
const size_t nmax = ptrlist[ibe]->be_node_num_snapshots;
be_snapshot_list_t ** const slist =
malloc(sizeof (be_snapshot_list_t *) * (nmax + 1));
be_snapshot_list_t *p;
- if (slist == NULL)
+ if (slist == NULL) {
+ ret = BE_ERR_NOMEM;
continue;
+ }
/* build array of linked list snapshot struct ptrs */
for (ns = 0, p = ptrlist[ibe]->be_node_snapshots;
ns < nmax && p != NULL;
ns++, p = p->be_next_snapshot) {
slist[ns] = p;
@@ -753,12 +768,14 @@
const size_t nmax = ptrlist[ibe]->be_node_num_datasets;
be_dataset_list_t ** const slist =
malloc(sizeof (be_dataset_list_t *) * (nmax + 1));
be_dataset_list_t *p;
- if (slist == NULL)
+ if (slist == NULL) {
+ ret = BE_ERR_NOMEM;
continue;
+ }
/* build array of linked list dataset struct ptrs */
for (ns = 0, p = ptrlist[ibe]->be_node_datasets;
ns < nmax && p != NULL;
ns++, p = p->be_next_dataset) {
slist[ns] = p;
@@ -777,10 +794,11 @@
free(slist);
}
}
free:
free(ptrlist);
+ return (ret);
}
/*
* Function: be_qsort_compare_BEs_date
* Description: compare BE creation times for qsort(3C)