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

Commit85f807d

Browse files
committed
Fix xmlelement() to initialize libxml correctly before using it, and to avoid
assuming that evaluation of its input expressions won't change the state oflibxml. This requires refactoring xml_init() to not call xmlInitParser(),since now not all of its callers want that. I also tweaked things to avoidrepeated execution of one-time-only tests inside xml_init(), though this ismostly for clarity rather than in hopes of saving any noticeable amount ofruntime. Per report from Sheikh Amjad and subsequent discussion.In passing, fix a couple of inadequately schema-qualified queries.
1 parentbcb3852 commit85f807d

File tree

1 file changed

+120
-55
lines changed
  • src/backend/utils/adt

1 file changed

+120
-55
lines changed

‎src/backend/utils/adt/xml.c

Lines changed: 120 additions & 55 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
* Portions Copyright (c) 1996-2007, PostgreSQL Global Development Group
88
* Portions Copyright (c) 1994, Regents of the University of California
99
*
10-
* $PostgreSQL: pgsql/src/backend/utils/adt/xml.c,v 1.49 2007/10/13 20:46:47 tgl Exp $
10+
* $PostgreSQL: pgsql/src/backend/utils/adt/xml.c,v 1.50 2007/11/05 22:23:07 tgl Exp $
1111
*
1212
*-------------------------------------------------------------------------
1313
*/
@@ -73,6 +73,10 @@
7373
#include"utils/xml.h"
7474

7575

76+
/* GUC variables */
77+
XmlBinaryTypexmlbinary;
78+
XmlOptionTypexmloption;
79+
7680
#ifdefUSE_LIBXML
7781

7882
staticStringInfoxml_err_buf=NULL;
@@ -104,11 +108,6 @@ static const char * map_sql_typecoll_to_xmlschema_types(List *tupdesc_list);
104108
staticconstchar*map_sql_type_to_xmlschema_type(Oidtypeoid,inttypmod);
105109
staticvoidSPI_sql_row_to_xmlelement(intrownum,StringInforesult,char*tablename,boolnulls,booltableforest,constchar*targetns,booltop_level);
106110

107-
108-
XmlBinaryTypexmlbinary;
109-
XmlOptionTypexmloption;
110-
111-
112111
#defineNO_XML_SUPPORT() \
113112
ereport(ERROR, \
114113
(errcode(ERRCODE_FEATURE_NOT_SUPPORTED), \
@@ -217,7 +216,8 @@ xml_out_internal(xmltype *x, pg_enc target_encoding)
217216
}
218217

219218
xml_ereport_by_code(WARNING,ERRCODE_INTERNAL_ERROR,
220-
"could not parse XML declaration in stored value",res_code);
219+
"could not parse XML declaration in stored value",
220+
res_code);
221221
#endif
222222
returnstr;
223223
}
@@ -540,52 +540,92 @@ xmlelement(XmlExprState *xmlExpr, ExprContext *econtext)
540540
{
541541
#ifdefUSE_LIBXML
542542
XmlExpr*xexpr= (XmlExpr*)xmlExpr->xprstate.expr;
543+
xmltype*result;
544+
List*named_arg_strings;
545+
List*arg_strings;
543546
inti;
544547
ListCell*arg;
545548
ListCell*narg;
546-
boolisnull;
547-
xmltype*result;
548-
Datumvalue;
549-
char*str;
550-
551549
xmlBufferPtrbuf;
552550
xmlTextWriterPtrwriter;
553551

554-
buf=xmlBufferCreate();
555-
writer=xmlNewTextWriterMemory(buf,0);
556-
557-
xmlTextWriterStartElement(writer, (xmlChar*)xexpr->name);
558-
552+
/*
553+
* We first evaluate all the arguments, then start up libxml and
554+
* create the result. This avoids issues if one of the arguments
555+
* involves a call to some other function or subsystem that wants to use
556+
* libxml on its own terms.
557+
*/
558+
named_arg_strings=NIL;
559559
i=0;
560-
forboth(arg,xmlExpr->named_args,narg,xexpr->arg_names)
560+
foreach(arg,xmlExpr->named_args)
561561
{
562562
ExprState*e= (ExprState*)lfirst(arg);
563-
char*argname=strVal(lfirst(narg));
563+
Datumvalue;
564+
boolisnull;
565+
char*str;
564566

565567
value=ExecEvalExpr(e,econtext,&isnull,NULL);
566-
if (!isnull)
567-
{
568+
if (isnull)
569+
str=NULL;
570+
else
568571
str=OutputFunctionCall(&xmlExpr->named_outfuncs[i],value);
569-
xmlTextWriterWriteAttribute(writer, (xmlChar*)argname, (xmlChar*)str);
570-
pfree(str);
571-
}
572+
named_arg_strings=lappend(named_arg_strings,str);
572573
i++;
573574
}
574575

576+
arg_strings=NIL;
575577
foreach(arg,xmlExpr->args)
576578
{
577579
ExprState*e= (ExprState*)lfirst(arg);
580+
Datumvalue;
581+
boolisnull;
582+
char*str;
578583

579584
value=ExecEvalExpr(e,econtext,&isnull,NULL);
585+
/* here we can just forget NULL elements immediately */
580586
if (!isnull)
581-
xmlTextWriterWriteRaw(writer, (xmlChar*)map_sql_value_to_xml_value(value,exprType((Node*)e->expr)));
587+
{
588+
str=map_sql_value_to_xml_value(value,
589+
exprType((Node*)e->expr));
590+
arg_strings=lappend(arg_strings,str);
591+
}
592+
}
593+
594+
/* now safe to run libxml */
595+
xml_init();
596+
597+
buf=xmlBufferCreate();
598+
writer=xmlNewTextWriterMemory(buf,0);
599+
600+
xmlTextWriterStartElement(writer, (xmlChar*)xexpr->name);
601+
602+
forboth(arg,named_arg_strings,narg,xexpr->arg_names)
603+
{
604+
char*str= (char*)lfirst(arg);
605+
char*argname=strVal(lfirst(narg));
606+
607+
if (str)
608+
{
609+
xmlTextWriterWriteAttribute(writer,
610+
(xmlChar*)argname,
611+
(xmlChar*)str);
612+
pfree(str);
613+
}
614+
}
615+
616+
foreach(arg,arg_strings)
617+
{
618+
char*str= (char*)lfirst(arg);
619+
620+
xmlTextWriterWriteRaw(writer, (xmlChar*)str);
582621
}
583622

584623
xmlTextWriterEndElement(writer);
585624
xmlFreeTextWriter(writer);
586625

587626
result=xmlBuffer_to_xmltype(buf);
588627
xmlBufferFree(buf);
628+
589629
returnresult;
590630
#else
591631
NO_XML_SUPPORT();
@@ -733,9 +773,10 @@ xmlvalidate(PG_FUNCTION_ARGS)
733773

734774
xml_init();
735775

736-
/* We use a PG_TRY block to ensure libxml is cleaned up on error */
776+
/* We use a PG_TRY block to ensure libxmlparseris cleaned up on error */
737777
PG_TRY();
738778
{
779+
xmlInitParser();
739780
ctxt=xmlNewParserCtxt();
740781
if (ctxt==NULL)
741782
xml_ereport(ERROR,ERRCODE_INTERNAL_ERROR,
@@ -860,43 +901,64 @@ xml_is_document(xmltype *arg)
860901
#ifdefUSE_LIBXML
861902

862903
/*
863-
* Container for some init stuff (not good design!)
864-
* TODO xmlChar is utf8-char, make proper tuning (initdb with enc!=utf8 and check)
904+
* Set up for use of libxml --- this should be called by each function that
905+
* is about to use libxml facilities.
906+
*
907+
* TODO: xmlChar is utf8-char, make proper tuning (initdb with enc!=utf8 and
908+
* check)
865909
*/
866910
staticvoid
867911
xml_init(void)
868912
{
869-
/*
870-
* Currently, we have no pure UTF-8 support for internals -- check
871-
* if we can work.
872-
*/
873-
if (sizeof (char)!=sizeof (xmlChar))
874-
ereport(ERROR,
875-
(errmsg("could not initialize XML library"),
876-
errdetail("libxml2 has incompatible char type: sizeof(char)=%u, sizeof(xmlChar)=%u.",
877-
(int)sizeof(char), (int)sizeof(xmlChar))));
913+
staticboolfirst_time= true;
878914

879-
if (xml_err_buf==NULL)
915+
if (first_time)
880916
{
881-
/*First time through: create error buffer in permanent context */
917+
/*Stuff we need do only once per session */
882918
MemoryContextoldcontext;
883919

920+
/*
921+
* Currently, we have no pure UTF-8 support for internals -- check
922+
* if we can work.
923+
*/
924+
if (sizeof(char)!=sizeof(xmlChar))
925+
ereport(ERROR,
926+
(errmsg("could not initialize XML library"),
927+
errdetail("libxml2 has incompatible char type: sizeof(char)=%u, sizeof(xmlChar)=%u.",
928+
(int)sizeof(char), (int)sizeof(xmlChar))));
929+
930+
/* create error buffer in permanent context */
884931
oldcontext=MemoryContextSwitchTo(TopMemoryContext);
885932
xml_err_buf=makeStringInfo();
886933
MemoryContextSwitchTo(oldcontext);
934+
935+
/* Now that xml_err_buf exists, safe to call xml_errorHandler */
936+
xmlSetGenericErrorFunc(NULL,xml_errorHandler);
937+
938+
/* Set up memory allocation our way, too */
939+
xmlMemSetup(xml_pfree,xml_palloc,xml_repalloc,xml_pstrdup);
940+
941+
/* Check library compatibility */
942+
LIBXML_TEST_VERSION;
943+
944+
first_time= false;
887945
}
888946
else
889947
{
890948
/* Reset pre-existing buffer to empty */
949+
Assert(xml_err_buf!=NULL);
891950
resetStringInfo(xml_err_buf);
892-
}
893-
/* Now that xml_err_buf exists, safe to call xml_errorHandler */
894-
xmlSetGenericErrorFunc(NULL,xml_errorHandler);
895-
896-
xmlMemSetup(xml_pfree,xml_palloc,xml_repalloc,xml_pstrdup);
897951

898-
xmlInitParser();
899-
LIBXML_TEST_VERSION;
952+
/*
953+
* We re-establish the callback functions every time. This makes it
954+
* safe for other subsystems (PL/Perl, say) to also use libxml with
955+
* their own callbacks ... so long as they likewise set up the
956+
* callbacks on every use. It's cheap enough to not be worth
957+
* worrying about, anyway.
958+
*/
959+
xmlSetGenericErrorFunc(NULL,xml_errorHandler);
960+
xmlMemSetup(xml_pfree,xml_palloc,xml_repalloc,xml_pstrdup);
961+
}
900962
}
901963

902964

@@ -1071,9 +1133,10 @@ print_xml_decl(StringInfo buf, const xmlChar *version, pg_enc encoding, int stan
10711133
appendStringInfo(buf," version=\"%s\"",PG_XML_DEFAULT_VERSION);
10721134

10731135
if (encoding&&encoding!=PG_UTF8)
1074-
/* XXX might be useful to convert this to IANA names
1075-
* (ISO-8859-1 instead of LATIN1 etc.); needs field
1076-
* experience */
1136+
/*
1137+
* XXX might be useful to convert this to IANA names
1138+
* (ISO-8859-1 instead of LATIN1 etc.); needs field experience
1139+
*/
10771140
appendStringInfo(buf," encoding=\"%s\"",pg_encoding_to_char(encoding));
10781141

10791142
if (standalone==1)
@@ -1115,9 +1178,10 @@ xml_parse(text *data, XmlOptionType xmloption_arg, bool preserve_whitespace, xml
11151178

11161179
xml_init();
11171180

1118-
/* We use a PG_TRY block to ensure libxml is cleaned up on error */
1181+
/* We use a PG_TRY block to ensure libxmlparseris cleaned up on error */
11191182
PG_TRY();
11201183
{
1184+
xmlInitParser();
11211185
ctxt=xmlNewParserCtxt();
11221186
if (ctxt==NULL)
11231187
xml_ereport(ERROR,ERRCODE_INTERNAL_ERROR,
@@ -1780,7 +1844,7 @@ schema_get_xml_visible_tables(Oid nspid)
17801844
StringInfoDataquery;
17811845

17821846
initStringInfo(&query);
1783-
appendStringInfo(&query,"SELECT oid FROM pg_class WHERE relnamespace = %u AND relkind IN ('r', 'v') AND has_table_privilege (oid, 'SELECT') ORDER BY relname;",nspid);
1847+
appendStringInfo(&query,"SELECT oid FROMpg_catalog.pg_class WHERE relnamespace = %u AND relkind IN ('r', 'v') ANDpg_catalog.has_table_privilege (oid, 'SELECT') ORDER BY relname;",nspid);
17841848

17851849
returnquery_to_oid_list(query.data);
17861850
}
@@ -1792,7 +1856,7 @@ schema_get_xml_visible_tables(Oid nspid)
17921856
*/
17931857
#defineXML_VISIBLE_SCHEMAS_EXCLUDE "nspname LIKE 'pg_%' ESCAPE '' OR nspname = 'information_schema'"
17941858

1795-
#defineXML_VISIBLE_SCHEMAS "SELECT oid FROM pg_namespace WHERE has_schema_privilege (oid, 'USAGE') AND NOT (" XML_VISIBLE_SCHEMAS_EXCLUDE ")"
1859+
#defineXML_VISIBLE_SCHEMAS "SELECT oid FROMpg_catalog.pg_namespace WHEREpg_catalog.has_schema_privilege (oid, 'USAGE') AND NOT (" XML_VISIBLE_SCHEMAS_EXCLUDE ")"
17961860

17971861

17981862
staticList*
@@ -1806,7 +1870,7 @@ static List *
18061870
database_get_xml_visible_tables(void)
18071871
{
18081872
/* At the moment there is no order required here. */
1809-
returnquery_to_oid_list("SELECT oid FROM pg_class WHERE relkind IN ('r', 'v') AND has_table_privilege (pg_class.oid, 'SELECT') AND relnamespace IN ("XML_VISIBLE_SCHEMAS");");
1873+
returnquery_to_oid_list("SELECT oid FROMpg_catalog.pg_class WHERE relkind IN ('r', 'v') ANDpg_catalog.has_table_privilege (pg_class.oid, 'SELECT') AND relnamespace IN ("XML_VISIBLE_SCHEMAS");");
18101874
}
18111875

18121876

@@ -2973,7 +3037,6 @@ SPI_sql_row_to_xmlelement(int rownum, StringInfo result, char *tablename, bool n
29733037
{
29743038
if (nulls)
29753039
appendStringInfo(result," <%s xsi:nil='true'/>\n",colname);
2976-
29773040
}
29783041
else
29793042
appendStringInfo(result," <%s>%s</%s>\n",
@@ -3170,10 +3233,12 @@ xpath(PG_FUNCTION_ARGS)
31703233

31713234
xml_init();
31723235

3236+
/* We use a PG_TRY block to ensure libxml parser is cleaned up on error */
31733237
PG_TRY();
31743238
{
3239+
xmlInitParser();
31753240
/*
3176-
* redundant XML parsing (two parsings for the same value *
3241+
* redundant XML parsing (two parsings for the same value
31773242
* during one command execution are possible)
31783243
*/
31793244
ctxt=xmlNewParserCtxt();

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp