]> granicus.if.org Git - postgresql/commitdiff
Check to see whether libxml2 handles error context the way we expect.
authorTom Lane <tgl@sss.pgh.pa.us>
Tue, 26 Jul 2011 20:29:53 +0000 (16:29 -0400)
committerTom Lane <tgl@sss.pgh.pa.us>
Tue, 26 Jul 2011 20:31:04 +0000 (16:31 -0400)
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

index f3db3f075481e8e1872d0ae13759ca7b9a8b2135..99b978c42c08089f3675f6e675f419b2c935a3ae 100644 (file)
@@ -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.