Location via proxy:   [ UP ]  
[Report a bug]   [Manage cookies]                
Skip to content

Commit 5e47403

Browse files
committed
Make contrib/xml2 use core xml.c's error handler, when available (that is,
in versions >= 8.3). The core code is more robust and efficient than what was there before, and this also reduces risks involved in swapping different libxml error handler settings. Before 8.3, there is still some risk of problems if add-on modules such as Perl invoke libxml without setting their own error handler. Given the lack of reports I'm not sure there's a risk in practice, so I didn't take the step of actually duplicating the core code into older contrib/xml2 branches. Instead I just tweaked the existing code to ensure it didn't leave a dangling pointer to short-lived memory when throwing an error.
1 parent 8bf1418 commit 5e47403

File tree

2 files changed

+19
-84
lines changed

2 files changed

+19
-84
lines changed

contrib/xml2/xpath.c

Lines changed: 11 additions & 73 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* $PostgreSQL: pgsql/contrib/xml2/xpath.c,v 1.28 2010/03/01 05:16:35 tgl Exp $
2+
* $PostgreSQL: pgsql/contrib/xml2/xpath.c,v 1.29 2010/03/03 19:10:22 tgl Exp $
33
*
44
* Parser interface for DOM-based parser (libxml) rather than
55
* stream-based SAX-type parser
@@ -12,6 +12,7 @@
1212
#include "lib/stringinfo.h"
1313
#include "miscadmin.h"
1414
#include "utils/builtins.h"
15+
#include "utils/xml.h"
1516

1617
/* libxml includes */
1718

@@ -35,15 +36,12 @@ Datum xpath_bool(PG_FUNCTION_ARGS);
3536
Datum xpath_list(PG_FUNCTION_ARGS);
3637
Datum xpath_table(PG_FUNCTION_ARGS);
3738

38-
/* these are exported for use by xslt_proc.c */
39+
/* exported for use by xslt_proc.c */
3940

40-
void elog_error(const char *explain, bool force);
4141
void pgxml_parser_init(void);
4242

4343
/* local declarations */
4444

45-
static void pgxml_errorHandler(void *ctxt, const char *msg,...);
46-
4745
static xmlChar *pgxmlNodeSetToText(xmlNodeSetPtr nodeset,
4846
xmlChar *toptagname, xmlChar *septagname,
4947
xmlChar *plainsep);
@@ -55,72 +53,15 @@ static xmlChar *pgxml_texttoxmlchar(text *textstring);
5553

5654
static xmlXPathObjectPtr pgxml_xpath(text *document, xmlChar *xpath);
5755

58-
/* Global variables */
59-
static char *pgxml_errorMsg = NULL; /* overall error message */
60-
61-
62-
/*
63-
* The error handling function. This formats an error message and sets
64-
* a flag - an ereport will be issued prior to return
65-
*/
66-
static void
67-
pgxml_errorHandler(void *ctxt, const char *msg,...)
68-
{
69-
char errbuf[1024]; /* per line error buffer */
70-
va_list args;
71-
72-
/* Format the message */
73-
va_start(args, msg);
74-
vsnprintf(errbuf, sizeof(errbuf), msg, args);
75-
va_end(args);
76-
/* Store in, or append to, pgxml_errorMsg */
77-
if (pgxml_errorMsg == NULL)
78-
pgxml_errorMsg = pstrdup(errbuf);
79-
else
80-
{
81-
size_t oldsize = strlen(pgxml_errorMsg);
82-
size_t newsize = strlen(errbuf);
83-
84-
/*
85-
* We intentionally discard the last char of the existing message,
86-
* which should be a carriage return. (XXX wouldn't it be saner
87-
* to keep it?)
88-
*/
89-
pgxml_errorMsg = repalloc(pgxml_errorMsg, oldsize + newsize);
90-
memcpy(&pgxml_errorMsg[oldsize - 1], errbuf, newsize);
91-
pgxml_errorMsg[oldsize + newsize - 1] = '\0';
92-
}
93-
}
94-
95-
/*
96-
* This function ereports the current message if any. If force is true
97-
* then an error is thrown even if pgxml_errorMsg hasn't been set.
98-
*/
99-
void
100-
elog_error(const char *explain, bool force)
101-
{
102-
if (force || pgxml_errorMsg != NULL)
103-
{
104-
if (pgxml_errorMsg == NULL)
105-
ereport(ERROR,
106-
(errcode(ERRCODE_EXTERNAL_ROUTINE_EXCEPTION),
107-
errmsg("%s", explain)));
108-
else
109-
ereport(ERROR,
110-
(errcode(ERRCODE_EXTERNAL_ROUTINE_EXCEPTION),
111-
errmsg("%s: %s", explain, pgxml_errorMsg)));
112-
}
113-
}
11456

11557
/*
11658
* Initialize for xml parsing.
11759
*/
11860
void
11961
pgxml_parser_init(void)
12062
{
121-
/* Set up error handling */
122-
pgxml_errorMsg = NULL;
123-
xmlSetGenericErrorFunc(NULL, pgxml_errorHandler);
63+
/* Set up error handling (we share the core's error handler) */
64+
pg_xml_init();
12465

12566
/* Initialize libxml */
12667
xmlInitParser();
@@ -466,7 +407,8 @@ pgxml_xpath(text *document, xmlChar *xpath)
466407
if (comppath == NULL)
467408
{
468409
xmlFreeDoc(doctree);
469-
elog_error("XPath Syntax Error", true);
410+
xml_ereport(ERROR, ERRCODE_EXTERNAL_ROUTINE_EXCEPTION,
411+
"XPath Syntax Error");
470412
}
471413

472414
/* Now evaluate the path expression. */
@@ -519,8 +461,6 @@ pgxml_result_to_text(xmlXPathObjectPtr res,
519461
/* Free various storage */
520462
xmlFree(xpresstr);
521463

522-
elog_error("XPath error", false);
523-
524464
return xpres;
525465
}
526466

@@ -691,10 +631,8 @@ xpath_table(PG_FUNCTION_ARGS)
691631
}
692632

693633
/*
694-
* Setup the parser. Beware that this must happen in the same context as
695-
* the cleanup - which means that any error from here on must do cleanup
696-
* to ensure that the entity table doesn't get freed by being out of
697-
* context.
634+
* Setup the parser. This should happen after we are done evaluating
635+
* the query, in case it calls functions that set up libxml differently.
698636
*/
699637
pgxml_parser_init();
700638

@@ -751,14 +689,14 @@ xpath_table(PG_FUNCTION_ARGS)
751689
{
752690
ctxt = xmlXPathNewContext(doctree);
753691
ctxt->node = xmlDocGetRootElement(doctree);
754-
xmlSetGenericErrorFunc(ctxt, pgxml_errorHandler);
755692

756693
/* compile the path */
757694
comppath = xmlXPathCompile(xpaths[j]);
758695
if (comppath == NULL)
759696
{
760697
xmlFreeDoc(doctree);
761-
elog_error("XPath Syntax Error", true);
698+
xml_ereport(ERROR, ERRCODE_EXTERNAL_ROUTINE_EXCEPTION,
699+
"XPath Syntax Error");
762700
}
763701

764702
/* Now evaluate the path expression. */

contrib/xml2/xslt_proc.c

Lines changed: 8 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* $PostgreSQL: pgsql/contrib/xml2/xslt_proc.c,v 1.19 2010/03/01 18:07:59 tgl Exp $
2+
* $PostgreSQL: pgsql/contrib/xml2/xslt_proc.c,v 1.20 2010/03/03 19:10:22 tgl Exp $
33
*
44
* XSLT processing functions (requiring libxslt)
55
*
@@ -12,6 +12,7 @@
1212
#include "funcapi.h"
1313
#include "miscadmin.h"
1414
#include "utils/builtins.h"
15+
#include "utils/xml.h"
1516

1617
#ifdef USE_LIBXSLT
1718

@@ -38,7 +39,6 @@ Datum xslt_process(PG_FUNCTION_ARGS);
3839
#ifdef USE_LIBXSLT
3940

4041
/* declarations to come from xpath.c */
41-
extern void elog_error(const char *explain, bool force);
4242
extern void pgxml_parser_init(void);
4343

4444
/* local defs */
@@ -88,11 +88,8 @@ xslt_process(PG_FUNCTION_ARGS)
8888
doctree = xmlParseFile(text_to_cstring(doct));
8989

9090
if (doctree == NULL)
91-
{
92-
elog_error("error parsing XML document", false);
93-
94-
PG_RETURN_NULL();
95-
}
91+
xml_ereport(ERROR, ERRCODE_EXTERNAL_ROUTINE_EXCEPTION,
92+
"error parsing XML document");
9693

9794
/* Same for stylesheet */
9895
if (VARDATA(ssheet)[0] == '<')
@@ -102,8 +99,8 @@ xslt_process(PG_FUNCTION_ARGS)
10299
if (ssdoc == NULL)
103100
{
104101
xmlFreeDoc(doctree);
105-
elog_error("error parsing stylesheet as XML document", false);
106-
PG_RETURN_NULL();
102+
xml_ereport(ERROR, ERRCODE_EXTERNAL_ROUTINE_EXCEPTION,
103+
"error parsing stylesheet as XML document");
107104
}
108105

109106
stylesheet = xsltParseStylesheetDoc(ssdoc);
@@ -116,8 +113,8 @@ xslt_process(PG_FUNCTION_ARGS)
116113
{
117114
xmlFreeDoc(doctree);
118115
xsltCleanupGlobals();
119-
elog_error("failed to parse stylesheet", false);
120-
PG_RETURN_NULL();
116+
xml_ereport(ERROR, ERRCODE_EXTERNAL_ROUTINE_EXCEPTION,
117+
"failed to parse stylesheet");
121118
}
122119

123120
restree = xsltApplyStylesheet(stylesheet, doctree, params);

0 commit comments

Comments
 (0)