From fd6d06b49db5b068fc758b65afd929fc6d6c0742 Mon Sep 17 00:00:00 2001 From: Karel Zak Date: Wed, 10 May 2006 14:48:20 +0000 Subject: [PATCH] XML-RPC errors checks --- ChangeLog | 5 ++ include/libvirt/virterror.h | 1 + include/virterror.h | 1 + src/virterror.c | 3 + src/xml.c | 8 -- src/xmlrpc.c | 173 ++++++++++++++++++++++++++---------- 6 files changed, 134 insertions(+), 57 deletions(-) diff --git a/ChangeLog b/ChangeLog index 41dc9902ac..8acac5ccb3 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,8 @@ +Wed May 10 15:50:32 CEST 2006 Karel Zak + + * src/virterror.c include/virterror.h: added VIR_FROM_RPC + * src/xmlrpc.c: added checks and _virRaiseError() + Wed May 10 13:17:00 CEST 2006 Karel Zak * src/xml.c src/xml.h: added virBufferNew() and virBufferStrcat() diff --git a/include/libvirt/virterror.h b/include/libvirt/virterror.h index 7ac908845c..992cac3298 100644 --- a/include/libvirt/virterror.h +++ b/include/libvirt/virterror.h @@ -44,6 +44,7 @@ typedef enum { VIR_FROM_SEXPR, /* Error in the S-Epression code */ VIR_FROM_XML, /* Error in the XML code */ VIR_FROM_DOM, /* Error when operating on a domain */ + VIR_FROM_RPC /* Error in the XML-RPC code */ } virErrorDomain; diff --git a/include/virterror.h b/include/virterror.h index 7ac908845c..992cac3298 100644 --- a/include/virterror.h +++ b/include/virterror.h @@ -44,6 +44,7 @@ typedef enum { VIR_FROM_SEXPR, /* Error in the S-Epression code */ VIR_FROM_XML, /* Error in the XML code */ VIR_FROM_DOM, /* Error when operating on a domain */ + VIR_FROM_RPC /* Error in the XML-RPC code */ } virErrorDomain; diff --git a/src/virterror.c b/src/virterror.c index de895988af..4958f84a02 100644 --- a/src/virterror.c +++ b/src/virterror.c @@ -262,6 +262,9 @@ virDefaultErrorFunc(virErrorPtr err) case VIR_FROM_DOM: dom = "Domain "; break; + case VIR_FROM_RPC: + dom = "XML-RPC "; + break; } if ((err->dom != NULL) && (err->code != VIR_ERR_INVALID_DOMAIN)) { domain = err->dom->name; diff --git a/src/xml.c b/src/xml.c index f46978bb4f..b7b6cf89e1 100644 --- a/src/xml.c +++ b/src/xml.c @@ -23,14 +23,6 @@ #include "sexpr.h" #include "xml.h" -/** - * virXenError: - * @conn: the connection if available - * @error: the error number - * @info: extra information string - * - * Handle an error at the xend daemon interface - */ static void virXMLError(virErrorNumber error, const char *info, int value) { diff --git a/src/xmlrpc.c b/src/xmlrpc.c index 2b6db87af7..e98e4e6631 100644 --- a/src/xmlrpc.c +++ b/src/xmlrpc.c @@ -9,6 +9,7 @@ */ #include "xmlrpc.h" +#include "internal.h" #include @@ -20,8 +21,6 @@ 2) xmlRpcValueToSexpr */ -#define TODO do { } while (0) - static xmlNodePtr xmlFirstElement(xmlNodePtr node); static xmlNodePtr xmlNextElement(xmlNodePtr node); @@ -32,19 +31,39 @@ struct _xmlRpcContext char *faultMessage; }; +static void xmlRpcError(virErrorNumber error, const char *info, int value) +{ + const char *errmsg; + + if (error == VIR_ERR_OK) + return; + + errmsg = __virErrorMsg(error, info); + __virRaiseError(NULL, NULL, VIR_FROM_RPC, error, VIR_ERR_ERROR, + errmsg, info, NULL, value, 0, errmsg, info, value); +} + static xmlRpcValuePtr xmlRpcValueNew(xmlRpcValueType type) { xmlRpcValuePtr ret = malloc(sizeof(*ret)); - if (ret) - ret->kind = type; + + if (!ret) + xmlRpcError(VIR_ERR_NO_MEMORY, "allocate value", sizeof(*ret)); + else + ret->kind = type; return ret; } static char *xmlGetText(xmlNodePtr node) { for (node = node->children; node; node = node->next) - if (node->type == XML_TEXT_NODE) - return strdup((const char *)node->content); + if (node->type == XML_TEXT_NODE) { + char *x = strdup((const char *)node->content); + if (!x) + xmlRpcError(VIR_ERR_NO_MEMORY, "copying node content", + strlen((const char *)node->content)); + return x; + } return NULL; } @@ -67,21 +86,23 @@ static xmlNodePtr xmlNextElement(xmlNodePtr node) static xmlRpcValuePtr xmlRpcValueUnmarshalDateTime(xmlNodePtr node ATTRIBUTE_UNUSED) { /* we don't need this */ - TODO; + TODO return NULL; } static xmlRpcValuePtr xmlRpcValueUnmarshalString(xmlNodePtr node) { xmlRpcValuePtr ret = xmlRpcValueNew(XML_RPC_STRING); - ret->value.string = xmlGetText(node); + + if (ret) + ret->value.string = xmlGetText(node); return ret; } static xmlRpcValuePtr xmlRpcValueUnmarshalBase64(xmlNodePtr node ATTRIBUTE_UNUSED) { /* we don't need this */ - TODO; + TODO return NULL; } @@ -89,11 +110,11 @@ static xmlRpcValuePtr xmlRpcValueUnmarshalInteger(xmlNodePtr node) { xmlRpcValuePtr ret = xmlRpcValueNew(XML_RPC_INTEGER); char *value = xmlGetText(node); - - ret->value.integer = atoi(value); - - free(value); - + + if (ret && value) + ret->value.integer = atoi(value); + if (value) + free(value); return ret; } @@ -102,13 +123,14 @@ static xmlRpcValuePtr xmlRpcValueUnmarshalBoolean(xmlNodePtr node) xmlRpcValuePtr ret = xmlRpcValueNew(XML_RPC_BOOLEAN); char *value = xmlGetText(node); - if (atoi(value)) + if (!ret) + return NULL; + if (value && atoi(value)) ret->value.boolean = true; else ret->value.boolean = false; - - free(value); - + if (value) + free(value); return ret; } @@ -117,10 +139,10 @@ static xmlRpcValuePtr xmlRpcValueUnmarshalDouble(xmlNodePtr node) xmlRpcValuePtr ret = xmlRpcValueNew(XML_RPC_DOUBLE); char *value = xmlGetText(node); - ret->value.real = atof(value); - - free(value); - + if (ret && value) + ret->value.real = atof(value); + if (value) + free(value); return ret; } @@ -130,11 +152,19 @@ static xmlRpcValuePtr xmlRpcValueUnmarshalArray(xmlNodePtr node) xmlNodePtr cur; int n_elements = 0; + if (!ret) + return NULL; + for (cur = xmlFirstElement(node); cur; cur = xmlNextElement(cur)) n_elements += 1; ret->value.array.elements = malloc(n_elements * sizeof(xmlRpcValue)); - + if (!ret->value.array.elements) { + xmlRpcError(VIR_ERR_NO_MEMORY, "allocate value array", + n_elements * sizeof(xmlRpcValue)); + free(ret); + return NULL; + } n_elements = 0; for (cur = xmlFirstElement(node); cur; cur = xmlNextElement(cur)) { ret->value.array.elements[n_elements] = xmlRpcValueUnmarshal(cur); @@ -151,6 +181,10 @@ static xmlRpcValueDictElementPtr xmlRpcValueUnmarshalDictElement(xmlNodePtr node xmlRpcValueDictElementPtr ret = malloc(sizeof(*ret)); xmlNodePtr cur; + if (!ret) { + xmlRpcError(VIR_ERR_NO_MEMORY, "allocate dict", sizeof(*ret)); + return NULL; + } memset(ret, 0, sizeof(*ret)); for (cur = xmlFirstElement(node); cur; cur = xmlNextElement(cur)) { @@ -159,7 +193,13 @@ static xmlRpcValueDictElementPtr xmlRpcValueUnmarshalDictElement(xmlNodePtr node } else if (xmlStrEqual(cur->name, BAD_CAST "value")) { ret->value = xmlRpcValueUnmarshal(cur); } else { - /* What? */ + xmlRpcError(VIR_ERR_XML_ERROR, "unexpected dict node", 0); + if (ret->name) + free(ret->name); + if (ret->value) + xmlRpcValueFree(ret->value); + free(ret); + return NULL; } } @@ -174,13 +214,20 @@ static xmlRpcValuePtr xmlRpcValueUnmarshalDict(xmlNodePtr node) xmlRpcValuePtr ret = xmlRpcValueNew(XML_RPC_STRUCT); xmlNodePtr cur; + if (!ret) + return NULL; + + ret->value.dict.root = root; + for (cur = xmlFirstElement(node); cur; cur = xmlNextElement(cur)) { *elem = xmlRpcValueUnmarshalDictElement(cur); + if (*elem==NULL) { + xmlRpcValueFree(ret); + return NULL; + } elem = &(*elem)->next; } - ret->value.dict.root = root; - return ret; } @@ -218,7 +265,7 @@ xmlRpcValuePtr xmlRpcValueUnmarshal(xmlNodePtr node) } else if (xmlStrEqual(node->name, BAD_CAST "nil")) { ret = xmlRpcValueNew(XML_RPC_NIL); } else { - /* bug */ + xmlRpcError(VIR_ERR_XML_ERROR, "unexpected value node", 0); } return ret; @@ -299,11 +346,11 @@ void xmlRpcValueMarshal(xmlRpcValuePtr value, virBufferPtr buf, int indent) break; case XML_RPC_DATE_TIME: /* FIXME */ - TODO; + TODO break; case XML_RPC_BASE64: /* FIXME */ - TODO; + TODO break; case XML_RPC_STRING: virBufferStrcat(buf, @@ -344,6 +391,9 @@ virBufferPtr xmlRpcMarshalRequest(const char *request, xmlRpcValuePtr xmlRpcUnmarshalResponse(xmlNodePtr node, bool *is_fault) { + if (!node) + return NULL; + if (!xmlStrEqual(node->name, BAD_CAST "methodResponse")) return NULL; @@ -361,7 +411,6 @@ xmlRpcValuePtr xmlRpcUnmarshalResponse(xmlNodePtr node, bool *is_fault) return xmlRpcValueUnmarshal(xmlFirstElement(node)); } else return NULL; - } static char *xmlRpcCallRaw(const char *url, const char *request) @@ -378,24 +427,29 @@ static char *xmlRpcCallRaw(const char *url, const char *request) NULL, strlen(request)); - if (cxt == NULL) + if (cxt == NULL) { + xmlRpcError(VIR_ERR_POST_FAILED, "send request", 0); goto error; + } if (contentType && strcmp(contentType, "text/xml") != 0) { errno = EINVAL; + xmlRpcError(VIR_ERR_POST_FAILED, "unexpected mime type", 0); goto error; } len = xmlNanoHTTPContentLength(cxt); response = malloc(len + 1); - if (response == NULL) + if (response == NULL) { + xmlRpcError(VIR_ERR_NO_MEMORY, "allocate response", len); goto error; - + } ret = xmlNanoHTTPRead(cxt, response, len); if (ret != len) { errno = EINVAL; free(response); response = NULL; + xmlRpcError(VIR_ERR_POST_FAILED, "read response", 0); } response[len] = 0; @@ -426,8 +480,10 @@ static char **xmlRpcStringArray(xmlRpcValuePtr value) if (value->value.array.elements[i]->kind == XML_RPC_STRING) size += strlen(value->value.array.elements[i]->value.string) + 1; - ptr = malloc(size); - + if (!(ptr = malloc(size))) { + xmlRpcError(VIR_ERR_NO_MEMORY, "allocate string array", size); + return NULL; + } ret = (char **)ptr; ptr += sizeof(char *) * (value->value.array.n_elements + 1); @@ -454,29 +510,35 @@ xmlRpcArgvNew(const char *fmt, va_list ap, int *argc) int i; *argc = strlen(fmt); - argv = malloc(sizeof(*argv) * *argc); - + if (!(argv = malloc(sizeof(*argv) * *argc))) { + xmlRpcError(VIR_ERR_NO_MEMORY, "read response", sizeof(*argv) * *argc); + return NULL; + } i = 0; for (ptr = fmt; *ptr; ptr++) { switch (*ptr) { case 'i': - argv[i] = xmlRpcValueNew(XML_RPC_INTEGER); - argv[i]->value.integer = va_arg(ap, int32_t); + if ((argv[i] = xmlRpcValueNew(XML_RPC_INTEGER))) + argv[i]->value.integer = va_arg(ap, int32_t); break; case 'f': - argv[i] = xmlRpcValueNew(XML_RPC_DOUBLE); - argv[i]->value.real = va_arg(ap, double); + if ((argv[i] = xmlRpcValueNew(XML_RPC_DOUBLE))) + argv[i]->value.real = va_arg(ap, double); break; case 'b': - argv[i] = xmlRpcValueNew(XML_RPC_BOOLEAN); - argv[i]->value.boolean = va_arg(ap, int); + if ((argv[i] = xmlRpcValueNew(XML_RPC_BOOLEAN))) + argv[i]->value.boolean = va_arg(ap, int); break; case 's': - argv[i] = xmlRpcValueNew(XML_RPC_STRING); - argv[i]->value.string = strdup(va_arg(ap, const char *)); + if ((argv[i] = xmlRpcValueNew(XML_RPC_STRING))) + argv[i]->value.string = strdup(va_arg(ap, const char *)); break; default: - xmlRpcArgvFree(i, argv); + argv[i] = NULL; + break; + } + if (argv[i]==NULL) { + xmlRpcArgvFree(i, argv); return NULL; } i++; @@ -488,6 +550,8 @@ void xmlRpcArgvFree(int argc, xmlRpcValuePtr *argv) { int i; + if (!argv) + return; for (i = 0; i < argc; i++) xmlRpcValueFree(argv[i]); @@ -513,7 +577,8 @@ int xmlRpcCall(xmlRpcContextPtr context, const char *method, if (retfmt && *retfmt) retval = va_arg(ap, void *); - argv = xmlRpcArgvNew(fmt, ap, &argc); + if (!(argv = xmlRpcArgvNew(fmt, ap, &argc))) + return -1; va_end(ap); @@ -521,10 +586,16 @@ int xmlRpcCall(xmlRpcContextPtr context, const char *method, xmlRpcArgvFree(argc, argv); + if (!buf) + return -1; + ret = xmlRpcCallRaw(context->uri, buf->content); virBufferFree(buf); + if (!ret) + return -1; + xml = xmlReadDoc((const xmlChar *)ret, "response.xml", NULL, XML_PARSE_NOENT | XML_PARSE_NONET | XML_PARSE_NOERROR | XML_PARSE_NOWARNING); @@ -532,6 +603,7 @@ int xmlRpcCall(xmlRpcContextPtr context, const char *method, if (xml == NULL) { errno = EINVAL; + xmlRpcError(VIR_ERR_XML_ERROR, "parse server response failed", 0); return -1; } @@ -572,7 +644,9 @@ int xmlRpcCall(xmlRpcContextPtr context, const char *method, xmlFreeDoc(xml); - if (fault) { /* FIXME we need generic dict routines */ + if (fault) { + /* FIXME we need generic dict routines */ + /* FIXME we need faultMessage propagate to libvirt error API */ context->faultCode = value->value.dict.root->value->value.integer; context->faultMessage = strdup(value->value.dict.root->next->value->value.string); xmlRpcValueFree(value); @@ -592,7 +666,8 @@ xmlRpcContextPtr xmlRpcContextNew(const char *uri) if (ret) { ret->uri = strdup(uri); ret->faultMessage = NULL; - } + } else + xmlRpcError(VIR_ERR_NO_MEMORY, "allocate new context", sizeof(*ret)); return ret; }