Received: from malur.postgresql.org ([217.196.149.56]) by arkaria.postgresql.org with esmtps (TLS1.3) tls TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 (Exim 4.94.2) (envelope-from ) id 1uO5dZ-00EoZ3-JA for pgsql-bugs@arkaria.postgresql.org; Sun, 08 Jun 2025 02:19:54 +0000 Received: from localhost ([127.0.0.1] helo=malur.postgresql.org) by malur.postgresql.org with esmtp (Exim 4.94.2) (envelope-from ) id 1uO5dX-00GGVR-B1 for pgsql-bugs@arkaria.postgresql.org; Sun, 08 Jun 2025 02:19:51 +0000 Received: from makus.postgresql.org ([2001:4800:3e1:1::229]) by malur.postgresql.org with esmtps (TLS1.3) tls TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 (Exim 4.94.2) (envelope-from ) id 1uO5dW-00GGVJ-DJ for pgsql-bugs@lists.postgresql.org; Sun, 08 Jun 2025 02:19:51 +0000 Received: from fhigh-a2-smtp.messagingengine.com ([103.168.172.153]) by makus.postgresql.org with esmtps (TLS1.3) tls TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 (Exim 4.96) (envelope-from ) id 1uO5dU-000q7f-1F for pgsql-bugs@lists.postgresql.org; Sun, 08 Jun 2025 02:19:50 +0000 Received: from phl-compute-05.internal (phl-compute-05.phl.internal [10.202.2.45]) by mailfhigh.phl.internal (Postfix) with ESMTP id 01A8511400F5; Sat, 7 Jun 2025 22:19:47 -0400 (EDT) Received: from phl-mailfrontend-02 ([10.202.2.163]) by phl-compute-05.internal (MEProxy); Sat, 07 Jun 2025 22:19:47 -0400 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=paquier.xyz; h= cc:cc:content-type:content-type:date:date:from:from:in-reply-to :in-reply-to:message-id:mime-version:references:reply-to:subject :subject:to:to; s=fm1; t=1749349186; x=1749435586; bh=5zlsL+oVsr KsXxvL3Dj/hWryMpqY2uLO+a8qb5Jgug0=; b=ostKKX7ulNGlhOxjQwTspn74X6 /6ST4dVnmurwYgAo3JFMQJZOx45CZEPeo6Mh8xrKSm1NDU6mulkjj/gl9i8ioFD4 +gYvASKPpWbtgQ6qTXLkbwn50wcNVgFFKf7xy9wesnqgIr/A3YMPgmi7XfYnhPfH eaMm3x8AwewVmFJ1Nl7HjUotwfYMrIpvX51Ex6Fn339sh1DfsKUOAuUJgOuInAQN bOdHgpCVdBublQdIoOoRBdsJewN6ZRdp+ThODjRxkwcEXfKj0yMIyZ0Irz3Ej6oS zaQrKDwCjES0PCBk7uhVNHMfZ/8sg0WNGQYv+s5WoU0h6iY+cq6rBO//Ncgg== DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d= messagingengine.com; h=cc:cc:content-type:content-type:date:date :feedback-id:feedback-id:from:from:in-reply-to:in-reply-to :message-id:mime-version:references:reply-to:subject:subject:to :to:x-me-proxy:x-me-sender:x-me-sender:x-sasl-enc; s=fm1; t= 1749349186; x=1749435586; bh=5zlsL+oVsrKsXxvL3Dj/hWryMpqY2uLO+a8 qb5Jgug0=; b=poxSXjCrzrK5yFn804Y1+cZs1E8ZbIoafLs+hON9uUFyDZ3tQpc qgDpHGJgXhqiW2ZzD9b+Tp5rRHzU0mEDZdY3/AwBk6HiKtyZCRKYPGLdNaFTCe/c dxUcXfywAi8Px+XWTHnuBL5W/5IUbH6TqoJUYyUJQuLS2f+6HMX36UhxM9bSjMWW mOXWmmE4AjgzYeyIErJp+FK/s0vHfK0u0jgjcVO3JOPCimI/2ye6LXpoRSdlOdEH Ia8fCEF53Z4msnZfWw5XX4TicliTAHjPdZnFqLL5XeX4e2vRvgmJ5m6Kg8sfHAEK oYzTntsWLDg/i0EnIWBSoU0XvPg3Y38nRoQ== X-ME-Sender: X-ME-Received: X-ME-Proxy-Cause: gggruggvucftvghtrhhoucdtuddrgeeffedrtddugdejfeeiucetufdoteggodetrfdotf fvucfrrhhofhhilhgvmecuhfgrshhtofgrihhlpdggtfgfnhhsuhgsshgtrhhisggvpdfu rfetoffkrfgpnffqhgenuceurghilhhouhhtmecufedttdenucesvcftvggtihhpihgvnh htshculddquddttddmnegfrhhlucfvnfffucdljedtmdenucfjughrpeffhffvvefukfhf gggtuggjsehgtderredttddvnecuhfhrohhmpefoihgthhgrvghlucfrrghquhhivghruc eomhhitghhrggvlhesphgrqhhuihgvrhdrgiihiieqnecuggftrfgrthhtvghrnhepteel ieefudffhffhtdetleeggeegfffhkeeuveetiefgudduvedutefggeeivdejnecuvehluh hsthgvrhfuihiivgeptdenucfrrghrrghmpehmrghilhhfrhhomhepmhhitghhrggvlhes phgrqhhuihgvrhdrgiihiidpnhgspghrtghpthhtohepgedpmhhouggvpehsmhhtphhouh htpdhrtghpthhtohepjhhimhdrjhhonhgvshesuhhnihdqmhhuvghnshhtvghrrdguvgdp rhgtphhtthhopehtghhlsehsshhsrdhpghhhrdhprgdruhhspdhrtghpthhtohepphhgsh hqlhdqsghughhssehlihhsthhsrdhpohhsthhgrhgvshhqlhdrohhrghdprhgtphhtthho pehmrghrrghlihhsthekieesmhgrihhlrdhruh X-ME-Proxy: Feedback-ID: i0fe9450f:Fastmail Received: by mail.messagingengine.com (Postfix) with ESMTPA; Sat, 7 Jun 2025 22:19:42 -0400 (EDT) Date: Sun, 8 Jun 2025 11:19:29 +0900 From: Michael Paquier To: Jim Jones Cc: Tom Lane , pgsql-bugs@lists.postgresql.org, maralist86@mail.ru Subject: Re: BUG #18943: Return value of a function 'xmlBufferCreate' is dereferenced at xpath.c:177 without checking for NUL Message-ID: References: <18943-2f2a04ab03904598@postgresql.org> <861593.1748970933@sss.pgh.pa.us> <31f3480e-cd7d-4021-b392-87922572cc37@uni-muenster.de> MIME-Version: 1.0 Content-Type: multipart/signed; micalg=pgp-sha512; protocol="application/pgp-signature"; boundary="SWTAmUvGf4/QaEo1" Content-Disposition: inline In-Reply-To: <31f3480e-cd7d-4021-b392-87922572cc37@uni-muenster.de> List-Id: List-Help: List-Subscribe: List-Post: List-Owner: List-Archive: Archived-At: Precedence: bulk --SWTAmUvGf4/QaEo1 Content-Type: multipart/mixed; boundary="UFYgHWu+bSQKqEbN" Content-Disposition: inline --UFYgHWu+bSQKqEbN Content-Type: text/plain; charset=us-ascii Content-Disposition: inline Content-Transfer-Encoding: quoted-printable On Fri, Jun 06, 2025 at 12:22:30PM +0200, Jim Jones wrote: > So, perhaps this? >=20 > if (xmlAddChildList(root, content_nodes) =3D=3D NULL || > xmlerrcxt->err_occurred) > xml_ereport(xmlerrcxt, > ERROR, ERRCODE_OUT_OF_MEMORY, > "could not add content nodes to root element"); ERRCODE_INTERNAL_ERROR would be more adapted, I'm only seeing error code paths caused by inconsistencies in the nodes. I have updated the patches with the attached, splitting the parts for contrib/xml2/ and the backend into two parts. These touch error paths that are very unlikely going to be hit in practice, so let's do all that once v19 opens for business only on HEAD. -- Michael --UFYgHWu+bSQKqEbN Content-Type: text/x-diff; charset=us-ascii Content-Disposition: attachment; filename="v4-0001-Improve-error-handling-with-calls-to-libxml2.patch" Content-Transfer-Encoding: quoted-printable =46rom 2513b80e18c2fe283faa24f541f9fb1ed799a335 Mon Sep 17 00:00:00 2001 =46rom: Michael Paquier Date: Sun, 8 Jun 2025 11:16:52 +0900 Subject: [PATCH v4 1/2] Improve error handling with calls to libxml2 This handles improvements in the backend code. --- src/backend/utils/adt/xml.c | 78 +++++++++++++++++++++++++++++-------- 1 file changed, 62 insertions(+), 16 deletions(-) diff --git a/src/backend/utils/adt/xml.c b/src/backend/utils/adt/xml.c index a4150bff2eae..2bd39b6ac4b0 100644 --- a/src/backend/utils/adt/xml.c +++ b/src/backend/utils/adt/xml.c @@ -529,14 +529,36 @@ xmltext(PG_FUNCTION_ARGS) #ifdef USE_LIBXML text *arg =3D PG_GETARG_TEXT_PP(0); text *result; - xmlChar *xmlbuf =3D NULL; + volatile xmlChar *xmlbuf =3D NULL; + PgXmlErrorContext *xmlerrcxt; =20 - xmlbuf =3D xmlEncodeSpecialChars(NULL, xml_text2xmlChar(arg)); + /* Otherwise, we gotta spin up some error handling. */ + xmlerrcxt =3D pg_xml_init(PG_XML_STRICTNESS_ALL); =20 - Assert(xmlbuf); + PG_TRY(); + { + xmlbuf =3D xmlEncodeSpecialChars(NULL, xml_text2xmlChar(arg)); + + if (xmlbuf =3D=3D NULL || xmlerrcxt->err_occurred) + xml_ereport(xmlerrcxt, ERROR, ERRCODE_OUT_OF_MEMORY, + "could not allocate xmlChar"); + + result =3D cstring_to_text_with_len((const char *) xmlbuf, + xmlStrlen((const xmlChar *) xmlbuf)); + } + PG_CATCH(); + { + if (xmlbuf) + xmlFree((xmlChar *) xmlbuf); + + pg_xml_done(xmlerrcxt, true); + PG_RE_THROW(); + } + PG_END_TRY(); + + xmlFree((xmlChar *) xmlbuf); + pg_xml_done(xmlerrcxt, false); =20 - result =3D cstring_to_text_with_len((const char *) xmlbuf, xmlStrlen(xmlb= uf)); - xmlFree(xmlbuf); PG_RETURN_XML_P(result); #else NO_XML_SUPPORT(); @@ -770,7 +792,10 @@ xmltotext_with_options(xmltype *data, XmlOptionType xm= loption_arg, bool indent) if (oldroot !=3D NULL) xmlFreeNode(oldroot); =20 - xmlAddChildList(root, content_nodes); + if (xmlAddChildList(root, content_nodes) =3D=3D NULL || + xmlerrcxt->err_occurred) + xml_ereport(xmlerrcxt, ERROR, ERRCODE_INTERNAL_ERROR, + "could not append xml node list"); =20 /* * We use this node to insert newlines in the dump. Note: in at @@ -931,7 +956,10 @@ xmlelement(XmlExpr *xexpr, xml_ereport(xmlerrcxt, ERROR, ERRCODE_OUT_OF_MEMORY, "could not allocate xmlTextWriter"); =20 - xmlTextWriterStartElement(writer, (xmlChar *) xexpr->name); + if (xmlTextWriterStartElement(writer, (xmlChar *) xexpr->name) < 0 || + xmlerrcxt->err_occurred) + xml_ereport(xmlerrcxt, ERROR, ERRCODE_INTERNAL_ERROR, + "could not start xml element"); =20 forboth(arg, named_arg_strings, narg, xexpr->arg_names) { @@ -939,19 +967,30 @@ xmlelement(XmlExpr *xexpr, char *argname =3D strVal(lfirst(narg)); =20 if (str) - xmlTextWriterWriteAttribute(writer, - (xmlChar *) argname, - (xmlChar *) str); + { + if (xmlTextWriterWriteAttribute(writer, + (xmlChar *) argname, + (xmlChar *) str) < 0 || + xmlerrcxt->err_occurred) + xml_ereport(xmlerrcxt, ERROR, ERRCODE_INTERNAL_ERROR, + "could not write xml attribute"); + } } =20 foreach(arg, arg_strings) { char *str =3D (char *) lfirst(arg); =20 - xmlTextWriterWriteRaw(writer, (xmlChar *) str); + if (xmlTextWriterWriteRaw(writer, (xmlChar *) str) < 0 || + xmlerrcxt->err_occurred) + xml_ereport(xmlerrcxt, ERROR, ERRCODE_INTERNAL_ERROR, + "could not write raw xml text"); } =20 - xmlTextWriterEndElement(writer); + if (xmlTextWriterEndElement(writer) < 0 || + xmlerrcxt->err_occurred) + xml_ereport(xmlerrcxt, ERROR, ERRCODE_INTERNAL_ERROR, + "could not end xml element"); =20 /* we MUST do this now to flush data out to the buffer ... */ xmlFreeTextWriter(writer); @@ -4220,20 +4259,27 @@ xml_xmlnodetoxmltype(xmlNodePtr cur, PgXmlErrorCont= ext *xmlerrcxt) } else { - xmlChar *str; + volatile xmlChar *str =3D NULL; =20 - str =3D xmlXPathCastNodeToString(cur); PG_TRY(); { + char *escaped; + + str =3D xmlXPathCastNodeToString(cur); + if (str =3D=3D NULL || xmlerrcxt->err_occurred) + xml_ereport(xmlerrcxt, ERROR, ERRCODE_OUT_OF_MEMORY, + "could not allocate xmlChar"); + /* Here we rely on XML having the same representation as TEXT */ - char *escaped =3D escape_xml((char *) str); + escaped =3D escape_xml((char *) str); =20 result =3D (xmltype *) cstring_to_text(escaped); pfree(escaped); } PG_FINALLY(); { - xmlFree(str); + if (str) + xmlFree((xmlChar *) str); } PG_END_TRY(); } --=20 2.49.0 --UFYgHWu+bSQKqEbN Content-Type: text/x-diff; charset=us-ascii Content-Disposition: attachment; filename="v4-0002-xml2-Improve-error-handling-in-corner-cases.patch" Content-Transfer-Encoding: quoted-printable =46rom a23b3707368a4db2cce53d219b7adf639d7003a5 Mon Sep 17 00:00:00 2001 =46rom: Michael Paquier Date: Sun, 8 Jun 2025 11:17:18 +0900 Subject: [PATCH v4 2/2] xml2: Improve error handling in corner cases --- contrib/xml2/xpath.c | 418 ++++++++++++++++++++++++++------------- contrib/xml2/xslt_proc.c | 26 +-- 2 files changed, 294 insertions(+), 150 deletions(-) diff --git a/contrib/xml2/xpath.c b/contrib/xml2/xpath.c index 23d3f332dbaa..9345a6c2d08f 100644 --- a/contrib/xml2/xpath.c +++ b/contrib/xml2/xpath.c @@ -51,10 +51,10 @@ static text *pgxml_result_to_text(xmlXPathObjectPtr res= , xmlChar *toptag, =20 static xmlChar *pgxml_texttoxmlchar(text *textstring); =20 -static xmlXPathObjectPtr pgxml_xpath(text *document, xmlChar *xpath, - xpath_workspace *workspace); +static xpath_workspace *pgxml_xpath(text *document, xmlChar *xpath, + PgXmlErrorContext *xmlerrcxt); =20 -static void cleanup_workspace(xpath_workspace *workspace); +static void cleanup_workspace(volatile xpath_workspace *workspace); =20 =20 /* @@ -89,18 +89,40 @@ xml_encode_special_chars(PG_FUNCTION_ARGS) { text *tin =3D PG_GETARG_TEXT_PP(0); text *tout; - xmlChar *ts, - *tt; + volatile xmlChar *tt =3D NULL; + PgXmlErrorContext *xmlerrcxt; =20 - ts =3D pgxml_texttoxmlchar(tin); + xmlerrcxt =3D pg_xml_init(PG_XML_STRICTNESS_ALL); =20 - tt =3D xmlEncodeSpecialChars(NULL, ts); + PG_TRY(); + { + xmlChar *ts; =20 - pfree(ts); + ts =3D pgxml_texttoxmlchar(tin); =20 - tout =3D cstring_to_text((char *) tt); + tt =3D xmlEncodeSpecialChars(NULL, ts); + if (tt =3D=3D NULL || pg_xml_error_occurred(xmlerrcxt)) + xml_ereport(xmlerrcxt, ERROR, ERRCODE_OUT_OF_MEMORY, + "could not allocate xmlChar"); + pfree(ts); =20 - xmlFree(tt); + tout =3D cstring_to_text((char *) tt); + } + PG_CATCH(); + { + if (tt !=3D NULL) + xmlFree((xmlChar *) tt); + + pg_xml_done(xmlerrcxt, true); + + PG_RE_THROW(); + } + PG_END_TRY(); + + if (tt !=3D NULL) + xmlFree((xmlChar *) tt); + + pg_xml_done(xmlerrcxt, false); =20 PG_RETURN_TEXT_P(tout); } @@ -122,62 +144,90 @@ pgxmlNodeSetToText(xmlNodeSetPtr nodeset, xmlChar *septagname, xmlChar *plainsep) { - xmlBufferPtr buf; + volatile xmlBufferPtr buf =3D NULL; xmlChar *result; int i; + PgXmlErrorContext *xmlerrcxt; =20 - buf =3D xmlBufferCreate(); + /* spin some error handling */ + xmlerrcxt =3D pg_xml_init(PG_XML_STRICTNESS_ALL); =20 - if ((toptagname !=3D NULL) && (xmlStrlen(toptagname) > 0)) + PG_TRY(); { - xmlBufferWriteChar(buf, "<"); - xmlBufferWriteCHAR(buf, toptagname); - xmlBufferWriteChar(buf, ">"); - } - if (nodeset !=3D NULL) - { - for (i =3D 0; i < nodeset->nodeNr; i++) + buf =3D xmlBufferCreate(); + + if (buf =3D=3D NULL || pg_xml_error_occurred(xmlerrcxt)) + xml_ereport(xmlerrcxt, ERROR, ERRCODE_OUT_OF_MEMORY, + "could not allocate xmlBuffer"); + + if ((toptagname !=3D NULL) && (xmlStrlen(toptagname) > 0)) { - if (plainsep !=3D NULL) + xmlBufferWriteChar(buf, "<"); + xmlBufferWriteCHAR(buf, toptagname); + xmlBufferWriteChar(buf, ">"); + } + if (nodeset !=3D NULL) + { + for (i =3D 0; i < nodeset->nodeNr; i++) { - xmlBufferWriteCHAR(buf, - xmlXPathCastNodeToString(nodeset->nodeTab[i])); - - /* If this isn't the last entry, write the plain sep. */ - if (i < (nodeset->nodeNr) - 1) - xmlBufferWriteChar(buf, (char *) plainsep); - } - else - { - if ((septagname !=3D NULL) && (xmlStrlen(septagname) > 0)) + if (plainsep !=3D NULL) { - xmlBufferWriteChar(buf, "<"); - xmlBufferWriteCHAR(buf, septagname); - xmlBufferWriteChar(buf, ">"); + xmlBufferWriteCHAR(buf, + xmlXPathCastNodeToString(nodeset->nodeTab[i])); + + /* If this isn't the last entry, write the plain sep. */ + if (i < (nodeset->nodeNr) - 1) + xmlBufferWriteChar(buf, (char *) plainsep); } - xmlNodeDump(buf, - nodeset->nodeTab[i]->doc, - nodeset->nodeTab[i], - 1, 0); - - if ((septagname !=3D NULL) && (xmlStrlen(septagname) > 0)) + else { - xmlBufferWriteChar(buf, ""); + if ((septagname !=3D NULL) && (xmlStrlen(septagname) > 0)) + { + xmlBufferWriteChar(buf, "<"); + xmlBufferWriteCHAR(buf, septagname); + xmlBufferWriteChar(buf, ">"); + } + xmlNodeDump(buf, + nodeset->nodeTab[i]->doc, + nodeset->nodeTab[i], + 1, 0); + + if ((septagname !=3D NULL) && (xmlStrlen(septagname) > 0)) + { + xmlBufferWriteChar(buf, ""); + } } } } - } =20 - if ((toptagname !=3D NULL) && (xmlStrlen(toptagname) > 0)) - { - xmlBufferWriteChar(buf, ""); + if ((toptagname !=3D NULL) && (xmlStrlen(toptagname) > 0)) + { + xmlBufferWriteChar(buf, ""); + } + + result =3D xmlStrdup(buf->content); + if (result =3D=3D NULL || pg_xml_error_occurred(xmlerrcxt)) + xml_ereport(xmlerrcxt, ERROR, ERRCODE_OUT_OF_MEMORY, + "could not allocate result"); } - result =3D xmlStrdup(buf->content); + PG_CATCH(); + { + if (buf) + xmlBufferFree(buf); + + pg_xml_done(xmlerrcxt, true); + + PG_RE_THROW(); + } + PG_END_TRY(); + xmlBufferFree(buf); + pg_xml_done(xmlerrcxt, false); + return result; } =20 @@ -208,16 +258,29 @@ xpath_nodeset(PG_FUNCTION_ARGS) xmlChar *septag =3D pgxml_texttoxmlchar(PG_GETARG_TEXT_PP(3)); xmlChar *xpath; text *xpres; - xmlXPathObjectPtr res; - xpath_workspace workspace; + volatile xpath_workspace *workspace; + PgXmlErrorContext *xmlerrcxt; =20 xpath =3D pgxml_texttoxmlchar(xpathsupp); + xmlerrcxt =3D pgxml_parser_init(PG_XML_STRICTNESS_LEGACY); =20 - res =3D pgxml_xpath(document, xpath, &workspace); + PG_TRY(); + { + workspace =3D pgxml_xpath(document, xpath, xmlerrcxt); + xpres =3D pgxml_result_to_text(workspace->res, toptag, septag, NULL); + } + PG_CATCH(); + { + if (workspace) + cleanup_workspace(workspace); =20 - xpres =3D pgxml_result_to_text(res, toptag, septag, NULL); + pg_xml_done(xmlerrcxt, true); + PG_RE_THROW(); + } + PG_END_TRY(); =20 - cleanup_workspace(&workspace); + cleanup_workspace(workspace); + pg_xml_done(xmlerrcxt, false); =20 pfree(xpath); =20 @@ -240,16 +303,29 @@ xpath_list(PG_FUNCTION_ARGS) xmlChar *plainsep =3D pgxml_texttoxmlchar(PG_GETARG_TEXT_PP(2)); xmlChar *xpath; text *xpres; - xmlXPathObjectPtr res; - xpath_workspace workspace; + volatile xpath_workspace *workspace; + PgXmlErrorContext *xmlerrcxt; =20 xpath =3D pgxml_texttoxmlchar(xpathsupp); + xmlerrcxt =3D pgxml_parser_init(PG_XML_STRICTNESS_LEGACY); =20 - res =3D pgxml_xpath(document, xpath, &workspace); + PG_TRY(); + { + workspace =3D pgxml_xpath(document, xpath, xmlerrcxt); + xpres =3D pgxml_result_to_text(workspace->res, NULL, NULL, plainsep); + } + PG_CATCH(); + { + if (workspace) + cleanup_workspace(workspace); =20 - xpres =3D pgxml_result_to_text(res, NULL, NULL, plainsep); + pg_xml_done(xmlerrcxt, true); + PG_RE_THROW(); + } + PG_END_TRY(); =20 - cleanup_workspace(&workspace); + cleanup_workspace(workspace); + pg_xml_done(xmlerrcxt, false); =20 pfree(xpath); =20 @@ -269,8 +345,8 @@ xpath_string(PG_FUNCTION_ARGS) xmlChar *xpath; int32 pathsize; text *xpres; - xmlXPathObjectPtr res; - xpath_workspace workspace; + volatile xpath_workspace *workspace; + PgXmlErrorContext *xmlerrcxt; =20 pathsize =3D VARSIZE_ANY_EXHDR(xpathsupp); =20 @@ -286,11 +362,24 @@ xpath_string(PG_FUNCTION_ARGS) xpath[pathsize + 7] =3D ')'; xpath[pathsize + 8] =3D '\0'; =20 - res =3D pgxml_xpath(document, xpath, &workspace); + xmlerrcxt =3D pgxml_parser_init(PG_XML_STRICTNESS_LEGACY); =20 - xpres =3D pgxml_result_to_text(res, NULL, NULL, NULL); + PG_TRY(); + { + workspace =3D pgxml_xpath(document, xpath, xmlerrcxt); + xpres =3D pgxml_result_to_text(workspace->res, NULL, NULL, NULL); + } + PG_CATCH(); + { + if (workspace) + cleanup_workspace(workspace); =20 - cleanup_workspace(&workspace); + pg_xml_done(xmlerrcxt, true); + PG_RE_THROW(); + } + PG_END_TRY(); + + cleanup_workspace(workspace); =20 pfree(xpath); =20 @@ -308,24 +397,38 @@ xpath_number(PG_FUNCTION_ARGS) text *document =3D PG_GETARG_TEXT_PP(0); text *xpathsupp =3D PG_GETARG_TEXT_PP(1); /* XPath expression */ xmlChar *xpath; - float4 fRes; - xmlXPathObjectPtr res; - xpath_workspace workspace; + float4 fRes =3D 0.0; + bool isNull =3D false; + volatile xpath_workspace *workspace =3D NULL; + PgXmlErrorContext *xmlerrcxt; =20 xpath =3D pgxml_texttoxmlchar(xpathsupp); + xmlerrcxt =3D pgxml_parser_init(PG_XML_STRICTNESS_LEGACY); =20 - res =3D pgxml_xpath(document, xpath, &workspace); + PG_TRY(); + { + workspace =3D pgxml_xpath(document, xpath, xmlerrcxt); + pfree(xpath); =20 - pfree(xpath); + if (workspace->res =3D=3D NULL) + isNull =3D true; + else + fRes =3D xmlXPathCastToNumber(workspace->res); + } + PG_CATCH(); + { + if (workspace) + cleanup_workspace(workspace); =20 - if (res =3D=3D NULL) - PG_RETURN_NULL(); + pg_xml_done(xmlerrcxt, true); + PG_RE_THROW(); + } + PG_END_TRY(); =20 - fRes =3D xmlXPathCastToNumber(res); + cleanup_workspace(workspace); + pg_xml_done(xmlerrcxt, false); =20 - cleanup_workspace(&workspace); - - if (xmlXPathIsNaN(fRes)) + if (isNull || xmlXPathIsNaN(fRes)) PG_RETURN_NULL(); =20 PG_RETURN_FLOAT4(fRes); @@ -341,21 +444,34 @@ xpath_bool(PG_FUNCTION_ARGS) text *xpathsupp =3D PG_GETARG_TEXT_PP(1); /* XPath expression */ xmlChar *xpath; int bRes; - xmlXPathObjectPtr res; - xpath_workspace workspace; + volatile xpath_workspace *workspace =3D NULL; + PgXmlErrorContext *xmlerrcxt; =20 xpath =3D pgxml_texttoxmlchar(xpathsupp); + xmlerrcxt =3D pgxml_parser_init(PG_XML_STRICTNESS_LEGACY); =20 - res =3D pgxml_xpath(document, xpath, &workspace); + PG_TRY(); + { + workspace =3D pgxml_xpath(document, xpath, xmlerrcxt); + pfree(xpath); =20 - pfree(xpath); + if (workspace->res =3D=3D NULL) + bRes =3D 0; + else + bRes =3D xmlXPathCastToBoolean(workspace->res); + } + PG_CATCH(); + { + if (workspace) + cleanup_workspace(workspace); =20 - if (res =3D=3D NULL) - PG_RETURN_BOOL(false); + pg_xml_done(xmlerrcxt, true); + PG_RE_THROW(); + } + PG_END_TRY(); =20 - bRes =3D xmlXPathCastToBoolean(res); - - cleanup_workspace(&workspace); + cleanup_workspace(workspace); + pg_xml_done(xmlerrcxt, false); =20 PG_RETURN_BOOL(bRes); } @@ -364,62 +480,44 @@ xpath_bool(PG_FUNCTION_ARGS) =20 /* Core function to evaluate XPath query */ =20 -static xmlXPathObjectPtr -pgxml_xpath(text *document, xmlChar *xpath, xpath_workspace *workspace) +static xpath_workspace * +pgxml_xpath(text *document, xmlChar *xpath, PgXmlErrorContext *xmlerrcxt) { int32 docsize =3D VARSIZE_ANY_EXHDR(document); - PgXmlErrorContext *xmlerrcxt; xmlXPathCompExprPtr comppath; + xpath_workspace *workspace =3D (xpath_workspace *) + palloc0(sizeof(xpath_workspace)); =20 workspace->doctree =3D NULL; workspace->ctxt =3D NULL; workspace->res =3D NULL; =20 - xmlerrcxt =3D pgxml_parser_init(PG_XML_STRICTNESS_LEGACY); - - PG_TRY(); + workspace->doctree =3D xmlReadMemory((char *) VARDATA_ANY(document), + docsize, NULL, NULL, + XML_PARSE_NOENT); + if (workspace->doctree !=3D NULL) { - workspace->doctree =3D xmlReadMemory((char *) VARDATA_ANY(document), - docsize, NULL, NULL, - XML_PARSE_NOENT); - if (workspace->doctree !=3D NULL) - { - workspace->ctxt =3D xmlXPathNewContext(workspace->doctree); - workspace->ctxt->node =3D xmlDocGetRootElement(workspace->doctree); + workspace->ctxt =3D xmlXPathNewContext(workspace->doctree); + workspace->ctxt->node =3D xmlDocGetRootElement(workspace->doctree); =20 - /* compile the path */ - comppath =3D xmlXPathCtxtCompile(workspace->ctxt, xpath); - if (comppath =3D=3D NULL) - xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY, + /* compile the path */ + comppath =3D xmlXPathCtxtCompile(workspace->ctxt, xpath); + if (comppath =3D=3D NULL || pg_xml_error_occurred(xmlerrcxt)) + xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY, "XPath Syntax Error"); =20 - /* Now evaluate the path expression. */ - workspace->res =3D xmlXPathCompiledEval(comppath, workspace->ctxt); + /* Now evaluate the path expression. */ + workspace->res =3D xmlXPathCompiledEval(comppath, workspace->ctxt); =20 - xmlXPathFreeCompExpr(comppath); - } + xmlXPathFreeCompExpr(comppath); } - PG_CATCH(); - { - cleanup_workspace(workspace); =20 - pg_xml_done(xmlerrcxt, true); - - PG_RE_THROW(); - } - PG_END_TRY(); - - if (workspace->res =3D=3D NULL) - cleanup_workspace(workspace); - - pg_xml_done(xmlerrcxt, false); - - return workspace->res; + return workspace; } =20 /* Clean up after processing the result of pgxml_xpath() */ static void -cleanup_workspace(xpath_workspace *workspace) +cleanup_workspace(volatile xpath_workspace *workspace) { if (workspace->res) xmlXPathFreeObject(workspace->res); @@ -438,34 +536,59 @@ pgxml_result_to_text(xmlXPathObjectPtr res, xmlChar *septag, xmlChar *plainsep) { - xmlChar *xpresstr; + volatile xmlChar *xpresstr =3D NULL; + PgXmlErrorContext *xmlerrcxt; text *xpres; =20 if (res =3D=3D NULL) return NULL; =20 - switch (res->type) + /* spin some error handling */ + xmlerrcxt =3D pg_xml_init(PG_XML_STRICTNESS_ALL); + + PG_TRY(); { - case XPATH_NODESET: - xpresstr =3D pgxmlNodeSetToText(res->nodesetval, - toptag, - septag, plainsep); - break; + switch (res->type) + { + case XPATH_NODESET: + xpresstr =3D pgxmlNodeSetToText(res->nodesetval, + toptag, + septag, plainsep); + break; =20 - case XPATH_STRING: - xpresstr =3D xmlStrdup(res->stringval); - break; + case XPATH_STRING: + xpresstr =3D xmlStrdup(res->stringval); + if (xpresstr =3D=3D NULL || pg_xml_error_occurred(xmlerrcxt)) + xml_ereport(xmlerrcxt, ERROR, ERRCODE_OUT_OF_MEMORY, + "could not allocate result"); + break; =20 - default: - elog(NOTICE, "unsupported XQuery result: %d", res->type); - xpresstr =3D xmlStrdup((const xmlChar *) ""); + default: + elog(NOTICE, "unsupported XQuery result: %d", res->type); + xpresstr =3D xmlStrdup((const xmlChar *) ""); + if (xpresstr =3D=3D NULL || pg_xml_error_occurred(xmlerrcxt)) + xml_ereport(xmlerrcxt, ERROR, ERRCODE_OUT_OF_MEMORY, + "could not allocate result"); + } + + /* Now convert this result back to text */ + xpres =3D cstring_to_text((char *) xpresstr); } + PG_CATCH(); + { + if (xpresstr !=3D NULL) + xmlFree((xmlChar *) xpresstr); =20 - /* Now convert this result back to text */ - xpres =3D cstring_to_text((char *) xpresstr); + pg_xml_done(xmlerrcxt, true); + + PG_RE_THROW(); + } + PG_END_TRY(); =20 /* Free various storage */ - xmlFree(xpresstr); + xmlFree((xmlChar *) xpresstr); + + pg_xml_done(xmlerrcxt, false); =20 return xpres; } @@ -648,11 +771,16 @@ xpath_table(PG_FUNCTION_ARGS) for (j =3D 0; j < numpaths; j++) { ctxt =3D xmlXPathNewContext(doctree); + if (ctxt =3D=3D NULL || pg_xml_error_occurred(xmlerrcxt)) + xml_ereport(xmlerrcxt, + ERROR, ERRCODE_OUT_OF_MEMORY, + "could not allocate XPath context"); + ctxt->node =3D xmlDocGetRootElement(doctree); =20 /* compile the path */ comppath =3D xmlXPathCtxtCompile(ctxt, xpaths[j]); - if (comppath =3D=3D NULL) + if (comppath =3D=3D NULL || pg_xml_error_occurred(xmlerrcxt)) xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY, "XPath Syntax Error"); @@ -671,6 +799,10 @@ xpath_table(PG_FUNCTION_ARGS) rownr < res->nodesetval->nodeNr) { resstr =3D xmlXPathCastNodeToString(res->nodesetval->nodeTab[row= nr]); + if (resstr =3D=3D NULL || pg_xml_error_occurred(xmlerrcxt)) + xml_ereport(xmlerrcxt, + ERROR, ERRCODE_OUT_OF_MEMORY, + "could not allocate result"); had_values =3D true; } else @@ -680,11 +812,19 @@ xpath_table(PG_FUNCTION_ARGS) =20 case XPATH_STRING: resstr =3D xmlStrdup(res->stringval); + if (resstr =3D=3D NULL || pg_xml_error_occurred(xmlerrcxt)) + xml_ereport(xmlerrcxt, + ERROR, ERRCODE_OUT_OF_MEMORY, + "could not allocate result"); break; =20 default: elog(NOTICE, "unsupported XQuery result: %d", res->type); resstr =3D xmlStrdup((const xmlChar *) ""); + if (resstr =3D=3D NULL || pg_xml_error_occurred(xmlerrcxt)) + xml_ereport(xmlerrcxt, + ERROR, ERRCODE_OUT_OF_MEMORY, + "could not allocate result"); } =20 /* diff --git a/contrib/xml2/xslt_proc.c b/contrib/xml2/xslt_proc.c index b720d89f754a..c8e7dd45ed5b 100644 --- a/contrib/xml2/xslt_proc.c +++ b/contrib/xml2/xslt_proc.c @@ -58,7 +58,7 @@ xslt_process(PG_FUNCTION_ARGS) volatile xsltSecurityPrefsPtr xslt_sec_prefs =3D NULL; volatile xsltTransformContextPtr xslt_ctxt =3D NULL; volatile int resstat =3D -1; - xmlChar *resstr =3D NULL; + volatile xmlChar *resstr =3D NULL; int reslen =3D 0; =20 if (fcinfo->nargs =3D=3D 3) @@ -86,7 +86,7 @@ xslt_process(PG_FUNCTION_ARGS) VARSIZE_ANY_EXHDR(doct), NULL, NULL, XML_PARSE_NOENT); =20 - if (doctree =3D=3D NULL) + if (doctree =3D=3D NULL || pg_xml_error_occurred(xmlerrcxt)) xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_XML_DOCUMENT, "error parsing XML document"); =20 @@ -95,14 +95,14 @@ xslt_process(PG_FUNCTION_ARGS) VARSIZE_ANY_EXHDR(ssheet), NULL, NULL, XML_PARSE_NOENT); =20 - if (ssdoc =3D=3D NULL) + if (ssdoc =3D=3D NULL || pg_xml_error_occurred(xmlerrcxt)) xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_XML_DOCUMENT, "error parsing stylesheet as XML document"); =20 /* After this call we need not free ssdoc separately */ stylesheet =3D xsltParseStylesheetDoc(ssdoc); =20 - if (stylesheet =3D=3D NULL) + if (stylesheet =3D=3D NULL || pg_xml_error_occurred(xmlerrcxt)) xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY, "failed to parse stylesheet"); =20 @@ -137,11 +137,15 @@ xslt_process(PG_FUNCTION_ARGS) restree =3D xsltApplyStylesheetUser(stylesheet, doctree, params, NULL, NULL, xslt_ctxt); =20 - if (restree =3D=3D NULL) + if (restree =3D=3D NULL || pg_xml_error_occurred(xmlerrcxt)) xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY, "failed to apply stylesheet"); =20 - resstat =3D xsltSaveResultToString(&resstr, &reslen, restree, stylesheet= ); + resstat =3D xsltSaveResultToString((xmlChar **) &resstr, &reslen, + restree, stylesheet); + + if (resstat >=3D 0) + result =3D cstring_to_text_with_len((char *) resstr, reslen); } PG_CATCH(); { @@ -155,6 +159,8 @@ xslt_process(PG_FUNCTION_ARGS) xsltFreeStylesheet(stylesheet); if (doctree !=3D NULL) xmlFreeDoc(doctree); + if (resstr !=3D NULL) + xmlFree((xmlChar *) resstr); xsltCleanupGlobals(); =20 pg_xml_done(xmlerrcxt, true); @@ -170,17 +176,15 @@ xslt_process(PG_FUNCTION_ARGS) xmlFreeDoc(doctree); xsltCleanupGlobals(); =20 + if (resstr) + xmlFree((xmlChar *) resstr); + pg_xml_done(xmlerrcxt, false); =20 /* XXX this is pretty dubious, really ought to throw error instead */ if (resstat < 0) PG_RETURN_NULL(); =20 - result =3D cstring_to_text_with_len((char *) resstr, reslen); - - if (resstr) - xmlFree(resstr); - PG_RETURN_TEXT_P(result); #else /* !USE_LIBXSLT */ =20 --=20 2.49.0 --UFYgHWu+bSQKqEbN-- --SWTAmUvGf4/QaEo1 Content-Type: application/pgp-signature; name="signature.asc" -----BEGIN PGP SIGNATURE----- iQIzBAABCgAdFiEEG72nH6vTowiyblFKnvQgOdbyQH0FAmhE8zEACgkQnvQgOdby QH0b+w/9FfsqbOLoX8hl6TxQnFYRYYfOYakzivsnqVvvjYD8ceHVjeSFHAraNEku 0++nysYhw6lpE3B/cedOgBbrhP32i85H3JZKd/ApQwgUlObSBxTZI8OxvguY9rWW MrOrHWvvr710FYCXj9PPNsUQIO28LRyFlM5LDNFI/ocjSZjqoLsyOuCHG182aHxH LOJAsX171PTgv0aEKz24DDVsFpV7lvFEnknmCV1fG0bVelCXQt0AdbMZS2m8waHm U3gmboGkVxc4FTocZzKrvWaviuP1LCWpIYGUtjuvI+PfxrGqTLcoCD+KONCzHteO YwbiepYtDdLabqJ0vSf/U5LHTu44No9fsAtaLX+WxVd/QY77RnTtpEA9cO3gxqJg 1hZXhyY+yhx9JZZGQkyPqWWMhyfCyqA6MOTHDVYTmoQ+Oh1+TPmUvcrq6HpY6maE VOR1JMKhh/vsa+eSo6uACbYktkbP+ro8khVzAkaALKpL0sb1R9KVxb1zyQFwMuDu vbwTiqauA/zg/lQGSBJObPpnejZfU8sNB6rkMshVSqMHUhtUwShFNFalbosOqAv3 H+Tydra5ZRE36haORcfGASpBia+wOc0wzwGvNUOOAWbBIeHsjMMas8xVa6rh2wGr 0p72O1OVqdB+VBtj3AFTZjx28sncwyrMaXihleKqUDXlFVn9IeQ= =Gaye -----END PGP SIGNATURE----- --SWTAmUvGf4/QaEo1--