Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commitcacd42d

Browse files
committed
Rewrite libxml error handling to be more robust.
libxml reports some errors (like invalid xmlns attributes) via the errorhandler hook, but still returns a success indicator to the library caller.This causes us to miss some errors that are important to report. Since the"generic" error handler hook doesn't know whether the message it's gettingis for an error, warning, or notice, stop using that and instead startusing the "structured" error handler hook, which gets enough informationto be useful.While at it, arrange to save and restore the error handler hook setting ineach libxml-using function, rather than assuming we can set and forget thehook. This should improve the odds of working nicely with third-partylibraries that also use libxml.In passing, volatile-ize some local variables that get modified withinPG_TRY blocks. I noticed this while testing with an older gcc versionthan I'd previously tried to compile xml.c with.Florian Pflug and Tom Lane, with extensive review/testing by Noah Misch
1 parentd79a601 commitcacd42d

File tree

10 files changed

+939
-219
lines changed

10 files changed

+939
-219
lines changed

‎configure

Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23655,6 +23655,75 @@ fi
2365523655

2365623656

2365723657

23658+
# Older versions of libxml2 lack the xmlStructuredErrorContext variable
23659+
# (which could be a macro referring to a function, if threading is enabled)
23660+
if test "$with_libxml" = yes ; then
23661+
{ $as_echo "$as_me:$LINENO: checking for xmlStructuredErrorContext" >&5
23662+
$as_echo_n "checking for xmlStructuredErrorContext... " >&6; }
23663+
if test "${pgac_cv_libxml_structerrctx+set}" = set; then
23664+
$as_echo_n "(cached) " >&6
23665+
else
23666+
cat >conftest.$ac_ext <<_ACEOF
23667+
/* confdefs.h. */
23668+
_ACEOF
23669+
cat confdefs.h >>conftest.$ac_ext
23670+
cat >>conftest.$ac_ext <<_ACEOF
23671+
/* end confdefs.h. */
23672+
#include <libxml/globals.h>
23673+
void *globptr;
23674+
int
23675+
main ()
23676+
{
23677+
globptr = xmlStructuredErrorContext
23678+
;
23679+
return 0;
23680+
}
23681+
_ACEOF
23682+
rm -f conftest.$ac_objext conftest$ac_exeext
23683+
if { (ac_try="$ac_link"
23684+
case "(($ac_try" in
23685+
*\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
23686+
*) ac_try_echo=$ac_try;;
23687+
esac
23688+
eval ac_try_echo="\"\$as_me:$LINENO: $ac_try_echo\""
23689+
$as_echo "$ac_try_echo") >&5
23690+
(eval "$ac_link") 2>conftest.er1
23691+
ac_status=$?
23692+
grep -v '^ *+' conftest.er1 >conftest.err
23693+
rm -f conftest.er1
23694+
cat conftest.err >&5
23695+
$as_echo "$as_me:$LINENO: \$? = $ac_status" >&5
23696+
(exit $ac_status); } && {
23697+
test -z "$ac_c_werror_flag" ||
23698+
test ! -s conftest.err
23699+
} && test -s conftest$ac_exeext && {
23700+
test "$cross_compiling" = yes ||
23701+
$as_test_x conftest$ac_exeext
23702+
}; then
23703+
pgac_cv_libxml_structerrctx=yes
23704+
else
23705+
$as_echo "$as_me: failed program was:" >&5
23706+
sed 's/^/| /' conftest.$ac_ext >&5
23707+
23708+
pgac_cv_libxml_structerrctx=no
23709+
fi
23710+
23711+
rm -rf conftest.dSYM
23712+
rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \
23713+
conftest$ac_exeext conftest.$ac_ext
23714+
fi
23715+
{ $as_echo "$as_me:$LINENO: result: $pgac_cv_libxml_structerrctx" >&5
23716+
$as_echo "$pgac_cv_libxml_structerrctx" >&6; }
23717+
if test x"$pgac_cv_libxml_structerrctx" = x"yes"; then
23718+
23719+
cat >>confdefs.h <<\_ACEOF
23720+
#define HAVE_XMLSTRUCTUREDERRORCONTEXT 1
23721+
_ACEOF
23722+
23723+
fi
23724+
fi
23725+
23726+
2365823727
# This test makes sure that run tests work at all. Sometimes a shared
2365923728
# library is found by the linker, but the runtime linker can't find it.
2366023729
# This check should come after all modifications of compiler or linker

‎configure.in

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1519,6 +1519,23 @@ AC_SUBST(LDAP_LIBS_FE)
15191519
AC_SUBST(LDAP_LIBS_BE)
15201520

15211521

1522+
# Older versions of libxml2 lack the xmlStructuredErrorContext variable
1523+
# (which could be a macro referring to a function, if threading is enabled)
1524+
if test "$with_libxml" = yes ; then
1525+
AC_CACHE_CHECK([for xmlStructuredErrorContext], pgac_cv_libxml_structerrctx,
1526+
[AC_TRY_LINK([#include <libxml/globals.h>
1527+
void *globptr;],
1528+
[globptr = xmlStructuredErrorContext],
1529+
[pgac_cv_libxml_structerrctx=yes],
1530+
[pgac_cv_libxml_structerrctx=no])])
1531+
if test x"$pgac_cv_libxml_structerrctx" = x"yes"; then
1532+
AC_DEFINE(HAVE_XMLSTRUCTUREDERRORCONTEXT,
1533+
1,
1534+
[Define to 1 if your libxml has xmlStructuredErrorContext.])
1535+
fi
1536+
fi
1537+
1538+
15221539
# This test makes sure that run tests work at all. Sometimes a shared
15231540
# library is found by the linker, but the runtime linker can't find it.
15241541
# This check should come after all modifications of compiler or linker

‎contrib/xml2/xpath.c

Lines changed: 93 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,7 @@ Datumxpath_table(PG_FUNCTION_ARGS);
3838

3939
/* exported for use by xslt_proc.c */
4040

41-
voidpgxml_parser_init(void);
41+
PgXmlErrorContext*pgxml_parser_init(PgXmlStrictnessstrictness);
4242

4343
/* workspace for pgxml_xpath() */
4444

@@ -68,18 +68,27 @@ static void cleanup_workspace(xpath_workspace *workspace);
6868

6969
/*
7070
* Initialize for xml parsing.
71+
*
72+
* As with the underlying pg_xml_init function, calls to this MUST be followed
73+
* by a PG_TRY block that guarantees that pg_xml_done is called.
7174
*/
72-
void
73-
pgxml_parser_init(void)
75+
PgXmlErrorContext*
76+
pgxml_parser_init(PgXmlStrictnessstrictness)
7477
{
78+
PgXmlErrorContext*xmlerrcxt;
79+
7580
/* Set up error handling (we share the core's error handler) */
76-
pg_xml_init();
81+
xmlerrcxt=pg_xml_init(strictness);
82+
83+
/* Note: we're assuming an elog cannot be thrown by the following calls */
7784

7885
/* Initialize libxml */
7986
xmlInitParser();
8087

8188
xmlSubstituteEntitiesDefault(1);
8289
xmlLoadExtDtdDefaultValue=1;
90+
91+
returnxmlerrcxt;
8392
}
8493

8594

@@ -98,16 +107,33 @@ Datum
98107
xml_is_well_formed(PG_FUNCTION_ARGS)
99108
{
100109
text*t=PG_GETARG_TEXT_P(0);/* document buffer */
110+
boolresult= false;
101111
int32docsize=VARSIZE(t)-VARHDRSZ;
102112
xmlDocPtrdoctree;
113+
PgXmlErrorContext*xmlerrcxt;
114+
115+
xmlerrcxt=pgxml_parser_init(PG_XML_STRICTNESS_LEGACY);
116+
117+
PG_TRY();
118+
{
119+
doctree=xmlParseMemory((char*)VARDATA(t),docsize);
120+
121+
result= (doctree!=NULL);
122+
123+
if (doctree!=NULL)
124+
xmlFreeDoc(doctree);
125+
}
126+
PG_CATCH();
127+
{
128+
pg_xml_done(xmlerrcxt, true);
103129

104-
pgxml_parser_init();
130+
PG_RE_THROW();
131+
}
132+
PG_END_TRY();
105133

106-
doctree=xmlParseMemory((char*)VARDATA(t),docsize);
107-
if (doctree==NULL)
108-
PG_RETURN_BOOL(false);/* i.e. not well-formed */
109-
xmlFreeDoc(doctree);
110-
PG_RETURN_BOOL(true);
134+
pg_xml_done(xmlerrcxt, false);
135+
136+
PG_RETURN_BOOL(result);
111137
}
112138

113139

@@ -399,41 +425,52 @@ static xmlXPathObjectPtr
399425
pgxml_xpath(text*document,xmlChar*xpath,xpath_workspace*workspace)
400426
{
401427
int32docsize=VARSIZE(document)-VARHDRSZ;
402-
xmlXPathObjectPtrres;
428+
PgXmlErrorContext*xmlerrcxt;
403429
xmlXPathCompExprPtrcomppath;
404430

405431
workspace->doctree=NULL;
406432
workspace->ctxt=NULL;
407433
workspace->res=NULL;
408434

409-
pgxml_parser_init();
435+
xmlerrcxt=pgxml_parser_init(PG_XML_STRICTNESS_LEGACY);
410436

411-
workspace->doctree=xmlParseMemory((char*)VARDATA(document),docsize);
412-
if (workspace->doctree==NULL)
413-
returnNULL;/* not well-formed */
437+
PG_TRY();
438+
{
439+
workspace->doctree=xmlParseMemory((char*)VARDATA(document),
440+
docsize);
441+
if (workspace->doctree!=NULL)
442+
{
443+
workspace->ctxt=xmlXPathNewContext(workspace->doctree);
444+
workspace->ctxt->node=xmlDocGetRootElement(workspace->doctree);
414445

415-
workspace->ctxt=xmlXPathNewContext(workspace->doctree);
416-
workspace->ctxt->node=xmlDocGetRootElement(workspace->doctree);
446+
/* compile the path */
447+
comppath=xmlXPathCompile(xpath);
448+
if (comppath==NULL)
449+
xml_ereport(xmlerrcxt,ERROR,ERRCODE_EXTERNAL_ROUTINE_EXCEPTION,
450+
"XPath Syntax Error");
417451

418-
/* compile the path */
419-
comppath=xmlXPathCompile(xpath);
420-
if (comppath==NULL)
452+
/* Now evaluate the path expression. */
453+
workspace->res=xmlXPathCompiledEval(comppath,workspace->ctxt);
454+
455+
xmlXPathFreeCompExpr(comppath);
456+
}
457+
}
458+
PG_CATCH();
421459
{
422460
cleanup_workspace(workspace);
423-
xml_ereport(ERROR,ERRCODE_EXTERNAL_ROUTINE_EXCEPTION,
424-
"XPath Syntax Error");
425-
}
426461

427-
/* Now evaluate the path expression. */
428-
res=xmlXPathCompiledEval(comppath,workspace->ctxt);
429-
workspace->res=res;
462+
pg_xml_done(xmlerrcxt, true);
430463

431-
xmlXPathFreeCompExpr(comppath);
464+
PG_RE_THROW();
465+
}
466+
PG_END_TRY();
432467

433-
if (res==NULL)
468+
if (workspace->res==NULL)
434469
cleanup_workspace(workspace);
435470

436-
returnres;
471+
pg_xml_done(xmlerrcxt, false);
472+
473+
returnworkspace->res;
437474
}
438475

439476
/* Clean up after processing the result of pgxml_xpath() */
@@ -534,6 +571,8 @@ xpath_table(PG_FUNCTION_ARGS)
534571
* document */
535572
boolhad_values;/* To determine end of nodeset results */
536573
StringInfoDataquery_buf;
574+
PgXmlErrorContext*xmlerrcxt;
575+
volatilexmlDocPtrdoctree=NULL;
537576

538577
/* We only have a valid tuple description in table function mode */
539578
if (rsinfo==NULL|| !IsA(rsinfo,ReturnSetInfo))
@@ -659,14 +698,15 @@ xpath_table(PG_FUNCTION_ARGS)
659698
* Setup the parser. This should happen after we are done evaluating the
660699
* query, in case it calls functions that set up libxml differently.
661700
*/
662-
pgxml_parser_init();
701+
xmlerrcxt=pgxml_parser_init(PG_XML_STRICTNESS_LEGACY);
663702

703+
PG_TRY();
704+
{
664705
/* For each row i.e. document returned from SPI */
665706
for (i=0;i<proc;i++)
666707
{
667708
char*pkey;
668709
char*xmldoc;
669-
xmlDocPtrdoctree;
670710
xmlXPathContextPtrctxt;
671711
xmlXPathObjectPtrres;
672712
xmlChar*resstr;
@@ -718,11 +758,9 @@ xpath_table(PG_FUNCTION_ARGS)
718758
/* compile the path */
719759
comppath=xmlXPathCompile(xpaths[j]);
720760
if (comppath==NULL)
721-
{
722-
xmlFreeDoc(doctree);
723-
xml_ereport(ERROR,ERRCODE_EXTERNAL_ROUTINE_EXCEPTION,
761+
xml_ereport(xmlerrcxt,ERROR,
762+
ERRCODE_EXTERNAL_ROUTINE_EXCEPTION,
724763
"XPath Syntax Error");
725-
}
726764

727765
/* Now evaluate the path expression. */
728766
res=xmlXPathCompiledEval(comppath,ctxt);
@@ -737,8 +775,7 @@ xpath_table(PG_FUNCTION_ARGS)
737775
if (res->nodesetval!=NULL&&
738776
rownr<res->nodesetval->nodeNr)
739777
{
740-
resstr=
741-
xmlXPathCastNodeToString(res->nodesetval->nodeTab[rownr]);
778+
resstr=xmlXPathCastNodeToString(res->nodesetval->nodeTab[rownr]);
742779
had_values= true;
743780
}
744781
else
@@ -776,13 +813,31 @@ xpath_table(PG_FUNCTION_ARGS)
776813
}while (had_values);
777814
}
778815

779-
xmlFreeDoc(doctree);
816+
if (doctree!=NULL)
817+
xmlFreeDoc(doctree);
818+
doctree=NULL;
780819

781820
if (pkey)
782821
pfree(pkey);
783822
if (xmldoc)
784823
pfree(xmldoc);
785824
}
825+
}
826+
PG_CATCH();
827+
{
828+
if (doctree!=NULL)
829+
xmlFreeDoc(doctree);
830+
831+
pg_xml_done(xmlerrcxt, true);
832+
833+
PG_RE_THROW();
834+
}
835+
PG_END_TRY();
836+
837+
if (doctree!=NULL)
838+
xmlFreeDoc(doctree);
839+
840+
pg_xml_done(xmlerrcxt, false);
786841

787842
tuplestore_donestoring(tupstore);
788843

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp