diff options
Diffstat (limited to 'contrib/xml2')
-rw-r--r-- | contrib/xml2/xpath.c | 131 | ||||
-rw-r--r-- | contrib/xml2/xslt_proc.c | 56 |
2 files changed, 127 insertions, 60 deletions
diff --git a/contrib/xml2/xpath.c b/contrib/xml2/xpath.c index 44c600e1348..2ddee59fcb7 100644 --- a/contrib/xml2/xpath.c +++ b/contrib/xml2/xpath.c @@ -38,7 +38,7 @@ Datum xpath_table(PG_FUNCTION_ARGS); /* exported for use by xslt_proc.c */ -void pgxml_parser_init(void); +PgXmlErrorContext *pgxml_parser_init(PgXmlStrictness strictness); /* workspace for pgxml_xpath() */ @@ -68,18 +68,27 @@ static void cleanup_workspace(xpath_workspace *workspace); /* * Initialize for xml parsing. + * + * As with the underlying pg_xml_init function, calls to this MUST be followed + * by a PG_TRY block that guarantees that pg_xml_done is called. */ -void -pgxml_parser_init(void) +PgXmlErrorContext * +pgxml_parser_init(PgXmlStrictness strictness) { + PgXmlErrorContext *xmlerrcxt; + /* Set up error handling (we share the core's error handler) */ - pg_xml_init(); + xmlerrcxt = pg_xml_init(strictness); + + /* Note: we're assuming an elog cannot be thrown by the following calls */ /* Initialize libxml */ xmlInitParser(); xmlSubstituteEntitiesDefault(1); xmlLoadExtDtdDefaultValue = 1; + + return xmlerrcxt; } @@ -98,16 +107,33 @@ Datum xml_is_well_formed(PG_FUNCTION_ARGS) { text *t = PG_GETARG_TEXT_P(0); /* document buffer */ + bool result = false; int32 docsize = VARSIZE(t) - VARHDRSZ; xmlDocPtr doctree; + PgXmlErrorContext *xmlerrcxt; + + xmlerrcxt = pgxml_parser_init(PG_XML_STRICTNESS_LEGACY); + + PG_TRY(); + { + doctree = xmlParseMemory((char *) VARDATA(t), docsize); + + result = (doctree != NULL); + + if (doctree != NULL) + xmlFreeDoc(doctree); + } + PG_CATCH(); + { + pg_xml_done(xmlerrcxt, true); - pgxml_parser_init(); + PG_RE_THROW(); + } + PG_END_TRY(); - doctree = xmlParseMemory((char *) VARDATA(t), docsize); - if (doctree == NULL) - PG_RETURN_BOOL(false); /* i.e. not well-formed */ - xmlFreeDoc(doctree); - PG_RETURN_BOOL(true); + pg_xml_done(xmlerrcxt, false); + + PG_RETURN_BOOL(result); } @@ -399,41 +425,52 @@ static xmlXPathObjectPtr pgxml_xpath(text *document, xmlChar *xpath, xpath_workspace *workspace) { int32 docsize = VARSIZE(document) - VARHDRSZ; - xmlXPathObjectPtr res; + PgXmlErrorContext *xmlerrcxt; xmlXPathCompExprPtr comppath; workspace->doctree = NULL; workspace->ctxt = NULL; workspace->res = NULL; - pgxml_parser_init(); + xmlerrcxt = pgxml_parser_init(PG_XML_STRICTNESS_LEGACY); - workspace->doctree = xmlParseMemory((char *) VARDATA(document), docsize); - if (workspace->doctree == NULL) - return NULL; /* not well-formed */ + PG_TRY(); + { + workspace->doctree = xmlParseMemory((char *) VARDATA(document), + docsize); + if (workspace->doctree != NULL) + { + workspace->ctxt = xmlXPathNewContext(workspace->doctree); + workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree); - workspace->ctxt = xmlXPathNewContext(workspace->doctree); - workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree); + /* compile the path */ + comppath = xmlXPathCompile(xpath); + if (comppath == NULL) + xml_ereport(xmlerrcxt, ERROR, ERRCODE_EXTERNAL_ROUTINE_EXCEPTION, + "XPath Syntax Error"); - /* compile the path */ - comppath = xmlXPathCompile(xpath); - if (comppath == NULL) + /* Now evaluate the path expression. */ + workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt); + + xmlXPathFreeCompExpr(comppath); + } + } + PG_CATCH(); { cleanup_workspace(workspace); - xml_ereport(ERROR, ERRCODE_EXTERNAL_ROUTINE_EXCEPTION, - "XPath Syntax Error"); - } - /* Now evaluate the path expression. */ - res = xmlXPathCompiledEval(comppath, workspace->ctxt); - workspace->res = res; + pg_xml_done(xmlerrcxt, true); - xmlXPathFreeCompExpr(comppath); + PG_RE_THROW(); + } + PG_END_TRY(); - if (res == NULL) + if (workspace->res == NULL) cleanup_workspace(workspace); - return res; + pg_xml_done(xmlerrcxt, false); + + return workspace->res; } /* Clean up after processing the result of pgxml_xpath() */ @@ -534,6 +571,8 @@ xpath_table(PG_FUNCTION_ARGS) * document */ bool had_values; /* To determine end of nodeset results */ StringInfoData query_buf; + PgXmlErrorContext *xmlerrcxt; + volatile xmlDocPtr doctree = NULL; /* We only have a valid tuple description in table function mode */ if (rsinfo == NULL || !IsA(rsinfo, ReturnSetInfo)) @@ -659,14 +698,15 @@ xpath_table(PG_FUNCTION_ARGS) * Setup the parser. This should happen after we are done evaluating the * query, in case it calls functions that set up libxml differently. */ - pgxml_parser_init(); + xmlerrcxt = pgxml_parser_init(PG_XML_STRICTNESS_LEGACY); + PG_TRY(); + { /* For each row i.e. document returned from SPI */ for (i = 0; i < proc; i++) { char *pkey; char *xmldoc; - xmlDocPtr doctree; xmlXPathContextPtr ctxt; xmlXPathObjectPtr res; xmlChar *resstr; @@ -718,11 +758,9 @@ xpath_table(PG_FUNCTION_ARGS) /* compile the path */ comppath = xmlXPathCompile(xpaths[j]); if (comppath == NULL) - { - xmlFreeDoc(doctree); - xml_ereport(ERROR, ERRCODE_EXTERNAL_ROUTINE_EXCEPTION, + xml_ereport(xmlerrcxt, ERROR, + ERRCODE_EXTERNAL_ROUTINE_EXCEPTION, "XPath Syntax Error"); - } /* Now evaluate the path expression. */ res = xmlXPathCompiledEval(comppath, ctxt); @@ -737,8 +775,7 @@ xpath_table(PG_FUNCTION_ARGS) if (res->nodesetval != NULL && rownr < res->nodesetval->nodeNr) { - resstr = - xmlXPathCastNodeToString(res->nodesetval->nodeTab[rownr]); + resstr = xmlXPathCastNodeToString(res->nodesetval->nodeTab[rownr]); had_values = true; } else @@ -776,13 +813,31 @@ xpath_table(PG_FUNCTION_ARGS) } while (had_values); } - xmlFreeDoc(doctree); + if (doctree != NULL) + xmlFreeDoc(doctree); + doctree = NULL; if (pkey) pfree(pkey); if (xmldoc) pfree(xmldoc); } + } + PG_CATCH(); + { + if (doctree != NULL) + xmlFreeDoc(doctree); + + pg_xml_done(xmlerrcxt, true); + + PG_RE_THROW(); + } + PG_END_TRY(); + + if (doctree != NULL) + xmlFreeDoc(doctree); + + pg_xml_done(xmlerrcxt, false); tuplestore_donestoring(tupstore); diff --git a/contrib/xml2/xslt_proc.c b/contrib/xml2/xslt_proc.c index f8f7d7263f9..a8e481a3ce8 100644 --- a/contrib/xml2/xslt_proc.c +++ b/contrib/xml2/xslt_proc.c @@ -38,7 +38,7 @@ Datum xslt_process(PG_FUNCTION_ARGS); #ifdef USE_LIBXSLT /* declarations to come from xpath.c */ -extern void pgxml_parser_init(void); +extern PgXmlErrorContext *pgxml_parser_init(PgXmlStrictness strictness); /* local defs */ static const char **parse_params(text *paramstr); @@ -56,13 +56,14 @@ xslt_process(PG_FUNCTION_ARGS) text *ssheet = PG_GETARG_TEXT_P(1); text *paramstr; const char **params; - xsltStylesheetPtr stylesheet = NULL; - xmlDocPtr doctree; - xmlDocPtr restree; - xmlDocPtr ssdoc = NULL; - xmlChar *resstr; - int resstat; - int reslen; + PgXmlErrorContext *xmlerrcxt; + volatile xsltStylesheetPtr stylesheet = NULL; + volatile xmlDocPtr doctree = NULL; + volatile xmlDocPtr restree = NULL; + volatile xmlDocPtr ssdoc = NULL; + volatile int resstat = -1; + xmlChar *resstr = NULL; + int reslen = 0; if (fcinfo->nargs == 3) { @@ -77,9 +78,11 @@ xslt_process(PG_FUNCTION_ARGS) } /* Setup parser */ - pgxml_parser_init(); + xmlerrcxt = pgxml_parser_init(PG_XML_STRICTNESS_LEGACY); - /* Check to see if document is a file or a literal */ + PG_TRY(); + { + /* Check to see if document is a file or a literal */ if (VARDATA(doct)[0] == '<') doctree = xmlParseMemory((char *) VARDATA(doct), VARSIZE(doct) - VARHDRSZ); @@ -87,7 +90,7 @@ xslt_process(PG_FUNCTION_ARGS) doctree = xmlParseFile(text_to_cstring(doct)); if (doctree == NULL) - xml_ereport(ERROR, ERRCODE_EXTERNAL_ROUTINE_EXCEPTION, + xml_ereport(xmlerrcxt, ERROR, ERRCODE_EXTERNAL_ROUTINE_EXCEPTION, "error parsing XML document"); /* Same for stylesheet */ @@ -96,35 +99,44 @@ xslt_process(PG_FUNCTION_ARGS) ssdoc = xmlParseMemory((char *) VARDATA(ssheet), VARSIZE(ssheet) - VARHDRSZ); if (ssdoc == NULL) - { - xmlFreeDoc(doctree); - xml_ereport(ERROR, ERRCODE_EXTERNAL_ROUTINE_EXCEPTION, + xml_ereport(xmlerrcxt, ERROR, ERRCODE_EXTERNAL_ROUTINE_EXCEPTION, "error parsing stylesheet as XML document"); - } stylesheet = xsltParseStylesheetDoc(ssdoc); } else stylesheet = xsltParseStylesheetFile((xmlChar *) text_to_cstring(ssheet)); - if (stylesheet == NULL) - { - xmlFreeDoc(doctree); - xsltCleanupGlobals(); - xml_ereport(ERROR, ERRCODE_EXTERNAL_ROUTINE_EXCEPTION, + xml_ereport(xmlerrcxt, ERROR, ERRCODE_EXTERNAL_ROUTINE_EXCEPTION, "failed to parse stylesheet"); - } restree = xsltApplyStylesheet(stylesheet, doctree, params); resstat = xsltSaveResultToString(&resstr, &reslen, restree, stylesheet); + } + PG_CATCH(); + { + if (stylesheet != NULL) + xsltFreeStylesheet(stylesheet); + if (restree != NULL) + xmlFreeDoc(restree); + if (doctree != NULL) + xmlFreeDoc(doctree); + xsltCleanupGlobals(); + + pg_xml_done(xmlerrcxt, true); + + PG_RE_THROW(); + } + PG_END_TRY(); xsltFreeStylesheet(stylesheet); xmlFreeDoc(restree); xmlFreeDoc(doctree); - xsltCleanupGlobals(); + pg_xml_done(xmlerrcxt, false); + if (resstat < 0) PG_RETURN_NULL(); |