Print this page
8954 libtopo cannot handle any array type other than string_array.
Reviewed by: Andy Stormont astormont@racktopsystems.com
Reviewed by: David Höppner 0xffea@gmail.com
Reviewed by: Rob Johnston rob.johnston@joyent.com

@@ -20,10 +20,11 @@
  */
 
 /*
  * Copyright (c) 2006, 2010, Oracle and/or its affiliates. All rights reserved.
  * Copyright (c) 2013, Joyent, Inc. All rights reserved.
+ * Copyright (c) 2018, Western Digital Technologies, Inc. All rights reserved.
  */
 
 #include <libxml/parser.h>
 #include <libxml/xinclude.h>
 #include <sys/fm/protocol.h>

@@ -192,11 +193,11 @@
         return (rv);
 }
 
 static int
 xlate_common(topo_mod_t *mp, xmlNodePtr xn, topo_type_t ptype, nvlist_t *nvl,
-const char *name)
+    const char *name)
 {
         int rv;
         uint64_t ui;
         uint_t i = 0, nelems = 0;
         nvlist_t *fmri;

@@ -242,25 +243,12 @@
                 break;
         case TOPO_TYPE_INT32_ARRAY:
         case TOPO_TYPE_UINT32_ARRAY:
         case TOPO_TYPE_INT64_ARRAY:
         case TOPO_TYPE_UINT64_ARRAY:
-                for (cn = xn->xmlChildrenNode; cn != NULL; cn = cn->next)
-                        if ((xmlStrcmp(cn->name, (xmlChar *)Propitem) == 0) ||
-                            (xmlStrcmp(cn->name, (xmlChar *)Argitem) == 0))
-                                nelems++;
-
-                if (nelems < 1) {
-                        topo_dprintf(mp->tm_hdl, TOPO_DBG_ERR, "No <propitem> "
-                            "or <argitem> elements found for array val");
-                        return (-1);
-                }
-                if ((arrbuf = topo_mod_alloc(mp, (nelems * sizeof (uint64_t))))
-                    == NULL)
-                        return (topo_mod_seterrno(mp, ETOPO_NOMEM));
-                break;
         case TOPO_TYPE_STRING_ARRAY:
+        case TOPO_TYPE_FMRI_ARRAY:
                 for (cn = xn->xmlChildrenNode; cn != NULL; cn = cn->next)
                         if ((xmlStrcmp(cn->name, (xmlChar *)Propitem) == 0) ||
                             (xmlStrcmp(cn->name, (xmlChar *)Argitem) == 0))
                                 nelems++;
 

@@ -267,42 +255,27 @@
                 if (nelems < 1) {
                         topo_dprintf(mp->tm_hdl, TOPO_DBG_ERR, "No <propitem> "
                             "or <argitem> elements found for array val");
                         return (-1);
                 }
-                if ((strarrbuf = topo_mod_alloc(mp, (nelems * sizeof (char *))))
-                    == NULL)
-                        return (topo_mod_seterrno(mp, ETOPO_NOMEM));
                 break;
-        case TOPO_TYPE_FMRI_ARRAY:
-                for (cn = xn->xmlChildrenNode; cn != NULL; cn = cn->next)
-                        if ((xmlStrcmp(cn->name, (xmlChar *)Propitem) == 0) ||
-                            (xmlStrcmp(cn->name, (xmlChar *)Argitem) == 0))
-                                nelems++;
-
-                if (nelems < 1) {
-                        topo_dprintf(mp->tm_hdl, TOPO_DBG_ERR, "No <propitem> "
-                            "elements found for array prop");
-                        return (-1);
-                }
-                if ((nvlarrbuf = topo_mod_alloc(mp, (nelems *
-                    sizeof (nvlist_t *)))) == NULL)
-                        return (topo_mod_seterrno(mp, ETOPO_NOMEM));
-                break;
         default:
                 topo_dprintf(mp->tm_hdl, TOPO_DBG_ERR,
                     "Unrecognized type attribute (ptype = %d)\n", ptype);
                 return (topo_mod_seterrno(mp, ETOPO_PRSR_BADTYPE));
         }
 
         switch (ptype) {
         case TOPO_TYPE_INT32_ARRAY:
+                if ((arrbuf = topo_mod_alloc(mp, (nelems * sizeof (int32_t))))
+                    == NULL)
+                        return (topo_mod_seterrno(mp, ETOPO_NOMEM));
                 for (cn = xn->xmlChildrenNode; cn != NULL; cn = cn->next) {
                         if ((xmlStrcmp(cn->name, (xmlChar *)Propitem) == 0) ||
                             (xmlStrcmp(cn->name, (xmlChar *)Argitem) == 0)) {
 
-                                if ((str = xmlGetProp(xn, (xmlChar *)Value))
+                                if ((str = xmlGetProp(cn, (xmlChar *)Value))
                                     == NULL)
                                         return (-1);
 
                                 ((int32_t *)arrbuf)[i++]
                                     = atoi((const char *)str);

@@ -310,18 +283,21 @@
                         }
                 }
 
                 rv = nvlist_add_int32_array(nvl, name, (int32_t *)arrbuf,
                     nelems);
-                free(arrbuf);
+                topo_mod_free(mp, arrbuf, (nelems * sizeof (int32_t)));
                 break;
         case TOPO_TYPE_UINT32_ARRAY:
+                if ((arrbuf = topo_mod_alloc(mp, (nelems * sizeof (uint32_t))))
+                    == NULL)
+                        return (topo_mod_seterrno(mp, ETOPO_NOMEM));
                 for (cn = xn->xmlChildrenNode; cn != NULL; cn = cn->next) {
                         if ((xmlStrcmp(cn->name, (xmlChar *)Propitem) == 0) ||
                             (xmlStrcmp(cn->name, (xmlChar *)Argitem) == 0)) {
 
-                                if ((str = xmlGetProp(xn, (xmlChar *)Value))
+                                if ((str = xmlGetProp(cn, (xmlChar *)Value))
                                     == NULL)
                                         return (-1);
 
                                 ((uint32_t *)arrbuf)[i++]
                                     = atoi((const char *)str);

@@ -329,18 +305,21 @@
                         }
                 }
 
                 rv = nvlist_add_uint32_array(nvl, name, (uint32_t *)arrbuf,
                     nelems);
-                free(arrbuf);
+                topo_mod_free(mp, arrbuf, (nelems * sizeof (uint32_t)));
                 break;
         case TOPO_TYPE_INT64_ARRAY:
+                if ((arrbuf = topo_mod_alloc(mp, (nelems * sizeof (int64_t))))
+                    == NULL)
+                        return (topo_mod_seterrno(mp, ETOPO_NOMEM));
                 for (cn = xn->xmlChildrenNode; cn != NULL; cn = cn->next) {
                         if ((xmlStrcmp(cn->name, (xmlChar *)Propitem) == 0) ||
                             (xmlStrcmp(cn->name, (xmlChar *)Argitem) == 0)) {
 
-                                if ((str = xmlGetProp(xn, (xmlChar *)Value))
+                                if ((str = xmlGetProp(cn, (xmlChar *)Value))
                                     == NULL)
                                         return (-1);
 
                                 ((int64_t *)arrbuf)[i++]
                                     = atol((const char *)str);

@@ -348,18 +327,21 @@
                         }
                 }
 
                 rv = nvlist_add_int64_array(nvl, name, (int64_t *)arrbuf,
                     nelems);
-                free(arrbuf);
+                topo_mod_free(mp, arrbuf, (nelems * sizeof (int64_t)));
                 break;
         case TOPO_TYPE_UINT64_ARRAY:
+                if ((arrbuf = topo_mod_alloc(mp, (nelems * sizeof (uint64_t))))
+                    == NULL)
+                        return (topo_mod_seterrno(mp, ETOPO_NOMEM));
                 for (cn = xn->xmlChildrenNode; cn != NULL; cn = cn->next) {
                         if ((xmlStrcmp(cn->name, (xmlChar *)Propitem) == 0) ||
                             (xmlStrcmp(cn->name, (xmlChar *)Argitem) == 0)) {
 
-                                if ((str = xmlGetProp(xn, (xmlChar *)Value))
+                                if ((str = xmlGetProp(cn, (xmlChar *)Value))
                                     == NULL)
                                         return (-1);
 
                                 ((uint64_t *)arrbuf)[i++]
                                     = atol((const char *)str);

@@ -367,13 +349,16 @@
                         }
                 }
 
                 rv = nvlist_add_uint64_array(nvl, name, arrbuf,
                     nelems);
-                free(arrbuf);
+                topo_mod_free(mp, arrbuf, (nelems * sizeof (uint64_t)));
                 break;
         case TOPO_TYPE_STRING_ARRAY:
+                if ((strarrbuf = topo_mod_alloc(mp, (nelems * sizeof (char *))))
+                    == NULL)
+                        return (topo_mod_seterrno(mp, ETOPO_NOMEM));
                 for (cn = xn->xmlChildrenNode; cn != NULL; cn = cn->next) {
                         if ((xmlStrcmp(cn->name, (xmlChar *)Propitem) == 0) ||
                             (xmlStrcmp(cn->name, (xmlChar *)Argitem) == 0)) {
 
                                 if ((str = xmlGetProp(cn, (xmlChar *)Value))

@@ -388,15 +373,18 @@
 
                 rv = nvlist_add_string_array(nvl, name, strarrbuf, nelems);
                 strarr_free(mp, strarrbuf, nelems);
                 break;
         case TOPO_TYPE_FMRI_ARRAY:
+                if ((nvlarrbuf = topo_mod_alloc(mp, (nelems *
+                    sizeof (nvlist_t *)))) == NULL)
+                        return (topo_mod_seterrno(mp, ETOPO_NOMEM));
                 for (cn = xn->xmlChildrenNode; cn != NULL; cn = cn->next) {
                         if ((xmlStrcmp(cn->name, (xmlChar *)Propitem) == 0) ||
                             (xmlStrcmp(cn->name, (xmlChar *)Argitem) == 0)) {
 
-                                if ((str = xmlGetProp(xn, (xmlChar *)Value))
+                                if ((str = xmlGetProp(cn, (xmlChar *)Value))
                                     == NULL)
                                         return (-1);
 
                                 if (topo_mod_str2nvl(mp, (const char *)str,
                                     &(nvlarrbuf[i++])) < 0) {

@@ -407,11 +395,11 @@
                         }
                 }
 
                 rv = nvlist_add_nvlist_array(nvl, name, nvlarrbuf,
                     nelems);
-                free(nvlarrbuf);
+                topo_mod_free(mp, nvlarrbuf, (nelems * sizeof (nvlist_t *)));
                 break;
         }
 
         if (rv != 0) {
                 topo_dprintf(mp->tm_hdl, TOPO_DBG_ERR,