[libvirt] [libvirt-php][PATCH 2/3] Fix some leaks related to get_string_from_xpath

Neal Gompa ngompa13 at gmail.com
Tue Apr 19 14:29:17 UTC 2016


On Tue, Apr 19, 2016 at 9:46 AM, Michal Privoznik <mprivozn at redhat.com> wrote:
> This function not only did not free return value of
> xmlNodeListGetString() it strdup()-ed its return value. Therefore
> plenty of memory has been lost definitely upon return from this
> function.
>
> Signed-off-by: Michal Privoznik <mprivozn at redhat.com>
> ---
>  src/libvirt-php.c | 110 ++++++++++++++++++++++++++++++------------------------
>  1 file changed, 62 insertions(+), 48 deletions(-)
>
> diff --git a/src/libvirt-php.c b/src/libvirt-php.c
> index 308e764..fb0679b 100644
> --- a/src/libvirt-php.c
> +++ b/src/libvirt-php.c
> @@ -3232,19 +3232,17 @@ char *get_string_from_xpath(char *xml, char *xpath, zval **val, int *retVal)
>      if (val != NULL) {
>          ret = 0;
>          for (i = 0; i < nodeset->nodeNr; i++) {
> -            if (xmlNodeListGetString(doc, nodeset->nodeTab[i]->xmlChildrenNode, 1) != NULL) {
> -                value = (char *)xmlNodeListGetString(doc, nodeset->nodeTab[i]->xmlChildrenNode, 1);
> -
> +            if ((value = xmlNodeListGetString(doc, nodeset->nodeTab[i]->xmlChildrenNode, 1))) {
>                  snprintf(key, sizeof(key), "%d", i);
>                  VIRT_ADD_ASSOC_STRING(*val, key, value);
> +                free(value);
> +                value = NULL;
>                  ret++;
>              }
>          }
>          add_assoc_long(*val, "num", (long)ret);
> -    }
> -    else {
> -        if (xmlNodeListGetString(doc, nodeset->nodeTab[0]->xmlChildrenNode, 1) != NULL)
> -            value = (char *)xmlNodeListGetString(doc, nodeset->nodeTab[0]->xmlChildrenNode, 1);
> +    } else {
> +        value = xmlNodeListGetString(doc, nodeset->nodeTab[0]->xmlChildrenNode, 1);
>      }
>
>   cleanup:
> @@ -3255,7 +3253,7 @@ char *get_string_from_xpath(char *xml, char *xpath, zval **val, int *retVal)
>      xmlFreeParserCtxt(xp);
>      xmlFreeDoc(doc);
>      xmlCleanupParser();
> -    return (value != NULL) ? strdup(value) : NULL;
> +    return value;
>  }
>
>  /*
> @@ -3327,11 +3325,8 @@ char **get_array_from_xpath(char *xml, char *xpath, int *num)
>      ret = 0;
>      val = (char **)malloc( nodeset->nodeNr  * sizeof(char *) );
>      for (i = 0; i < nodeset->nodeNr; i++) {
> -        if (xmlNodeListGetString(doc, nodeset->nodeTab[i]->xmlChildrenNode, 1) != NULL) {
> -            value = (char *)xmlNodeListGetString(doc, nodeset->nodeTab[i]->xmlChildrenNode, 1);
> -
> -            val[ret++] = strdup(value);
> -        }
> +        if ((value = xmlNodeListGetString(doc, nodeset->nodeTab[i]->xmlChildrenNode, 1)))
> +            val[ret++] = value;
>      }
>
>      xmlXPathFreeContext(context);
> @@ -3506,20 +3501,23 @@ long get_next_free_numeric_value(virDomainPtr domain, char *xpath)
>   */
>  char *connection_get_domain_type(virConnectPtr conn, char *arch TSRMLS_DC)
>  {
> -    int retval = -1;
> +    char *ret = NULL;
>      char *tmp = NULL;
>      char *caps = NULL;
> +    char *tmpArch = NULL;
>      char xpath[1024] = { 0 };
> +    int retval = -1;
>
>      caps = virConnectGetCapabilities(conn);
>      if (caps == NULL)
>          return NULL;
>
>      if (arch == NULL) {
> -        arch = get_string_from_xpath(caps, "//capabilities/host/cpu/arch", NULL, &retval);
> -        DPRINTF("%s: No architecture defined, got '%s' from capabilities XML\n", __FUNCTION__, arch);
> -        if ((arch == NULL) || (retval < 0))
> -            return NULL;
> +        tmpArch = get_string_from_xpath(caps, "//capabilities/host/cpu/arch", NULL, &retval);
> +        DPRINTF("%s: No architecture defined, got '%s' from capabilities XML\n", __FUNCTION__, tmpArch);
> +        if (!tmpArch || retval < 0)
> +            goto cleanup;
> +        arch = tmpArch;
>      }
>
>      DPRINTF("%s: Requested domain type for arch '%s'\n",  __FUNCTION__, arch);
> @@ -3529,12 +3527,17 @@ char *connection_get_domain_type(virConnectPtr conn, char *arch TSRMLS_DC)
>      tmp = get_string_from_xpath(caps, xpath, NULL, &retval);
>      if ((tmp == NULL) || (retval < 0)) {
>          DPRINTF("%s: No domain type found in XML...\n", __FUNCTION__);
> -        return NULL;
> +        goto cleanup;
>      }
>
> -    DPRINTF("%s: Domain type is '%s'\n",  __FUNCTION__, tmp);
> -
> -    return tmp;
> +    ret = tmp;
> +    tmp = NULL;
> +    DPRINTF("%s: Domain type is '%s'\n",  __FUNCTION__, ret);
> + cleanup:
> +    free(tmpArch);
> +    free(caps);
> +    free(tmp);
> +    return ret;
>  }
>
>  /*
> @@ -3547,20 +3550,23 @@ char *connection_get_domain_type(virConnectPtr conn, char *arch TSRMLS_DC)
>   */
>  char *connection_get_emulator(virConnectPtr conn, char *arch TSRMLS_DC)
>  {
> -    int retval = -1;
> +    char *ret = NULL;
>      char *tmp = NULL;
>      char *caps = NULL;
> +    char *tmpArch = NULL;
>      char xpath[1024] = { 0 };
> +    int retval = -1;
>
>      caps = virConnectGetCapabilities(conn);
>      if (caps == NULL)
>          return NULL;
>
>      if (arch == NULL) {
> -        arch = get_string_from_xpath(caps, "//capabilities/host/cpu/arch", NULL, &retval);
> -        DPRINTF("%s: No architecture defined, got '%s' from capabilities XML\n", __FUNCTION__, arch);
> -        if ((arch == NULL) || (retval < 0))
> -            return NULL;
> +        tmpArch = get_string_from_xpath(caps, "//capabilities/host/cpu/arch", NULL, &retval);
> +        DPRINTF("%s: No architecture defined, got '%s' from capabilities XML\n", __FUNCTION__, tmpArch);
> +        if (!tmpArch || retval < 0)
> +            goto cleanup;
> +        arch = tmpArch;
>      }
>
>      DPRINTF("%s: Requested emulator for arch '%s'\n",  __FUNCTION__, arch);
> @@ -3568,26 +3574,30 @@ char *connection_get_emulator(virConnectPtr conn, char *arch TSRMLS_DC)
>      snprintf(xpath, sizeof(xpath), "//capabilities/guest/arch[@name='%s']/domain/emulator", arch);
>      DPRINTF("%s: Applying xPath '%s' to capabilities XML output\n", __FUNCTION__, xpath);
>      tmp = get_string_from_xpath(caps, xpath, NULL, &retval);
> -    if ((tmp == NULL) || (retval < 0)) {
> -        DPRINTF("%s: No emulator found. Trying next location ...\n", __FUNCTION__);
> -        snprintf(xpath, sizeof(xpath), "//capabilities/guest/arch[@name='%s']/emulator", arch);
> -    }
> -    else {
> +    if (tmp && retval >= 0) {
>          DPRINTF("%s: Emulator is '%s'\n",  __FUNCTION__, tmp);
> -        return tmp;
> +        goto done;
>      }
>
> +    DPRINTF("%s: No emulator found. Trying next location ...\n", __FUNCTION__);
> +    snprintf(xpath, sizeof(xpath), "//capabilities/guest/arch[@name='%s']/emulator", arch);
>      DPRINTF("%s: Applying xPath '%s' to capabilities XML output\n",  __FUNCTION__, xpath);
> -
> +    free(tmp);
>      tmp = get_string_from_xpath(caps, xpath, NULL, &retval);
> -    if ((tmp == NULL) || (retval < 0)) {
> -        DPRINTF("%s: Emulator is '%s'\n",  __FUNCTION__, tmp);
> -        return NULL;
> +    if (!tmp || retval < 0) {
> +        DPRINTF("%s: None emulator found\n",  __FUNCTION__);
> +        goto cleanup;
>      }
>
> -    DPRINTF("%s: Emulator is '%s'\n",  __FUNCTION__, tmp);
> -
> -    return tmp;
> + done:
> +    ret = tmp;
> +    tmp = NULL;
> +    DPRINTF("%s: Emulator is '%s'\n",  __FUNCTION__, ret);
> + cleanup:
> +    free(tmpArch);
> +    free(caps);
> +    free(tmp);
> +    return ret;
>  }
>
>  /*
> @@ -3599,26 +3609,29 @@ char *connection_get_emulator(virConnectPtr conn, char *arch TSRMLS_DC)
>   */
>  char *connection_get_arch(virConnectPtr conn TSRMLS_DC)
>  {
> -    int retval = -1;
> +    char *ret = NULL;
>      char *tmp = NULL;
>      char *caps = NULL;
> -    // char xpath[1024] = { 0 };
> +    int retval = -1;
>
>      caps = virConnectGetCapabilities(conn);
>      if (caps == NULL)
>          return NULL;
>
>      tmp = get_string_from_xpath(caps, "//capabilities/host/cpu/arch", NULL, &retval);
> -    free(caps);
> -
>      if ((tmp == NULL) || (retval < 0)) {
>          DPRINTF("%s: Cannot get host CPU architecture from capabilities XML\n", __FUNCTION__);
> -        return NULL;
> +        goto cleanup;
>      }
>
> -    DPRINTF("%s: Host CPU architecture is '%s'\n",  __FUNCTION__, tmp);
> +    ret = tmp;
> +    tmp = NULL;
> +    DPRINTF("%s: Host CPU architecture is '%s'\n",  __FUNCTION__, ret);
>
> -    return tmp;
> + cleanup:
> +    free(caps);
> +    free(tmp);
> +    return ret;
>  }
>
>  /*
> @@ -7130,7 +7143,8 @@ PHP_FUNCTION(libvirt_domain_xml_xpath)
>
>      array_init(return_value);
>
> -    if ((tmp = get_string_from_xpath(xml, (char *)zpath, &return_value, &rc)) == NULL) {
> +    free(get_string_from_xpath(xml, (char *)zpath, &return_value, &rc));
> +    if (return_value < 0) {
>          free(xml);
>          RETURN_FALSE;
>      }
> --
> 2.7.3
>

Applied locally and tested. Works okay for me. :)



-- 
真実はいつも一つ!/ Always, there's only one truth!




More information about the libvir-list mailing list