|
48 | 48 | #ifdef USE_LIBXML
|
49 | 49 | #include <libxml/chvalid.h>
|
50 | 50 | #include <libxml/parser.h>
|
| 51 | +#include <libxml/parserInternals.h> |
51 | 52 | #include <libxml/tree.h>
|
52 | 53 | #include <libxml/uri.h>
|
53 | 54 | #include <libxml/xmlerror.h>
|
@@ -99,8 +100,12 @@ struct PgXmlErrorContext
|
99 | 100 | /* previous libxml error handling state (saved by pg_xml_init) */
|
100 | 101 | xmlStructuredErrorFunc saved_errfunc;
|
101 | 102 | void *saved_errcxt;
|
| 103 | + /* previous libxml entity handler (saved by pg_xml_init) */ |
| 104 | + xmlExternalEntityLoader saved_entityfunc; |
102 | 105 | };
|
103 | 106 |
|
| 107 | +static xmlParserInputPtr xmlPgEntityLoader(const char *URL, const char *ID, |
| 108 | + xmlParserCtxtPtr ctxt); |
104 | 109 | static void xml_errorHandler(void *data, xmlErrorPtr error);
|
105 | 110 | static void xml_ereport_by_code(int level, int sqlcode,
|
106 | 111 | const char *msg, int errcode);
|
@@ -985,6 +990,13 @@ pg_xml_init(PgXmlStrictness strictness)
|
985 | 990 | " being used is not compatible with the libxml2"
|
986 | 991 | " header files that PostgreSQL was built with.")));
|
987 | 992 |
|
| 993 | + /* |
| 994 | + * Also, install an entity loader to prevent unwanted fetches of external |
| 995 | + * files and URLs. |
| 996 | + */ |
| 997 | + errcxt->saved_entityfunc = xmlGetExternalEntityLoader(); |
| 998 | + xmlSetExternalEntityLoader(xmlPgEntityLoader); |
| 999 | + |
988 | 1000 | return errcxt;
|
989 | 1001 | }
|
990 | 1002 |
|
@@ -1027,8 +1039,9 @@ pg_xml_done(PgXmlErrorContext *errcxt, bool isError)
|
1027 | 1039 | if (cur_errcxt != (void *) errcxt)
|
1028 | 1040 | elog(WARNING, "libxml error handling state is out of sync with xml.c");
|
1029 | 1041 |
|
1030 |
| - /* Restore the saved handler */ |
| 1042 | + /* Restore the saved handlers */ |
1031 | 1043 | xmlSetStructuredErrorFunc(errcxt->saved_errcxt, errcxt->saved_errfunc);
|
| 1044 | + xmlSetExternalEntityLoader(errcxt->saved_entityfunc); |
1032 | 1045 |
|
1033 | 1046 | /*
|
1034 | 1047 | * Mark the struct as invalid, just in case somebody somehow manages to
|
@@ -1472,6 +1485,25 @@ xml_pstrdup(const char *string)
|
1472 | 1485 | #endif /* USE_LIBXMLCONTEXT */
|
1473 | 1486 |
|
1474 | 1487 |
|
| 1488 | +/* |
| 1489 | + * xmlPgEntityLoader --- entity loader callback function |
| 1490 | + * |
| 1491 | + * Silently prevent any external entity URL from being loaded. We don't want |
| 1492 | + * to throw an error, so instead make the entity appear to expand to an empty |
| 1493 | + * string. |
| 1494 | + * |
| 1495 | + * We would prefer to allow loading entities that exist in the system's |
| 1496 | + * global XML catalog; but the available libxml2 APIs make that a complex |
| 1497 | + * and fragile task. For now, just shut down all external access. |
| 1498 | + */ |
| 1499 | +static xmlParserInputPtr |
| 1500 | +xmlPgEntityLoader(const char *URL, const char *ID, |
| 1501 | + xmlParserCtxtPtr ctxt) |
| 1502 | +{ |
| 1503 | + return xmlNewStringInputStream(ctxt, (const xmlChar *) ""); |
| 1504 | +} |
| 1505 | + |
| 1506 | + |
1475 | 1507 | /*
|
1476 | 1508 | * xml_ereport --- report an XML-related error
|
1477 | 1509 | *
|
@@ -1566,7 +1598,14 @@ xml_errorHandler(void *data, xmlErrorPtr error)
|
1566 | 1598 | case XML_FROM_NONE:
|
1567 | 1599 | case XML_FROM_MEMORY:
|
1568 | 1600 | case XML_FROM_IO:
|
1569 |
| - /* Accept error regardless of the parsing purpose */ |
| 1601 | + /* |
| 1602 | + * Suppress warnings about undeclared entities. We need to do |
| 1603 | + * this to avoid problems due to not loading DTD definitions. |
| 1604 | + */ |
| 1605 | + if (error->code == XML_WAR_UNDECLARED_ENTITY) |
| 1606 | + return; |
| 1607 | + |
| 1608 | + /* Otherwise, accept error regardless of the parsing purpose */ |
1570 | 1609 | break;
|
1571 | 1610 |
|
1572 | 1611 | default:
|
|
0 commit comments