From c1420fcf7d9e899b3378e25f5e21776f6461b4a4 Mon Sep 17 00:00:00 2001 From: Tom Lane Date: Tue, 26 Jul 2011 16:29:53 -0400 Subject: [PATCH] Check to see whether libxml2 handles error context the way we expect. It turns out to be possible to link against a libxml2.so that does this differently than the version we configured and built against, so we need a runtime check to avoid bizarre behavior. Per report from Bernd Helmle. Patch by Florian Pflug. --- src/backend/utils/adt/xml.c | 38 +++++++++++++++++++++++++++++++++++-- 1 file changed, 36 insertions(+), 2 deletions(-) diff --git a/src/backend/utils/adt/xml.c b/src/backend/utils/adt/xml.c index f3db3f0754..99b978c42c 100644 --- a/src/backend/utils/adt/xml.c +++ b/src/backend/utils/adt/xml.c @@ -928,6 +928,7 @@ PgXmlErrorContext * pg_xml_init(PgXmlStrictness strictness) { PgXmlErrorContext *errcxt; + void *new_errcxt; /* Do one-time setup if needed */ pg_xml_init_library(); @@ -956,6 +957,34 @@ pg_xml_init(PgXmlStrictness strictness) xmlSetStructuredErrorFunc((void *) errcxt, xml_errorHandler); + /* + * Verify that xmlSetStructuredErrorFunc set the context variable we + * expected it to. If not, the error context pointer we just saved is not + * the correct thing to restore, and since that leaves us without a way to + * restore the context in pg_xml_done, we must fail. + * + * The only known situation in which this test fails is if we compile with + * headers from a libxml2 that doesn't track the structured error context + * separately (<= 2.7.3), but at runtime use a version that does, or vice + * versa. The libxml2 authors did not treat that change as constituting + * an ABI break, so the LIBXML_TEST_VERSION test in pg_xml_init_library + * fails to protect us from this. + */ + +#ifdef HAVE_XMLSTRUCTUREDERRORCONTEXT + new_errcxt = xmlStructuredErrorContext; +#else + new_errcxt = xmlGenericErrorContext; +#endif + + if (new_errcxt != (void *) errcxt) + ereport(ERROR, + (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), + errmsg("could not set up XML error handler"), + errhint("This probably indicates that the version of libxml2" + " being used is not compatible with the libxml2" + " header files that PostgreSQL was built with."))); + return errcxt; } @@ -1494,9 +1523,14 @@ xml_errorHandler(void *data, xmlErrorPtr error) int level = error->level; StringInfo errorBuf; - /* Defend against someone passing us a bogus context struct */ + /* + * Defend against someone passing us a bogus context struct. + * + * We force a backend exit if this check fails because longjmp'ing out of + * libxml would likely render it unsafe to use further. + */ if (xmlerrcxt->magic != ERRCXT_MAGIC) - elog(ERROR, "xml_errorHandler called with invalid PgXmlErrorContext"); + elog(FATAL, "xml_errorHandler called with invalid PgXmlErrorContext"); /*---------- * Older libxml versions report some errors differently. -- 2.40.0