pá 8. 3. 2019 v 7:41 odesílatel Pavel Stehule <pavel.steh...@gmail.com>
napsal:

> Hi
>
> pá 8. 3. 2019 v 3:44 odesílatel Alvaro Herrera <alvhe...@2ndquadrant.com>
> napsal:
>
>> On 2019-Mar-07, Alvaro Herrera wrote:
>>
>> > On 2019-Feb-11, Chapman Flack wrote:
>> >
>> > > xmltable-xpath-result-processing-bugfix-6.patch includes a
>> regress/expected
>> > > output for the no-libxml case that was left out of -5.
>> >
>> > Pushed this one, with some trivial changes: I renamed and relocated
>> > Pavel's function to strdup-and-free and fused the new test cases to use
>> > less queries for the same functionality.  Naturally I had to adjust the
>> > expected files ... I tried to do my best but there's always a little
>> > something that sneaks under one's nose.
>>
>> So we now have a double-free bug here or something ...  Too tired right
>> now to do anything about it.
>>
>>
>> https://buildfarm.postgresql.org/cgi-bin/show_log.pl?nm=grison&dt=2019-03-08%2002%3A00%3A02
>>
>> ================== stack trace:
>> pgsql.build/src/test/regress/tmp_check/data/core ==================
>> [New LWP 20275]
>>
>> warning: Can't read pathname for load map: Input/output error.
>> [Thread debugging using libthread_db enabled]
>> Using host libthread_db library
>> "/lib/arm-linux-gnueabihf/libthread_db.so.1".
>> Core was generated by `postgres: pgbuildfarm regression [local] SELECT
>>                            '.
>> Program terminated with signal 11, Segmentation fault.
>> #0  0x76a32e04 in free () from /lib/arm-linux-gnueabihf/libc.so.6
>> #0  0x76a32e04 in free () from /lib/arm-linux-gnueabihf/libc.so.6
>> #1  0x76e28380 in xmlFreeNode () from
>> /usr/lib/arm-linux-gnueabihf/libxml2.so.2
>> #2  0x00481f94 in xml_xmlnodetoxmltype (cur=<optimized out>,
>> xmlerrcxt=<optimized out>) at xml.c:3751
>> #3  0x004823dc in XmlTableGetValue (state=0x148c370, colnum=1994818404,
>> typid=2124685192, typmod=0, isnull=0x7ea42117) at xml.c:4540
>> #4  0x0026df60 in tfuncLoadRows (econtext=0x2, tstate=0x14a8578) at
>> nodeTableFuncscan.c:489
>> #5  tfuncFetchRows (tstate=0x14a8578, econtext=0x2) at
>> nodeTableFuncscan.c:318
>> #6  0x0026e248 in TableFuncNext (node=0x14a83e0) at nodeTableFuncscan.c:65
>> #7  0x0023e640 in ExecScanFetch (recheckMtd=0x23e640 <ExecScan+816>,
>> accessMtd=0x26db1c <TableFuncRecheck>, node=0x14a83e0) at execScan.c:93
>> #8  ExecScan (node=0x14a83e0, accessMtd=0x26db1c <TableFuncRecheck>,
>> recheckMtd=0x23e640 <ExecScan+816>) at execScan.c:143
>> #9  0x0023c638 in ExecProcNodeFirst (node=0x14a83e0) at execProcnode.c:445
>> #10 0x00235630 in ExecProcNode (node=0x14a83e0) at
>> ../../../src/include/executor/executor.h:241
>> #11 ExecutePlan (execute_once=<optimized out>, dest=0x14b8d08,
>> direction=<optimized out>, numberTuples=0, sendTuples=<optimized out>,
>> operation=CMD_SELECT, use_parallel_mode=<optimized out>,
>> planstate=0x14a83e0, estate=0x14a82a0) at execMain.c:1643
>> #12 standard_ExecutorRun (queryDesc=0x142c0e0, direction=<optimized out>,
>> count=0, execute_once=true) at execMain.c:362
>> #13 0x003955f4 in PortalRunSelect (portal=0x13e3f48, forward=<optimized
>> out>, count=0, dest=<optimized out>) at pquery.c:929
>> #14 0x00396a0c in PortalRun (portal=0x0, count=0, isTopLevel=<optimized
>> out>, run_once=<optimized out>, dest=0x14b8d08, altdest=0x14b8d08,
>> completionTag=0x7ea42414 "") at pquery.c:770
>> #15 0x003923c8 in exec_simple_query (query_string=0x7ea42414 "") at
>> postgres.c:1215
>> #16 0x00393e8c in PostgresMain (argc=<optimized out>, argv=<optimized
>> out>, dbname=0x0, username=<optimized out>) at postgres.c:4256
>> #17 0x000849a8 in BackendRun (port=0x13967b8) at postmaster.c:4399
>> #18 BackendStartup (port=0x13967b8) at postmaster.c:4090
>> #19 ServerLoop () at postmaster.c:1703
>> #20 0x0031607c in PostmasterMain (argc=<optimized out>, argv=<optimized
>> out>) at postmaster.c:1376
>> #21 0x000864d4 in main (argc=7301080, argv=0x8) at main.c:228
>>
>
>
looks like error in xmlXPathCompiledEval function, that produce little bit
broken result for XML_DOCUMENT_NODE type. I hadn't this problem with
libxml2 2.7.6 64bit, but I seen this issue on same version on 32bit.

Currently I had not fresh 32 bit system to check it.

I found a workaround - in this case copy (and release xmlNode) is not
necessary.

please, apply attached patch.


> Pavel
>
>
>>
>> --
>> Álvaro Herrera                https://www.2ndQuadrant.com/
>> PostgreSQL Development, 24x7 Support, Remote DBA, Training & Services
>>
>
diff --git a/src/backend/utils/adt/xml.c b/src/backend/utils/adt/xml.c
index 28b3eaaa20..41145e697a 100644
--- a/src/backend/utils/adt/xml.c
+++ b/src/backend/utils/adt/xml.c
@@ -3720,35 +3720,58 @@ xml_xmlnodetoxmltype(xmlNodePtr cur, PgXmlErrorContext *xmlerrcxt)
 
 	if (cur->type != XML_ATTRIBUTE_NODE && cur->type != XML_TEXT_NODE)
 	{
-		xmlBufferPtr buf;
-		xmlNodePtr	cur_copy;
+		volatile xmlBufferPtr buf = NULL;
+		volatile xmlNodePtr	cur_copy = NULL;
 
-		buf = xmlBufferCreate();
+		PG_TRY();
+		{
+			int		bytes;
 
-		/*
-		 * The result of xmlNodeDump() won't contain namespace definitions
-		 * from parent nodes, but xmlCopyNode() duplicates a node along with
-		 * its required namespace definitions.
-		 */
-		cur_copy = xmlCopyNode(cur, 1);
+			buf = xmlBufferCreate();
 
-		if (cur_copy == NULL)
-			xml_ereport(xmlerrcxt, ERROR, ERRCODE_OUT_OF_MEMORY,
-						"could not copy node");
+			if (buf == NULL || xmlerrcxt->err_occurred)
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_OUT_OF_MEMORY,
+							"could not allocate xmlBuffer");
+
+			/*
+			 * The result of xmlNodeDump() won't contain namespace definitions
+			 * from parent nodes, but xmlCopyNode() duplicates a node along with
+			 * its required namespace definitions.
+			 *
+			 * Some older libxml2 like 2.7.6 produces partialy broken
+			 * XML_DOCUMENT_NODE nodes (unset content field). The copy of this node
+			 * is ok, but xmlFreeNode fails. Fortunately, XML_DOCUMENT_NODE should
+			 * not to have parent nodes, and we don't need to use xmlCopyNode.
+			 */
+			if (cur->type != XML_DOCUMENT_NODE)
+			{
+				cur_copy = xmlCopyNode(cur, 1);
+				if (cur == NULL || xmlerrcxt->err_occurred)
+					xml_ereport(xmlerrcxt, ERROR, ERRCODE_OUT_OF_MEMORY,
+								"could not copy node");
+			}
+			else
+				cur_copy = cur;
+
+			bytes = xmlNodeDump(buf, NULL, cur_copy, 0, 1);
+			if (bytes == -1 || xmlerrcxt->err_occurred)
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_OUT_OF_MEMORY,
+							"could not dump node");
 
-		PG_TRY();
-		{
-			xmlNodeDump(buf, NULL, cur_copy, 0, 1);
 			result = xmlBuffer_to_xmltype(buf);
 		}
 		PG_CATCH();
 		{
-			xmlFreeNode(cur_copy);
-			xmlBufferFree(buf);
+			if (cur_copy && cur_copy != cur)
+				xmlFreeNode(cur_copy);
+			if (buf)
+				xmlBufferFree(buf);
 			PG_RE_THROW();
 		}
 		PG_END_TRY();
-		xmlFreeNode(cur_copy);
+
+		if (cur_copy != cur)
+			xmlFreeNode(cur_copy);
 		xmlBufferFree(buf);
 	}
 	else

Reply via email to