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
>

I have not any hypotheses what is reason - maybe we hit some libxml2 error
in xmlCopyNode function - now it is called for larger set of node types.

What I see, a error handling in original code was not probably correct.
Hard to say if attached patch fix it, but probably it is more correct than
now.

Regards

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..173784da4b 100644
--- a/src/backend/utils/adt/xml.c
+++ b/src/backend/utils/adt/xml.c
@@ -3720,31 +3720,42 @@ 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.
+			 */
+			cur_copy = xmlCopyNode(cur, 1);
+			if (cur == NULL || xmlerrcxt->err_occurred)
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_OUT_OF_MEMORY,
+							"could not copy node");
+
+			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)
+				xmlFreeNode(cur_copy);
+			if (buf)
+				xmlBufferFree(buf);
 			PG_RE_THROW();
 		}
 		PG_END_TRY();

Reply via email to