Ug... and trying to "locally" fix the RW/RO discovered two more issues...
On 06/11/2014 08:21 AM, John Ferlan wrote:
This patch has resulted in many new Coverity errors - mostly resource
leaks as a result of the virVBoxSnapshotConfAllChildren() recursive
function. I would clean them up, but I'm a bit leary of missing some
nuance in the original design.
There were also a couple of issues in
virVBoxSnapshotConfGetRWDisksPathsFromLibvirtXML and
virVBoxSnapshotConfGetRODisksPathsFromLibvirtXML
Details of the issues and some thoughts are inline below in the functions
These should be cleaned up before the next release...
John
<...snip...>
> +
> +/*
> + *getRWDisksPathsFromLibvirtXML: Parse a libvirt XML snapshot file, allocates and
> + *fills a list of read-write disk paths.
> + *return array length on success, -1 on failure.
> + */
> +int virVBoxSnapshotConfGetRWDisksPathsFromLibvirtXML(char *filePath, char
***rwDisksPath)
> +{
> + int result = -1;
> + size_t i = 0;
> + char **ret;
Needs to be initialized to NULL (char **ret = NULL;)
> + xmlDocPtr xml = NULL;
> + xmlXPathContextPtr xPathContext = NULL;
> + xmlNodePtr *nodes = NULL;
> + int nodeSize = 0;
> + if (filePath == NULL) {
> + virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
> + _("filePath is null"));
> + goto cleanup;
> + }
> + xml = virXMLParse(filePath, NULL, NULL);
> + if (xml == NULL) {
> + virReportError(VIR_ERR_XML_ERROR, "%s",
> + _("Unable to parse the xml"));
> + goto cleanup;
> + }
> + if (!(xPathContext = xmlXPathNewContext(xml))) {
> + virReportOOMError();
> + goto cleanup;
> + }
> + xPathContext->node = xmlDocGetRootElement(xml);
> + nodeSize = virXPathNodeSet("/domainsnapshot/disks/disk", xPathContext,
&nodes);
Coverity comlains that nodeSize can be a negative number. Other code in
libvirt will do something like:
if ((nodeSize = virXPathNodeSet("/domainsnapshot/disks/disk",
xPathContext, &nodes)) < 0)
goto cleanup;
> +
> + if (VIR_ALLOC_N(ret, nodeSize) < 0)
> + goto cleanup;
> +
> + for (i = 0; i < nodeSize; i++) {
> + xmlNodePtr node = nodes[i];
> + xPathContext->node = node;
> + xmlNodePtr sourceNode = virXPathNode("./source", xPathContext);
> + if (sourceNode) {
> + ret[i] = virXMLPropString(sourceNode, "file");
> + }
> + }
> + result = 0;
> +
> + cleanup:
> + xmlFreeDoc(xml);
> + xmlXPathFreeContext(xPathContext);
> + if (result < 0) {
> + virStringFreeList(ret);
> + nodeSize = -1;
> + }
> + *rwDisksPath = ret;
> + return nodeSize;
> +}
> +
> +/*
> + *getRODisksPathsFromLibvirtXML: *Parse a libvirt XML snapshot file, allocates and
fills
> + *a list of read-only disk paths (the parents of the read-write disks).
> + *return array length on success, -1 on failure.
> + */
> +int virVBoxSnapshotConfGetRODisksPathsFromLibvirtXML(char *filePath, char
***roDisksPath)
> +{
> + int result = -1;
> + size_t i = 0;
> + char **ret;
> + xmlDocPtr xml = NULL;
> + xmlXPathContextPtr xPathContext = NULL;
> + xmlNodePtr *nodes = NULL;
> + int nodeSize = 0;
> + if (filePath == NULL) {
> + virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
> + _("filePath is null"));
> + goto cleanup;
> + }
> + xml = virXMLParse(filePath, NULL, NULL);
> + if (xml == NULL) {
> + virReportError(VIR_ERR_XML_ERROR, "%s",
> + _("Unable to parse the xml"));
> + goto cleanup;
> + }
> + if (!(xPathContext = xmlXPathNewContext(xml))) {
> + virReportOOMError();
> + goto cleanup;
> + }
> + xPathContext->node = xmlDocGetRootElement(xml);
> + nodeSize = virXPathNodeSet("/domainsnapshot/domain/devices/disk",
> + xPathContext,
> + &nodes);
Same issue here as the RW code - you need to handle nodeSize return:
if ((nodeSize = virXPathNodeSet("/domainsnapshot/domain/devices/disk",
xPathContext,
&nodes)) < 0)
goto cleanup;
> + if (VIR_ALLOC_N(ret, nodeSize) < 0)
> + goto cleanup;
> +
> + for (i = 0; i < nodeSize; i++) {
> + xmlNodePtr node = nodes[i];
> + xPathContext->node = node;
> + xmlNodePtr sourceNode = virXPathNode("./source", xPathContext);
> + if (sourceNode) {
> + ret[i] = virXMLPropString(sourceNode, "file");
> + }
> + }
> + result = 0;
> +
> + cleanup:
> + xmlFreeDoc(xml);
> + xmlXPathFreeContext(xPathContext);
> + if (result < 0) {
> + virStringFreeList(ret);
> + nodeSize = -1;
> + }
> + *roDisksPath = ret;
Use:
+ } else {
+ *roDisksPath = ret;
}
> + return nodeSize;
> +}
> +