1
0
mirror of https://gitlab.gnome.org/GNOME/libxml2.git synced 2025-03-21 22:50:08 +03:00

schematron: Improve error handling

Implement xmlSchematronVErr.

Handle malloc failure from xmlRaiseError.

Stop using xmlGenericError.

Remove argument from memory error handler.

Use xmlRaiseMemoryError.

Remove TODO macro.
This commit is contained in:
Nick Wellnhofer 2023-12-18 21:25:28 +01:00
parent 83c6aeef49
commit 664db89e0e

View File

@ -63,16 +63,6 @@ static const xmlChar *xmlOldSchematronNs = SCT_OLD_NS;
node = node->next; \
}
/**
* TODO:
*
* macro to flag unimplemented blocks
*/
#define TODO \
xmlGenericError(xmlGenericErrorContext, \
"Unimplemented block at %s:%d\n", \
__FILE__, __LINE__);
typedef enum {
XML_SCHEMATRON_ASSERT=1,
XML_SCHEMATRON_REPORT=2
@ -242,13 +232,11 @@ struct _xmlSchematronParserCtxt {
* Handle an out of memory condition
*/
static void
xmlSchematronPErrMemory(xmlSchematronParserCtxtPtr ctxt,
const char *extra, xmlNodePtr node)
xmlSchematronPErrMemory(xmlSchematronParserCtxtPtr ctxt)
{
if (ctxt != NULL)
ctxt->nberrors++;
__xmlSimpleError(XML_FROM_SCHEMASP, XML_ERR_NO_MEMORY, node, NULL,
extra);
xmlRaiseMemoryError(NULL, NULL, NULL, XML_FROM_SCHEMASP, NULL);
}
/**
@ -269,6 +257,7 @@ xmlSchematronPErr(xmlSchematronParserCtxtPtr ctxt, xmlNodePtr node, int error,
xmlGenericErrorFunc channel = NULL;
xmlStructuredErrorFunc schannel = NULL;
void *data = NULL;
int res;
if (ctxt != NULL) {
ctxt->nberrors++;
@ -276,10 +265,13 @@ xmlSchematronPErr(xmlSchematronParserCtxtPtr ctxt, xmlNodePtr node, int error,
data = ctxt->userData;
schannel = ctxt->serror;
}
__xmlRaiseError(schannel, channel, data, ctxt, node, XML_FROM_SCHEMASP,
error, XML_ERR_ERROR, NULL, 0,
(const char *) str1, (const char *) str2, NULL, 0, 0,
msg, str1, str2);
res = __xmlRaiseError(schannel, channel, data, ctxt, node,
XML_FROM_SCHEMASP, error, XML_ERR_ERROR, NULL, 0,
(const char *) str1, (const char *) str2, NULL, 0, 0,
msg, str1, str2);
if (res < 0)
xmlSchematronPErrMemory(ctxt);
}
/**
@ -290,15 +282,48 @@ xmlSchematronPErr(xmlSchematronParserCtxtPtr ctxt, xmlNodePtr node, int error,
* Handle an out of memory condition
*/
static void
xmlSchematronVErrMemory(xmlSchematronValidCtxtPtr ctxt,
const char *extra, xmlNodePtr node)
xmlSchematronVErrMemory(xmlSchematronValidCtxtPtr ctxt)
{
if (ctxt != NULL) {
ctxt->nberrors++;
ctxt->err = XML_SCHEMAV_INTERNAL;
}
__xmlSimpleError(XML_FROM_SCHEMASV, XML_ERR_NO_MEMORY, node, NULL,
extra);
xmlRaiseMemoryError(NULL, NULL, NULL, XML_FROM_SCHEMASV, NULL);
}
/**
* xmlSchematronVErr:
* @ctxt: the parsing context
* @node: the context node
* @error: the error code
* @msg: the error message
* @str1: extra data
* @str2: extra data
*
* Handle a validation error
*/
static void LIBXML_ATTR_FORMAT(3,0)
xmlSchematronVErr(xmlSchematronValidCtxtPtr ctxt, int error,
const char *msg, const xmlChar * str1)
{
xmlGenericErrorFunc channel = NULL;
xmlStructuredErrorFunc schannel = NULL;
void *data = NULL;
int res;
if (ctxt != NULL) {
ctxt->nberrors++;
channel = ctxt->error;
data = ctxt->userData;
schannel = ctxt->serror;
}
res = __xmlRaiseError(schannel, channel, data, ctxt, NULL,
XML_FROM_SCHEMASV, error, XML_ERR_ERROR, NULL, 0,
(const char *) str1, NULL, NULL, 0, 0,
msg, str1);
if (res < 0)
xmlSchematronVErrMemory(ctxt);
}
/************************************************************************
@ -347,7 +372,7 @@ xmlSchematronAddTest(xmlSchematronParserCtxtPtr ctxt,
ret = (xmlSchematronTestPtr) xmlMalloc(sizeof(xmlSchematronTest));
if (ret == NULL) {
xmlSchematronPErrMemory(ctxt, "allocating schema test", node);
xmlSchematronPErrMemory(ctxt);
return (NULL);
}
memset(ret, 0, sizeof(xmlSchematronTest));
@ -451,7 +476,7 @@ xmlSchematronAddRule(xmlSchematronParserCtxtPtr ctxt, xmlSchematronPtr schema,
ret = (xmlSchematronRulePtr) xmlMalloc(sizeof(xmlSchematronRule));
if (ret == NULL) {
xmlSchematronPErrMemory(ctxt, "allocating schema rule", node);
xmlSchematronPErrMemory(ctxt);
return (NULL);
}
memset(ret, 0, sizeof(xmlSchematronRule));
@ -532,7 +557,7 @@ xmlSchematronAddPattern(xmlSchematronParserCtxtPtr ctxt,
ret = (xmlSchematronPatternPtr) xmlMalloc(sizeof(xmlSchematronPattern));
if (ret == NULL) {
xmlSchematronPErrMemory(ctxt, "allocating schema pattern", node);
xmlSchematronPErrMemory(ctxt);
return (NULL);
}
memset(ret, 0, sizeof(xmlSchematronPattern));
@ -584,7 +609,7 @@ xmlSchematronNewSchematron(xmlSchematronParserCtxtPtr ctxt)
ret = (xmlSchematronPtr) xmlMalloc(sizeof(xmlSchematron));
if (ret == NULL) {
xmlSchematronPErrMemory(ctxt, "allocating schema", NULL);
xmlSchematronPErrMemory(ctxt);
return (NULL);
}
memset(ret, 0, sizeof(xmlSchematron));
@ -639,8 +664,7 @@ xmlSchematronNewParserCtxt(const char *URL)
(xmlSchematronParserCtxtPtr)
xmlMalloc(sizeof(xmlSchematronParserCtxt));
if (ret == NULL) {
xmlSchematronPErrMemory(NULL, "allocating schema parser context",
NULL);
xmlSchematronPErrMemory(NULL);
return (NULL);
}
memset(ret, 0, sizeof(xmlSchematronParserCtxt));
@ -650,8 +674,7 @@ xmlSchematronNewParserCtxt(const char *URL)
ret->includes = NULL;
ret->xctxt = xmlXPathNewContext(NULL);
if (ret->xctxt == NULL) {
xmlSchematronPErrMemory(NULL, "allocating schema parser XPath context",
NULL);
xmlSchematronPErrMemory(NULL);
xmlSchematronFreeParserCtxt(ret);
return (NULL);
}
@ -681,8 +704,7 @@ xmlSchematronNewMemParserCtxt(const char *buffer, int size)
(xmlSchematronParserCtxtPtr)
xmlMalloc(sizeof(xmlSchematronParserCtxt));
if (ret == NULL) {
xmlSchematronPErrMemory(NULL, "allocating schema parser context",
NULL);
xmlSchematronPErrMemory(NULL);
return (NULL);
}
memset(ret, 0, sizeof(xmlSchematronParserCtxt));
@ -691,8 +713,7 @@ xmlSchematronNewMemParserCtxt(const char *buffer, int size)
ret->dict = xmlDictCreate();
ret->xctxt = xmlXPathNewContext(NULL);
if (ret->xctxt == NULL) {
xmlSchematronPErrMemory(NULL, "allocating schema parser XPath context",
NULL);
xmlSchematronPErrMemory(NULL);
xmlSchematronFreeParserCtxt(ret);
return (NULL);
}
@ -720,8 +741,7 @@ xmlSchematronNewDocParserCtxt(xmlDocPtr doc)
(xmlSchematronParserCtxtPtr)
xmlMalloc(sizeof(xmlSchematronParserCtxt));
if (ret == NULL) {
xmlSchematronPErrMemory(NULL, "allocating schema parser context",
NULL);
xmlSchematronPErrMemory(NULL);
return (NULL);
}
memset(ret, 0, sizeof(xmlSchematronParserCtxt));
@ -731,8 +751,7 @@ xmlSchematronNewDocParserCtxt(xmlDocPtr doc)
ret->preserve = 1;
ret->xctxt = xmlXPathNewContext(doc);
if (ret->xctxt == NULL) {
xmlSchematronPErrMemory(NULL, "allocating schema parser XPath context",
NULL);
xmlSchematronPErrMemory(NULL);
xmlSchematronFreeParserCtxt(ret);
return (NULL);
}
@ -780,8 +799,7 @@ xmlSchematronPushInclude(xmlSchematronParserCtxtPtr ctxt,
ctxt->includes = (xmlNodePtr *)
xmlMalloc(ctxt->maxIncludes * 2 * sizeof(xmlNodePtr));
if (ctxt->includes == NULL) {
xmlSchematronPErrMemory(NULL, "allocating parser includes",
NULL);
xmlSchematronPErrMemory(NULL);
return;
}
ctxt->nbIncludes = 0;
@ -792,8 +810,7 @@ xmlSchematronPushInclude(xmlSchematronParserCtxtPtr ctxt,
xmlRealloc(ctxt->includes, ctxt->maxIncludes * 4 *
sizeof(xmlNodePtr));
if (tmp == NULL) {
xmlSchematronPErrMemory(NULL, "allocating parser includes",
NULL);
xmlSchematronPErrMemory(NULL);
return;
}
ctxt->includes = tmp;
@ -850,8 +867,7 @@ xmlSchematronAddNamespace(xmlSchematronParserCtxtPtr ctxt,
ctxt->namespaces = (const xmlChar **)
xmlMalloc(ctxt->maxNamespaces * 2 * sizeof(const xmlChar *));
if (ctxt->namespaces == NULL) {
xmlSchematronPErrMemory(NULL, "allocating parser namespaces",
NULL);
xmlSchematronPErrMemory(NULL);
return;
}
ctxt->nbNamespaces = 0;
@ -862,8 +878,7 @@ xmlSchematronAddNamespace(xmlSchematronParserCtxtPtr ctxt,
xmlRealloc((xmlChar **) ctxt->namespaces, ctxt->maxNamespaces * 4 *
sizeof(const xmlChar *));
if (tmp == NULL) {
xmlSchematronPErrMemory(NULL, "allocating parser namespaces",
NULL);
xmlSchematronPErrMemory(NULL);
return;
}
ctxt->namespaces = tmp;
@ -1493,9 +1508,6 @@ xmlSchematronFormatReport(xmlSchematronValidCtxtPtr ctxt,
ret = xmlStrcat(ret, spacer);
ret = xmlStrcat(ret, eval->nodesetval->nodeTab[indx]->name);
}
} else {
xmlGenericError(xmlGenericErrorContext,
"Empty node set\n");
}
break;
}
@ -1521,8 +1533,8 @@ xmlSchematronFormatReport(xmlSchematronValidCtxtPtr ctxt,
ret = xmlStrcat(ret, eval->stringval);
break;
default:
xmlGenericError(xmlGenericErrorContext,
"Unsupported XPATH Type: %d\n", eval->type);
xmlSchematronVErr(ctxt, XML_ERR_INTERNAL_ERROR,
"Unsupported XPATH Type\n", NULL);
}
xmlXPathFreeObject(eval);
xmlXPathFreeCompExpr(comp);
@ -1581,7 +1593,7 @@ xmlSchematronReportSuccess(xmlSchematronValidCtxtPtr ctxt,
(test->type == XML_SCHEMATRON_REPORT))
return;
if (ctxt->flags & XML_SCHEMATRON_OUT_XML) {
TODO
/* TODO */
} else {
xmlChar *path;
char msg[1000];
@ -1612,26 +1624,28 @@ xmlSchematronReportSuccess(xmlSchematronValidCtxtPtr ctxt,
line, (const char *) report);
if (ctxt->flags & XML_SCHEMATRON_OUT_ERROR) {
xmlStructuredErrorFunc schannel = NULL;
xmlGenericErrorFunc channel = NULL;
void *data = NULL;
xmlStructuredErrorFunc schannel;
xmlGenericErrorFunc channel;
void *data;
int res;
if (ctxt != NULL) {
if (ctxt->serror != NULL)
schannel = ctxt->serror;
else
channel = ctxt->error;
data = ctxt->userData;
}
schannel = ctxt->serror;
channel = ctxt->error;
data = ctxt->userData;
__xmlRaiseError(schannel, channel, data,
NULL, cur, XML_FROM_SCHEMATRONV,
(test->type == XML_SCHEMATRON_ASSERT)?XML_SCHEMATRONV_ASSERT:XML_SCHEMATRONV_REPORT,
XML_ERR_ERROR, NULL, line,
(pattern == NULL)?NULL:((const char *) pattern->name),
(const char *) path,
(const char *) report, 0, 0,
"%s", msg);
res = __xmlRaiseError(schannel, channel, data, NULL, cur,
XML_FROM_SCHEMATRONV,
(test->type == XML_SCHEMATRON_ASSERT) ?
XML_SCHEMATRONV_ASSERT :
XML_SCHEMATRONV_REPORT,
XML_ERR_ERROR, NULL, line,
(pattern == NULL) ?
NULL :
(const char *) pattern->name,
(const char *) path, (const char *) report, 0, 0,
"%s", msg);
if (res < 0)
xmlSchematronVErrMemory(ctxt);
} else {
xmlSchematronReportOutput(ctxt, cur, &msg[0]);
}
@ -1658,7 +1672,7 @@ xmlSchematronReportPattern(xmlSchematronValidCtxtPtr ctxt,
if ((ctxt->flags & XML_SCHEMATRON_OUT_QUIET) || (ctxt->flags & XML_SCHEMATRON_OUT_ERROR)) /* Error gives pattern name as part of error */
return;
if (ctxt->flags & XML_SCHEMATRON_OUT_XML) {
TODO
/* TODO */
} else {
char msg[1000];
@ -1713,8 +1727,7 @@ xmlSchematronNewValidCtxt(xmlSchematronPtr schema, int options)
ret = (xmlSchematronValidCtxtPtr) xmlMalloc(sizeof(xmlSchematronValidCtxt));
if (ret == NULL) {
xmlSchematronVErrMemory(NULL, "allocating validation context",
NULL);
xmlSchematronVErrMemory(NULL);
return (NULL);
}
memset(ret, 0, sizeof(xmlSchematronValidCtxt));
@ -1723,8 +1736,7 @@ xmlSchematronNewValidCtxt(xmlSchematronPtr schema, int options)
ret->xctxt = xmlXPathNewContext(NULL);
ret->flags = options;
if (ret->xctxt == NULL) {
xmlSchematronPErrMemory(NULL, "allocating schema parser XPath context",
NULL);
xmlSchematronPErrMemory(NULL);
xmlSchematronFreeValidCtxt(ret);
return (NULL);
}
@ -1870,7 +1882,9 @@ xmlSchematronRunTest(xmlSchematronValidCtxtPtr ctxt,
* Returns -1 in case of errors, otherwise 0
*/
static int
xmlSchematronRegisterVariables(xmlXPathContextPtr ctxt, xmlSchematronLetPtr let,
xmlSchematronRegisterVariables(xmlSchematronValidCtxtPtr vctxt,
xmlXPathContextPtr ctxt,
xmlSchematronLetPtr let,
xmlDocPtr instance, xmlNodePtr cur)
{
xmlXPathObjectPtr let_eval;
@ -1880,13 +1894,14 @@ xmlSchematronRegisterVariables(xmlXPathContextPtr ctxt, xmlSchematronLetPtr let,
while (let != NULL) {
let_eval = xmlXPathCompiledEval(let->comp, ctxt);
if (let_eval == NULL) {
xmlGenericError(xmlGenericErrorContext,
"Evaluation of compiled expression failed\n");
xmlSchematronVErr(vctxt, XML_ERR_INTERNAL_ERROR,
"Evaluation of compiled expression failed\n",
NULL);
return -1;
}
if(xmlXPathRegisterVariableNS(ctxt, let->name, NULL, let_eval)) {
xmlGenericError(xmlGenericErrorContext,
"Registering a let variable failed\n");
xmlSchematronVErr(vctxt, XML_ERR_INTERNAL_ERROR,
"Registering a let variable failed\n", NULL);
return -1;
}
let = let->next;
@ -1904,12 +1919,14 @@ xmlSchematronRegisterVariables(xmlXPathContextPtr ctxt, xmlSchematronLetPtr let,
* Returns -1 in case of errors, otherwise 0
*/
static int
xmlSchematronUnregisterVariables(xmlXPathContextPtr ctxt, xmlSchematronLetPtr let)
xmlSchematronUnregisterVariables(xmlSchematronValidCtxtPtr vctxt,
xmlXPathContextPtr ctxt,
xmlSchematronLetPtr let)
{
while (let != NULL) {
if (xmlXPathRegisterVariableNS(ctxt, let->name, NULL, NULL)) {
xmlGenericError(xmlGenericErrorContext,
"Unregistering a let variable failed\n");
xmlSchematronVErr(vctxt, XML_ERR_INTERNAL_ERROR,
"Unregistering a let variable failed\n", NULL);
return -1;
}
let = let->next;
@ -1941,7 +1958,7 @@ xmlSchematronValidateDoc(xmlSchematronValidCtxtPtr ctxt, xmlDocPtr instance)
ctxt->nberrors = 0;
root = xmlDocGetRootElement(instance);
if (root == NULL) {
TODO
/* TODO */
ctxt->nberrors++;
return(1);
}
@ -1958,7 +1975,8 @@ xmlSchematronValidateDoc(xmlSchematronValidCtxtPtr ctxt, xmlDocPtr instance)
if (xmlPatternMatch(rule->pattern, cur) == 1) {
test = rule->tests;
if (xmlSchematronRegisterVariables(ctxt->xctxt, rule->lets, instance, cur))
if (xmlSchematronRegisterVariables(ctxt, ctxt->xctxt,
rule->lets, instance, cur))
return -1;
while (test != NULL) {
@ -1966,7 +1984,8 @@ xmlSchematronValidateDoc(xmlSchematronValidCtxtPtr ctxt, xmlDocPtr instance)
test = test->next;
}
if (xmlSchematronUnregisterVariables(ctxt->xctxt, rule->lets))
if (xmlSchematronUnregisterVariables(ctxt, ctxt->xctxt,
rule->lets))
return -1;
}
@ -1996,15 +2015,16 @@ xmlSchematronValidateDoc(xmlSchematronValidCtxtPtr ctxt, xmlDocPtr instance)
while (rule != NULL) {
if (xmlPatternMatch(rule->pattern, cur) == 1) {
test = rule->tests;
xmlSchematronRegisterVariables(ctxt->xctxt, rule->lets,
instance, cur);
xmlSchematronRegisterVariables(ctxt, ctxt->xctxt,
rule->lets, instance, cur);
while (test != NULL) {
xmlSchematronRunTest(ctxt, test, instance, cur, pattern);
test = test->next;
}
xmlSchematronUnregisterVariables(ctxt->xctxt, rule->lets);
xmlSchematronUnregisterVariables(ctxt, ctxt->xctxt,
rule->lets);
}
rule = rule->patnext;
}