agora inbox for pgsql-hackers@postgresql.org  
help / color / mirror / Atom feed
posix_fadvise() and pg_receivexlog
611+ messages / 6 participants
[nested] [flat]

* posix_fadvise() and pg_receivexlog
@ 2014-08-06 17:39 Fujii Masao <masao.fujii@gmail.com>
  2014-08-06 18:56 ` Re: posix_fadvise() and pg_receivexlog Robert Haas <robertmhaas@gmail.com>
  2014-08-06 18:59 ` Re: posix_fadvise() and pg_receivexlog Heikki Linnakangas <hlinnakangas@vmware.com>
  0 siblings, 2 replies; 611+ messages in thread

From: Fujii Masao @ 2014-08-06 17:39 UTC (permalink / raw)
  To: pgsql-hackers

Hi,

The WAL files that pg_receivexlog writes will not be re-read soon basically,
so we can advise the OS to release any cached pages when WAL file is
closed. I feel inclined to change pg_receivexlog that way. Thought?

Regards,

-- 
Fujii Masao


-- 
Sent via pgsql-hackers mailing list (pgsql-hackers@postgresql.org)
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-hackers



^ permalink  raw  reply  [nested|flat] 611+ messages in thread

* Re: posix_fadvise() and pg_receivexlog
  2014-08-06 17:39 posix_fadvise() and pg_receivexlog Fujii Masao <masao.fujii@gmail.com>
@ 2014-08-06 18:56 ` Robert Haas <robertmhaas@gmail.com>
  1 sibling, 0 replies; 611+ messages in thread

From: Robert Haas @ 2014-08-06 18:56 UTC (permalink / raw)
  To: Fujii Masao <masao.fujii@gmail.com>; +Cc: pgsql-hackers

On Wed, Aug 6, 2014 at 1:39 PM, Fujii Masao <masao.fujii@gmail.com> wrote:
> The WAL files that pg_receivexlog writes will not be re-read soon basically,
> so we can advise the OS to release any cached pages when WAL file is
> closed. I feel inclined to change pg_receivexlog that way. Thought?

How do we know that the user doesn't plan to read them soon?

-- 
Robert Haas
EnterpriseDB: http://www.enterprisedb.com
The Enterprise PostgreSQL Company


-- 
Sent via pgsql-hackers mailing list (pgsql-hackers@postgresql.org)
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-hackers



^ permalink  raw  reply  [nested|flat] 611+ messages in thread

* Re: posix_fadvise() and pg_receivexlog
  2014-08-06 17:39 posix_fadvise() and pg_receivexlog Fujii Masao <masao.fujii@gmail.com>
@ 2014-08-06 18:59 ` Heikki Linnakangas <hlinnakangas@vmware.com>
  2014-08-07 04:47   ` Re: posix_fadvise() and pg_receivexlog Fujii Masao <masao.fujii@gmail.com>
  1 sibling, 1 reply; 611+ messages in thread

From: Heikki Linnakangas @ 2014-08-06 18:59 UTC (permalink / raw)
  To: Fujii Masao <masao.fujii@gmail.com>; pgsql-hackers

On 08/06/2014 08:39 PM, Fujii Masao wrote:
> Hi,
>
> The WAL files that pg_receivexlog writes will not be re-read soon basically,
> so we can advise the OS to release any cached pages when WAL file is
> closed. I feel inclined to change pg_receivexlog that way. Thought?

-1. The OS should be smart enough to not thrash the cache by files that 
are written sequentially and never read. If we go down this path, we'd 
need to sprinkle posix_fadvises into many, many places.

Anyway, who are we to say that they won't be re-read soon? You might e.g 
have a secondary backup site where you copy the files received by 
pg_receivexlog, as soon as they're completed.

- Heikki



-- 
Sent via pgsql-hackers mailing list (pgsql-hackers@postgresql.org)
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-hackers



^ permalink  raw  reply  [nested|flat] 611+ messages in thread

* Re: posix_fadvise() and pg_receivexlog
  2014-08-06 17:39 posix_fadvise() and pg_receivexlog Fujii Masao <masao.fujii@gmail.com>
  2014-08-06 18:59 ` Re: posix_fadvise() and pg_receivexlog Heikki Linnakangas <hlinnakangas@vmware.com>
@ 2014-08-07 04:47   ` Fujii Masao <masao.fujii@gmail.com>
  2014-08-07 07:10     ` Re: posix_fadvise() and pg_receivexlog Mitsumasa KONDO <kondo.mitsumasa@gmail.com>
  0 siblings, 1 reply; 611+ messages in thread

From: Fujii Masao @ 2014-08-07 04:47 UTC (permalink / raw)
  To: Heikki Linnakangas <hlinnakangas@vmware.com>; +Cc: pgsql-hackers

On Thu, Aug 7, 2014 at 3:59 AM, Heikki Linnakangas
<hlinnakangas@vmware.com> wrote:
> On 08/06/2014 08:39 PM, Fujii Masao wrote:
>>
>> Hi,
>>
>> The WAL files that pg_receivexlog writes will not be re-read soon
>> basically,
>> so we can advise the OS to release any cached pages when WAL file is
>> closed. I feel inclined to change pg_receivexlog that way. Thought?
>
>
> -1. The OS should be smart enough to not thrash the cache by files that are
> written sequentially and never read.

Yep, the OS should be so smart, but I'm not sure if it actually is. Maybe not,
so I was thinking that posix_fadvise is called when the server closes WAL file.

> If we go down this path, we'd need to
> sprinkle posix_fadvises into many, many places.

Yes, that's valid concern. But if we can prove that adding posix_fadvise to
a certain place can improve the performance well, I'm inclined to do that.

> Anyway, who are we to say that they won't be re-read soon? You might e.g
> have a secondary backup site where you copy the files received by
> pg_receivexlog, as soon as they're completed.

So whether posix_fadvise is called or not needs to be exposed as an
user-configurable option. We would need to measure how useful exposing
that is, though.

Regards,

-- 
Fujii Masao


-- 
Sent via pgsql-hackers mailing list (pgsql-hackers@postgresql.org)
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-hackers



^ permalink  raw  reply  [nested|flat] 611+ messages in thread

* Re: posix_fadvise() and pg_receivexlog
  2014-08-06 17:39 posix_fadvise() and pg_receivexlog Fujii Masao <masao.fujii@gmail.com>
  2014-08-06 18:59 ` Re: posix_fadvise() and pg_receivexlog Heikki Linnakangas <hlinnakangas@vmware.com>
  2014-08-07 04:47   ` Re: posix_fadvise() and pg_receivexlog Fujii Masao <masao.fujii@gmail.com>
@ 2014-08-07 07:10     ` Mitsumasa KONDO <kondo.mitsumasa@gmail.com>
  2014-08-07 08:02       ` Re: posix_fadvise() and pg_receivexlog Heikki Linnakangas <hlinnakangas@vmware.com>
  0 siblings, 1 reply; 611+ messages in thread

From: Mitsumasa KONDO @ 2014-08-07 07:10 UTC (permalink / raw)
  To: Fujii Masao <masao.fujii@gmail.com>; Heikki Linnakangas <hlinnakangas@vmware.com>; +Cc: pgsql-hackers

Hi,

2014-08-07 13:47 GMT+09:00 Fujii Masao <masao.fujii@gmail.com>:

> On Thu, Aug 7, 2014 at 3:59 AM, Heikki Linnakangas
> <hlinnakangas@vmware.com> wrote:
> > On 08/06/2014 08:39 PM, Fujii Masao wrote:
> >> The WAL files that pg_receivexlog writes will not be re-read soon
> >> basically,
> >> so we can advise the OS to release any cached pages when WAL file is
> >> closed. I feel inclined to change pg_receivexlog that way. Thought?
> >
> >
> > -1. The OS should be smart enough to not thrash the cache by files that
> are
> > written sequentially and never read.
>
OS's buffer strategy is optimized for general situation. Do you forget OS
hackers discussion last a half of year?


> Yep, the OS should be so smart, but I'm not sure if it actually is. Maybe
> not,
> so I was thinking that posix_fadvise is called when the server closes WAL
> file.

That's right.


> > If we go down this path, we'd need to
> > sprinkle posix_fadvises into many, many places.
>
Why do you aim to be perfect at the beginning?
It is as same as history of postgres, your concern doesn't make sense.


> > Anyway, who are we to say that they won't be re-read soon? You might e.g
> > have a secondary backup site where you copy the files received by
> > pg_receivexlog, as soon as they're completed.
>
> So whether posix_fadvise is called or not needs to be exposed as an
> user-configurable option. We would need to measure how useful exposing
> that is, though.

By the way, does pg_receivexlog process have fsync() in every WAL commit?
If yes, I think that we need no or less fsync() option for the better
performance. It is general in NOSQL storages.
If no, we need fsync() option for more getting reliability and data
integrarity.


Best regards,
--
Mitsumasa KONDO

^ permalink  raw  reply  [nested|flat] 611+ messages in thread

* Re: posix_fadvise() and pg_receivexlog
  2014-08-06 17:39 posix_fadvise() and pg_receivexlog Fujii Masao <masao.fujii@gmail.com>
  2014-08-06 18:59 ` Re: posix_fadvise() and pg_receivexlog Heikki Linnakangas <hlinnakangas@vmware.com>
  2014-08-07 04:47   ` Re: posix_fadvise() and pg_receivexlog Fujii Masao <masao.fujii@gmail.com>
  2014-08-07 07:10     ` Re: posix_fadvise() and pg_receivexlog Mitsumasa KONDO <kondo.mitsumasa@gmail.com>
@ 2014-08-07 08:02       ` Heikki Linnakangas <hlinnakangas@vmware.com>
  2014-08-07 10:54         ` Re: posix_fadvise() and pg_receivexlog Fujii Masao <masao.fujii@gmail.com>
  2014-09-09 12:07         ` Re: posix_fadvise() and pg_receivexlog didier <did447@gmail.com>
  0 siblings, 2 replies; 611+ messages in thread

From: Heikki Linnakangas @ 2014-08-07 08:02 UTC (permalink / raw)
  To: Mitsumasa KONDO <kondo.mitsumasa@gmail.com>; Fujii Masao <masao.fujii@gmail.com>; +Cc: pgsql-hackers

On 08/07/2014 10:10 AM, Mitsumasa KONDO wrote:
> 2014-08-07 13:47 GMT+09:00 Fujii Masao <masao.fujii@gmail.com>:
>
>> On Thu, Aug 7, 2014 at 3:59 AM, Heikki Linnakangas
>> <hlinnakangas@vmware.com> wrote:
>>> On 08/06/2014 08:39 PM, Fujii Masao wrote:
>>>> The WAL files that pg_receivexlog writes will not be re-read soon
>>>> basically,
>>>> so we can advise the OS to release any cached pages when WAL file is
>>>> closed. I feel inclined to change pg_receivexlog that way. Thought?
>>>
>>>
>>> -1. The OS should be smart enough to not thrash the cache by files that
>> are
>>> written sequentially and never read.
>>
> OS's buffer strategy is optimized for general situation. Do you forget OS
> hackers discussion last a half of year?
>
>> Yep, the OS should be so smart, but I'm not sure if it actually is. Maybe
>> not,
>> so I was thinking that posix_fadvise is called when the server closes WAL
>> file.
>
> That's right.

Well, I'd like to hear someone from the field complaining that 
pg_receivexlog is thrashing the cache and thus reducing the performance 
of some other process. Or a least a synthetic test case that 
demonstrates that happening.

> By the way, does pg_receivexlog process have fsync() in every WAL commit?

It fsync's each file after finishing to write it. Ie. each WAL file is 
fsync'd once.

> If yes, I think that we need no or less fsync() option for the better
> performance. It is general in NOSQL storages.
> If no, we need fsync() option for more getting reliability and data
> integrarity.

Hmm. An fsync=off style option might make sense, although I doubt the 
one fsync at end of file is causing a performance problem for anyone in 
practice. Haven't heard any complaints, anyway.

An option to fsync after every commit record might make sense if you use 
pg_receivexlog with synchronous replication. Doing that would require 
parsing the WAL, though, to see where the commit records are. But then 
again, the fsync's wouldn't need to correspond to commit records. We 
could fsync just before we go to sleep to wait for more WAL to be received.

- Heikki



-- 
Sent via pgsql-hackers mailing list (pgsql-hackers@postgresql.org)
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-hackers



^ permalink  raw  reply  [nested|flat] 611+ messages in thread

* Re: posix_fadvise() and pg_receivexlog
  2014-08-06 17:39 posix_fadvise() and pg_receivexlog Fujii Masao <masao.fujii@gmail.com>
  2014-08-06 18:59 ` Re: posix_fadvise() and pg_receivexlog Heikki Linnakangas <hlinnakangas@vmware.com>
  2014-08-07 04:47   ` Re: posix_fadvise() and pg_receivexlog Fujii Masao <masao.fujii@gmail.com>
  2014-08-07 07:10     ` Re: posix_fadvise() and pg_receivexlog Mitsumasa KONDO <kondo.mitsumasa@gmail.com>
  2014-08-07 08:02       ` Re: posix_fadvise() and pg_receivexlog Heikki Linnakangas <hlinnakangas@vmware.com>
@ 2014-08-07 10:54         ` Fujii Masao <masao.fujii@gmail.com>
  1 sibling, 0 replies; 611+ messages in thread

From: Fujii Masao @ 2014-08-07 10:54 UTC (permalink / raw)
  To: Heikki Linnakangas <hlinnakangas@vmware.com>; +Cc: Mitsumasa KONDO <kondo.mitsumasa@gmail.com>; pgsql-hackers

On Thu, Aug 7, 2014 at 5:02 PM, Heikki Linnakangas
<hlinnakangas@vmware.com> wrote:
> On 08/07/2014 10:10 AM, Mitsumasa KONDO wrote:
>>
>> 2014-08-07 13:47 GMT+09:00 Fujii Masao <masao.fujii@gmail.com>:
>>
>>> On Thu, Aug 7, 2014 at 3:59 AM, Heikki Linnakangas
>>> <hlinnakangas@vmware.com> wrote:
>>>>
>>>> On 08/06/2014 08:39 PM, Fujii Masao wrote:
>>>>>
>>>>> The WAL files that pg_receivexlog writes will not be re-read soon
>>>>> basically,
>>>>> so we can advise the OS to release any cached pages when WAL file is
>>>>> closed. I feel inclined to change pg_receivexlog that way. Thought?
>>>>
>>>>
>>>>
>>>> -1. The OS should be smart enough to not thrash the cache by files that
>>>
>>> are
>>>>
>>>> written sequentially and never read.
>>>
>>>
>> OS's buffer strategy is optimized for general situation. Do you forget OS
>> hackers discussion last a half of year?
>>
>>> Yep, the OS should be so smart, but I'm not sure if it actually is. Maybe
>>> not,
>>> so I was thinking that posix_fadvise is called when the server closes WAL
>>> file.
>>
>>
>> That's right.
>
>
> Well, I'd like to hear someone from the field complaining that
> pg_receivexlog is thrashing the cache and thus reducing the performance of
> some other process. Or a least a synthetic test case that demonstrates that
> happening.

Yeah, I will test that by seeing the performance of PostgreSQL which is
running in the same server as pg_receivexlog is running. We can just
compare that performance with normal pg_receivexlog and that with
the patched one (i.e., posix_fadvise is called).

>
>
>> By the way, does pg_receivexlog process have fsync() in every WAL commit?
>
>
> It fsync's each file after finishing to write it. Ie. each WAL file is
> fsync'd once.
>
>
>> If yes, I think that we need no or less fsync() option for the better
>> performance. It is general in NOSQL storages.
>> If no, we need fsync() option for more getting reliability and data
>> integrarity.
>
>
> Hmm. An fsync=off style option might make sense, although I doubt the one
> fsync at end of file is causing a performance problem for anyone in
> practice. Haven't heard any complaints, anyway.
>
> An option to fsync after every commit record might make sense if you use
> pg_receivexlog with synchronous replication. Doing that would require
> parsing the WAL, though, to see where the commit records are. But then
> again, the fsync's wouldn't need to correspond to commit records. We could
> fsync just before we go to sleep to wait for more WAL to be received.

That's what Furuya-san proposed in last CommitFest.

Regards,

-- 
Fujii Masao


-- 
Sent via pgsql-hackers mailing list (pgsql-hackers@postgresql.org)
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-hackers



^ permalink  raw  reply  [nested|flat] 611+ messages in thread

* Re: posix_fadvise() and pg_receivexlog
  2014-08-06 17:39 posix_fadvise() and pg_receivexlog Fujii Masao <masao.fujii@gmail.com>
  2014-08-06 18:59 ` Re: posix_fadvise() and pg_receivexlog Heikki Linnakangas <hlinnakangas@vmware.com>
  2014-08-07 04:47   ` Re: posix_fadvise() and pg_receivexlog Fujii Masao <masao.fujii@gmail.com>
  2014-08-07 07:10     ` Re: posix_fadvise() and pg_receivexlog Mitsumasa KONDO <kondo.mitsumasa@gmail.com>
  2014-08-07 08:02       ` Re: posix_fadvise() and pg_receivexlog Heikki Linnakangas <hlinnakangas@vmware.com>
@ 2014-09-09 12:07         ` didier <did447@gmail.com>
  2014-09-09 13:48           ` Re: posix_fadvise() and pg_receivexlog Fujii Masao <masao.fujii@gmail.com>
  2014-09-09 18:19           ` Re: posix_fadvise() and pg_receivexlog Robert Haas <robertmhaas@gmail.com>
  1 sibling, 2 replies; 611+ messages in thread

From: didier @ 2014-09-09 12:07 UTC (permalink / raw)
  To: Heikki Linnakangas <hlinnakangas@vmware.com>; +Cc: Mitsumasa KONDO <kondo.mitsumasa@gmail.com>; Fujii Masao <masao.fujii@gmail.com>; pgsql-hackers

Hi

> Well, I'd like to hear someone from the field complaining that
> pg_receivexlog is thrashing the cache and thus reducing the performance of
> some other process. Or a least a synthetic test case that demonstrates that
> happening.
It's not with pg_receivexlog but it's related.

On a small box without replication server connected perfs were good
enough but not so with a replication server connected, there was 1GB
worth of WAL sitting in RAM vs next to nothing without slave!
setup:
8GB RAM
2GB shared_buffers (smaller has other issues)
checkpoint_segments 40 (smaller value trigger too much xlog checkpoint)
checkpoints spread over 10 mn and write 30 to 50% of shared buffers.
live data set fit in RAM.
constant load.

On startup (1 or 2/hour) applications were running requests on cold
data which were now saturating IO.
I'm not sure it's an OS bug as the WAL were 'hotter' than the cold data.

A cron task every minute with vmtouch -e for evicting old WAL files
from memory has solved the issue.

Regards


-- 
Sent via pgsql-hackers mailing list (pgsql-hackers@postgresql.org)
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-hackers



^ permalink  raw  reply  [nested|flat] 611+ messages in thread

* Re: posix_fadvise() and pg_receivexlog
  2014-08-06 17:39 posix_fadvise() and pg_receivexlog Fujii Masao <masao.fujii@gmail.com>
  2014-08-06 18:59 ` Re: posix_fadvise() and pg_receivexlog Heikki Linnakangas <hlinnakangas@vmware.com>
  2014-08-07 04:47   ` Re: posix_fadvise() and pg_receivexlog Fujii Masao <masao.fujii@gmail.com>
  2014-08-07 07:10     ` Re: posix_fadvise() and pg_receivexlog Mitsumasa KONDO <kondo.mitsumasa@gmail.com>
  2014-08-07 08:02       ` Re: posix_fadvise() and pg_receivexlog Heikki Linnakangas <hlinnakangas@vmware.com>
  2014-09-09 12:07         ` Re: posix_fadvise() and pg_receivexlog didier <did447@gmail.com>
@ 2014-09-09 13:48           ` Fujii Masao <masao.fujii@gmail.com>
  1 sibling, 0 replies; 611+ messages in thread

From: Fujii Masao @ 2014-09-09 13:48 UTC (permalink / raw)
  To: didier <did447@gmail.com>; +Cc: Heikki Linnakangas <hlinnakangas@vmware.com>; Mitsumasa KONDO <kondo.mitsumasa@gmail.com>; pgsql-hackers

On Tue, Sep 9, 2014 at 9:07 PM, didier <did447@gmail.com> wrote:
> Hi
>
>> Well, I'd like to hear someone from the field complaining that
>> pg_receivexlog is thrashing the cache and thus reducing the performance of
>> some other process. Or a least a synthetic test case that demonstrates that
>> happening.
> It's not with pg_receivexlog but it's related.
>
> On a small box without replication server connected perfs were good
> enough but not so with a replication server connected, there was 1GB
> worth of WAL sitting in RAM vs next to nothing without slave!

After WAL file is filled up and closed, it will not be re-read
if wal_level is set to minimal (i.e., neither archiving nor
replication is enabled). So, in this case, PostgreSQL advises the OS
to release any cached pages of that WAL file. But not if archiving
or replication is enabled, and then WAL file keeps being cached
even after it's closed. Probably this is the cause of what you
observed, I guess.

Regards,

-- 
Fujii Masao


-- 
Sent via pgsql-hackers mailing list (pgsql-hackers@postgresql.org)
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-hackers



^ permalink  raw  reply  [nested|flat] 611+ messages in thread

* Re: posix_fadvise() and pg_receivexlog
  2014-08-06 17:39 posix_fadvise() and pg_receivexlog Fujii Masao <masao.fujii@gmail.com>
  2014-08-06 18:59 ` Re: posix_fadvise() and pg_receivexlog Heikki Linnakangas <hlinnakangas@vmware.com>
  2014-08-07 04:47   ` Re: posix_fadvise() and pg_receivexlog Fujii Masao <masao.fujii@gmail.com>
  2014-08-07 07:10     ` Re: posix_fadvise() and pg_receivexlog Mitsumasa KONDO <kondo.mitsumasa@gmail.com>
  2014-08-07 08:02       ` Re: posix_fadvise() and pg_receivexlog Heikki Linnakangas <hlinnakangas@vmware.com>
  2014-09-09 12:07         ` Re: posix_fadvise() and pg_receivexlog didier <did447@gmail.com>
@ 2014-09-09 18:19           ` Robert Haas <robertmhaas@gmail.com>
  1 sibling, 0 replies; 611+ messages in thread

From: Robert Haas @ 2014-09-09 18:19 UTC (permalink / raw)
  To: didier <did447@gmail.com>; +Cc: Heikki Linnakangas <hlinnakangas@vmware.com>; Mitsumasa KONDO <kondo.mitsumasa@gmail.com>; Fujii Masao <masao.fujii@gmail.com>; pgsql-hackers

On Tue, Sep 9, 2014 at 8:07 AM, didier <did447@gmail.com> wrote:
>> Well, I'd like to hear someone from the field complaining that
>> pg_receivexlog is thrashing the cache and thus reducing the performance of
>> some other process. Or a least a synthetic test case that demonstrates that
>> happening.
> It's not with pg_receivexlog but it's related.
>
> On a small box without replication server connected perfs were good
> enough but not so with a replication server connected, there was 1GB
> worth of WAL sitting in RAM vs next to nothing without slave!
> setup:
> 8GB RAM
> 2GB shared_buffers (smaller has other issues)
> checkpoint_segments 40 (smaller value trigger too much xlog checkpoint)
> checkpoints spread over 10 mn and write 30 to 50% of shared buffers.
> live data set fit in RAM.
> constant load.
>
> On startup (1 or 2/hour) applications were running requests on cold
> data which were now saturating IO.
> I'm not sure it's an OS bug as the WAL were 'hotter' than the cold data.
>
> A cron task every minute with vmtouch -e for evicting old WAL files
> from memory has solved the issue.

That seems like pretty good evidence that it might be worth doing
something here.  But I still think maybe it should be optional,
because if the user plans to reread those files and, say, copy them
somewhere else, then they won't want this behavior.

-- 
Robert Haas
EnterpriseDB: http://www.enterprisedb.com
The Enterprise PostgreSQL Company


-- 
Sent via pgsql-hackers mailing list (pgsql-hackers@postgresql.org)
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-hackers



^ permalink  raw  reply  [nested|flat] 611+ messages in thread

* [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths
@ 2026-06-01 22:41 Andrey Chernyy <andrey.cherny@tantorlabs.com>
  0 siblings, 0 replies; 611+ messages in thread

From: Andrey Chernyy @ 2026-06-01 22:41 UTC (permalink / raw)

pgxml_xpath() builds an xpath_workspace before returning it to
callers.  If an ERROR is thrown before the function returns, callers
have not received the workspace pointer yet and cannot run
cleanup_workspace().

Add local error cleanup for the partially built workspace and the
compiled XPath expression.  Also check xmlXPathNewContext() before
dereferencing the returned context.
---
 contrib/xml2/xpath.c | 51 +++++++++++++++++++++++++++-----------------
 1 file changed, 32 insertions(+), 19 deletions(-)

diff --git a/contrib/xml2/xpath.c b/contrib/xml2/xpath.c
index 9fe75cb5ff4..283bb51178d 100644
--- a/contrib/xml2/xpath.c
+++ b/contrib/xml2/xpath.c
@@ -497,36 +497,49 @@ static xpath_workspace *
 pgxml_xpath(text *document, xmlChar *xpath, PgXmlErrorContext *xmlerrcxt)
 {
 	int32		docsize = VARSIZE_ANY_EXHDR(document);
-	xmlXPathCompExprPtr comppath;
+	xmlXPathCompExprPtr volatile comppath = NULL;
 	xpath_workspace *workspace = palloc0_object(xpath_workspace);
 
 	workspace->doctree = NULL;
 	workspace->ctxt = NULL;
 	workspace->res = NULL;
 
-	workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
-									   docsize, NULL, NULL,
-									   XML_PARSE_NOENT);
-	if (workspace->doctree != NULL)
+	PG_TRY();
 	{
-		workspace->ctxt = xmlXPathNewContext(workspace->doctree);
-		workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
-
-		/* compile the path */
-		comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
-		if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+		workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
+										   docsize, NULL, NULL,
+										   XML_PARSE_NOENT);
+		if (workspace->doctree != NULL)
 		{
-			if (comppath != NULL)
-				xmlXPathFreeCompExpr(comppath);
-			xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
-						"XPath Syntax Error");
-		}
+			workspace->ctxt = xmlXPathNewContext(workspace->doctree);
+			if (workspace->ctxt == NULL)
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_OUT_OF_MEMORY,
+							"could not allocate XPath context");
 
-		/* Now evaluate the path expression. */
-		workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+			workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
+
+			/* compile the path */
+			comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
+			if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
+							"XPath Syntax Error");
+
+			/* Now evaluate the path expression. */
+			workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+
+			xmlXPathFreeCompExpr(comppath);
+			comppath = NULL;
+		}
+	}
+	PG_CATCH();
+	{
+		if (comppath != NULL)
+			xmlXPathFreeCompExpr(comppath);
+		cleanup_workspace(workspace);
 
-		xmlXPathFreeCompExpr(comppath);
+		PG_RE_THROW();
 	}
+	PG_END_TRY();
 
 	return workspace;
 }
-- 
2.54.0


--MP_/LMSk9=uMhuQ1QiIJDarDO8G--





^ permalink  raw  reply  [nested|flat] 611+ messages in thread

* [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths
@ 2026-06-01 22:41 Andrey Chernyy <andrey.cherny@tantorlabs.com>
  0 siblings, 0 replies; 611+ messages in thread

From: Andrey Chernyy @ 2026-06-01 22:41 UTC (permalink / raw)

pgxml_xpath() builds an xpath_workspace before returning it to
callers.  If an ERROR is thrown before the function returns, callers
have not received the workspace pointer yet and cannot run
cleanup_workspace().

Add local error cleanup for the partially built workspace and the
compiled XPath expression.  Also check xmlXPathNewContext() before
dereferencing the returned context.
---
 contrib/xml2/xpath.c | 51 +++++++++++++++++++++++++++-----------------
 1 file changed, 32 insertions(+), 19 deletions(-)

diff --git a/contrib/xml2/xpath.c b/contrib/xml2/xpath.c
index 9fe75cb5ff4..283bb51178d 100644
--- a/contrib/xml2/xpath.c
+++ b/contrib/xml2/xpath.c
@@ -497,36 +497,49 @@ static xpath_workspace *
 pgxml_xpath(text *document, xmlChar *xpath, PgXmlErrorContext *xmlerrcxt)
 {
 	int32		docsize = VARSIZE_ANY_EXHDR(document);
-	xmlXPathCompExprPtr comppath;
+	xmlXPathCompExprPtr volatile comppath = NULL;
 	xpath_workspace *workspace = palloc0_object(xpath_workspace);
 
 	workspace->doctree = NULL;
 	workspace->ctxt = NULL;
 	workspace->res = NULL;
 
-	workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
-									   docsize, NULL, NULL,
-									   XML_PARSE_NOENT);
-	if (workspace->doctree != NULL)
+	PG_TRY();
 	{
-		workspace->ctxt = xmlXPathNewContext(workspace->doctree);
-		workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
-
-		/* compile the path */
-		comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
-		if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+		workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
+										   docsize, NULL, NULL,
+										   XML_PARSE_NOENT);
+		if (workspace->doctree != NULL)
 		{
-			if (comppath != NULL)
-				xmlXPathFreeCompExpr(comppath);
-			xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
-						"XPath Syntax Error");
-		}
+			workspace->ctxt = xmlXPathNewContext(workspace->doctree);
+			if (workspace->ctxt == NULL)
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_OUT_OF_MEMORY,
+							"could not allocate XPath context");
 
-		/* Now evaluate the path expression. */
-		workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+			workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
+
+			/* compile the path */
+			comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
+			if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
+							"XPath Syntax Error");
+
+			/* Now evaluate the path expression. */
+			workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+
+			xmlXPathFreeCompExpr(comppath);
+			comppath = NULL;
+		}
+	}
+	PG_CATCH();
+	{
+		if (comppath != NULL)
+			xmlXPathFreeCompExpr(comppath);
+		cleanup_workspace(workspace);
 
-		xmlXPathFreeCompExpr(comppath);
+		PG_RE_THROW();
 	}
+	PG_END_TRY();
 
 	return workspace;
 }
-- 
2.54.0


--MP_/LMSk9=uMhuQ1QiIJDarDO8G--





^ permalink  raw  reply  [nested|flat] 611+ messages in thread

* [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths
@ 2026-06-01 22:41 Andrey Chernyy <andrey.cherny@tantorlabs.com>
  0 siblings, 0 replies; 611+ messages in thread

From: Andrey Chernyy @ 2026-06-01 22:41 UTC (permalink / raw)

pgxml_xpath() builds an xpath_workspace before returning it to
callers.  If an ERROR is thrown before the function returns, callers
have not received the workspace pointer yet and cannot run
cleanup_workspace().

Add local error cleanup for the partially built workspace and the
compiled XPath expression.  Also check xmlXPathNewContext() before
dereferencing the returned context.
---
 contrib/xml2/xpath.c | 51 +++++++++++++++++++++++++++-----------------
 1 file changed, 32 insertions(+), 19 deletions(-)

diff --git a/contrib/xml2/xpath.c b/contrib/xml2/xpath.c
index 9fe75cb5ff4..283bb51178d 100644
--- a/contrib/xml2/xpath.c
+++ b/contrib/xml2/xpath.c
@@ -497,36 +497,49 @@ static xpath_workspace *
 pgxml_xpath(text *document, xmlChar *xpath, PgXmlErrorContext *xmlerrcxt)
 {
 	int32		docsize = VARSIZE_ANY_EXHDR(document);
-	xmlXPathCompExprPtr comppath;
+	xmlXPathCompExprPtr volatile comppath = NULL;
 	xpath_workspace *workspace = palloc0_object(xpath_workspace);
 
 	workspace->doctree = NULL;
 	workspace->ctxt = NULL;
 	workspace->res = NULL;
 
-	workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
-									   docsize, NULL, NULL,
-									   XML_PARSE_NOENT);
-	if (workspace->doctree != NULL)
+	PG_TRY();
 	{
-		workspace->ctxt = xmlXPathNewContext(workspace->doctree);
-		workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
-
-		/* compile the path */
-		comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
-		if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+		workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
+										   docsize, NULL, NULL,
+										   XML_PARSE_NOENT);
+		if (workspace->doctree != NULL)
 		{
-			if (comppath != NULL)
-				xmlXPathFreeCompExpr(comppath);
-			xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
-						"XPath Syntax Error");
-		}
+			workspace->ctxt = xmlXPathNewContext(workspace->doctree);
+			if (workspace->ctxt == NULL)
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_OUT_OF_MEMORY,
+							"could not allocate XPath context");
 
-		/* Now evaluate the path expression. */
-		workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+			workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
+
+			/* compile the path */
+			comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
+			if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
+							"XPath Syntax Error");
+
+			/* Now evaluate the path expression. */
+			workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+
+			xmlXPathFreeCompExpr(comppath);
+			comppath = NULL;
+		}
+	}
+	PG_CATCH();
+	{
+		if (comppath != NULL)
+			xmlXPathFreeCompExpr(comppath);
+		cleanup_workspace(workspace);
 
-		xmlXPathFreeCompExpr(comppath);
+		PG_RE_THROW();
 	}
+	PG_END_TRY();
 
 	return workspace;
 }
-- 
2.54.0


--MP_/LMSk9=uMhuQ1QiIJDarDO8G--





^ permalink  raw  reply  [nested|flat] 611+ messages in thread

* [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths
@ 2026-06-01 22:41 Andrey Chernyy <andrey.cherny@tantorlabs.com>
  0 siblings, 0 replies; 611+ messages in thread

From: Andrey Chernyy @ 2026-06-01 22:41 UTC (permalink / raw)

pgxml_xpath() builds an xpath_workspace before returning it to
callers.  If an ERROR is thrown before the function returns, callers
have not received the workspace pointer yet and cannot run
cleanup_workspace().

Add local error cleanup for the partially built workspace and the
compiled XPath expression.  Also check xmlXPathNewContext() before
dereferencing the returned context.
---
 contrib/xml2/xpath.c | 51 +++++++++++++++++++++++++++-----------------
 1 file changed, 32 insertions(+), 19 deletions(-)

diff --git a/contrib/xml2/xpath.c b/contrib/xml2/xpath.c
index 9fe75cb5ff4..283bb51178d 100644
--- a/contrib/xml2/xpath.c
+++ b/contrib/xml2/xpath.c
@@ -497,36 +497,49 @@ static xpath_workspace *
 pgxml_xpath(text *document, xmlChar *xpath, PgXmlErrorContext *xmlerrcxt)
 {
 	int32		docsize = VARSIZE_ANY_EXHDR(document);
-	xmlXPathCompExprPtr comppath;
+	xmlXPathCompExprPtr volatile comppath = NULL;
 	xpath_workspace *workspace = palloc0_object(xpath_workspace);
 
 	workspace->doctree = NULL;
 	workspace->ctxt = NULL;
 	workspace->res = NULL;
 
-	workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
-									   docsize, NULL, NULL,
-									   XML_PARSE_NOENT);
-	if (workspace->doctree != NULL)
+	PG_TRY();
 	{
-		workspace->ctxt = xmlXPathNewContext(workspace->doctree);
-		workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
-
-		/* compile the path */
-		comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
-		if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+		workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
+										   docsize, NULL, NULL,
+										   XML_PARSE_NOENT);
+		if (workspace->doctree != NULL)
 		{
-			if (comppath != NULL)
-				xmlXPathFreeCompExpr(comppath);
-			xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
-						"XPath Syntax Error");
-		}
+			workspace->ctxt = xmlXPathNewContext(workspace->doctree);
+			if (workspace->ctxt == NULL)
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_OUT_OF_MEMORY,
+							"could not allocate XPath context");
 
-		/* Now evaluate the path expression. */
-		workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+			workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
+
+			/* compile the path */
+			comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
+			if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
+							"XPath Syntax Error");
+
+			/* Now evaluate the path expression. */
+			workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+
+			xmlXPathFreeCompExpr(comppath);
+			comppath = NULL;
+		}
+	}
+	PG_CATCH();
+	{
+		if (comppath != NULL)
+			xmlXPathFreeCompExpr(comppath);
+		cleanup_workspace(workspace);
 
-		xmlXPathFreeCompExpr(comppath);
+		PG_RE_THROW();
 	}
+	PG_END_TRY();
 
 	return workspace;
 }
-- 
2.54.0


--MP_/LMSk9=uMhuQ1QiIJDarDO8G--






^ permalink  raw  reply  [nested|flat] 611+ messages in thread

* [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths
@ 2026-06-01 22:41 Andrey Chernyy <andrey.cherny@tantorlabs.com>
  0 siblings, 0 replies; 611+ messages in thread

From: Andrey Chernyy @ 2026-06-01 22:41 UTC (permalink / raw)

pgxml_xpath() builds an xpath_workspace before returning it to
callers.  If an ERROR is thrown before the function returns, callers
have not received the workspace pointer yet and cannot run
cleanup_workspace().

Add local error cleanup for the partially built workspace and the
compiled XPath expression.  Also check xmlXPathNewContext() before
dereferencing the returned context.
---
 contrib/xml2/xpath.c | 51 +++++++++++++++++++++++++++-----------------
 1 file changed, 32 insertions(+), 19 deletions(-)

diff --git a/contrib/xml2/xpath.c b/contrib/xml2/xpath.c
index 9fe75cb5ff4..283bb51178d 100644
--- a/contrib/xml2/xpath.c
+++ b/contrib/xml2/xpath.c
@@ -497,36 +497,49 @@ static xpath_workspace *
 pgxml_xpath(text *document, xmlChar *xpath, PgXmlErrorContext *xmlerrcxt)
 {
 	int32		docsize = VARSIZE_ANY_EXHDR(document);
-	xmlXPathCompExprPtr comppath;
+	xmlXPathCompExprPtr volatile comppath = NULL;
 	xpath_workspace *workspace = palloc0_object(xpath_workspace);
 
 	workspace->doctree = NULL;
 	workspace->ctxt = NULL;
 	workspace->res = NULL;
 
-	workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
-									   docsize, NULL, NULL,
-									   XML_PARSE_NOENT);
-	if (workspace->doctree != NULL)
+	PG_TRY();
 	{
-		workspace->ctxt = xmlXPathNewContext(workspace->doctree);
-		workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
-
-		/* compile the path */
-		comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
-		if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+		workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
+										   docsize, NULL, NULL,
+										   XML_PARSE_NOENT);
+		if (workspace->doctree != NULL)
 		{
-			if (comppath != NULL)
-				xmlXPathFreeCompExpr(comppath);
-			xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
-						"XPath Syntax Error");
-		}
+			workspace->ctxt = xmlXPathNewContext(workspace->doctree);
+			if (workspace->ctxt == NULL)
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_OUT_OF_MEMORY,
+							"could not allocate XPath context");
 
-		/* Now evaluate the path expression. */
-		workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+			workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
+
+			/* compile the path */
+			comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
+			if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
+							"XPath Syntax Error");
+
+			/* Now evaluate the path expression. */
+			workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+
+			xmlXPathFreeCompExpr(comppath);
+			comppath = NULL;
+		}
+	}
+	PG_CATCH();
+	{
+		if (comppath != NULL)
+			xmlXPathFreeCompExpr(comppath);
+		cleanup_workspace(workspace);
 
-		xmlXPathFreeCompExpr(comppath);
+		PG_RE_THROW();
 	}
+	PG_END_TRY();
 
 	return workspace;
 }
-- 
2.54.0


--MP_/LMSk9=uMhuQ1QiIJDarDO8G--






^ permalink  raw  reply  [nested|flat] 611+ messages in thread

* [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths
@ 2026-06-01 22:41 Andrey Chernyy <andrey.cherny@tantorlabs.com>
  0 siblings, 0 replies; 611+ messages in thread

From: Andrey Chernyy @ 2026-06-01 22:41 UTC (permalink / raw)

pgxml_xpath() builds an xpath_workspace before returning it to
callers.  If an ERROR is thrown before the function returns, callers
have not received the workspace pointer yet and cannot run
cleanup_workspace().

Add local error cleanup for the partially built workspace and the
compiled XPath expression.  Also check xmlXPathNewContext() before
dereferencing the returned context.
---
 contrib/xml2/xpath.c | 51 +++++++++++++++++++++++++++-----------------
 1 file changed, 32 insertions(+), 19 deletions(-)

diff --git a/contrib/xml2/xpath.c b/contrib/xml2/xpath.c
index 9fe75cb5ff4..283bb51178d 100644
--- a/contrib/xml2/xpath.c
+++ b/contrib/xml2/xpath.c
@@ -497,36 +497,49 @@ static xpath_workspace *
 pgxml_xpath(text *document, xmlChar *xpath, PgXmlErrorContext *xmlerrcxt)
 {
 	int32		docsize = VARSIZE_ANY_EXHDR(document);
-	xmlXPathCompExprPtr comppath;
+	xmlXPathCompExprPtr volatile comppath = NULL;
 	xpath_workspace *workspace = palloc0_object(xpath_workspace);
 
 	workspace->doctree = NULL;
 	workspace->ctxt = NULL;
 	workspace->res = NULL;
 
-	workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
-									   docsize, NULL, NULL,
-									   XML_PARSE_NOENT);
-	if (workspace->doctree != NULL)
+	PG_TRY();
 	{
-		workspace->ctxt = xmlXPathNewContext(workspace->doctree);
-		workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
-
-		/* compile the path */
-		comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
-		if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+		workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
+										   docsize, NULL, NULL,
+										   XML_PARSE_NOENT);
+		if (workspace->doctree != NULL)
 		{
-			if (comppath != NULL)
-				xmlXPathFreeCompExpr(comppath);
-			xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
-						"XPath Syntax Error");
-		}
+			workspace->ctxt = xmlXPathNewContext(workspace->doctree);
+			if (workspace->ctxt == NULL)
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_OUT_OF_MEMORY,
+							"could not allocate XPath context");
 
-		/* Now evaluate the path expression. */
-		workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+			workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
+
+			/* compile the path */
+			comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
+			if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
+							"XPath Syntax Error");
+
+			/* Now evaluate the path expression. */
+			workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+
+			xmlXPathFreeCompExpr(comppath);
+			comppath = NULL;
+		}
+	}
+	PG_CATCH();
+	{
+		if (comppath != NULL)
+			xmlXPathFreeCompExpr(comppath);
+		cleanup_workspace(workspace);
 
-		xmlXPathFreeCompExpr(comppath);
+		PG_RE_THROW();
 	}
+	PG_END_TRY();
 
 	return workspace;
 }
-- 
2.54.0


--MP_/LMSk9=uMhuQ1QiIJDarDO8G--





^ permalink  raw  reply  [nested|flat] 611+ messages in thread

* [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths
@ 2026-06-01 22:41 Andrey Chernyy <andrey.cherny@tantorlabs.com>
  0 siblings, 0 replies; 611+ messages in thread

From: Andrey Chernyy @ 2026-06-01 22:41 UTC (permalink / raw)

pgxml_xpath() builds an xpath_workspace before returning it to
callers.  If an ERROR is thrown before the function returns, callers
have not received the workspace pointer yet and cannot run
cleanup_workspace().

Add local error cleanup for the partially built workspace and the
compiled XPath expression.  Also check xmlXPathNewContext() before
dereferencing the returned context.
---
 contrib/xml2/xpath.c | 51 +++++++++++++++++++++++++++-----------------
 1 file changed, 32 insertions(+), 19 deletions(-)

diff --git a/contrib/xml2/xpath.c b/contrib/xml2/xpath.c
index 9fe75cb5ff4..283bb51178d 100644
--- a/contrib/xml2/xpath.c
+++ b/contrib/xml2/xpath.c
@@ -497,36 +497,49 @@ static xpath_workspace *
 pgxml_xpath(text *document, xmlChar *xpath, PgXmlErrorContext *xmlerrcxt)
 {
 	int32		docsize = VARSIZE_ANY_EXHDR(document);
-	xmlXPathCompExprPtr comppath;
+	xmlXPathCompExprPtr volatile comppath = NULL;
 	xpath_workspace *workspace = palloc0_object(xpath_workspace);
 
 	workspace->doctree = NULL;
 	workspace->ctxt = NULL;
 	workspace->res = NULL;
 
-	workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
-									   docsize, NULL, NULL,
-									   XML_PARSE_NOENT);
-	if (workspace->doctree != NULL)
+	PG_TRY();
 	{
-		workspace->ctxt = xmlXPathNewContext(workspace->doctree);
-		workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
-
-		/* compile the path */
-		comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
-		if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+		workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
+										   docsize, NULL, NULL,
+										   XML_PARSE_NOENT);
+		if (workspace->doctree != NULL)
 		{
-			if (comppath != NULL)
-				xmlXPathFreeCompExpr(comppath);
-			xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
-						"XPath Syntax Error");
-		}
+			workspace->ctxt = xmlXPathNewContext(workspace->doctree);
+			if (workspace->ctxt == NULL)
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_OUT_OF_MEMORY,
+							"could not allocate XPath context");
 
-		/* Now evaluate the path expression. */
-		workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+			workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
+
+			/* compile the path */
+			comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
+			if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
+							"XPath Syntax Error");
+
+			/* Now evaluate the path expression. */
+			workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+
+			xmlXPathFreeCompExpr(comppath);
+			comppath = NULL;
+		}
+	}
+	PG_CATCH();
+	{
+		if (comppath != NULL)
+			xmlXPathFreeCompExpr(comppath);
+		cleanup_workspace(workspace);
 
-		xmlXPathFreeCompExpr(comppath);
+		PG_RE_THROW();
 	}
+	PG_END_TRY();
 
 	return workspace;
 }
-- 
2.54.0


--MP_/LMSk9=uMhuQ1QiIJDarDO8G--






^ permalink  raw  reply  [nested|flat] 611+ messages in thread

* [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths
@ 2026-06-01 22:41 Andrey Chernyy <andrey.cherny@tantorlabs.com>
  0 siblings, 0 replies; 611+ messages in thread

From: Andrey Chernyy @ 2026-06-01 22:41 UTC (permalink / raw)

pgxml_xpath() builds an xpath_workspace before returning it to
callers.  If an ERROR is thrown before the function returns, callers
have not received the workspace pointer yet and cannot run
cleanup_workspace().

Add local error cleanup for the partially built workspace and the
compiled XPath expression.  Also check xmlXPathNewContext() before
dereferencing the returned context.
---
 contrib/xml2/xpath.c | 51 +++++++++++++++++++++++++++-----------------
 1 file changed, 32 insertions(+), 19 deletions(-)

diff --git a/contrib/xml2/xpath.c b/contrib/xml2/xpath.c
index 9fe75cb5ff4..283bb51178d 100644
--- a/contrib/xml2/xpath.c
+++ b/contrib/xml2/xpath.c
@@ -497,36 +497,49 @@ static xpath_workspace *
 pgxml_xpath(text *document, xmlChar *xpath, PgXmlErrorContext *xmlerrcxt)
 {
 	int32		docsize = VARSIZE_ANY_EXHDR(document);
-	xmlXPathCompExprPtr comppath;
+	xmlXPathCompExprPtr volatile comppath = NULL;
 	xpath_workspace *workspace = palloc0_object(xpath_workspace);
 
 	workspace->doctree = NULL;
 	workspace->ctxt = NULL;
 	workspace->res = NULL;
 
-	workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
-									   docsize, NULL, NULL,
-									   XML_PARSE_NOENT);
-	if (workspace->doctree != NULL)
+	PG_TRY();
 	{
-		workspace->ctxt = xmlXPathNewContext(workspace->doctree);
-		workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
-
-		/* compile the path */
-		comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
-		if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+		workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
+										   docsize, NULL, NULL,
+										   XML_PARSE_NOENT);
+		if (workspace->doctree != NULL)
 		{
-			if (comppath != NULL)
-				xmlXPathFreeCompExpr(comppath);
-			xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
-						"XPath Syntax Error");
-		}
+			workspace->ctxt = xmlXPathNewContext(workspace->doctree);
+			if (workspace->ctxt == NULL)
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_OUT_OF_MEMORY,
+							"could not allocate XPath context");
 
-		/* Now evaluate the path expression. */
-		workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+			workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
+
+			/* compile the path */
+			comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
+			if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
+							"XPath Syntax Error");
+
+			/* Now evaluate the path expression. */
+			workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+
+			xmlXPathFreeCompExpr(comppath);
+			comppath = NULL;
+		}
+	}
+	PG_CATCH();
+	{
+		if (comppath != NULL)
+			xmlXPathFreeCompExpr(comppath);
+		cleanup_workspace(workspace);
 
-		xmlXPathFreeCompExpr(comppath);
+		PG_RE_THROW();
 	}
+	PG_END_TRY();
 
 	return workspace;
 }
-- 
2.54.0


--MP_/LMSk9=uMhuQ1QiIJDarDO8G--






^ permalink  raw  reply  [nested|flat] 611+ messages in thread

* [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths
@ 2026-06-01 22:41 Andrey Chernyy <andrey.cherny@tantorlabs.com>
  0 siblings, 0 replies; 611+ messages in thread

From: Andrey Chernyy @ 2026-06-01 22:41 UTC (permalink / raw)

pgxml_xpath() builds an xpath_workspace before returning it to
callers.  If an ERROR is thrown before the function returns, callers
have not received the workspace pointer yet and cannot run
cleanup_workspace().

Add local error cleanup for the partially built workspace and the
compiled XPath expression.  Also check xmlXPathNewContext() before
dereferencing the returned context.
---
 contrib/xml2/xpath.c | 51 +++++++++++++++++++++++++++-----------------
 1 file changed, 32 insertions(+), 19 deletions(-)

diff --git a/contrib/xml2/xpath.c b/contrib/xml2/xpath.c
index 9fe75cb5ff4..283bb51178d 100644
--- a/contrib/xml2/xpath.c
+++ b/contrib/xml2/xpath.c
@@ -497,36 +497,49 @@ static xpath_workspace *
 pgxml_xpath(text *document, xmlChar *xpath, PgXmlErrorContext *xmlerrcxt)
 {
 	int32		docsize = VARSIZE_ANY_EXHDR(document);
-	xmlXPathCompExprPtr comppath;
+	xmlXPathCompExprPtr volatile comppath = NULL;
 	xpath_workspace *workspace = palloc0_object(xpath_workspace);
 
 	workspace->doctree = NULL;
 	workspace->ctxt = NULL;
 	workspace->res = NULL;
 
-	workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
-									   docsize, NULL, NULL,
-									   XML_PARSE_NOENT);
-	if (workspace->doctree != NULL)
+	PG_TRY();
 	{
-		workspace->ctxt = xmlXPathNewContext(workspace->doctree);
-		workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
-
-		/* compile the path */
-		comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
-		if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+		workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
+										   docsize, NULL, NULL,
+										   XML_PARSE_NOENT);
+		if (workspace->doctree != NULL)
 		{
-			if (comppath != NULL)
-				xmlXPathFreeCompExpr(comppath);
-			xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
-						"XPath Syntax Error");
-		}
+			workspace->ctxt = xmlXPathNewContext(workspace->doctree);
+			if (workspace->ctxt == NULL)
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_OUT_OF_MEMORY,
+							"could not allocate XPath context");
 
-		/* Now evaluate the path expression. */
-		workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+			workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
+
+			/* compile the path */
+			comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
+			if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
+							"XPath Syntax Error");
+
+			/* Now evaluate the path expression. */
+			workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+
+			xmlXPathFreeCompExpr(comppath);
+			comppath = NULL;
+		}
+	}
+	PG_CATCH();
+	{
+		if (comppath != NULL)
+			xmlXPathFreeCompExpr(comppath);
+		cleanup_workspace(workspace);
 
-		xmlXPathFreeCompExpr(comppath);
+		PG_RE_THROW();
 	}
+	PG_END_TRY();
 
 	return workspace;
 }
-- 
2.54.0


--MP_/LMSk9=uMhuQ1QiIJDarDO8G--





^ permalink  raw  reply  [nested|flat] 611+ messages in thread

* [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths
@ 2026-06-01 22:41 Andrey Chernyy <andrey.cherny@tantorlabs.com>
  0 siblings, 0 replies; 611+ messages in thread

From: Andrey Chernyy @ 2026-06-01 22:41 UTC (permalink / raw)

pgxml_xpath() builds an xpath_workspace before returning it to
callers.  If an ERROR is thrown before the function returns, callers
have not received the workspace pointer yet and cannot run
cleanup_workspace().

Add local error cleanup for the partially built workspace and the
compiled XPath expression.  Also check xmlXPathNewContext() before
dereferencing the returned context.
---
 contrib/xml2/xpath.c | 51 +++++++++++++++++++++++++++-----------------
 1 file changed, 32 insertions(+), 19 deletions(-)

diff --git a/contrib/xml2/xpath.c b/contrib/xml2/xpath.c
index 9fe75cb5ff4..283bb51178d 100644
--- a/contrib/xml2/xpath.c
+++ b/contrib/xml2/xpath.c
@@ -497,36 +497,49 @@ static xpath_workspace *
 pgxml_xpath(text *document, xmlChar *xpath, PgXmlErrorContext *xmlerrcxt)
 {
 	int32		docsize = VARSIZE_ANY_EXHDR(document);
-	xmlXPathCompExprPtr comppath;
+	xmlXPathCompExprPtr volatile comppath = NULL;
 	xpath_workspace *workspace = palloc0_object(xpath_workspace);
 
 	workspace->doctree = NULL;
 	workspace->ctxt = NULL;
 	workspace->res = NULL;
 
-	workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
-									   docsize, NULL, NULL,
-									   XML_PARSE_NOENT);
-	if (workspace->doctree != NULL)
+	PG_TRY();
 	{
-		workspace->ctxt = xmlXPathNewContext(workspace->doctree);
-		workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
-
-		/* compile the path */
-		comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
-		if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+		workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
+										   docsize, NULL, NULL,
+										   XML_PARSE_NOENT);
+		if (workspace->doctree != NULL)
 		{
-			if (comppath != NULL)
-				xmlXPathFreeCompExpr(comppath);
-			xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
-						"XPath Syntax Error");
-		}
+			workspace->ctxt = xmlXPathNewContext(workspace->doctree);
+			if (workspace->ctxt == NULL)
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_OUT_OF_MEMORY,
+							"could not allocate XPath context");
 
-		/* Now evaluate the path expression. */
-		workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+			workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
+
+			/* compile the path */
+			comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
+			if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
+							"XPath Syntax Error");
+
+			/* Now evaluate the path expression. */
+			workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+
+			xmlXPathFreeCompExpr(comppath);
+			comppath = NULL;
+		}
+	}
+	PG_CATCH();
+	{
+		if (comppath != NULL)
+			xmlXPathFreeCompExpr(comppath);
+		cleanup_workspace(workspace);
 
-		xmlXPathFreeCompExpr(comppath);
+		PG_RE_THROW();
 	}
+	PG_END_TRY();
 
 	return workspace;
 }
-- 
2.54.0


--MP_/LMSk9=uMhuQ1QiIJDarDO8G--





^ permalink  raw  reply  [nested|flat] 611+ messages in thread

* [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths
@ 2026-06-01 22:41 Andrey Chernyy <andrey.cherny@tantorlabs.com>
  0 siblings, 0 replies; 611+ messages in thread

From: Andrey Chernyy @ 2026-06-01 22:41 UTC (permalink / raw)

pgxml_xpath() builds an xpath_workspace before returning it to
callers.  If an ERROR is thrown before the function returns, callers
have not received the workspace pointer yet and cannot run
cleanup_workspace().

Add local error cleanup for the partially built workspace and the
compiled XPath expression.  Also check xmlXPathNewContext() before
dereferencing the returned context.
---
 contrib/xml2/xpath.c | 51 +++++++++++++++++++++++++++-----------------
 1 file changed, 32 insertions(+), 19 deletions(-)

diff --git a/contrib/xml2/xpath.c b/contrib/xml2/xpath.c
index 9fe75cb5ff4..283bb51178d 100644
--- a/contrib/xml2/xpath.c
+++ b/contrib/xml2/xpath.c
@@ -497,36 +497,49 @@ static xpath_workspace *
 pgxml_xpath(text *document, xmlChar *xpath, PgXmlErrorContext *xmlerrcxt)
 {
 	int32		docsize = VARSIZE_ANY_EXHDR(document);
-	xmlXPathCompExprPtr comppath;
+	xmlXPathCompExprPtr volatile comppath = NULL;
 	xpath_workspace *workspace = palloc0_object(xpath_workspace);
 
 	workspace->doctree = NULL;
 	workspace->ctxt = NULL;
 	workspace->res = NULL;
 
-	workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
-									   docsize, NULL, NULL,
-									   XML_PARSE_NOENT);
-	if (workspace->doctree != NULL)
+	PG_TRY();
 	{
-		workspace->ctxt = xmlXPathNewContext(workspace->doctree);
-		workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
-
-		/* compile the path */
-		comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
-		if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+		workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
+										   docsize, NULL, NULL,
+										   XML_PARSE_NOENT);
+		if (workspace->doctree != NULL)
 		{
-			if (comppath != NULL)
-				xmlXPathFreeCompExpr(comppath);
-			xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
-						"XPath Syntax Error");
-		}
+			workspace->ctxt = xmlXPathNewContext(workspace->doctree);
+			if (workspace->ctxt == NULL)
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_OUT_OF_MEMORY,
+							"could not allocate XPath context");
 
-		/* Now evaluate the path expression. */
-		workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+			workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
+
+			/* compile the path */
+			comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
+			if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
+							"XPath Syntax Error");
+
+			/* Now evaluate the path expression. */
+			workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+
+			xmlXPathFreeCompExpr(comppath);
+			comppath = NULL;
+		}
+	}
+	PG_CATCH();
+	{
+		if (comppath != NULL)
+			xmlXPathFreeCompExpr(comppath);
+		cleanup_workspace(workspace);
 
-		xmlXPathFreeCompExpr(comppath);
+		PG_RE_THROW();
 	}
+	PG_END_TRY();
 
 	return workspace;
 }
-- 
2.54.0


--MP_/LMSk9=uMhuQ1QiIJDarDO8G--





^ permalink  raw  reply  [nested|flat] 611+ messages in thread

* [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths
@ 2026-06-01 22:41 Andrey Chernyy <andrey.cherny@tantorlabs.com>
  0 siblings, 0 replies; 611+ messages in thread

From: Andrey Chernyy @ 2026-06-01 22:41 UTC (permalink / raw)

pgxml_xpath() builds an xpath_workspace before returning it to
callers.  If an ERROR is thrown before the function returns, callers
have not received the workspace pointer yet and cannot run
cleanup_workspace().

Add local error cleanup for the partially built workspace and the
compiled XPath expression.  Also check xmlXPathNewContext() before
dereferencing the returned context.
---
 contrib/xml2/xpath.c | 51 +++++++++++++++++++++++++++-----------------
 1 file changed, 32 insertions(+), 19 deletions(-)

diff --git a/contrib/xml2/xpath.c b/contrib/xml2/xpath.c
index 9fe75cb5ff4..283bb51178d 100644
--- a/contrib/xml2/xpath.c
+++ b/contrib/xml2/xpath.c
@@ -497,36 +497,49 @@ static xpath_workspace *
 pgxml_xpath(text *document, xmlChar *xpath, PgXmlErrorContext *xmlerrcxt)
 {
 	int32		docsize = VARSIZE_ANY_EXHDR(document);
-	xmlXPathCompExprPtr comppath;
+	xmlXPathCompExprPtr volatile comppath = NULL;
 	xpath_workspace *workspace = palloc0_object(xpath_workspace);
 
 	workspace->doctree = NULL;
 	workspace->ctxt = NULL;
 	workspace->res = NULL;
 
-	workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
-									   docsize, NULL, NULL,
-									   XML_PARSE_NOENT);
-	if (workspace->doctree != NULL)
+	PG_TRY();
 	{
-		workspace->ctxt = xmlXPathNewContext(workspace->doctree);
-		workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
-
-		/* compile the path */
-		comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
-		if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+		workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
+										   docsize, NULL, NULL,
+										   XML_PARSE_NOENT);
+		if (workspace->doctree != NULL)
 		{
-			if (comppath != NULL)
-				xmlXPathFreeCompExpr(comppath);
-			xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
-						"XPath Syntax Error");
-		}
+			workspace->ctxt = xmlXPathNewContext(workspace->doctree);
+			if (workspace->ctxt == NULL)
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_OUT_OF_MEMORY,
+							"could not allocate XPath context");
 
-		/* Now evaluate the path expression. */
-		workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+			workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
+
+			/* compile the path */
+			comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
+			if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
+							"XPath Syntax Error");
+
+			/* Now evaluate the path expression. */
+			workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+
+			xmlXPathFreeCompExpr(comppath);
+			comppath = NULL;
+		}
+	}
+	PG_CATCH();
+	{
+		if (comppath != NULL)
+			xmlXPathFreeCompExpr(comppath);
+		cleanup_workspace(workspace);
 
-		xmlXPathFreeCompExpr(comppath);
+		PG_RE_THROW();
 	}
+	PG_END_TRY();
 
 	return workspace;
 }
-- 
2.54.0


--MP_/LMSk9=uMhuQ1QiIJDarDO8G--






^ permalink  raw  reply  [nested|flat] 611+ messages in thread

* [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths
@ 2026-06-01 22:41 Andrey Chernyy <andrey.cherny@tantorlabs.com>
  0 siblings, 0 replies; 611+ messages in thread

From: Andrey Chernyy @ 2026-06-01 22:41 UTC (permalink / raw)

pgxml_xpath() builds an xpath_workspace before returning it to
callers.  If an ERROR is thrown before the function returns, callers
have not received the workspace pointer yet and cannot run
cleanup_workspace().

Add local error cleanup for the partially built workspace and the
compiled XPath expression.  Also check xmlXPathNewContext() before
dereferencing the returned context.
---
 contrib/xml2/xpath.c | 51 +++++++++++++++++++++++++++-----------------
 1 file changed, 32 insertions(+), 19 deletions(-)

diff --git a/contrib/xml2/xpath.c b/contrib/xml2/xpath.c
index 9fe75cb5ff4..283bb51178d 100644
--- a/contrib/xml2/xpath.c
+++ b/contrib/xml2/xpath.c
@@ -497,36 +497,49 @@ static xpath_workspace *
 pgxml_xpath(text *document, xmlChar *xpath, PgXmlErrorContext *xmlerrcxt)
 {
 	int32		docsize = VARSIZE_ANY_EXHDR(document);
-	xmlXPathCompExprPtr comppath;
+	xmlXPathCompExprPtr volatile comppath = NULL;
 	xpath_workspace *workspace = palloc0_object(xpath_workspace);
 
 	workspace->doctree = NULL;
 	workspace->ctxt = NULL;
 	workspace->res = NULL;
 
-	workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
-									   docsize, NULL, NULL,
-									   XML_PARSE_NOENT);
-	if (workspace->doctree != NULL)
+	PG_TRY();
 	{
-		workspace->ctxt = xmlXPathNewContext(workspace->doctree);
-		workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
-
-		/* compile the path */
-		comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
-		if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+		workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
+										   docsize, NULL, NULL,
+										   XML_PARSE_NOENT);
+		if (workspace->doctree != NULL)
 		{
-			if (comppath != NULL)
-				xmlXPathFreeCompExpr(comppath);
-			xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
-						"XPath Syntax Error");
-		}
+			workspace->ctxt = xmlXPathNewContext(workspace->doctree);
+			if (workspace->ctxt == NULL)
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_OUT_OF_MEMORY,
+							"could not allocate XPath context");
 
-		/* Now evaluate the path expression. */
-		workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+			workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
+
+			/* compile the path */
+			comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
+			if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
+							"XPath Syntax Error");
+
+			/* Now evaluate the path expression. */
+			workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+
+			xmlXPathFreeCompExpr(comppath);
+			comppath = NULL;
+		}
+	}
+	PG_CATCH();
+	{
+		if (comppath != NULL)
+			xmlXPathFreeCompExpr(comppath);
+		cleanup_workspace(workspace);
 
-		xmlXPathFreeCompExpr(comppath);
+		PG_RE_THROW();
 	}
+	PG_END_TRY();
 
 	return workspace;
 }
-- 
2.54.0


--MP_/LMSk9=uMhuQ1QiIJDarDO8G--





^ permalink  raw  reply  [nested|flat] 611+ messages in thread

* [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths
@ 2026-06-01 22:41 Andrey Chernyy <andrey.cherny@tantorlabs.com>
  0 siblings, 0 replies; 611+ messages in thread

From: Andrey Chernyy @ 2026-06-01 22:41 UTC (permalink / raw)

pgxml_xpath() builds an xpath_workspace before returning it to
callers.  If an ERROR is thrown before the function returns, callers
have not received the workspace pointer yet and cannot run
cleanup_workspace().

Add local error cleanup for the partially built workspace and the
compiled XPath expression.  Also check xmlXPathNewContext() before
dereferencing the returned context.
---
 contrib/xml2/xpath.c | 51 +++++++++++++++++++++++++++-----------------
 1 file changed, 32 insertions(+), 19 deletions(-)

diff --git a/contrib/xml2/xpath.c b/contrib/xml2/xpath.c
index 9fe75cb5ff4..283bb51178d 100644
--- a/contrib/xml2/xpath.c
+++ b/contrib/xml2/xpath.c
@@ -497,36 +497,49 @@ static xpath_workspace *
 pgxml_xpath(text *document, xmlChar *xpath, PgXmlErrorContext *xmlerrcxt)
 {
 	int32		docsize = VARSIZE_ANY_EXHDR(document);
-	xmlXPathCompExprPtr comppath;
+	xmlXPathCompExprPtr volatile comppath = NULL;
 	xpath_workspace *workspace = palloc0_object(xpath_workspace);
 
 	workspace->doctree = NULL;
 	workspace->ctxt = NULL;
 	workspace->res = NULL;
 
-	workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
-									   docsize, NULL, NULL,
-									   XML_PARSE_NOENT);
-	if (workspace->doctree != NULL)
+	PG_TRY();
 	{
-		workspace->ctxt = xmlXPathNewContext(workspace->doctree);
-		workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
-
-		/* compile the path */
-		comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
-		if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+		workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
+										   docsize, NULL, NULL,
+										   XML_PARSE_NOENT);
+		if (workspace->doctree != NULL)
 		{
-			if (comppath != NULL)
-				xmlXPathFreeCompExpr(comppath);
-			xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
-						"XPath Syntax Error");
-		}
+			workspace->ctxt = xmlXPathNewContext(workspace->doctree);
+			if (workspace->ctxt == NULL)
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_OUT_OF_MEMORY,
+							"could not allocate XPath context");
 
-		/* Now evaluate the path expression. */
-		workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+			workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
+
+			/* compile the path */
+			comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
+			if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
+							"XPath Syntax Error");
+
+			/* Now evaluate the path expression. */
+			workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+
+			xmlXPathFreeCompExpr(comppath);
+			comppath = NULL;
+		}
+	}
+	PG_CATCH();
+	{
+		if (comppath != NULL)
+			xmlXPathFreeCompExpr(comppath);
+		cleanup_workspace(workspace);
 
-		xmlXPathFreeCompExpr(comppath);
+		PG_RE_THROW();
 	}
+	PG_END_TRY();
 
 	return workspace;
 }
-- 
2.54.0


--MP_/LMSk9=uMhuQ1QiIJDarDO8G--





^ permalink  raw  reply  [nested|flat] 611+ messages in thread

* [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths
@ 2026-06-01 22:41 Andrey Chernyy <andrey.cherny@tantorlabs.com>
  0 siblings, 0 replies; 611+ messages in thread

From: Andrey Chernyy @ 2026-06-01 22:41 UTC (permalink / raw)

pgxml_xpath() builds an xpath_workspace before returning it to
callers.  If an ERROR is thrown before the function returns, callers
have not received the workspace pointer yet and cannot run
cleanup_workspace().

Add local error cleanup for the partially built workspace and the
compiled XPath expression.  Also check xmlXPathNewContext() before
dereferencing the returned context.
---
 contrib/xml2/xpath.c | 51 +++++++++++++++++++++++++++-----------------
 1 file changed, 32 insertions(+), 19 deletions(-)

diff --git a/contrib/xml2/xpath.c b/contrib/xml2/xpath.c
index 9fe75cb5ff4..283bb51178d 100644
--- a/contrib/xml2/xpath.c
+++ b/contrib/xml2/xpath.c
@@ -497,36 +497,49 @@ static xpath_workspace *
 pgxml_xpath(text *document, xmlChar *xpath, PgXmlErrorContext *xmlerrcxt)
 {
 	int32		docsize = VARSIZE_ANY_EXHDR(document);
-	xmlXPathCompExprPtr comppath;
+	xmlXPathCompExprPtr volatile comppath = NULL;
 	xpath_workspace *workspace = palloc0_object(xpath_workspace);
 
 	workspace->doctree = NULL;
 	workspace->ctxt = NULL;
 	workspace->res = NULL;
 
-	workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
-									   docsize, NULL, NULL,
-									   XML_PARSE_NOENT);
-	if (workspace->doctree != NULL)
+	PG_TRY();
 	{
-		workspace->ctxt = xmlXPathNewContext(workspace->doctree);
-		workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
-
-		/* compile the path */
-		comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
-		if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+		workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
+										   docsize, NULL, NULL,
+										   XML_PARSE_NOENT);
+		if (workspace->doctree != NULL)
 		{
-			if (comppath != NULL)
-				xmlXPathFreeCompExpr(comppath);
-			xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
-						"XPath Syntax Error");
-		}
+			workspace->ctxt = xmlXPathNewContext(workspace->doctree);
+			if (workspace->ctxt == NULL)
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_OUT_OF_MEMORY,
+							"could not allocate XPath context");
 
-		/* Now evaluate the path expression. */
-		workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+			workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
+
+			/* compile the path */
+			comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
+			if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
+							"XPath Syntax Error");
+
+			/* Now evaluate the path expression. */
+			workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+
+			xmlXPathFreeCompExpr(comppath);
+			comppath = NULL;
+		}
+	}
+	PG_CATCH();
+	{
+		if (comppath != NULL)
+			xmlXPathFreeCompExpr(comppath);
+		cleanup_workspace(workspace);
 
-		xmlXPathFreeCompExpr(comppath);
+		PG_RE_THROW();
 	}
+	PG_END_TRY();
 
 	return workspace;
 }
-- 
2.54.0


--MP_/LMSk9=uMhuQ1QiIJDarDO8G--






^ permalink  raw  reply  [nested|flat] 611+ messages in thread

* [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths
@ 2026-06-01 22:41 Andrey Chernyy <andrey.cherny@tantorlabs.com>
  0 siblings, 0 replies; 611+ messages in thread

From: Andrey Chernyy @ 2026-06-01 22:41 UTC (permalink / raw)

pgxml_xpath() builds an xpath_workspace before returning it to
callers.  If an ERROR is thrown before the function returns, callers
have not received the workspace pointer yet and cannot run
cleanup_workspace().

Add local error cleanup for the partially built workspace and the
compiled XPath expression.  Also check xmlXPathNewContext() before
dereferencing the returned context.
---
 contrib/xml2/xpath.c | 51 +++++++++++++++++++++++++++-----------------
 1 file changed, 32 insertions(+), 19 deletions(-)

diff --git a/contrib/xml2/xpath.c b/contrib/xml2/xpath.c
index 9fe75cb5ff4..283bb51178d 100644
--- a/contrib/xml2/xpath.c
+++ b/contrib/xml2/xpath.c
@@ -497,36 +497,49 @@ static xpath_workspace *
 pgxml_xpath(text *document, xmlChar *xpath, PgXmlErrorContext *xmlerrcxt)
 {
 	int32		docsize = VARSIZE_ANY_EXHDR(document);
-	xmlXPathCompExprPtr comppath;
+	xmlXPathCompExprPtr volatile comppath = NULL;
 	xpath_workspace *workspace = palloc0_object(xpath_workspace);
 
 	workspace->doctree = NULL;
 	workspace->ctxt = NULL;
 	workspace->res = NULL;
 
-	workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
-									   docsize, NULL, NULL,
-									   XML_PARSE_NOENT);
-	if (workspace->doctree != NULL)
+	PG_TRY();
 	{
-		workspace->ctxt = xmlXPathNewContext(workspace->doctree);
-		workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
-
-		/* compile the path */
-		comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
-		if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+		workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
+										   docsize, NULL, NULL,
+										   XML_PARSE_NOENT);
+		if (workspace->doctree != NULL)
 		{
-			if (comppath != NULL)
-				xmlXPathFreeCompExpr(comppath);
-			xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
-						"XPath Syntax Error");
-		}
+			workspace->ctxt = xmlXPathNewContext(workspace->doctree);
+			if (workspace->ctxt == NULL)
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_OUT_OF_MEMORY,
+							"could not allocate XPath context");
 
-		/* Now evaluate the path expression. */
-		workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+			workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
+
+			/* compile the path */
+			comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
+			if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
+							"XPath Syntax Error");
+
+			/* Now evaluate the path expression. */
+			workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+
+			xmlXPathFreeCompExpr(comppath);
+			comppath = NULL;
+		}
+	}
+	PG_CATCH();
+	{
+		if (comppath != NULL)
+			xmlXPathFreeCompExpr(comppath);
+		cleanup_workspace(workspace);
 
-		xmlXPathFreeCompExpr(comppath);
+		PG_RE_THROW();
 	}
+	PG_END_TRY();
 
 	return workspace;
 }
-- 
2.54.0


--MP_/LMSk9=uMhuQ1QiIJDarDO8G--





^ permalink  raw  reply  [nested|flat] 611+ messages in thread

* [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths
@ 2026-06-01 22:41 Andrey Chernyy <andrey.cherny@tantorlabs.com>
  0 siblings, 0 replies; 611+ messages in thread

From: Andrey Chernyy @ 2026-06-01 22:41 UTC (permalink / raw)

pgxml_xpath() builds an xpath_workspace before returning it to
callers.  If an ERROR is thrown before the function returns, callers
have not received the workspace pointer yet and cannot run
cleanup_workspace().

Add local error cleanup for the partially built workspace and the
compiled XPath expression.  Also check xmlXPathNewContext() before
dereferencing the returned context.
---
 contrib/xml2/xpath.c | 51 +++++++++++++++++++++++++++-----------------
 1 file changed, 32 insertions(+), 19 deletions(-)

diff --git a/contrib/xml2/xpath.c b/contrib/xml2/xpath.c
index 9fe75cb5ff4..283bb51178d 100644
--- a/contrib/xml2/xpath.c
+++ b/contrib/xml2/xpath.c
@@ -497,36 +497,49 @@ static xpath_workspace *
 pgxml_xpath(text *document, xmlChar *xpath, PgXmlErrorContext *xmlerrcxt)
 {
 	int32		docsize = VARSIZE_ANY_EXHDR(document);
-	xmlXPathCompExprPtr comppath;
+	xmlXPathCompExprPtr volatile comppath = NULL;
 	xpath_workspace *workspace = palloc0_object(xpath_workspace);
 
 	workspace->doctree = NULL;
 	workspace->ctxt = NULL;
 	workspace->res = NULL;
 
-	workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
-									   docsize, NULL, NULL,
-									   XML_PARSE_NOENT);
-	if (workspace->doctree != NULL)
+	PG_TRY();
 	{
-		workspace->ctxt = xmlXPathNewContext(workspace->doctree);
-		workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
-
-		/* compile the path */
-		comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
-		if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+		workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
+										   docsize, NULL, NULL,
+										   XML_PARSE_NOENT);
+		if (workspace->doctree != NULL)
 		{
-			if (comppath != NULL)
-				xmlXPathFreeCompExpr(comppath);
-			xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
-						"XPath Syntax Error");
-		}
+			workspace->ctxt = xmlXPathNewContext(workspace->doctree);
+			if (workspace->ctxt == NULL)
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_OUT_OF_MEMORY,
+							"could not allocate XPath context");
 
-		/* Now evaluate the path expression. */
-		workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+			workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
+
+			/* compile the path */
+			comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
+			if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
+							"XPath Syntax Error");
+
+			/* Now evaluate the path expression. */
+			workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+
+			xmlXPathFreeCompExpr(comppath);
+			comppath = NULL;
+		}
+	}
+	PG_CATCH();
+	{
+		if (comppath != NULL)
+			xmlXPathFreeCompExpr(comppath);
+		cleanup_workspace(workspace);
 
-		xmlXPathFreeCompExpr(comppath);
+		PG_RE_THROW();
 	}
+	PG_END_TRY();
 
 	return workspace;
 }
-- 
2.54.0


--MP_/LMSk9=uMhuQ1QiIJDarDO8G--





^ permalink  raw  reply  [nested|flat] 611+ messages in thread

* [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths
@ 2026-06-01 22:41 Andrey Chernyy <andrey.cherny@tantorlabs.com>
  0 siblings, 0 replies; 611+ messages in thread

From: Andrey Chernyy @ 2026-06-01 22:41 UTC (permalink / raw)

pgxml_xpath() builds an xpath_workspace before returning it to
callers.  If an ERROR is thrown before the function returns, callers
have not received the workspace pointer yet and cannot run
cleanup_workspace().

Add local error cleanup for the partially built workspace and the
compiled XPath expression.  Also check xmlXPathNewContext() before
dereferencing the returned context.
---
 contrib/xml2/xpath.c | 51 +++++++++++++++++++++++++++-----------------
 1 file changed, 32 insertions(+), 19 deletions(-)

diff --git a/contrib/xml2/xpath.c b/contrib/xml2/xpath.c
index 9fe75cb5ff4..283bb51178d 100644
--- a/contrib/xml2/xpath.c
+++ b/contrib/xml2/xpath.c
@@ -497,36 +497,49 @@ static xpath_workspace *
 pgxml_xpath(text *document, xmlChar *xpath, PgXmlErrorContext *xmlerrcxt)
 {
 	int32		docsize = VARSIZE_ANY_EXHDR(document);
-	xmlXPathCompExprPtr comppath;
+	xmlXPathCompExprPtr volatile comppath = NULL;
 	xpath_workspace *workspace = palloc0_object(xpath_workspace);
 
 	workspace->doctree = NULL;
 	workspace->ctxt = NULL;
 	workspace->res = NULL;
 
-	workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
-									   docsize, NULL, NULL,
-									   XML_PARSE_NOENT);
-	if (workspace->doctree != NULL)
+	PG_TRY();
 	{
-		workspace->ctxt = xmlXPathNewContext(workspace->doctree);
-		workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
-
-		/* compile the path */
-		comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
-		if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+		workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
+										   docsize, NULL, NULL,
+										   XML_PARSE_NOENT);
+		if (workspace->doctree != NULL)
 		{
-			if (comppath != NULL)
-				xmlXPathFreeCompExpr(comppath);
-			xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
-						"XPath Syntax Error");
-		}
+			workspace->ctxt = xmlXPathNewContext(workspace->doctree);
+			if (workspace->ctxt == NULL)
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_OUT_OF_MEMORY,
+							"could not allocate XPath context");
 
-		/* Now evaluate the path expression. */
-		workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+			workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
+
+			/* compile the path */
+			comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
+			if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
+							"XPath Syntax Error");
+
+			/* Now evaluate the path expression. */
+			workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+
+			xmlXPathFreeCompExpr(comppath);
+			comppath = NULL;
+		}
+	}
+	PG_CATCH();
+	{
+		if (comppath != NULL)
+			xmlXPathFreeCompExpr(comppath);
+		cleanup_workspace(workspace);
 
-		xmlXPathFreeCompExpr(comppath);
+		PG_RE_THROW();
 	}
+	PG_END_TRY();
 
 	return workspace;
 }
-- 
2.54.0


--MP_/LMSk9=uMhuQ1QiIJDarDO8G--






^ permalink  raw  reply  [nested|flat] 611+ messages in thread

* [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths
@ 2026-06-01 22:41 Andrey Chernyy <andrey.cherny@tantorlabs.com>
  0 siblings, 0 replies; 611+ messages in thread

From: Andrey Chernyy @ 2026-06-01 22:41 UTC (permalink / raw)

pgxml_xpath() builds an xpath_workspace before returning it to
callers.  If an ERROR is thrown before the function returns, callers
have not received the workspace pointer yet and cannot run
cleanup_workspace().

Add local error cleanup for the partially built workspace and the
compiled XPath expression.  Also check xmlXPathNewContext() before
dereferencing the returned context.
---
 contrib/xml2/xpath.c | 51 +++++++++++++++++++++++++++-----------------
 1 file changed, 32 insertions(+), 19 deletions(-)

diff --git a/contrib/xml2/xpath.c b/contrib/xml2/xpath.c
index 9fe75cb5ff4..283bb51178d 100644
--- a/contrib/xml2/xpath.c
+++ b/contrib/xml2/xpath.c
@@ -497,36 +497,49 @@ static xpath_workspace *
 pgxml_xpath(text *document, xmlChar *xpath, PgXmlErrorContext *xmlerrcxt)
 {
 	int32		docsize = VARSIZE_ANY_EXHDR(document);
-	xmlXPathCompExprPtr comppath;
+	xmlXPathCompExprPtr volatile comppath = NULL;
 	xpath_workspace *workspace = palloc0_object(xpath_workspace);
 
 	workspace->doctree = NULL;
 	workspace->ctxt = NULL;
 	workspace->res = NULL;
 
-	workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
-									   docsize, NULL, NULL,
-									   XML_PARSE_NOENT);
-	if (workspace->doctree != NULL)
+	PG_TRY();
 	{
-		workspace->ctxt = xmlXPathNewContext(workspace->doctree);
-		workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
-
-		/* compile the path */
-		comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
-		if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+		workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
+										   docsize, NULL, NULL,
+										   XML_PARSE_NOENT);
+		if (workspace->doctree != NULL)
 		{
-			if (comppath != NULL)
-				xmlXPathFreeCompExpr(comppath);
-			xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
-						"XPath Syntax Error");
-		}
+			workspace->ctxt = xmlXPathNewContext(workspace->doctree);
+			if (workspace->ctxt == NULL)
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_OUT_OF_MEMORY,
+							"could not allocate XPath context");
 
-		/* Now evaluate the path expression. */
-		workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+			workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
+
+			/* compile the path */
+			comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
+			if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
+							"XPath Syntax Error");
+
+			/* Now evaluate the path expression. */
+			workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+
+			xmlXPathFreeCompExpr(comppath);
+			comppath = NULL;
+		}
+	}
+	PG_CATCH();
+	{
+		if (comppath != NULL)
+			xmlXPathFreeCompExpr(comppath);
+		cleanup_workspace(workspace);
 
-		xmlXPathFreeCompExpr(comppath);
+		PG_RE_THROW();
 	}
+	PG_END_TRY();
 
 	return workspace;
 }
-- 
2.54.0


--MP_/LMSk9=uMhuQ1QiIJDarDO8G--





^ permalink  raw  reply  [nested|flat] 611+ messages in thread

* [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths
@ 2026-06-01 22:41 Andrey Chernyy <andrey.cherny@tantorlabs.com>
  0 siblings, 0 replies; 611+ messages in thread

From: Andrey Chernyy @ 2026-06-01 22:41 UTC (permalink / raw)

pgxml_xpath() builds an xpath_workspace before returning it to
callers.  If an ERROR is thrown before the function returns, callers
have not received the workspace pointer yet and cannot run
cleanup_workspace().

Add local error cleanup for the partially built workspace and the
compiled XPath expression.  Also check xmlXPathNewContext() before
dereferencing the returned context.
---
 contrib/xml2/xpath.c | 51 +++++++++++++++++++++++++++-----------------
 1 file changed, 32 insertions(+), 19 deletions(-)

diff --git a/contrib/xml2/xpath.c b/contrib/xml2/xpath.c
index 9fe75cb5ff4..283bb51178d 100644
--- a/contrib/xml2/xpath.c
+++ b/contrib/xml2/xpath.c
@@ -497,36 +497,49 @@ static xpath_workspace *
 pgxml_xpath(text *document, xmlChar *xpath, PgXmlErrorContext *xmlerrcxt)
 {
 	int32		docsize = VARSIZE_ANY_EXHDR(document);
-	xmlXPathCompExprPtr comppath;
+	xmlXPathCompExprPtr volatile comppath = NULL;
 	xpath_workspace *workspace = palloc0_object(xpath_workspace);
 
 	workspace->doctree = NULL;
 	workspace->ctxt = NULL;
 	workspace->res = NULL;
 
-	workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
-									   docsize, NULL, NULL,
-									   XML_PARSE_NOENT);
-	if (workspace->doctree != NULL)
+	PG_TRY();
 	{
-		workspace->ctxt = xmlXPathNewContext(workspace->doctree);
-		workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
-
-		/* compile the path */
-		comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
-		if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+		workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
+										   docsize, NULL, NULL,
+										   XML_PARSE_NOENT);
+		if (workspace->doctree != NULL)
 		{
-			if (comppath != NULL)
-				xmlXPathFreeCompExpr(comppath);
-			xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
-						"XPath Syntax Error");
-		}
+			workspace->ctxt = xmlXPathNewContext(workspace->doctree);
+			if (workspace->ctxt == NULL)
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_OUT_OF_MEMORY,
+							"could not allocate XPath context");
 
-		/* Now evaluate the path expression. */
-		workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+			workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
+
+			/* compile the path */
+			comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
+			if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
+							"XPath Syntax Error");
+
+			/* Now evaluate the path expression. */
+			workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+
+			xmlXPathFreeCompExpr(comppath);
+			comppath = NULL;
+		}
+	}
+	PG_CATCH();
+	{
+		if (comppath != NULL)
+			xmlXPathFreeCompExpr(comppath);
+		cleanup_workspace(workspace);
 
-		xmlXPathFreeCompExpr(comppath);
+		PG_RE_THROW();
 	}
+	PG_END_TRY();
 
 	return workspace;
 }
-- 
2.54.0


--MP_/LMSk9=uMhuQ1QiIJDarDO8G--






^ permalink  raw  reply  [nested|flat] 611+ messages in thread

* [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths
@ 2026-06-01 22:41 Andrey Chernyy <andrey.cherny@tantorlabs.com>
  0 siblings, 0 replies; 611+ messages in thread

From: Andrey Chernyy @ 2026-06-01 22:41 UTC (permalink / raw)

pgxml_xpath() builds an xpath_workspace before returning it to
callers.  If an ERROR is thrown before the function returns, callers
have not received the workspace pointer yet and cannot run
cleanup_workspace().

Add local error cleanup for the partially built workspace and the
compiled XPath expression.  Also check xmlXPathNewContext() before
dereferencing the returned context.
---
 contrib/xml2/xpath.c | 51 +++++++++++++++++++++++++++-----------------
 1 file changed, 32 insertions(+), 19 deletions(-)

diff --git a/contrib/xml2/xpath.c b/contrib/xml2/xpath.c
index 9fe75cb5ff4..283bb51178d 100644
--- a/contrib/xml2/xpath.c
+++ b/contrib/xml2/xpath.c
@@ -497,36 +497,49 @@ static xpath_workspace *
 pgxml_xpath(text *document, xmlChar *xpath, PgXmlErrorContext *xmlerrcxt)
 {
 	int32		docsize = VARSIZE_ANY_EXHDR(document);
-	xmlXPathCompExprPtr comppath;
+	xmlXPathCompExprPtr volatile comppath = NULL;
 	xpath_workspace *workspace = palloc0_object(xpath_workspace);
 
 	workspace->doctree = NULL;
 	workspace->ctxt = NULL;
 	workspace->res = NULL;
 
-	workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
-									   docsize, NULL, NULL,
-									   XML_PARSE_NOENT);
-	if (workspace->doctree != NULL)
+	PG_TRY();
 	{
-		workspace->ctxt = xmlXPathNewContext(workspace->doctree);
-		workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
-
-		/* compile the path */
-		comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
-		if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+		workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
+										   docsize, NULL, NULL,
+										   XML_PARSE_NOENT);
+		if (workspace->doctree != NULL)
 		{
-			if (comppath != NULL)
-				xmlXPathFreeCompExpr(comppath);
-			xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
-						"XPath Syntax Error");
-		}
+			workspace->ctxt = xmlXPathNewContext(workspace->doctree);
+			if (workspace->ctxt == NULL)
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_OUT_OF_MEMORY,
+							"could not allocate XPath context");
 
-		/* Now evaluate the path expression. */
-		workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+			workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
+
+			/* compile the path */
+			comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
+			if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
+							"XPath Syntax Error");
+
+			/* Now evaluate the path expression. */
+			workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+
+			xmlXPathFreeCompExpr(comppath);
+			comppath = NULL;
+		}
+	}
+	PG_CATCH();
+	{
+		if (comppath != NULL)
+			xmlXPathFreeCompExpr(comppath);
+		cleanup_workspace(workspace);
 
-		xmlXPathFreeCompExpr(comppath);
+		PG_RE_THROW();
 	}
+	PG_END_TRY();
 
 	return workspace;
 }
-- 
2.54.0


--MP_/LMSk9=uMhuQ1QiIJDarDO8G--





^ permalink  raw  reply  [nested|flat] 611+ messages in thread

* [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths
@ 2026-06-01 22:41 Andrey Chernyy <andrey.cherny@tantorlabs.com>
  0 siblings, 0 replies; 611+ messages in thread

From: Andrey Chernyy @ 2026-06-01 22:41 UTC (permalink / raw)

pgxml_xpath() builds an xpath_workspace before returning it to
callers.  If an ERROR is thrown before the function returns, callers
have not received the workspace pointer yet and cannot run
cleanup_workspace().

Add local error cleanup for the partially built workspace and the
compiled XPath expression.  Also check xmlXPathNewContext() before
dereferencing the returned context.
---
 contrib/xml2/xpath.c | 51 +++++++++++++++++++++++++++-----------------
 1 file changed, 32 insertions(+), 19 deletions(-)

diff --git a/contrib/xml2/xpath.c b/contrib/xml2/xpath.c
index 9fe75cb5ff4..283bb51178d 100644
--- a/contrib/xml2/xpath.c
+++ b/contrib/xml2/xpath.c
@@ -497,36 +497,49 @@ static xpath_workspace *
 pgxml_xpath(text *document, xmlChar *xpath, PgXmlErrorContext *xmlerrcxt)
 {
 	int32		docsize = VARSIZE_ANY_EXHDR(document);
-	xmlXPathCompExprPtr comppath;
+	xmlXPathCompExprPtr volatile comppath = NULL;
 	xpath_workspace *workspace = palloc0_object(xpath_workspace);
 
 	workspace->doctree = NULL;
 	workspace->ctxt = NULL;
 	workspace->res = NULL;
 
-	workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
-									   docsize, NULL, NULL,
-									   XML_PARSE_NOENT);
-	if (workspace->doctree != NULL)
+	PG_TRY();
 	{
-		workspace->ctxt = xmlXPathNewContext(workspace->doctree);
-		workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
-
-		/* compile the path */
-		comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
-		if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+		workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
+										   docsize, NULL, NULL,
+										   XML_PARSE_NOENT);
+		if (workspace->doctree != NULL)
 		{
-			if (comppath != NULL)
-				xmlXPathFreeCompExpr(comppath);
-			xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
-						"XPath Syntax Error");
-		}
+			workspace->ctxt = xmlXPathNewContext(workspace->doctree);
+			if (workspace->ctxt == NULL)
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_OUT_OF_MEMORY,
+							"could not allocate XPath context");
 
-		/* Now evaluate the path expression. */
-		workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+			workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
+
+			/* compile the path */
+			comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
+			if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
+							"XPath Syntax Error");
+
+			/* Now evaluate the path expression. */
+			workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+
+			xmlXPathFreeCompExpr(comppath);
+			comppath = NULL;
+		}
+	}
+	PG_CATCH();
+	{
+		if (comppath != NULL)
+			xmlXPathFreeCompExpr(comppath);
+		cleanup_workspace(workspace);
 
-		xmlXPathFreeCompExpr(comppath);
+		PG_RE_THROW();
 	}
+	PG_END_TRY();
 
 	return workspace;
 }
-- 
2.54.0


--MP_/LMSk9=uMhuQ1QiIJDarDO8G--





^ permalink  raw  reply  [nested|flat] 611+ messages in thread

* [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths
@ 2026-06-01 22:41 Andrey Chernyy <andrey.cherny@tantorlabs.com>
  0 siblings, 0 replies; 611+ messages in thread

From: Andrey Chernyy @ 2026-06-01 22:41 UTC (permalink / raw)

pgxml_xpath() builds an xpath_workspace before returning it to
callers.  If an ERROR is thrown before the function returns, callers
have not received the workspace pointer yet and cannot run
cleanup_workspace().

Add local error cleanup for the partially built workspace and the
compiled XPath expression.  Also check xmlXPathNewContext() before
dereferencing the returned context.
---
 contrib/xml2/xpath.c | 51 +++++++++++++++++++++++++++-----------------
 1 file changed, 32 insertions(+), 19 deletions(-)

diff --git a/contrib/xml2/xpath.c b/contrib/xml2/xpath.c
index 9fe75cb5ff4..283bb51178d 100644
--- a/contrib/xml2/xpath.c
+++ b/contrib/xml2/xpath.c
@@ -497,36 +497,49 @@ static xpath_workspace *
 pgxml_xpath(text *document, xmlChar *xpath, PgXmlErrorContext *xmlerrcxt)
 {
 	int32		docsize = VARSIZE_ANY_EXHDR(document);
-	xmlXPathCompExprPtr comppath;
+	xmlXPathCompExprPtr volatile comppath = NULL;
 	xpath_workspace *workspace = palloc0_object(xpath_workspace);
 
 	workspace->doctree = NULL;
 	workspace->ctxt = NULL;
 	workspace->res = NULL;
 
-	workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
-									   docsize, NULL, NULL,
-									   XML_PARSE_NOENT);
-	if (workspace->doctree != NULL)
+	PG_TRY();
 	{
-		workspace->ctxt = xmlXPathNewContext(workspace->doctree);
-		workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
-
-		/* compile the path */
-		comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
-		if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+		workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
+										   docsize, NULL, NULL,
+										   XML_PARSE_NOENT);
+		if (workspace->doctree != NULL)
 		{
-			if (comppath != NULL)
-				xmlXPathFreeCompExpr(comppath);
-			xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
-						"XPath Syntax Error");
-		}
+			workspace->ctxt = xmlXPathNewContext(workspace->doctree);
+			if (workspace->ctxt == NULL)
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_OUT_OF_MEMORY,
+							"could not allocate XPath context");
 
-		/* Now evaluate the path expression. */
-		workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+			workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
+
+			/* compile the path */
+			comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
+			if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
+							"XPath Syntax Error");
+
+			/* Now evaluate the path expression. */
+			workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+
+			xmlXPathFreeCompExpr(comppath);
+			comppath = NULL;
+		}
+	}
+	PG_CATCH();
+	{
+		if (comppath != NULL)
+			xmlXPathFreeCompExpr(comppath);
+		cleanup_workspace(workspace);
 
-		xmlXPathFreeCompExpr(comppath);
+		PG_RE_THROW();
 	}
+	PG_END_TRY();
 
 	return workspace;
 }
-- 
2.54.0


--MP_/LMSk9=uMhuQ1QiIJDarDO8G--






^ permalink  raw  reply  [nested|flat] 611+ messages in thread

* [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths
@ 2026-06-01 22:41 Andrey Chernyy <andrey.cherny@tantorlabs.com>
  0 siblings, 0 replies; 611+ messages in thread

From: Andrey Chernyy @ 2026-06-01 22:41 UTC (permalink / raw)

pgxml_xpath() builds an xpath_workspace before returning it to
callers.  If an ERROR is thrown before the function returns, callers
have not received the workspace pointer yet and cannot run
cleanup_workspace().

Add local error cleanup for the partially built workspace and the
compiled XPath expression.  Also check xmlXPathNewContext() before
dereferencing the returned context.
---
 contrib/xml2/xpath.c | 51 +++++++++++++++++++++++++++-----------------
 1 file changed, 32 insertions(+), 19 deletions(-)

diff --git a/contrib/xml2/xpath.c b/contrib/xml2/xpath.c
index 9fe75cb5ff4..283bb51178d 100644
--- a/contrib/xml2/xpath.c
+++ b/contrib/xml2/xpath.c
@@ -497,36 +497,49 @@ static xpath_workspace *
 pgxml_xpath(text *document, xmlChar *xpath, PgXmlErrorContext *xmlerrcxt)
 {
 	int32		docsize = VARSIZE_ANY_EXHDR(document);
-	xmlXPathCompExprPtr comppath;
+	xmlXPathCompExprPtr volatile comppath = NULL;
 	xpath_workspace *workspace = palloc0_object(xpath_workspace);
 
 	workspace->doctree = NULL;
 	workspace->ctxt = NULL;
 	workspace->res = NULL;
 
-	workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
-									   docsize, NULL, NULL,
-									   XML_PARSE_NOENT);
-	if (workspace->doctree != NULL)
+	PG_TRY();
 	{
-		workspace->ctxt = xmlXPathNewContext(workspace->doctree);
-		workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
-
-		/* compile the path */
-		comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
-		if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+		workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
+										   docsize, NULL, NULL,
+										   XML_PARSE_NOENT);
+		if (workspace->doctree != NULL)
 		{
-			if (comppath != NULL)
-				xmlXPathFreeCompExpr(comppath);
-			xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
-						"XPath Syntax Error");
-		}
+			workspace->ctxt = xmlXPathNewContext(workspace->doctree);
+			if (workspace->ctxt == NULL)
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_OUT_OF_MEMORY,
+							"could not allocate XPath context");
 
-		/* Now evaluate the path expression. */
-		workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+			workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
+
+			/* compile the path */
+			comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
+			if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
+							"XPath Syntax Error");
+
+			/* Now evaluate the path expression. */
+			workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+
+			xmlXPathFreeCompExpr(comppath);
+			comppath = NULL;
+		}
+	}
+	PG_CATCH();
+	{
+		if (comppath != NULL)
+			xmlXPathFreeCompExpr(comppath);
+		cleanup_workspace(workspace);
 
-		xmlXPathFreeCompExpr(comppath);
+		PG_RE_THROW();
 	}
+	PG_END_TRY();
 
 	return workspace;
 }
-- 
2.54.0


--MP_/LMSk9=uMhuQ1QiIJDarDO8G--






^ permalink  raw  reply  [nested|flat] 611+ messages in thread

* [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths
@ 2026-06-01 22:41 Andrey Chernyy <andrey.cherny@tantorlabs.com>
  0 siblings, 0 replies; 611+ messages in thread

From: Andrey Chernyy @ 2026-06-01 22:41 UTC (permalink / raw)

pgxml_xpath() builds an xpath_workspace before returning it to
callers.  If an ERROR is thrown before the function returns, callers
have not received the workspace pointer yet and cannot run
cleanup_workspace().

Add local error cleanup for the partially built workspace and the
compiled XPath expression.  Also check xmlXPathNewContext() before
dereferencing the returned context.
---
 contrib/xml2/xpath.c | 51 +++++++++++++++++++++++++++-----------------
 1 file changed, 32 insertions(+), 19 deletions(-)

diff --git a/contrib/xml2/xpath.c b/contrib/xml2/xpath.c
index 9fe75cb5ff4..283bb51178d 100644
--- a/contrib/xml2/xpath.c
+++ b/contrib/xml2/xpath.c
@@ -497,36 +497,49 @@ static xpath_workspace *
 pgxml_xpath(text *document, xmlChar *xpath, PgXmlErrorContext *xmlerrcxt)
 {
 	int32		docsize = VARSIZE_ANY_EXHDR(document);
-	xmlXPathCompExprPtr comppath;
+	xmlXPathCompExprPtr volatile comppath = NULL;
 	xpath_workspace *workspace = palloc0_object(xpath_workspace);
 
 	workspace->doctree = NULL;
 	workspace->ctxt = NULL;
 	workspace->res = NULL;
 
-	workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
-									   docsize, NULL, NULL,
-									   XML_PARSE_NOENT);
-	if (workspace->doctree != NULL)
+	PG_TRY();
 	{
-		workspace->ctxt = xmlXPathNewContext(workspace->doctree);
-		workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
-
-		/* compile the path */
-		comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
-		if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+		workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
+										   docsize, NULL, NULL,
+										   XML_PARSE_NOENT);
+		if (workspace->doctree != NULL)
 		{
-			if (comppath != NULL)
-				xmlXPathFreeCompExpr(comppath);
-			xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
-						"XPath Syntax Error");
-		}
+			workspace->ctxt = xmlXPathNewContext(workspace->doctree);
+			if (workspace->ctxt == NULL)
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_OUT_OF_MEMORY,
+							"could not allocate XPath context");
 
-		/* Now evaluate the path expression. */
-		workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+			workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
+
+			/* compile the path */
+			comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
+			if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
+							"XPath Syntax Error");
+
+			/* Now evaluate the path expression. */
+			workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+
+			xmlXPathFreeCompExpr(comppath);
+			comppath = NULL;
+		}
+	}
+	PG_CATCH();
+	{
+		if (comppath != NULL)
+			xmlXPathFreeCompExpr(comppath);
+		cleanup_workspace(workspace);
 
-		xmlXPathFreeCompExpr(comppath);
+		PG_RE_THROW();
 	}
+	PG_END_TRY();
 
 	return workspace;
 }
-- 
2.54.0


--MP_/LMSk9=uMhuQ1QiIJDarDO8G--





^ permalink  raw  reply  [nested|flat] 611+ messages in thread

* [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths
@ 2026-06-01 22:41 Andrey Chernyy <andrey.cherny@tantorlabs.com>
  0 siblings, 0 replies; 611+ messages in thread

From: Andrey Chernyy @ 2026-06-01 22:41 UTC (permalink / raw)

pgxml_xpath() builds an xpath_workspace before returning it to
callers.  If an ERROR is thrown before the function returns, callers
have not received the workspace pointer yet and cannot run
cleanup_workspace().

Add local error cleanup for the partially built workspace and the
compiled XPath expression.  Also check xmlXPathNewContext() before
dereferencing the returned context.
---
 contrib/xml2/xpath.c | 51 +++++++++++++++++++++++++++-----------------
 1 file changed, 32 insertions(+), 19 deletions(-)

diff --git a/contrib/xml2/xpath.c b/contrib/xml2/xpath.c
index 9fe75cb5ff4..283bb51178d 100644
--- a/contrib/xml2/xpath.c
+++ b/contrib/xml2/xpath.c
@@ -497,36 +497,49 @@ static xpath_workspace *
 pgxml_xpath(text *document, xmlChar *xpath, PgXmlErrorContext *xmlerrcxt)
 {
 	int32		docsize = VARSIZE_ANY_EXHDR(document);
-	xmlXPathCompExprPtr comppath;
+	xmlXPathCompExprPtr volatile comppath = NULL;
 	xpath_workspace *workspace = palloc0_object(xpath_workspace);
 
 	workspace->doctree = NULL;
 	workspace->ctxt = NULL;
 	workspace->res = NULL;
 
-	workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
-									   docsize, NULL, NULL,
-									   XML_PARSE_NOENT);
-	if (workspace->doctree != NULL)
+	PG_TRY();
 	{
-		workspace->ctxt = xmlXPathNewContext(workspace->doctree);
-		workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
-
-		/* compile the path */
-		comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
-		if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+		workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
+										   docsize, NULL, NULL,
+										   XML_PARSE_NOENT);
+		if (workspace->doctree != NULL)
 		{
-			if (comppath != NULL)
-				xmlXPathFreeCompExpr(comppath);
-			xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
-						"XPath Syntax Error");
-		}
+			workspace->ctxt = xmlXPathNewContext(workspace->doctree);
+			if (workspace->ctxt == NULL)
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_OUT_OF_MEMORY,
+							"could not allocate XPath context");
 
-		/* Now evaluate the path expression. */
-		workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+			workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
+
+			/* compile the path */
+			comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
+			if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
+							"XPath Syntax Error");
+
+			/* Now evaluate the path expression. */
+			workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+
+			xmlXPathFreeCompExpr(comppath);
+			comppath = NULL;
+		}
+	}
+	PG_CATCH();
+	{
+		if (comppath != NULL)
+			xmlXPathFreeCompExpr(comppath);
+		cleanup_workspace(workspace);
 
-		xmlXPathFreeCompExpr(comppath);
+		PG_RE_THROW();
 	}
+	PG_END_TRY();
 
 	return workspace;
 }
-- 
2.54.0


--MP_/LMSk9=uMhuQ1QiIJDarDO8G--





^ permalink  raw  reply  [nested|flat] 611+ messages in thread

* [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths
@ 2026-06-01 22:41 Andrey Chernyy <andrey.cherny@tantorlabs.com>
  0 siblings, 0 replies; 611+ messages in thread

From: Andrey Chernyy @ 2026-06-01 22:41 UTC (permalink / raw)

pgxml_xpath() builds an xpath_workspace before returning it to
callers.  If an ERROR is thrown before the function returns, callers
have not received the workspace pointer yet and cannot run
cleanup_workspace().

Add local error cleanup for the partially built workspace and the
compiled XPath expression.  Also check xmlXPathNewContext() before
dereferencing the returned context.
---
 contrib/xml2/xpath.c | 51 +++++++++++++++++++++++++++-----------------
 1 file changed, 32 insertions(+), 19 deletions(-)

diff --git a/contrib/xml2/xpath.c b/contrib/xml2/xpath.c
index 9fe75cb5ff4..283bb51178d 100644
--- a/contrib/xml2/xpath.c
+++ b/contrib/xml2/xpath.c
@@ -497,36 +497,49 @@ static xpath_workspace *
 pgxml_xpath(text *document, xmlChar *xpath, PgXmlErrorContext *xmlerrcxt)
 {
 	int32		docsize = VARSIZE_ANY_EXHDR(document);
-	xmlXPathCompExprPtr comppath;
+	xmlXPathCompExprPtr volatile comppath = NULL;
 	xpath_workspace *workspace = palloc0_object(xpath_workspace);
 
 	workspace->doctree = NULL;
 	workspace->ctxt = NULL;
 	workspace->res = NULL;
 
-	workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
-									   docsize, NULL, NULL,
-									   XML_PARSE_NOENT);
-	if (workspace->doctree != NULL)
+	PG_TRY();
 	{
-		workspace->ctxt = xmlXPathNewContext(workspace->doctree);
-		workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
-
-		/* compile the path */
-		comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
-		if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+		workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
+										   docsize, NULL, NULL,
+										   XML_PARSE_NOENT);
+		if (workspace->doctree != NULL)
 		{
-			if (comppath != NULL)
-				xmlXPathFreeCompExpr(comppath);
-			xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
-						"XPath Syntax Error");
-		}
+			workspace->ctxt = xmlXPathNewContext(workspace->doctree);
+			if (workspace->ctxt == NULL)
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_OUT_OF_MEMORY,
+							"could not allocate XPath context");
 
-		/* Now evaluate the path expression. */
-		workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+			workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
+
+			/* compile the path */
+			comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
+			if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
+							"XPath Syntax Error");
+
+			/* Now evaluate the path expression. */
+			workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+
+			xmlXPathFreeCompExpr(comppath);
+			comppath = NULL;
+		}
+	}
+	PG_CATCH();
+	{
+		if (comppath != NULL)
+			xmlXPathFreeCompExpr(comppath);
+		cleanup_workspace(workspace);
 
-		xmlXPathFreeCompExpr(comppath);
+		PG_RE_THROW();
 	}
+	PG_END_TRY();
 
 	return workspace;
 }
-- 
2.54.0


--MP_/LMSk9=uMhuQ1QiIJDarDO8G--






^ permalink  raw  reply  [nested|flat] 611+ messages in thread

* [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths
@ 2026-06-01 22:41 Andrey Chernyy <andrey.cherny@tantorlabs.com>
  0 siblings, 0 replies; 611+ messages in thread

From: Andrey Chernyy @ 2026-06-01 22:41 UTC (permalink / raw)

pgxml_xpath() builds an xpath_workspace before returning it to
callers.  If an ERROR is thrown before the function returns, callers
have not received the workspace pointer yet and cannot run
cleanup_workspace().

Add local error cleanup for the partially built workspace and the
compiled XPath expression.  Also check xmlXPathNewContext() before
dereferencing the returned context.
---
 contrib/xml2/xpath.c | 51 +++++++++++++++++++++++++++-----------------
 1 file changed, 32 insertions(+), 19 deletions(-)

diff --git a/contrib/xml2/xpath.c b/contrib/xml2/xpath.c
index 9fe75cb5ff4..283bb51178d 100644
--- a/contrib/xml2/xpath.c
+++ b/contrib/xml2/xpath.c
@@ -497,36 +497,49 @@ static xpath_workspace *
 pgxml_xpath(text *document, xmlChar *xpath, PgXmlErrorContext *xmlerrcxt)
 {
 	int32		docsize = VARSIZE_ANY_EXHDR(document);
-	xmlXPathCompExprPtr comppath;
+	xmlXPathCompExprPtr volatile comppath = NULL;
 	xpath_workspace *workspace = palloc0_object(xpath_workspace);
 
 	workspace->doctree = NULL;
 	workspace->ctxt = NULL;
 	workspace->res = NULL;
 
-	workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
-									   docsize, NULL, NULL,
-									   XML_PARSE_NOENT);
-	if (workspace->doctree != NULL)
+	PG_TRY();
 	{
-		workspace->ctxt = xmlXPathNewContext(workspace->doctree);
-		workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
-
-		/* compile the path */
-		comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
-		if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+		workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
+										   docsize, NULL, NULL,
+										   XML_PARSE_NOENT);
+		if (workspace->doctree != NULL)
 		{
-			if (comppath != NULL)
-				xmlXPathFreeCompExpr(comppath);
-			xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
-						"XPath Syntax Error");
-		}
+			workspace->ctxt = xmlXPathNewContext(workspace->doctree);
+			if (workspace->ctxt == NULL)
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_OUT_OF_MEMORY,
+							"could not allocate XPath context");
 
-		/* Now evaluate the path expression. */
-		workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+			workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
+
+			/* compile the path */
+			comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
+			if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
+							"XPath Syntax Error");
+
+			/* Now evaluate the path expression. */
+			workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+
+			xmlXPathFreeCompExpr(comppath);
+			comppath = NULL;
+		}
+	}
+	PG_CATCH();
+	{
+		if (comppath != NULL)
+			xmlXPathFreeCompExpr(comppath);
+		cleanup_workspace(workspace);
 
-		xmlXPathFreeCompExpr(comppath);
+		PG_RE_THROW();
 	}
+	PG_END_TRY();
 
 	return workspace;
 }
-- 
2.54.0


--MP_/LMSk9=uMhuQ1QiIJDarDO8G--





^ permalink  raw  reply  [nested|flat] 611+ messages in thread

* [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths
@ 2026-06-01 22:41 Andrey Chernyy <andrey.cherny@tantorlabs.com>
  0 siblings, 0 replies; 611+ messages in thread

From: Andrey Chernyy @ 2026-06-01 22:41 UTC (permalink / raw)

pgxml_xpath() builds an xpath_workspace before returning it to
callers.  If an ERROR is thrown before the function returns, callers
have not received the workspace pointer yet and cannot run
cleanup_workspace().

Add local error cleanup for the partially built workspace and the
compiled XPath expression.  Also check xmlXPathNewContext() before
dereferencing the returned context.
---
 contrib/xml2/xpath.c | 51 +++++++++++++++++++++++++++-----------------
 1 file changed, 32 insertions(+), 19 deletions(-)

diff --git a/contrib/xml2/xpath.c b/contrib/xml2/xpath.c
index 9fe75cb5ff4..283bb51178d 100644
--- a/contrib/xml2/xpath.c
+++ b/contrib/xml2/xpath.c
@@ -497,36 +497,49 @@ static xpath_workspace *
 pgxml_xpath(text *document, xmlChar *xpath, PgXmlErrorContext *xmlerrcxt)
 {
 	int32		docsize = VARSIZE_ANY_EXHDR(document);
-	xmlXPathCompExprPtr comppath;
+	xmlXPathCompExprPtr volatile comppath = NULL;
 	xpath_workspace *workspace = palloc0_object(xpath_workspace);
 
 	workspace->doctree = NULL;
 	workspace->ctxt = NULL;
 	workspace->res = NULL;
 
-	workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
-									   docsize, NULL, NULL,
-									   XML_PARSE_NOENT);
-	if (workspace->doctree != NULL)
+	PG_TRY();
 	{
-		workspace->ctxt = xmlXPathNewContext(workspace->doctree);
-		workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
-
-		/* compile the path */
-		comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
-		if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+		workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
+										   docsize, NULL, NULL,
+										   XML_PARSE_NOENT);
+		if (workspace->doctree != NULL)
 		{
-			if (comppath != NULL)
-				xmlXPathFreeCompExpr(comppath);
-			xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
-						"XPath Syntax Error");
-		}
+			workspace->ctxt = xmlXPathNewContext(workspace->doctree);
+			if (workspace->ctxt == NULL)
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_OUT_OF_MEMORY,
+							"could not allocate XPath context");
 
-		/* Now evaluate the path expression. */
-		workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+			workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
+
+			/* compile the path */
+			comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
+			if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
+							"XPath Syntax Error");
+
+			/* Now evaluate the path expression. */
+			workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+
+			xmlXPathFreeCompExpr(comppath);
+			comppath = NULL;
+		}
+	}
+	PG_CATCH();
+	{
+		if (comppath != NULL)
+			xmlXPathFreeCompExpr(comppath);
+		cleanup_workspace(workspace);
 
-		xmlXPathFreeCompExpr(comppath);
+		PG_RE_THROW();
 	}
+	PG_END_TRY();
 
 	return workspace;
 }
-- 
2.54.0


--MP_/LMSk9=uMhuQ1QiIJDarDO8G--






^ permalink  raw  reply  [nested|flat] 611+ messages in thread

* [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths
@ 2026-06-01 22:41 Andrey Chernyy <andrey.cherny@tantorlabs.com>
  0 siblings, 0 replies; 611+ messages in thread

From: Andrey Chernyy @ 2026-06-01 22:41 UTC (permalink / raw)

pgxml_xpath() builds an xpath_workspace before returning it to
callers.  If an ERROR is thrown before the function returns, callers
have not received the workspace pointer yet and cannot run
cleanup_workspace().

Add local error cleanup for the partially built workspace and the
compiled XPath expression.  Also check xmlXPathNewContext() before
dereferencing the returned context.
---
 contrib/xml2/xpath.c | 51 +++++++++++++++++++++++++++-----------------
 1 file changed, 32 insertions(+), 19 deletions(-)

diff --git a/contrib/xml2/xpath.c b/contrib/xml2/xpath.c
index 9fe75cb5ff4..283bb51178d 100644
--- a/contrib/xml2/xpath.c
+++ b/contrib/xml2/xpath.c
@@ -497,36 +497,49 @@ static xpath_workspace *
 pgxml_xpath(text *document, xmlChar *xpath, PgXmlErrorContext *xmlerrcxt)
 {
 	int32		docsize = VARSIZE_ANY_EXHDR(document);
-	xmlXPathCompExprPtr comppath;
+	xmlXPathCompExprPtr volatile comppath = NULL;
 	xpath_workspace *workspace = palloc0_object(xpath_workspace);
 
 	workspace->doctree = NULL;
 	workspace->ctxt = NULL;
 	workspace->res = NULL;
 
-	workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
-									   docsize, NULL, NULL,
-									   XML_PARSE_NOENT);
-	if (workspace->doctree != NULL)
+	PG_TRY();
 	{
-		workspace->ctxt = xmlXPathNewContext(workspace->doctree);
-		workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
-
-		/* compile the path */
-		comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
-		if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+		workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
+										   docsize, NULL, NULL,
+										   XML_PARSE_NOENT);
+		if (workspace->doctree != NULL)
 		{
-			if (comppath != NULL)
-				xmlXPathFreeCompExpr(comppath);
-			xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
-						"XPath Syntax Error");
-		}
+			workspace->ctxt = xmlXPathNewContext(workspace->doctree);
+			if (workspace->ctxt == NULL)
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_OUT_OF_MEMORY,
+							"could not allocate XPath context");
 
-		/* Now evaluate the path expression. */
-		workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+			workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
+
+			/* compile the path */
+			comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
+			if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
+							"XPath Syntax Error");
+
+			/* Now evaluate the path expression. */
+			workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+
+			xmlXPathFreeCompExpr(comppath);
+			comppath = NULL;
+		}
+	}
+	PG_CATCH();
+	{
+		if (comppath != NULL)
+			xmlXPathFreeCompExpr(comppath);
+		cleanup_workspace(workspace);
 
-		xmlXPathFreeCompExpr(comppath);
+		PG_RE_THROW();
 	}
+	PG_END_TRY();
 
 	return workspace;
 }
-- 
2.54.0


--MP_/LMSk9=uMhuQ1QiIJDarDO8G--





^ permalink  raw  reply  [nested|flat] 611+ messages in thread

* [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths
@ 2026-06-01 22:41 Andrey Chernyy <andrey.cherny@tantorlabs.com>
  0 siblings, 0 replies; 611+ messages in thread

From: Andrey Chernyy @ 2026-06-01 22:41 UTC (permalink / raw)

pgxml_xpath() builds an xpath_workspace before returning it to
callers.  If an ERROR is thrown before the function returns, callers
have not received the workspace pointer yet and cannot run
cleanup_workspace().

Add local error cleanup for the partially built workspace and the
compiled XPath expression.  Also check xmlXPathNewContext() before
dereferencing the returned context.
---
 contrib/xml2/xpath.c | 51 +++++++++++++++++++++++++++-----------------
 1 file changed, 32 insertions(+), 19 deletions(-)

diff --git a/contrib/xml2/xpath.c b/contrib/xml2/xpath.c
index 9fe75cb5ff4..283bb51178d 100644
--- a/contrib/xml2/xpath.c
+++ b/contrib/xml2/xpath.c
@@ -497,36 +497,49 @@ static xpath_workspace *
 pgxml_xpath(text *document, xmlChar *xpath, PgXmlErrorContext *xmlerrcxt)
 {
 	int32		docsize = VARSIZE_ANY_EXHDR(document);
-	xmlXPathCompExprPtr comppath;
+	xmlXPathCompExprPtr volatile comppath = NULL;
 	xpath_workspace *workspace = palloc0_object(xpath_workspace);
 
 	workspace->doctree = NULL;
 	workspace->ctxt = NULL;
 	workspace->res = NULL;
 
-	workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
-									   docsize, NULL, NULL,
-									   XML_PARSE_NOENT);
-	if (workspace->doctree != NULL)
+	PG_TRY();
 	{
-		workspace->ctxt = xmlXPathNewContext(workspace->doctree);
-		workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
-
-		/* compile the path */
-		comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
-		if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+		workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
+										   docsize, NULL, NULL,
+										   XML_PARSE_NOENT);
+		if (workspace->doctree != NULL)
 		{
-			if (comppath != NULL)
-				xmlXPathFreeCompExpr(comppath);
-			xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
-						"XPath Syntax Error");
-		}
+			workspace->ctxt = xmlXPathNewContext(workspace->doctree);
+			if (workspace->ctxt == NULL)
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_OUT_OF_MEMORY,
+							"could not allocate XPath context");
 
-		/* Now evaluate the path expression. */
-		workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+			workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
+
+			/* compile the path */
+			comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
+			if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
+							"XPath Syntax Error");
+
+			/* Now evaluate the path expression. */
+			workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+
+			xmlXPathFreeCompExpr(comppath);
+			comppath = NULL;
+		}
+	}
+	PG_CATCH();
+	{
+		if (comppath != NULL)
+			xmlXPathFreeCompExpr(comppath);
+		cleanup_workspace(workspace);
 
-		xmlXPathFreeCompExpr(comppath);
+		PG_RE_THROW();
 	}
+	PG_END_TRY();
 
 	return workspace;
 }
-- 
2.54.0


--MP_/LMSk9=uMhuQ1QiIJDarDO8G--






^ permalink  raw  reply  [nested|flat] 611+ messages in thread

* [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths
@ 2026-06-01 22:41 Andrey Chernyy <andrey.cherny@tantorlabs.com>
  0 siblings, 0 replies; 611+ messages in thread

From: Andrey Chernyy @ 2026-06-01 22:41 UTC (permalink / raw)

pgxml_xpath() builds an xpath_workspace before returning it to
callers.  If an ERROR is thrown before the function returns, callers
have not received the workspace pointer yet and cannot run
cleanup_workspace().

Add local error cleanup for the partially built workspace and the
compiled XPath expression.  Also check xmlXPathNewContext() before
dereferencing the returned context.
---
 contrib/xml2/xpath.c | 51 +++++++++++++++++++++++++++-----------------
 1 file changed, 32 insertions(+), 19 deletions(-)

diff --git a/contrib/xml2/xpath.c b/contrib/xml2/xpath.c
index 9fe75cb5ff4..283bb51178d 100644
--- a/contrib/xml2/xpath.c
+++ b/contrib/xml2/xpath.c
@@ -497,36 +497,49 @@ static xpath_workspace *
 pgxml_xpath(text *document, xmlChar *xpath, PgXmlErrorContext *xmlerrcxt)
 {
 	int32		docsize = VARSIZE_ANY_EXHDR(document);
-	xmlXPathCompExprPtr comppath;
+	xmlXPathCompExprPtr volatile comppath = NULL;
 	xpath_workspace *workspace = palloc0_object(xpath_workspace);
 
 	workspace->doctree = NULL;
 	workspace->ctxt = NULL;
 	workspace->res = NULL;
 
-	workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
-									   docsize, NULL, NULL,
-									   XML_PARSE_NOENT);
-	if (workspace->doctree != NULL)
+	PG_TRY();
 	{
-		workspace->ctxt = xmlXPathNewContext(workspace->doctree);
-		workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
-
-		/* compile the path */
-		comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
-		if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+		workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
+										   docsize, NULL, NULL,
+										   XML_PARSE_NOENT);
+		if (workspace->doctree != NULL)
 		{
-			if (comppath != NULL)
-				xmlXPathFreeCompExpr(comppath);
-			xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
-						"XPath Syntax Error");
-		}
+			workspace->ctxt = xmlXPathNewContext(workspace->doctree);
+			if (workspace->ctxt == NULL)
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_OUT_OF_MEMORY,
+							"could not allocate XPath context");
 
-		/* Now evaluate the path expression. */
-		workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+			workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
+
+			/* compile the path */
+			comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
+			if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
+							"XPath Syntax Error");
+
+			/* Now evaluate the path expression. */
+			workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+
+			xmlXPathFreeCompExpr(comppath);
+			comppath = NULL;
+		}
+	}
+	PG_CATCH();
+	{
+		if (comppath != NULL)
+			xmlXPathFreeCompExpr(comppath);
+		cleanup_workspace(workspace);
 
-		xmlXPathFreeCompExpr(comppath);
+		PG_RE_THROW();
 	}
+	PG_END_TRY();
 
 	return workspace;
 }
-- 
2.54.0


--MP_/LMSk9=uMhuQ1QiIJDarDO8G--





^ permalink  raw  reply  [nested|flat] 611+ messages in thread

* [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths
@ 2026-06-01 22:41 Andrey Chernyy <andrey.cherny@tantorlabs.com>
  0 siblings, 0 replies; 611+ messages in thread

From: Andrey Chernyy @ 2026-06-01 22:41 UTC (permalink / raw)

pgxml_xpath() builds an xpath_workspace before returning it to
callers.  If an ERROR is thrown before the function returns, callers
have not received the workspace pointer yet and cannot run
cleanup_workspace().

Add local error cleanup for the partially built workspace and the
compiled XPath expression.  Also check xmlXPathNewContext() before
dereferencing the returned context.
---
 contrib/xml2/xpath.c | 51 +++++++++++++++++++++++++++-----------------
 1 file changed, 32 insertions(+), 19 deletions(-)

diff --git a/contrib/xml2/xpath.c b/contrib/xml2/xpath.c
index 9fe75cb5ff4..283bb51178d 100644
--- a/contrib/xml2/xpath.c
+++ b/contrib/xml2/xpath.c
@@ -497,36 +497,49 @@ static xpath_workspace *
 pgxml_xpath(text *document, xmlChar *xpath, PgXmlErrorContext *xmlerrcxt)
 {
 	int32		docsize = VARSIZE_ANY_EXHDR(document);
-	xmlXPathCompExprPtr comppath;
+	xmlXPathCompExprPtr volatile comppath = NULL;
 	xpath_workspace *workspace = palloc0_object(xpath_workspace);
 
 	workspace->doctree = NULL;
 	workspace->ctxt = NULL;
 	workspace->res = NULL;
 
-	workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
-									   docsize, NULL, NULL,
-									   XML_PARSE_NOENT);
-	if (workspace->doctree != NULL)
+	PG_TRY();
 	{
-		workspace->ctxt = xmlXPathNewContext(workspace->doctree);
-		workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
-
-		/* compile the path */
-		comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
-		if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+		workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
+										   docsize, NULL, NULL,
+										   XML_PARSE_NOENT);
+		if (workspace->doctree != NULL)
 		{
-			if (comppath != NULL)
-				xmlXPathFreeCompExpr(comppath);
-			xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
-						"XPath Syntax Error");
-		}
+			workspace->ctxt = xmlXPathNewContext(workspace->doctree);
+			if (workspace->ctxt == NULL)
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_OUT_OF_MEMORY,
+							"could not allocate XPath context");
 
-		/* Now evaluate the path expression. */
-		workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+			workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
+
+			/* compile the path */
+			comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
+			if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
+							"XPath Syntax Error");
+
+			/* Now evaluate the path expression. */
+			workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+
+			xmlXPathFreeCompExpr(comppath);
+			comppath = NULL;
+		}
+	}
+	PG_CATCH();
+	{
+		if (comppath != NULL)
+			xmlXPathFreeCompExpr(comppath);
+		cleanup_workspace(workspace);
 
-		xmlXPathFreeCompExpr(comppath);
+		PG_RE_THROW();
 	}
+	PG_END_TRY();
 
 	return workspace;
 }
-- 
2.54.0


--MP_/LMSk9=uMhuQ1QiIJDarDO8G--





^ permalink  raw  reply  [nested|flat] 611+ messages in thread

* [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths
@ 2026-06-01 22:41 Andrey Chernyy <andrey.cherny@tantorlabs.com>
  0 siblings, 0 replies; 611+ messages in thread

From: Andrey Chernyy @ 2026-06-01 22:41 UTC (permalink / raw)

pgxml_xpath() builds an xpath_workspace before returning it to
callers.  If an ERROR is thrown before the function returns, callers
have not received the workspace pointer yet and cannot run
cleanup_workspace().

Add local error cleanup for the partially built workspace and the
compiled XPath expression.  Also check xmlXPathNewContext() before
dereferencing the returned context.
---
 contrib/xml2/xpath.c | 51 +++++++++++++++++++++++++++-----------------
 1 file changed, 32 insertions(+), 19 deletions(-)

diff --git a/contrib/xml2/xpath.c b/contrib/xml2/xpath.c
index 9fe75cb5ff4..283bb51178d 100644
--- a/contrib/xml2/xpath.c
+++ b/contrib/xml2/xpath.c
@@ -497,36 +497,49 @@ static xpath_workspace *
 pgxml_xpath(text *document, xmlChar *xpath, PgXmlErrorContext *xmlerrcxt)
 {
 	int32		docsize = VARSIZE_ANY_EXHDR(document);
-	xmlXPathCompExprPtr comppath;
+	xmlXPathCompExprPtr volatile comppath = NULL;
 	xpath_workspace *workspace = palloc0_object(xpath_workspace);
 
 	workspace->doctree = NULL;
 	workspace->ctxt = NULL;
 	workspace->res = NULL;
 
-	workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
-									   docsize, NULL, NULL,
-									   XML_PARSE_NOENT);
-	if (workspace->doctree != NULL)
+	PG_TRY();
 	{
-		workspace->ctxt = xmlXPathNewContext(workspace->doctree);
-		workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
-
-		/* compile the path */
-		comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
-		if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+		workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
+										   docsize, NULL, NULL,
+										   XML_PARSE_NOENT);
+		if (workspace->doctree != NULL)
 		{
-			if (comppath != NULL)
-				xmlXPathFreeCompExpr(comppath);
-			xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
-						"XPath Syntax Error");
-		}
+			workspace->ctxt = xmlXPathNewContext(workspace->doctree);
+			if (workspace->ctxt == NULL)
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_OUT_OF_MEMORY,
+							"could not allocate XPath context");
 
-		/* Now evaluate the path expression. */
-		workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+			workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
+
+			/* compile the path */
+			comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
+			if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
+							"XPath Syntax Error");
+
+			/* Now evaluate the path expression. */
+			workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+
+			xmlXPathFreeCompExpr(comppath);
+			comppath = NULL;
+		}
+	}
+	PG_CATCH();
+	{
+		if (comppath != NULL)
+			xmlXPathFreeCompExpr(comppath);
+		cleanup_workspace(workspace);
 
-		xmlXPathFreeCompExpr(comppath);
+		PG_RE_THROW();
 	}
+	PG_END_TRY();
 
 	return workspace;
 }
-- 
2.54.0


--MP_/LMSk9=uMhuQ1QiIJDarDO8G--






^ permalink  raw  reply  [nested|flat] 611+ messages in thread

* [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths
@ 2026-06-01 22:41 Andrey Chernyy <andrey.cherny@tantorlabs.com>
  0 siblings, 0 replies; 611+ messages in thread

From: Andrey Chernyy @ 2026-06-01 22:41 UTC (permalink / raw)

pgxml_xpath() builds an xpath_workspace before returning it to
callers.  If an ERROR is thrown before the function returns, callers
have not received the workspace pointer yet and cannot run
cleanup_workspace().

Add local error cleanup for the partially built workspace and the
compiled XPath expression.  Also check xmlXPathNewContext() before
dereferencing the returned context.
---
 contrib/xml2/xpath.c | 51 +++++++++++++++++++++++++++-----------------
 1 file changed, 32 insertions(+), 19 deletions(-)

diff --git a/contrib/xml2/xpath.c b/contrib/xml2/xpath.c
index 9fe75cb5ff4..283bb51178d 100644
--- a/contrib/xml2/xpath.c
+++ b/contrib/xml2/xpath.c
@@ -497,36 +497,49 @@ static xpath_workspace *
 pgxml_xpath(text *document, xmlChar *xpath, PgXmlErrorContext *xmlerrcxt)
 {
 	int32		docsize = VARSIZE_ANY_EXHDR(document);
-	xmlXPathCompExprPtr comppath;
+	xmlXPathCompExprPtr volatile comppath = NULL;
 	xpath_workspace *workspace = palloc0_object(xpath_workspace);
 
 	workspace->doctree = NULL;
 	workspace->ctxt = NULL;
 	workspace->res = NULL;
 
-	workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
-									   docsize, NULL, NULL,
-									   XML_PARSE_NOENT);
-	if (workspace->doctree != NULL)
+	PG_TRY();
 	{
-		workspace->ctxt = xmlXPathNewContext(workspace->doctree);
-		workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
-
-		/* compile the path */
-		comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
-		if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+		workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
+										   docsize, NULL, NULL,
+										   XML_PARSE_NOENT);
+		if (workspace->doctree != NULL)
 		{
-			if (comppath != NULL)
-				xmlXPathFreeCompExpr(comppath);
-			xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
-						"XPath Syntax Error");
-		}
+			workspace->ctxt = xmlXPathNewContext(workspace->doctree);
+			if (workspace->ctxt == NULL)
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_OUT_OF_MEMORY,
+							"could not allocate XPath context");
 
-		/* Now evaluate the path expression. */
-		workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+			workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
+
+			/* compile the path */
+			comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
+			if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
+							"XPath Syntax Error");
+
+			/* Now evaluate the path expression. */
+			workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+
+			xmlXPathFreeCompExpr(comppath);
+			comppath = NULL;
+		}
+	}
+	PG_CATCH();
+	{
+		if (comppath != NULL)
+			xmlXPathFreeCompExpr(comppath);
+		cleanup_workspace(workspace);
 
-		xmlXPathFreeCompExpr(comppath);
+		PG_RE_THROW();
 	}
+	PG_END_TRY();
 
 	return workspace;
 }
-- 
2.54.0


--MP_/LMSk9=uMhuQ1QiIJDarDO8G--






^ permalink  raw  reply  [nested|flat] 611+ messages in thread

* [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths
@ 2026-06-01 22:41 Andrey Chernyy <andrey.cherny@tantorlabs.com>
  0 siblings, 0 replies; 611+ messages in thread

From: Andrey Chernyy @ 2026-06-01 22:41 UTC (permalink / raw)

pgxml_xpath() builds an xpath_workspace before returning it to
callers.  If an ERROR is thrown before the function returns, callers
have not received the workspace pointer yet and cannot run
cleanup_workspace().

Add local error cleanup for the partially built workspace and the
compiled XPath expression.  Also check xmlXPathNewContext() before
dereferencing the returned context.
---
 contrib/xml2/xpath.c | 51 +++++++++++++++++++++++++++-----------------
 1 file changed, 32 insertions(+), 19 deletions(-)

diff --git a/contrib/xml2/xpath.c b/contrib/xml2/xpath.c
index 9fe75cb5ff4..283bb51178d 100644
--- a/contrib/xml2/xpath.c
+++ b/contrib/xml2/xpath.c
@@ -497,36 +497,49 @@ static xpath_workspace *
 pgxml_xpath(text *document, xmlChar *xpath, PgXmlErrorContext *xmlerrcxt)
 {
 	int32		docsize = VARSIZE_ANY_EXHDR(document);
-	xmlXPathCompExprPtr comppath;
+	xmlXPathCompExprPtr volatile comppath = NULL;
 	xpath_workspace *workspace = palloc0_object(xpath_workspace);
 
 	workspace->doctree = NULL;
 	workspace->ctxt = NULL;
 	workspace->res = NULL;
 
-	workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
-									   docsize, NULL, NULL,
-									   XML_PARSE_NOENT);
-	if (workspace->doctree != NULL)
+	PG_TRY();
 	{
-		workspace->ctxt = xmlXPathNewContext(workspace->doctree);
-		workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
-
-		/* compile the path */
-		comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
-		if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+		workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
+										   docsize, NULL, NULL,
+										   XML_PARSE_NOENT);
+		if (workspace->doctree != NULL)
 		{
-			if (comppath != NULL)
-				xmlXPathFreeCompExpr(comppath);
-			xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
-						"XPath Syntax Error");
-		}
+			workspace->ctxt = xmlXPathNewContext(workspace->doctree);
+			if (workspace->ctxt == NULL)
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_OUT_OF_MEMORY,
+							"could not allocate XPath context");
 
-		/* Now evaluate the path expression. */
-		workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+			workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
+
+			/* compile the path */
+			comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
+			if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
+							"XPath Syntax Error");
+
+			/* Now evaluate the path expression. */
+			workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+
+			xmlXPathFreeCompExpr(comppath);
+			comppath = NULL;
+		}
+	}
+	PG_CATCH();
+	{
+		if (comppath != NULL)
+			xmlXPathFreeCompExpr(comppath);
+		cleanup_workspace(workspace);
 
-		xmlXPathFreeCompExpr(comppath);
+		PG_RE_THROW();
 	}
+	PG_END_TRY();
 
 	return workspace;
 }
-- 
2.54.0


--MP_/LMSk9=uMhuQ1QiIJDarDO8G--





^ permalink  raw  reply  [nested|flat] 611+ messages in thread

* [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths
@ 2026-06-01 22:41 Andrey Chernyy <andrey.cherny@tantorlabs.com>
  0 siblings, 0 replies; 611+ messages in thread

From: Andrey Chernyy @ 2026-06-01 22:41 UTC (permalink / raw)

pgxml_xpath() builds an xpath_workspace before returning it to
callers.  If an ERROR is thrown before the function returns, callers
have not received the workspace pointer yet and cannot run
cleanup_workspace().

Add local error cleanup for the partially built workspace and the
compiled XPath expression.  Also check xmlXPathNewContext() before
dereferencing the returned context.
---
 contrib/xml2/xpath.c | 51 +++++++++++++++++++++++++++-----------------
 1 file changed, 32 insertions(+), 19 deletions(-)

diff --git a/contrib/xml2/xpath.c b/contrib/xml2/xpath.c
index 9fe75cb5ff4..283bb51178d 100644
--- a/contrib/xml2/xpath.c
+++ b/contrib/xml2/xpath.c
@@ -497,36 +497,49 @@ static xpath_workspace *
 pgxml_xpath(text *document, xmlChar *xpath, PgXmlErrorContext *xmlerrcxt)
 {
 	int32		docsize = VARSIZE_ANY_EXHDR(document);
-	xmlXPathCompExprPtr comppath;
+	xmlXPathCompExprPtr volatile comppath = NULL;
 	xpath_workspace *workspace = palloc0_object(xpath_workspace);
 
 	workspace->doctree = NULL;
 	workspace->ctxt = NULL;
 	workspace->res = NULL;
 
-	workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
-									   docsize, NULL, NULL,
-									   XML_PARSE_NOENT);
-	if (workspace->doctree != NULL)
+	PG_TRY();
 	{
-		workspace->ctxt = xmlXPathNewContext(workspace->doctree);
-		workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
-
-		/* compile the path */
-		comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
-		if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+		workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
+										   docsize, NULL, NULL,
+										   XML_PARSE_NOENT);
+		if (workspace->doctree != NULL)
 		{
-			if (comppath != NULL)
-				xmlXPathFreeCompExpr(comppath);
-			xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
-						"XPath Syntax Error");
-		}
+			workspace->ctxt = xmlXPathNewContext(workspace->doctree);
+			if (workspace->ctxt == NULL)
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_OUT_OF_MEMORY,
+							"could not allocate XPath context");
 
-		/* Now evaluate the path expression. */
-		workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+			workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
+
+			/* compile the path */
+			comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
+			if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
+							"XPath Syntax Error");
+
+			/* Now evaluate the path expression. */
+			workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+
+			xmlXPathFreeCompExpr(comppath);
+			comppath = NULL;
+		}
+	}
+	PG_CATCH();
+	{
+		if (comppath != NULL)
+			xmlXPathFreeCompExpr(comppath);
+		cleanup_workspace(workspace);
 
-		xmlXPathFreeCompExpr(comppath);
+		PG_RE_THROW();
 	}
+	PG_END_TRY();
 
 	return workspace;
 }
-- 
2.54.0


--MP_/LMSk9=uMhuQ1QiIJDarDO8G--






^ permalink  raw  reply  [nested|flat] 611+ messages in thread

* [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths
@ 2026-06-01 22:41 Andrey Chernyy <andrey.cherny@tantorlabs.com>
  0 siblings, 0 replies; 611+ messages in thread

From: Andrey Chernyy @ 2026-06-01 22:41 UTC (permalink / raw)

pgxml_xpath() builds an xpath_workspace before returning it to
callers.  If an ERROR is thrown before the function returns, callers
have not received the workspace pointer yet and cannot run
cleanup_workspace().

Add local error cleanup for the partially built workspace and the
compiled XPath expression.  Also check xmlXPathNewContext() before
dereferencing the returned context.
---
 contrib/xml2/xpath.c | 51 +++++++++++++++++++++++++++-----------------
 1 file changed, 32 insertions(+), 19 deletions(-)

diff --git a/contrib/xml2/xpath.c b/contrib/xml2/xpath.c
index 9fe75cb5ff4..283bb51178d 100644
--- a/contrib/xml2/xpath.c
+++ b/contrib/xml2/xpath.c
@@ -497,36 +497,49 @@ static xpath_workspace *
 pgxml_xpath(text *document, xmlChar *xpath, PgXmlErrorContext *xmlerrcxt)
 {
 	int32		docsize = VARSIZE_ANY_EXHDR(document);
-	xmlXPathCompExprPtr comppath;
+	xmlXPathCompExprPtr volatile comppath = NULL;
 	xpath_workspace *workspace = palloc0_object(xpath_workspace);
 
 	workspace->doctree = NULL;
 	workspace->ctxt = NULL;
 	workspace->res = NULL;
 
-	workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
-									   docsize, NULL, NULL,
-									   XML_PARSE_NOENT);
-	if (workspace->doctree != NULL)
+	PG_TRY();
 	{
-		workspace->ctxt = xmlXPathNewContext(workspace->doctree);
-		workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
-
-		/* compile the path */
-		comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
-		if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+		workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
+										   docsize, NULL, NULL,
+										   XML_PARSE_NOENT);
+		if (workspace->doctree != NULL)
 		{
-			if (comppath != NULL)
-				xmlXPathFreeCompExpr(comppath);
-			xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
-						"XPath Syntax Error");
-		}
+			workspace->ctxt = xmlXPathNewContext(workspace->doctree);
+			if (workspace->ctxt == NULL)
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_OUT_OF_MEMORY,
+							"could not allocate XPath context");
 
-		/* Now evaluate the path expression. */
-		workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+			workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
+
+			/* compile the path */
+			comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
+			if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
+							"XPath Syntax Error");
+
+			/* Now evaluate the path expression. */
+			workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+
+			xmlXPathFreeCompExpr(comppath);
+			comppath = NULL;
+		}
+	}
+	PG_CATCH();
+	{
+		if (comppath != NULL)
+			xmlXPathFreeCompExpr(comppath);
+		cleanup_workspace(workspace);
 
-		xmlXPathFreeCompExpr(comppath);
+		PG_RE_THROW();
 	}
+	PG_END_TRY();
 
 	return workspace;
 }
-- 
2.54.0


--MP_/LMSk9=uMhuQ1QiIJDarDO8G--






^ permalink  raw  reply  [nested|flat] 611+ messages in thread

* [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths
@ 2026-06-01 22:41 Andrey Chernyy <andrey.cherny@tantorlabs.com>
  0 siblings, 0 replies; 611+ messages in thread

From: Andrey Chernyy @ 2026-06-01 22:41 UTC (permalink / raw)

pgxml_xpath() builds an xpath_workspace before returning it to
callers.  If an ERROR is thrown before the function returns, callers
have not received the workspace pointer yet and cannot run
cleanup_workspace().

Add local error cleanup for the partially built workspace and the
compiled XPath expression.  Also check xmlXPathNewContext() before
dereferencing the returned context.
---
 contrib/xml2/xpath.c | 51 +++++++++++++++++++++++++++-----------------
 1 file changed, 32 insertions(+), 19 deletions(-)

diff --git a/contrib/xml2/xpath.c b/contrib/xml2/xpath.c
index 9fe75cb5ff4..283bb51178d 100644
--- a/contrib/xml2/xpath.c
+++ b/contrib/xml2/xpath.c
@@ -497,36 +497,49 @@ static xpath_workspace *
 pgxml_xpath(text *document, xmlChar *xpath, PgXmlErrorContext *xmlerrcxt)
 {
 	int32		docsize = VARSIZE_ANY_EXHDR(document);
-	xmlXPathCompExprPtr comppath;
+	xmlXPathCompExprPtr volatile comppath = NULL;
 	xpath_workspace *workspace = palloc0_object(xpath_workspace);
 
 	workspace->doctree = NULL;
 	workspace->ctxt = NULL;
 	workspace->res = NULL;
 
-	workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
-									   docsize, NULL, NULL,
-									   XML_PARSE_NOENT);
-	if (workspace->doctree != NULL)
+	PG_TRY();
 	{
-		workspace->ctxt = xmlXPathNewContext(workspace->doctree);
-		workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
-
-		/* compile the path */
-		comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
-		if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+		workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
+										   docsize, NULL, NULL,
+										   XML_PARSE_NOENT);
+		if (workspace->doctree != NULL)
 		{
-			if (comppath != NULL)
-				xmlXPathFreeCompExpr(comppath);
-			xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
-						"XPath Syntax Error");
-		}
+			workspace->ctxt = xmlXPathNewContext(workspace->doctree);
+			if (workspace->ctxt == NULL)
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_OUT_OF_MEMORY,
+							"could not allocate XPath context");
 
-		/* Now evaluate the path expression. */
-		workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+			workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
+
+			/* compile the path */
+			comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
+			if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
+							"XPath Syntax Error");
+
+			/* Now evaluate the path expression. */
+			workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+
+			xmlXPathFreeCompExpr(comppath);
+			comppath = NULL;
+		}
+	}
+	PG_CATCH();
+	{
+		if (comppath != NULL)
+			xmlXPathFreeCompExpr(comppath);
+		cleanup_workspace(workspace);
 
-		xmlXPathFreeCompExpr(comppath);
+		PG_RE_THROW();
 	}
+	PG_END_TRY();
 
 	return workspace;
 }
-- 
2.54.0


--MP_/LMSk9=uMhuQ1QiIJDarDO8G--






^ permalink  raw  reply  [nested|flat] 611+ messages in thread

* [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths
@ 2026-06-01 22:41 Andrey Chernyy <andrey.cherny@tantorlabs.com>
  0 siblings, 0 replies; 611+ messages in thread

From: Andrey Chernyy @ 2026-06-01 22:41 UTC (permalink / raw)

pgxml_xpath() builds an xpath_workspace before returning it to
callers.  If an ERROR is thrown before the function returns, callers
have not received the workspace pointer yet and cannot run
cleanup_workspace().

Add local error cleanup for the partially built workspace and the
compiled XPath expression.  Also check xmlXPathNewContext() before
dereferencing the returned context.
---
 contrib/xml2/xpath.c | 51 +++++++++++++++++++++++++++-----------------
 1 file changed, 32 insertions(+), 19 deletions(-)

diff --git a/contrib/xml2/xpath.c b/contrib/xml2/xpath.c
index 9fe75cb5ff4..283bb51178d 100644
--- a/contrib/xml2/xpath.c
+++ b/contrib/xml2/xpath.c
@@ -497,36 +497,49 @@ static xpath_workspace *
 pgxml_xpath(text *document, xmlChar *xpath, PgXmlErrorContext *xmlerrcxt)
 {
 	int32		docsize = VARSIZE_ANY_EXHDR(document);
-	xmlXPathCompExprPtr comppath;
+	xmlXPathCompExprPtr volatile comppath = NULL;
 	xpath_workspace *workspace = palloc0_object(xpath_workspace);
 
 	workspace->doctree = NULL;
 	workspace->ctxt = NULL;
 	workspace->res = NULL;
 
-	workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
-									   docsize, NULL, NULL,
-									   XML_PARSE_NOENT);
-	if (workspace->doctree != NULL)
+	PG_TRY();
 	{
-		workspace->ctxt = xmlXPathNewContext(workspace->doctree);
-		workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
-
-		/* compile the path */
-		comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
-		if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+		workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
+										   docsize, NULL, NULL,
+										   XML_PARSE_NOENT);
+		if (workspace->doctree != NULL)
 		{
-			if (comppath != NULL)
-				xmlXPathFreeCompExpr(comppath);
-			xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
-						"XPath Syntax Error");
-		}
+			workspace->ctxt = xmlXPathNewContext(workspace->doctree);
+			if (workspace->ctxt == NULL)
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_OUT_OF_MEMORY,
+							"could not allocate XPath context");
 
-		/* Now evaluate the path expression. */
-		workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+			workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
+
+			/* compile the path */
+			comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
+			if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
+							"XPath Syntax Error");
+
+			/* Now evaluate the path expression. */
+			workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+
+			xmlXPathFreeCompExpr(comppath);
+			comppath = NULL;
+		}
+	}
+	PG_CATCH();
+	{
+		if (comppath != NULL)
+			xmlXPathFreeCompExpr(comppath);
+		cleanup_workspace(workspace);
 
-		xmlXPathFreeCompExpr(comppath);
+		PG_RE_THROW();
 	}
+	PG_END_TRY();
 
 	return workspace;
 }
-- 
2.54.0


--MP_/LMSk9=uMhuQ1QiIJDarDO8G--






^ permalink  raw  reply  [nested|flat] 611+ messages in thread

* [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths
@ 2026-06-01 22:41 Andrey Chernyy <andrey.cherny@tantorlabs.com>
  0 siblings, 0 replies; 611+ messages in thread

From: Andrey Chernyy @ 2026-06-01 22:41 UTC (permalink / raw)

pgxml_xpath() builds an xpath_workspace before returning it to
callers.  If an ERROR is thrown before the function returns, callers
have not received the workspace pointer yet and cannot run
cleanup_workspace().

Add local error cleanup for the partially built workspace and the
compiled XPath expression.  Also check xmlXPathNewContext() before
dereferencing the returned context.
---
 contrib/xml2/xpath.c | 51 +++++++++++++++++++++++++++-----------------
 1 file changed, 32 insertions(+), 19 deletions(-)

diff --git a/contrib/xml2/xpath.c b/contrib/xml2/xpath.c
index 9fe75cb5ff4..283bb51178d 100644
--- a/contrib/xml2/xpath.c
+++ b/contrib/xml2/xpath.c
@@ -497,36 +497,49 @@ static xpath_workspace *
 pgxml_xpath(text *document, xmlChar *xpath, PgXmlErrorContext *xmlerrcxt)
 {
 	int32		docsize = VARSIZE_ANY_EXHDR(document);
-	xmlXPathCompExprPtr comppath;
+	xmlXPathCompExprPtr volatile comppath = NULL;
 	xpath_workspace *workspace = palloc0_object(xpath_workspace);
 
 	workspace->doctree = NULL;
 	workspace->ctxt = NULL;
 	workspace->res = NULL;
 
-	workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
-									   docsize, NULL, NULL,
-									   XML_PARSE_NOENT);
-	if (workspace->doctree != NULL)
+	PG_TRY();
 	{
-		workspace->ctxt = xmlXPathNewContext(workspace->doctree);
-		workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
-
-		/* compile the path */
-		comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
-		if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+		workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
+										   docsize, NULL, NULL,
+										   XML_PARSE_NOENT);
+		if (workspace->doctree != NULL)
 		{
-			if (comppath != NULL)
-				xmlXPathFreeCompExpr(comppath);
-			xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
-						"XPath Syntax Error");
-		}
+			workspace->ctxt = xmlXPathNewContext(workspace->doctree);
+			if (workspace->ctxt == NULL)
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_OUT_OF_MEMORY,
+							"could not allocate XPath context");
 
-		/* Now evaluate the path expression. */
-		workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+			workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
+
+			/* compile the path */
+			comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
+			if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
+							"XPath Syntax Error");
+
+			/* Now evaluate the path expression. */
+			workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+
+			xmlXPathFreeCompExpr(comppath);
+			comppath = NULL;
+		}
+	}
+	PG_CATCH();
+	{
+		if (comppath != NULL)
+			xmlXPathFreeCompExpr(comppath);
+		cleanup_workspace(workspace);
 
-		xmlXPathFreeCompExpr(comppath);
+		PG_RE_THROW();
 	}
+	PG_END_TRY();
 
 	return workspace;
 }
-- 
2.54.0


--MP_/LMSk9=uMhuQ1QiIJDarDO8G--






^ permalink  raw  reply  [nested|flat] 611+ messages in thread

* [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths
@ 2026-06-01 22:41 Andrey Chernyy <andrey.cherny@tantorlabs.com>
  0 siblings, 0 replies; 611+ messages in thread

From: Andrey Chernyy @ 2026-06-01 22:41 UTC (permalink / raw)

pgxml_xpath() builds an xpath_workspace before returning it to
callers.  If an ERROR is thrown before the function returns, callers
have not received the workspace pointer yet and cannot run
cleanup_workspace().

Add local error cleanup for the partially built workspace and the
compiled XPath expression.  Also check xmlXPathNewContext() before
dereferencing the returned context.
---
 contrib/xml2/xpath.c | 51 +++++++++++++++++++++++++++-----------------
 1 file changed, 32 insertions(+), 19 deletions(-)

diff --git a/contrib/xml2/xpath.c b/contrib/xml2/xpath.c
index 9fe75cb5ff4..283bb51178d 100644
--- a/contrib/xml2/xpath.c
+++ b/contrib/xml2/xpath.c
@@ -497,36 +497,49 @@ static xpath_workspace *
 pgxml_xpath(text *document, xmlChar *xpath, PgXmlErrorContext *xmlerrcxt)
 {
 	int32		docsize = VARSIZE_ANY_EXHDR(document);
-	xmlXPathCompExprPtr comppath;
+	xmlXPathCompExprPtr volatile comppath = NULL;
 	xpath_workspace *workspace = palloc0_object(xpath_workspace);
 
 	workspace->doctree = NULL;
 	workspace->ctxt = NULL;
 	workspace->res = NULL;
 
-	workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
-									   docsize, NULL, NULL,
-									   XML_PARSE_NOENT);
-	if (workspace->doctree != NULL)
+	PG_TRY();
 	{
-		workspace->ctxt = xmlXPathNewContext(workspace->doctree);
-		workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
-
-		/* compile the path */
-		comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
-		if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+		workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
+										   docsize, NULL, NULL,
+										   XML_PARSE_NOENT);
+		if (workspace->doctree != NULL)
 		{
-			if (comppath != NULL)
-				xmlXPathFreeCompExpr(comppath);
-			xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
-						"XPath Syntax Error");
-		}
+			workspace->ctxt = xmlXPathNewContext(workspace->doctree);
+			if (workspace->ctxt == NULL)
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_OUT_OF_MEMORY,
+							"could not allocate XPath context");
 
-		/* Now evaluate the path expression. */
-		workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+			workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
+
+			/* compile the path */
+			comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
+			if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
+							"XPath Syntax Error");
+
+			/* Now evaluate the path expression. */
+			workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+
+			xmlXPathFreeCompExpr(comppath);
+			comppath = NULL;
+		}
+	}
+	PG_CATCH();
+	{
+		if (comppath != NULL)
+			xmlXPathFreeCompExpr(comppath);
+		cleanup_workspace(workspace);
 
-		xmlXPathFreeCompExpr(comppath);
+		PG_RE_THROW();
 	}
+	PG_END_TRY();
 
 	return workspace;
 }
-- 
2.54.0


--MP_/LMSk9=uMhuQ1QiIJDarDO8G--






^ permalink  raw  reply  [nested|flat] 611+ messages in thread

* [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths
@ 2026-06-01 22:41 Andrey Chernyy <andrey.cherny@tantorlabs.com>
  0 siblings, 0 replies; 611+ messages in thread

From: Andrey Chernyy @ 2026-06-01 22:41 UTC (permalink / raw)

pgxml_xpath() builds an xpath_workspace before returning it to
callers.  If an ERROR is thrown before the function returns, callers
have not received the workspace pointer yet and cannot run
cleanup_workspace().

Add local error cleanup for the partially built workspace and the
compiled XPath expression.  Also check xmlXPathNewContext() before
dereferencing the returned context.
---
 contrib/xml2/xpath.c | 51 +++++++++++++++++++++++++++-----------------
 1 file changed, 32 insertions(+), 19 deletions(-)

diff --git a/contrib/xml2/xpath.c b/contrib/xml2/xpath.c
index 9fe75cb5ff4..283bb51178d 100644
--- a/contrib/xml2/xpath.c
+++ b/contrib/xml2/xpath.c
@@ -497,36 +497,49 @@ static xpath_workspace *
 pgxml_xpath(text *document, xmlChar *xpath, PgXmlErrorContext *xmlerrcxt)
 {
 	int32		docsize = VARSIZE_ANY_EXHDR(document);
-	xmlXPathCompExprPtr comppath;
+	xmlXPathCompExprPtr volatile comppath = NULL;
 	xpath_workspace *workspace = palloc0_object(xpath_workspace);
 
 	workspace->doctree = NULL;
 	workspace->ctxt = NULL;
 	workspace->res = NULL;
 
-	workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
-									   docsize, NULL, NULL,
-									   XML_PARSE_NOENT);
-	if (workspace->doctree != NULL)
+	PG_TRY();
 	{
-		workspace->ctxt = xmlXPathNewContext(workspace->doctree);
-		workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
-
-		/* compile the path */
-		comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
-		if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+		workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
+										   docsize, NULL, NULL,
+										   XML_PARSE_NOENT);
+		if (workspace->doctree != NULL)
 		{
-			if (comppath != NULL)
-				xmlXPathFreeCompExpr(comppath);
-			xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
-						"XPath Syntax Error");
-		}
+			workspace->ctxt = xmlXPathNewContext(workspace->doctree);
+			if (workspace->ctxt == NULL)
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_OUT_OF_MEMORY,
+							"could not allocate XPath context");
 
-		/* Now evaluate the path expression. */
-		workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+			workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
+
+			/* compile the path */
+			comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
+			if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
+							"XPath Syntax Error");
+
+			/* Now evaluate the path expression. */
+			workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+
+			xmlXPathFreeCompExpr(comppath);
+			comppath = NULL;
+		}
+	}
+	PG_CATCH();
+	{
+		if (comppath != NULL)
+			xmlXPathFreeCompExpr(comppath);
+		cleanup_workspace(workspace);
 
-		xmlXPathFreeCompExpr(comppath);
+		PG_RE_THROW();
 	}
+	PG_END_TRY();
 
 	return workspace;
 }
-- 
2.54.0


--MP_/LMSk9=uMhuQ1QiIJDarDO8G--





^ permalink  raw  reply  [nested|flat] 611+ messages in thread

* [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths
@ 2026-06-01 22:41 Andrey Chernyy <andrey.cherny@tantorlabs.com>
  0 siblings, 0 replies; 611+ messages in thread

From: Andrey Chernyy @ 2026-06-01 22:41 UTC (permalink / raw)

pgxml_xpath() builds an xpath_workspace before returning it to
callers.  If an ERROR is thrown before the function returns, callers
have not received the workspace pointer yet and cannot run
cleanup_workspace().

Add local error cleanup for the partially built workspace and the
compiled XPath expression.  Also check xmlXPathNewContext() before
dereferencing the returned context.
---
 contrib/xml2/xpath.c | 51 +++++++++++++++++++++++++++-----------------
 1 file changed, 32 insertions(+), 19 deletions(-)

diff --git a/contrib/xml2/xpath.c b/contrib/xml2/xpath.c
index 9fe75cb5ff4..283bb51178d 100644
--- a/contrib/xml2/xpath.c
+++ b/contrib/xml2/xpath.c
@@ -497,36 +497,49 @@ static xpath_workspace *
 pgxml_xpath(text *document, xmlChar *xpath, PgXmlErrorContext *xmlerrcxt)
 {
 	int32		docsize = VARSIZE_ANY_EXHDR(document);
-	xmlXPathCompExprPtr comppath;
+	xmlXPathCompExprPtr volatile comppath = NULL;
 	xpath_workspace *workspace = palloc0_object(xpath_workspace);
 
 	workspace->doctree = NULL;
 	workspace->ctxt = NULL;
 	workspace->res = NULL;
 
-	workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
-									   docsize, NULL, NULL,
-									   XML_PARSE_NOENT);
-	if (workspace->doctree != NULL)
+	PG_TRY();
 	{
-		workspace->ctxt = xmlXPathNewContext(workspace->doctree);
-		workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
-
-		/* compile the path */
-		comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
-		if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+		workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
+										   docsize, NULL, NULL,
+										   XML_PARSE_NOENT);
+		if (workspace->doctree != NULL)
 		{
-			if (comppath != NULL)
-				xmlXPathFreeCompExpr(comppath);
-			xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
-						"XPath Syntax Error");
-		}
+			workspace->ctxt = xmlXPathNewContext(workspace->doctree);
+			if (workspace->ctxt == NULL)
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_OUT_OF_MEMORY,
+							"could not allocate XPath context");
 
-		/* Now evaluate the path expression. */
-		workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+			workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
+
+			/* compile the path */
+			comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
+			if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
+							"XPath Syntax Error");
+
+			/* Now evaluate the path expression. */
+			workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+
+			xmlXPathFreeCompExpr(comppath);
+			comppath = NULL;
+		}
+	}
+	PG_CATCH();
+	{
+		if (comppath != NULL)
+			xmlXPathFreeCompExpr(comppath);
+		cleanup_workspace(workspace);
 
-		xmlXPathFreeCompExpr(comppath);
+		PG_RE_THROW();
 	}
+	PG_END_TRY();
 
 	return workspace;
 }
-- 
2.54.0


--MP_/LMSk9=uMhuQ1QiIJDarDO8G--





^ permalink  raw  reply  [nested|flat] 611+ messages in thread

* [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths
@ 2026-06-01 22:41 Andrey Chernyy <andrey.cherny@tantorlabs.com>
  0 siblings, 0 replies; 611+ messages in thread

From: Andrey Chernyy @ 2026-06-01 22:41 UTC (permalink / raw)

pgxml_xpath() builds an xpath_workspace before returning it to
callers.  If an ERROR is thrown before the function returns, callers
have not received the workspace pointer yet and cannot run
cleanup_workspace().

Add local error cleanup for the partially built workspace and the
compiled XPath expression.  Also check xmlXPathNewContext() before
dereferencing the returned context.
---
 contrib/xml2/xpath.c | 51 +++++++++++++++++++++++++++-----------------
 1 file changed, 32 insertions(+), 19 deletions(-)

diff --git a/contrib/xml2/xpath.c b/contrib/xml2/xpath.c
index 9fe75cb5ff4..283bb51178d 100644
--- a/contrib/xml2/xpath.c
+++ b/contrib/xml2/xpath.c
@@ -497,36 +497,49 @@ static xpath_workspace *
 pgxml_xpath(text *document, xmlChar *xpath, PgXmlErrorContext *xmlerrcxt)
 {
 	int32		docsize = VARSIZE_ANY_EXHDR(document);
-	xmlXPathCompExprPtr comppath;
+	xmlXPathCompExprPtr volatile comppath = NULL;
 	xpath_workspace *workspace = palloc0_object(xpath_workspace);
 
 	workspace->doctree = NULL;
 	workspace->ctxt = NULL;
 	workspace->res = NULL;
 
-	workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
-									   docsize, NULL, NULL,
-									   XML_PARSE_NOENT);
-	if (workspace->doctree != NULL)
+	PG_TRY();
 	{
-		workspace->ctxt = xmlXPathNewContext(workspace->doctree);
-		workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
-
-		/* compile the path */
-		comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
-		if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+		workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
+										   docsize, NULL, NULL,
+										   XML_PARSE_NOENT);
+		if (workspace->doctree != NULL)
 		{
-			if (comppath != NULL)
-				xmlXPathFreeCompExpr(comppath);
-			xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
-						"XPath Syntax Error");
-		}
+			workspace->ctxt = xmlXPathNewContext(workspace->doctree);
+			if (workspace->ctxt == NULL)
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_OUT_OF_MEMORY,
+							"could not allocate XPath context");
 
-		/* Now evaluate the path expression. */
-		workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+			workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
+
+			/* compile the path */
+			comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
+			if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
+							"XPath Syntax Error");
+
+			/* Now evaluate the path expression. */
+			workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+
+			xmlXPathFreeCompExpr(comppath);
+			comppath = NULL;
+		}
+	}
+	PG_CATCH();
+	{
+		if (comppath != NULL)
+			xmlXPathFreeCompExpr(comppath);
+		cleanup_workspace(workspace);
 
-		xmlXPathFreeCompExpr(comppath);
+		PG_RE_THROW();
 	}
+	PG_END_TRY();
 
 	return workspace;
 }
-- 
2.54.0


--MP_/LMSk9=uMhuQ1QiIJDarDO8G--






^ permalink  raw  reply  [nested|flat] 611+ messages in thread

* [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths
@ 2026-06-01 22:41 Andrey Chernyy <andrey.cherny@tantorlabs.com>
  0 siblings, 0 replies; 611+ messages in thread

From: Andrey Chernyy @ 2026-06-01 22:41 UTC (permalink / raw)

pgxml_xpath() builds an xpath_workspace before returning it to
callers.  If an ERROR is thrown before the function returns, callers
have not received the workspace pointer yet and cannot run
cleanup_workspace().

Add local error cleanup for the partially built workspace and the
compiled XPath expression.  Also check xmlXPathNewContext() before
dereferencing the returned context.
---
 contrib/xml2/xpath.c | 51 +++++++++++++++++++++++++++-----------------
 1 file changed, 32 insertions(+), 19 deletions(-)

diff --git a/contrib/xml2/xpath.c b/contrib/xml2/xpath.c
index 9fe75cb5ff4..283bb51178d 100644
--- a/contrib/xml2/xpath.c
+++ b/contrib/xml2/xpath.c
@@ -497,36 +497,49 @@ static xpath_workspace *
 pgxml_xpath(text *document, xmlChar *xpath, PgXmlErrorContext *xmlerrcxt)
 {
 	int32		docsize = VARSIZE_ANY_EXHDR(document);
-	xmlXPathCompExprPtr comppath;
+	xmlXPathCompExprPtr volatile comppath = NULL;
 	xpath_workspace *workspace = palloc0_object(xpath_workspace);
 
 	workspace->doctree = NULL;
 	workspace->ctxt = NULL;
 	workspace->res = NULL;
 
-	workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
-									   docsize, NULL, NULL,
-									   XML_PARSE_NOENT);
-	if (workspace->doctree != NULL)
+	PG_TRY();
 	{
-		workspace->ctxt = xmlXPathNewContext(workspace->doctree);
-		workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
-
-		/* compile the path */
-		comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
-		if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+		workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
+										   docsize, NULL, NULL,
+										   XML_PARSE_NOENT);
+		if (workspace->doctree != NULL)
 		{
-			if (comppath != NULL)
-				xmlXPathFreeCompExpr(comppath);
-			xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
-						"XPath Syntax Error");
-		}
+			workspace->ctxt = xmlXPathNewContext(workspace->doctree);
+			if (workspace->ctxt == NULL)
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_OUT_OF_MEMORY,
+							"could not allocate XPath context");
 
-		/* Now evaluate the path expression. */
-		workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+			workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
+
+			/* compile the path */
+			comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
+			if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
+							"XPath Syntax Error");
+
+			/* Now evaluate the path expression. */
+			workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+
+			xmlXPathFreeCompExpr(comppath);
+			comppath = NULL;
+		}
+	}
+	PG_CATCH();
+	{
+		if (comppath != NULL)
+			xmlXPathFreeCompExpr(comppath);
+		cleanup_workspace(workspace);
 
-		xmlXPathFreeCompExpr(comppath);
+		PG_RE_THROW();
 	}
+	PG_END_TRY();
 
 	return workspace;
 }
-- 
2.54.0


--MP_/LMSk9=uMhuQ1QiIJDarDO8G--






^ permalink  raw  reply  [nested|flat] 611+ messages in thread

* [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths
@ 2026-06-01 22:41 Andrey Chernyy <andrey.cherny@tantorlabs.com>
  0 siblings, 0 replies; 611+ messages in thread

From: Andrey Chernyy @ 2026-06-01 22:41 UTC (permalink / raw)

pgxml_xpath() builds an xpath_workspace before returning it to
callers.  If an ERROR is thrown before the function returns, callers
have not received the workspace pointer yet and cannot run
cleanup_workspace().

Add local error cleanup for the partially built workspace and the
compiled XPath expression.  Also check xmlXPathNewContext() before
dereferencing the returned context.
---
 contrib/xml2/xpath.c | 51 +++++++++++++++++++++++++++-----------------
 1 file changed, 32 insertions(+), 19 deletions(-)

diff --git a/contrib/xml2/xpath.c b/contrib/xml2/xpath.c
index 9fe75cb5ff4..283bb51178d 100644
--- a/contrib/xml2/xpath.c
+++ b/contrib/xml2/xpath.c
@@ -497,36 +497,49 @@ static xpath_workspace *
 pgxml_xpath(text *document, xmlChar *xpath, PgXmlErrorContext *xmlerrcxt)
 {
 	int32		docsize = VARSIZE_ANY_EXHDR(document);
-	xmlXPathCompExprPtr comppath;
+	xmlXPathCompExprPtr volatile comppath = NULL;
 	xpath_workspace *workspace = palloc0_object(xpath_workspace);
 
 	workspace->doctree = NULL;
 	workspace->ctxt = NULL;
 	workspace->res = NULL;
 
-	workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
-									   docsize, NULL, NULL,
-									   XML_PARSE_NOENT);
-	if (workspace->doctree != NULL)
+	PG_TRY();
 	{
-		workspace->ctxt = xmlXPathNewContext(workspace->doctree);
-		workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
-
-		/* compile the path */
-		comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
-		if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+		workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
+										   docsize, NULL, NULL,
+										   XML_PARSE_NOENT);
+		if (workspace->doctree != NULL)
 		{
-			if (comppath != NULL)
-				xmlXPathFreeCompExpr(comppath);
-			xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
-						"XPath Syntax Error");
-		}
+			workspace->ctxt = xmlXPathNewContext(workspace->doctree);
+			if (workspace->ctxt == NULL)
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_OUT_OF_MEMORY,
+							"could not allocate XPath context");
 
-		/* Now evaluate the path expression. */
-		workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+			workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
+
+			/* compile the path */
+			comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
+			if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
+							"XPath Syntax Error");
+
+			/* Now evaluate the path expression. */
+			workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+
+			xmlXPathFreeCompExpr(comppath);
+			comppath = NULL;
+		}
+	}
+	PG_CATCH();
+	{
+		if (comppath != NULL)
+			xmlXPathFreeCompExpr(comppath);
+		cleanup_workspace(workspace);
 
-		xmlXPathFreeCompExpr(comppath);
+		PG_RE_THROW();
 	}
+	PG_END_TRY();
 
 	return workspace;
 }
-- 
2.54.0


--MP_/LMSk9=uMhuQ1QiIJDarDO8G--






^ permalink  raw  reply  [nested|flat] 611+ messages in thread

* [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths
@ 2026-06-01 22:41 Andrey Chernyy <andrey.cherny@tantorlabs.com>
  0 siblings, 0 replies; 611+ messages in thread

From: Andrey Chernyy @ 2026-06-01 22:41 UTC (permalink / raw)

pgxml_xpath() builds an xpath_workspace before returning it to
callers.  If an ERROR is thrown before the function returns, callers
have not received the workspace pointer yet and cannot run
cleanup_workspace().

Add local error cleanup for the partially built workspace and the
compiled XPath expression.  Also check xmlXPathNewContext() before
dereferencing the returned context.
---
 contrib/xml2/xpath.c | 51 +++++++++++++++++++++++++++-----------------
 1 file changed, 32 insertions(+), 19 deletions(-)

diff --git a/contrib/xml2/xpath.c b/contrib/xml2/xpath.c
index 9fe75cb5ff4..283bb51178d 100644
--- a/contrib/xml2/xpath.c
+++ b/contrib/xml2/xpath.c
@@ -497,36 +497,49 @@ static xpath_workspace *
 pgxml_xpath(text *document, xmlChar *xpath, PgXmlErrorContext *xmlerrcxt)
 {
 	int32		docsize = VARSIZE_ANY_EXHDR(document);
-	xmlXPathCompExprPtr comppath;
+	xmlXPathCompExprPtr volatile comppath = NULL;
 	xpath_workspace *workspace = palloc0_object(xpath_workspace);
 
 	workspace->doctree = NULL;
 	workspace->ctxt = NULL;
 	workspace->res = NULL;
 
-	workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
-									   docsize, NULL, NULL,
-									   XML_PARSE_NOENT);
-	if (workspace->doctree != NULL)
+	PG_TRY();
 	{
-		workspace->ctxt = xmlXPathNewContext(workspace->doctree);
-		workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
-
-		/* compile the path */
-		comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
-		if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+		workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
+										   docsize, NULL, NULL,
+										   XML_PARSE_NOENT);
+		if (workspace->doctree != NULL)
 		{
-			if (comppath != NULL)
-				xmlXPathFreeCompExpr(comppath);
-			xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
-						"XPath Syntax Error");
-		}
+			workspace->ctxt = xmlXPathNewContext(workspace->doctree);
+			if (workspace->ctxt == NULL)
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_OUT_OF_MEMORY,
+							"could not allocate XPath context");
 
-		/* Now evaluate the path expression. */
-		workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+			workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
+
+			/* compile the path */
+			comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
+			if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
+							"XPath Syntax Error");
+
+			/* Now evaluate the path expression. */
+			workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+
+			xmlXPathFreeCompExpr(comppath);
+			comppath = NULL;
+		}
+	}
+	PG_CATCH();
+	{
+		if (comppath != NULL)
+			xmlXPathFreeCompExpr(comppath);
+		cleanup_workspace(workspace);
 
-		xmlXPathFreeCompExpr(comppath);
+		PG_RE_THROW();
 	}
+	PG_END_TRY();
 
 	return workspace;
 }
-- 
2.54.0


--MP_/LMSk9=uMhuQ1QiIJDarDO8G--






^ permalink  raw  reply  [nested|flat] 611+ messages in thread

* [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths
@ 2026-06-01 22:41 Andrey Chernyy <andrey.cherny@tantorlabs.com>
  0 siblings, 0 replies; 611+ messages in thread

From: Andrey Chernyy @ 2026-06-01 22:41 UTC (permalink / raw)

pgxml_xpath() builds an xpath_workspace before returning it to
callers.  If an ERROR is thrown before the function returns, callers
have not received the workspace pointer yet and cannot run
cleanup_workspace().

Add local error cleanup for the partially built workspace and the
compiled XPath expression.  Also check xmlXPathNewContext() before
dereferencing the returned context.
---
 contrib/xml2/xpath.c | 51 +++++++++++++++++++++++++++-----------------
 1 file changed, 32 insertions(+), 19 deletions(-)

diff --git a/contrib/xml2/xpath.c b/contrib/xml2/xpath.c
index 9fe75cb5ff4..283bb51178d 100644
--- a/contrib/xml2/xpath.c
+++ b/contrib/xml2/xpath.c
@@ -497,36 +497,49 @@ static xpath_workspace *
 pgxml_xpath(text *document, xmlChar *xpath, PgXmlErrorContext *xmlerrcxt)
 {
 	int32		docsize = VARSIZE_ANY_EXHDR(document);
-	xmlXPathCompExprPtr comppath;
+	xmlXPathCompExprPtr volatile comppath = NULL;
 	xpath_workspace *workspace = palloc0_object(xpath_workspace);
 
 	workspace->doctree = NULL;
 	workspace->ctxt = NULL;
 	workspace->res = NULL;
 
-	workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
-									   docsize, NULL, NULL,
-									   XML_PARSE_NOENT);
-	if (workspace->doctree != NULL)
+	PG_TRY();
 	{
-		workspace->ctxt = xmlXPathNewContext(workspace->doctree);
-		workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
-
-		/* compile the path */
-		comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
-		if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+		workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
+										   docsize, NULL, NULL,
+										   XML_PARSE_NOENT);
+		if (workspace->doctree != NULL)
 		{
-			if (comppath != NULL)
-				xmlXPathFreeCompExpr(comppath);
-			xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
-						"XPath Syntax Error");
-		}
+			workspace->ctxt = xmlXPathNewContext(workspace->doctree);
+			if (workspace->ctxt == NULL)
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_OUT_OF_MEMORY,
+							"could not allocate XPath context");
 
-		/* Now evaluate the path expression. */
-		workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+			workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
+
+			/* compile the path */
+			comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
+			if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
+							"XPath Syntax Error");
+
+			/* Now evaluate the path expression. */
+			workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+
+			xmlXPathFreeCompExpr(comppath);
+			comppath = NULL;
+		}
+	}
+	PG_CATCH();
+	{
+		if (comppath != NULL)
+			xmlXPathFreeCompExpr(comppath);
+		cleanup_workspace(workspace);
 
-		xmlXPathFreeCompExpr(comppath);
+		PG_RE_THROW();
 	}
+	PG_END_TRY();
 
 	return workspace;
 }
-- 
2.54.0


--MP_/LMSk9=uMhuQ1QiIJDarDO8G--





^ permalink  raw  reply  [nested|flat] 611+ messages in thread

* [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths
@ 2026-06-01 22:41 Andrey Chernyy <andrey.cherny@tantorlabs.com>
  0 siblings, 0 replies; 611+ messages in thread

From: Andrey Chernyy @ 2026-06-01 22:41 UTC (permalink / raw)

pgxml_xpath() builds an xpath_workspace before returning it to
callers.  If an ERROR is thrown before the function returns, callers
have not received the workspace pointer yet and cannot run
cleanup_workspace().

Add local error cleanup for the partially built workspace and the
compiled XPath expression.  Also check xmlXPathNewContext() before
dereferencing the returned context.
---
 contrib/xml2/xpath.c | 51 +++++++++++++++++++++++++++-----------------
 1 file changed, 32 insertions(+), 19 deletions(-)

diff --git a/contrib/xml2/xpath.c b/contrib/xml2/xpath.c
index 9fe75cb5ff4..283bb51178d 100644
--- a/contrib/xml2/xpath.c
+++ b/contrib/xml2/xpath.c
@@ -497,36 +497,49 @@ static xpath_workspace *
 pgxml_xpath(text *document, xmlChar *xpath, PgXmlErrorContext *xmlerrcxt)
 {
 	int32		docsize = VARSIZE_ANY_EXHDR(document);
-	xmlXPathCompExprPtr comppath;
+	xmlXPathCompExprPtr volatile comppath = NULL;
 	xpath_workspace *workspace = palloc0_object(xpath_workspace);
 
 	workspace->doctree = NULL;
 	workspace->ctxt = NULL;
 	workspace->res = NULL;
 
-	workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
-									   docsize, NULL, NULL,
-									   XML_PARSE_NOENT);
-	if (workspace->doctree != NULL)
+	PG_TRY();
 	{
-		workspace->ctxt = xmlXPathNewContext(workspace->doctree);
-		workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
-
-		/* compile the path */
-		comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
-		if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+		workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
+										   docsize, NULL, NULL,
+										   XML_PARSE_NOENT);
+		if (workspace->doctree != NULL)
 		{
-			if (comppath != NULL)
-				xmlXPathFreeCompExpr(comppath);
-			xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
-						"XPath Syntax Error");
-		}
+			workspace->ctxt = xmlXPathNewContext(workspace->doctree);
+			if (workspace->ctxt == NULL)
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_OUT_OF_MEMORY,
+							"could not allocate XPath context");
 
-		/* Now evaluate the path expression. */
-		workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+			workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
+
+			/* compile the path */
+			comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
+			if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
+							"XPath Syntax Error");
+
+			/* Now evaluate the path expression. */
+			workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+
+			xmlXPathFreeCompExpr(comppath);
+			comppath = NULL;
+		}
+	}
+	PG_CATCH();
+	{
+		if (comppath != NULL)
+			xmlXPathFreeCompExpr(comppath);
+		cleanup_workspace(workspace);
 
-		xmlXPathFreeCompExpr(comppath);
+		PG_RE_THROW();
 	}
+	PG_END_TRY();
 
 	return workspace;
 }
-- 
2.54.0


--MP_/LMSk9=uMhuQ1QiIJDarDO8G--





^ permalink  raw  reply  [nested|flat] 611+ messages in thread

* [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths
@ 2026-06-01 22:41 Andrey Chernyy <andrey.cherny@tantorlabs.com>
  0 siblings, 0 replies; 611+ messages in thread

From: Andrey Chernyy @ 2026-06-01 22:41 UTC (permalink / raw)

pgxml_xpath() builds an xpath_workspace before returning it to
callers.  If an ERROR is thrown before the function returns, callers
have not received the workspace pointer yet and cannot run
cleanup_workspace().

Add local error cleanup for the partially built workspace and the
compiled XPath expression.  Also check xmlXPathNewContext() before
dereferencing the returned context.
---
 contrib/xml2/xpath.c | 51 +++++++++++++++++++++++++++-----------------
 1 file changed, 32 insertions(+), 19 deletions(-)

diff --git a/contrib/xml2/xpath.c b/contrib/xml2/xpath.c
index 9fe75cb5ff4..283bb51178d 100644
--- a/contrib/xml2/xpath.c
+++ b/contrib/xml2/xpath.c
@@ -497,36 +497,49 @@ static xpath_workspace *
 pgxml_xpath(text *document, xmlChar *xpath, PgXmlErrorContext *xmlerrcxt)
 {
 	int32		docsize = VARSIZE_ANY_EXHDR(document);
-	xmlXPathCompExprPtr comppath;
+	xmlXPathCompExprPtr volatile comppath = NULL;
 	xpath_workspace *workspace = palloc0_object(xpath_workspace);
 
 	workspace->doctree = NULL;
 	workspace->ctxt = NULL;
 	workspace->res = NULL;
 
-	workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
-									   docsize, NULL, NULL,
-									   XML_PARSE_NOENT);
-	if (workspace->doctree != NULL)
+	PG_TRY();
 	{
-		workspace->ctxt = xmlXPathNewContext(workspace->doctree);
-		workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
-
-		/* compile the path */
-		comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
-		if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+		workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
+										   docsize, NULL, NULL,
+										   XML_PARSE_NOENT);
+		if (workspace->doctree != NULL)
 		{
-			if (comppath != NULL)
-				xmlXPathFreeCompExpr(comppath);
-			xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
-						"XPath Syntax Error");
-		}
+			workspace->ctxt = xmlXPathNewContext(workspace->doctree);
+			if (workspace->ctxt == NULL)
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_OUT_OF_MEMORY,
+							"could not allocate XPath context");
 
-		/* Now evaluate the path expression. */
-		workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+			workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
+
+			/* compile the path */
+			comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
+			if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
+							"XPath Syntax Error");
+
+			/* Now evaluate the path expression. */
+			workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+
+			xmlXPathFreeCompExpr(comppath);
+			comppath = NULL;
+		}
+	}
+	PG_CATCH();
+	{
+		if (comppath != NULL)
+			xmlXPathFreeCompExpr(comppath);
+		cleanup_workspace(workspace);
 
-		xmlXPathFreeCompExpr(comppath);
+		PG_RE_THROW();
 	}
+	PG_END_TRY();
 
 	return workspace;
 }
-- 
2.54.0


--MP_/LMSk9=uMhuQ1QiIJDarDO8G--






^ permalink  raw  reply  [nested|flat] 611+ messages in thread

* [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths
@ 2026-06-01 22:41 Andrey Chernyy <andrey.cherny@tantorlabs.com>
  0 siblings, 0 replies; 611+ messages in thread

From: Andrey Chernyy @ 2026-06-01 22:41 UTC (permalink / raw)

pgxml_xpath() builds an xpath_workspace before returning it to
callers.  If an ERROR is thrown before the function returns, callers
have not received the workspace pointer yet and cannot run
cleanup_workspace().

Add local error cleanup for the partially built workspace and the
compiled XPath expression.  Also check xmlXPathNewContext() before
dereferencing the returned context.
---
 contrib/xml2/xpath.c | 51 +++++++++++++++++++++++++++-----------------
 1 file changed, 32 insertions(+), 19 deletions(-)

diff --git a/contrib/xml2/xpath.c b/contrib/xml2/xpath.c
index 9fe75cb5ff4..283bb51178d 100644
--- a/contrib/xml2/xpath.c
+++ b/contrib/xml2/xpath.c
@@ -497,36 +497,49 @@ static xpath_workspace *
 pgxml_xpath(text *document, xmlChar *xpath, PgXmlErrorContext *xmlerrcxt)
 {
 	int32		docsize = VARSIZE_ANY_EXHDR(document);
-	xmlXPathCompExprPtr comppath;
+	xmlXPathCompExprPtr volatile comppath = NULL;
 	xpath_workspace *workspace = palloc0_object(xpath_workspace);
 
 	workspace->doctree = NULL;
 	workspace->ctxt = NULL;
 	workspace->res = NULL;
 
-	workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
-									   docsize, NULL, NULL,
-									   XML_PARSE_NOENT);
-	if (workspace->doctree != NULL)
+	PG_TRY();
 	{
-		workspace->ctxt = xmlXPathNewContext(workspace->doctree);
-		workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
-
-		/* compile the path */
-		comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
-		if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+		workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
+										   docsize, NULL, NULL,
+										   XML_PARSE_NOENT);
+		if (workspace->doctree != NULL)
 		{
-			if (comppath != NULL)
-				xmlXPathFreeCompExpr(comppath);
-			xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
-						"XPath Syntax Error");
-		}
+			workspace->ctxt = xmlXPathNewContext(workspace->doctree);
+			if (workspace->ctxt == NULL)
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_OUT_OF_MEMORY,
+							"could not allocate XPath context");
 
-		/* Now evaluate the path expression. */
-		workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+			workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
+
+			/* compile the path */
+			comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
+			if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
+							"XPath Syntax Error");
+
+			/* Now evaluate the path expression. */
+			workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+
+			xmlXPathFreeCompExpr(comppath);
+			comppath = NULL;
+		}
+	}
+	PG_CATCH();
+	{
+		if (comppath != NULL)
+			xmlXPathFreeCompExpr(comppath);
+		cleanup_workspace(workspace);
 
-		xmlXPathFreeCompExpr(comppath);
+		PG_RE_THROW();
 	}
+	PG_END_TRY();
 
 	return workspace;
 }
-- 
2.54.0


--MP_/LMSk9=uMhuQ1QiIJDarDO8G--






^ permalink  raw  reply  [nested|flat] 611+ messages in thread

* [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths
@ 2026-06-01 22:41 Andrey Chernyy <andrey.cherny@tantorlabs.com>
  0 siblings, 0 replies; 611+ messages in thread

From: Andrey Chernyy @ 2026-06-01 22:41 UTC (permalink / raw)

pgxml_xpath() builds an xpath_workspace before returning it to
callers.  If an ERROR is thrown before the function returns, callers
have not received the workspace pointer yet and cannot run
cleanup_workspace().

Add local error cleanup for the partially built workspace and the
compiled XPath expression.  Also check xmlXPathNewContext() before
dereferencing the returned context.
---
 contrib/xml2/xpath.c | 51 +++++++++++++++++++++++++++-----------------
 1 file changed, 32 insertions(+), 19 deletions(-)

diff --git a/contrib/xml2/xpath.c b/contrib/xml2/xpath.c
index 9fe75cb5ff4..283bb51178d 100644
--- a/contrib/xml2/xpath.c
+++ b/contrib/xml2/xpath.c
@@ -497,36 +497,49 @@ static xpath_workspace *
 pgxml_xpath(text *document, xmlChar *xpath, PgXmlErrorContext *xmlerrcxt)
 {
 	int32		docsize = VARSIZE_ANY_EXHDR(document);
-	xmlXPathCompExprPtr comppath;
+	xmlXPathCompExprPtr volatile comppath = NULL;
 	xpath_workspace *workspace = palloc0_object(xpath_workspace);
 
 	workspace->doctree = NULL;
 	workspace->ctxt = NULL;
 	workspace->res = NULL;
 
-	workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
-									   docsize, NULL, NULL,
-									   XML_PARSE_NOENT);
-	if (workspace->doctree != NULL)
+	PG_TRY();
 	{
-		workspace->ctxt = xmlXPathNewContext(workspace->doctree);
-		workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
-
-		/* compile the path */
-		comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
-		if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+		workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
+										   docsize, NULL, NULL,
+										   XML_PARSE_NOENT);
+		if (workspace->doctree != NULL)
 		{
-			if (comppath != NULL)
-				xmlXPathFreeCompExpr(comppath);
-			xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
-						"XPath Syntax Error");
-		}
+			workspace->ctxt = xmlXPathNewContext(workspace->doctree);
+			if (workspace->ctxt == NULL)
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_OUT_OF_MEMORY,
+							"could not allocate XPath context");
 
-		/* Now evaluate the path expression. */
-		workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+			workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
+
+			/* compile the path */
+			comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
+			if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
+							"XPath Syntax Error");
+
+			/* Now evaluate the path expression. */
+			workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+
+			xmlXPathFreeCompExpr(comppath);
+			comppath = NULL;
+		}
+	}
+	PG_CATCH();
+	{
+		if (comppath != NULL)
+			xmlXPathFreeCompExpr(comppath);
+		cleanup_workspace(workspace);
 
-		xmlXPathFreeCompExpr(comppath);
+		PG_RE_THROW();
 	}
+	PG_END_TRY();
 
 	return workspace;
 }
-- 
2.54.0


--MP_/LMSk9=uMhuQ1QiIJDarDO8G--






^ permalink  raw  reply  [nested|flat] 611+ messages in thread

* [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths
@ 2026-06-01 22:41 Andrey Chernyy <andrey.cherny@tantorlabs.com>
  0 siblings, 0 replies; 611+ messages in thread

From: Andrey Chernyy @ 2026-06-01 22:41 UTC (permalink / raw)

pgxml_xpath() builds an xpath_workspace before returning it to
callers.  If an ERROR is thrown before the function returns, callers
have not received the workspace pointer yet and cannot run
cleanup_workspace().

Add local error cleanup for the partially built workspace and the
compiled XPath expression.  Also check xmlXPathNewContext() before
dereferencing the returned context.
---
 contrib/xml2/xpath.c | 51 +++++++++++++++++++++++++++-----------------
 1 file changed, 32 insertions(+), 19 deletions(-)

diff --git a/contrib/xml2/xpath.c b/contrib/xml2/xpath.c
index 9fe75cb5ff4..283bb51178d 100644
--- a/contrib/xml2/xpath.c
+++ b/contrib/xml2/xpath.c
@@ -497,36 +497,49 @@ static xpath_workspace *
 pgxml_xpath(text *document, xmlChar *xpath, PgXmlErrorContext *xmlerrcxt)
 {
 	int32		docsize = VARSIZE_ANY_EXHDR(document);
-	xmlXPathCompExprPtr comppath;
+	xmlXPathCompExprPtr volatile comppath = NULL;
 	xpath_workspace *workspace = palloc0_object(xpath_workspace);
 
 	workspace->doctree = NULL;
 	workspace->ctxt = NULL;
 	workspace->res = NULL;
 
-	workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
-									   docsize, NULL, NULL,
-									   XML_PARSE_NOENT);
-	if (workspace->doctree != NULL)
+	PG_TRY();
 	{
-		workspace->ctxt = xmlXPathNewContext(workspace->doctree);
-		workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
-
-		/* compile the path */
-		comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
-		if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+		workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
+										   docsize, NULL, NULL,
+										   XML_PARSE_NOENT);
+		if (workspace->doctree != NULL)
 		{
-			if (comppath != NULL)
-				xmlXPathFreeCompExpr(comppath);
-			xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
-						"XPath Syntax Error");
-		}
+			workspace->ctxt = xmlXPathNewContext(workspace->doctree);
+			if (workspace->ctxt == NULL)
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_OUT_OF_MEMORY,
+							"could not allocate XPath context");
 
-		/* Now evaluate the path expression. */
-		workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+			workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
+
+			/* compile the path */
+			comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
+			if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
+							"XPath Syntax Error");
+
+			/* Now evaluate the path expression. */
+			workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+
+			xmlXPathFreeCompExpr(comppath);
+			comppath = NULL;
+		}
+	}
+	PG_CATCH();
+	{
+		if (comppath != NULL)
+			xmlXPathFreeCompExpr(comppath);
+		cleanup_workspace(workspace);
 
-		xmlXPathFreeCompExpr(comppath);
+		PG_RE_THROW();
 	}
+	PG_END_TRY();
 
 	return workspace;
 }
-- 
2.54.0


--MP_/LMSk9=uMhuQ1QiIJDarDO8G--






^ permalink  raw  reply  [nested|flat] 611+ messages in thread

* [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths
@ 2026-06-01 22:41 Andrey Chernyy <andrey.cherny@tantorlabs.com>
  0 siblings, 0 replies; 611+ messages in thread

From: Andrey Chernyy @ 2026-06-01 22:41 UTC (permalink / raw)

pgxml_xpath() builds an xpath_workspace before returning it to
callers.  If an ERROR is thrown before the function returns, callers
have not received the workspace pointer yet and cannot run
cleanup_workspace().

Add local error cleanup for the partially built workspace and the
compiled XPath expression.  Also check xmlXPathNewContext() before
dereferencing the returned context.
---
 contrib/xml2/xpath.c | 51 +++++++++++++++++++++++++++-----------------
 1 file changed, 32 insertions(+), 19 deletions(-)

diff --git a/contrib/xml2/xpath.c b/contrib/xml2/xpath.c
index 9fe75cb5ff4..283bb51178d 100644
--- a/contrib/xml2/xpath.c
+++ b/contrib/xml2/xpath.c
@@ -497,36 +497,49 @@ static xpath_workspace *
 pgxml_xpath(text *document, xmlChar *xpath, PgXmlErrorContext *xmlerrcxt)
 {
 	int32		docsize = VARSIZE_ANY_EXHDR(document);
-	xmlXPathCompExprPtr comppath;
+	xmlXPathCompExprPtr volatile comppath = NULL;
 	xpath_workspace *workspace = palloc0_object(xpath_workspace);
 
 	workspace->doctree = NULL;
 	workspace->ctxt = NULL;
 	workspace->res = NULL;
 
-	workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
-									   docsize, NULL, NULL,
-									   XML_PARSE_NOENT);
-	if (workspace->doctree != NULL)
+	PG_TRY();
 	{
-		workspace->ctxt = xmlXPathNewContext(workspace->doctree);
-		workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
-
-		/* compile the path */
-		comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
-		if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+		workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
+										   docsize, NULL, NULL,
+										   XML_PARSE_NOENT);
+		if (workspace->doctree != NULL)
 		{
-			if (comppath != NULL)
-				xmlXPathFreeCompExpr(comppath);
-			xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
-						"XPath Syntax Error");
-		}
+			workspace->ctxt = xmlXPathNewContext(workspace->doctree);
+			if (workspace->ctxt == NULL)
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_OUT_OF_MEMORY,
+							"could not allocate XPath context");
 
-		/* Now evaluate the path expression. */
-		workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+			workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
+
+			/* compile the path */
+			comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
+			if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
+							"XPath Syntax Error");
+
+			/* Now evaluate the path expression. */
+			workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+
+			xmlXPathFreeCompExpr(comppath);
+			comppath = NULL;
+		}
+	}
+	PG_CATCH();
+	{
+		if (comppath != NULL)
+			xmlXPathFreeCompExpr(comppath);
+		cleanup_workspace(workspace);
 
-		xmlXPathFreeCompExpr(comppath);
+		PG_RE_THROW();
 	}
+	PG_END_TRY();
 
 	return workspace;
 }
-- 
2.54.0


--MP_/LMSk9=uMhuQ1QiIJDarDO8G--






^ permalink  raw  reply  [nested|flat] 611+ messages in thread

* [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths
@ 2026-06-01 22:41 Andrey Chernyy <andrey.cherny@tantorlabs.com>
  0 siblings, 0 replies; 611+ messages in thread

From: Andrey Chernyy @ 2026-06-01 22:41 UTC (permalink / raw)

pgxml_xpath() builds an xpath_workspace before returning it to
callers.  If an ERROR is thrown before the function returns, callers
have not received the workspace pointer yet and cannot run
cleanup_workspace().

Add local error cleanup for the partially built workspace and the
compiled XPath expression.  Also check xmlXPathNewContext() before
dereferencing the returned context.
---
 contrib/xml2/xpath.c | 51 +++++++++++++++++++++++++++-----------------
 1 file changed, 32 insertions(+), 19 deletions(-)

diff --git a/contrib/xml2/xpath.c b/contrib/xml2/xpath.c
index 9fe75cb5ff4..283bb51178d 100644
--- a/contrib/xml2/xpath.c
+++ b/contrib/xml2/xpath.c
@@ -497,36 +497,49 @@ static xpath_workspace *
 pgxml_xpath(text *document, xmlChar *xpath, PgXmlErrorContext *xmlerrcxt)
 {
 	int32		docsize = VARSIZE_ANY_EXHDR(document);
-	xmlXPathCompExprPtr comppath;
+	xmlXPathCompExprPtr volatile comppath = NULL;
 	xpath_workspace *workspace = palloc0_object(xpath_workspace);
 
 	workspace->doctree = NULL;
 	workspace->ctxt = NULL;
 	workspace->res = NULL;
 
-	workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
-									   docsize, NULL, NULL,
-									   XML_PARSE_NOENT);
-	if (workspace->doctree != NULL)
+	PG_TRY();
 	{
-		workspace->ctxt = xmlXPathNewContext(workspace->doctree);
-		workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
-
-		/* compile the path */
-		comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
-		if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+		workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
+										   docsize, NULL, NULL,
+										   XML_PARSE_NOENT);
+		if (workspace->doctree != NULL)
 		{
-			if (comppath != NULL)
-				xmlXPathFreeCompExpr(comppath);
-			xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
-						"XPath Syntax Error");
-		}
+			workspace->ctxt = xmlXPathNewContext(workspace->doctree);
+			if (workspace->ctxt == NULL)
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_OUT_OF_MEMORY,
+							"could not allocate XPath context");
 
-		/* Now evaluate the path expression. */
-		workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+			workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
+
+			/* compile the path */
+			comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
+			if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
+							"XPath Syntax Error");
+
+			/* Now evaluate the path expression. */
+			workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+
+			xmlXPathFreeCompExpr(comppath);
+			comppath = NULL;
+		}
+	}
+	PG_CATCH();
+	{
+		if (comppath != NULL)
+			xmlXPathFreeCompExpr(comppath);
+		cleanup_workspace(workspace);
 
-		xmlXPathFreeCompExpr(comppath);
+		PG_RE_THROW();
 	}
+	PG_END_TRY();
 
 	return workspace;
 }
-- 
2.54.0


--MP_/LMSk9=uMhuQ1QiIJDarDO8G--






^ permalink  raw  reply  [nested|flat] 611+ messages in thread

* [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths
@ 2026-06-01 22:41 Andrey Chernyy <andrey.cherny@tantorlabs.com>
  0 siblings, 0 replies; 611+ messages in thread

From: Andrey Chernyy @ 2026-06-01 22:41 UTC (permalink / raw)

pgxml_xpath() builds an xpath_workspace before returning it to
callers.  If an ERROR is thrown before the function returns, callers
have not received the workspace pointer yet and cannot run
cleanup_workspace().

Add local error cleanup for the partially built workspace and the
compiled XPath expression.  Also check xmlXPathNewContext() before
dereferencing the returned context.
---
 contrib/xml2/xpath.c | 51 +++++++++++++++++++++++++++-----------------
 1 file changed, 32 insertions(+), 19 deletions(-)

diff --git a/contrib/xml2/xpath.c b/contrib/xml2/xpath.c
index 9fe75cb5ff4..283bb51178d 100644
--- a/contrib/xml2/xpath.c
+++ b/contrib/xml2/xpath.c
@@ -497,36 +497,49 @@ static xpath_workspace *
 pgxml_xpath(text *document, xmlChar *xpath, PgXmlErrorContext *xmlerrcxt)
 {
 	int32		docsize = VARSIZE_ANY_EXHDR(document);
-	xmlXPathCompExprPtr comppath;
+	xmlXPathCompExprPtr volatile comppath = NULL;
 	xpath_workspace *workspace = palloc0_object(xpath_workspace);
 
 	workspace->doctree = NULL;
 	workspace->ctxt = NULL;
 	workspace->res = NULL;
 
-	workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
-									   docsize, NULL, NULL,
-									   XML_PARSE_NOENT);
-	if (workspace->doctree != NULL)
+	PG_TRY();
 	{
-		workspace->ctxt = xmlXPathNewContext(workspace->doctree);
-		workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
-
-		/* compile the path */
-		comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
-		if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+		workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
+										   docsize, NULL, NULL,
+										   XML_PARSE_NOENT);
+		if (workspace->doctree != NULL)
 		{
-			if (comppath != NULL)
-				xmlXPathFreeCompExpr(comppath);
-			xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
-						"XPath Syntax Error");
-		}
+			workspace->ctxt = xmlXPathNewContext(workspace->doctree);
+			if (workspace->ctxt == NULL)
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_OUT_OF_MEMORY,
+							"could not allocate XPath context");
 
-		/* Now evaluate the path expression. */
-		workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+			workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
+
+			/* compile the path */
+			comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
+			if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
+							"XPath Syntax Error");
+
+			/* Now evaluate the path expression. */
+			workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+
+			xmlXPathFreeCompExpr(comppath);
+			comppath = NULL;
+		}
+	}
+	PG_CATCH();
+	{
+		if (comppath != NULL)
+			xmlXPathFreeCompExpr(comppath);
+		cleanup_workspace(workspace);
 
-		xmlXPathFreeCompExpr(comppath);
+		PG_RE_THROW();
 	}
+	PG_END_TRY();
 
 	return workspace;
 }
-- 
2.54.0


--MP_/LMSk9=uMhuQ1QiIJDarDO8G--






^ permalink  raw  reply  [nested|flat] 611+ messages in thread

* [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths
@ 2026-06-01 22:41 Andrey Chernyy <andrey.cherny@tantorlabs.com>
  0 siblings, 0 replies; 611+ messages in thread

From: Andrey Chernyy @ 2026-06-01 22:41 UTC (permalink / raw)

pgxml_xpath() builds an xpath_workspace before returning it to
callers.  If an ERROR is thrown before the function returns, callers
have not received the workspace pointer yet and cannot run
cleanup_workspace().

Add local error cleanup for the partially built workspace and the
compiled XPath expression.  Also check xmlXPathNewContext() before
dereferencing the returned context.
---
 contrib/xml2/xpath.c | 51 +++++++++++++++++++++++++++-----------------
 1 file changed, 32 insertions(+), 19 deletions(-)

diff --git a/contrib/xml2/xpath.c b/contrib/xml2/xpath.c
index 9fe75cb5ff4..283bb51178d 100644
--- a/contrib/xml2/xpath.c
+++ b/contrib/xml2/xpath.c
@@ -497,36 +497,49 @@ static xpath_workspace *
 pgxml_xpath(text *document, xmlChar *xpath, PgXmlErrorContext *xmlerrcxt)
 {
 	int32		docsize = VARSIZE_ANY_EXHDR(document);
-	xmlXPathCompExprPtr comppath;
+	xmlXPathCompExprPtr volatile comppath = NULL;
 	xpath_workspace *workspace = palloc0_object(xpath_workspace);
 
 	workspace->doctree = NULL;
 	workspace->ctxt = NULL;
 	workspace->res = NULL;
 
-	workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
-									   docsize, NULL, NULL,
-									   XML_PARSE_NOENT);
-	if (workspace->doctree != NULL)
+	PG_TRY();
 	{
-		workspace->ctxt = xmlXPathNewContext(workspace->doctree);
-		workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
-
-		/* compile the path */
-		comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
-		if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+		workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
+										   docsize, NULL, NULL,
+										   XML_PARSE_NOENT);
+		if (workspace->doctree != NULL)
 		{
-			if (comppath != NULL)
-				xmlXPathFreeCompExpr(comppath);
-			xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
-						"XPath Syntax Error");
-		}
+			workspace->ctxt = xmlXPathNewContext(workspace->doctree);
+			if (workspace->ctxt == NULL)
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_OUT_OF_MEMORY,
+							"could not allocate XPath context");
 
-		/* Now evaluate the path expression. */
-		workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+			workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
+
+			/* compile the path */
+			comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
+			if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
+							"XPath Syntax Error");
+
+			/* Now evaluate the path expression. */
+			workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+
+			xmlXPathFreeCompExpr(comppath);
+			comppath = NULL;
+		}
+	}
+	PG_CATCH();
+	{
+		if (comppath != NULL)
+			xmlXPathFreeCompExpr(comppath);
+		cleanup_workspace(workspace);
 
-		xmlXPathFreeCompExpr(comppath);
+		PG_RE_THROW();
 	}
+	PG_END_TRY();
 
 	return workspace;
 }
-- 
2.54.0


--MP_/LMSk9=uMhuQ1QiIJDarDO8G--






^ permalink  raw  reply  [nested|flat] 611+ messages in thread

* [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths
@ 2026-06-01 22:41 Andrey Chernyy <andrey.cherny@tantorlabs.com>
  0 siblings, 0 replies; 611+ messages in thread

From: Andrey Chernyy @ 2026-06-01 22:41 UTC (permalink / raw)

pgxml_xpath() builds an xpath_workspace before returning it to
callers.  If an ERROR is thrown before the function returns, callers
have not received the workspace pointer yet and cannot run
cleanup_workspace().

Add local error cleanup for the partially built workspace and the
compiled XPath expression.  Also check xmlXPathNewContext() before
dereferencing the returned context.
---
 contrib/xml2/xpath.c | 51 +++++++++++++++++++++++++++-----------------
 1 file changed, 32 insertions(+), 19 deletions(-)

diff --git a/contrib/xml2/xpath.c b/contrib/xml2/xpath.c
index 9fe75cb5ff4..283bb51178d 100644
--- a/contrib/xml2/xpath.c
+++ b/contrib/xml2/xpath.c
@@ -497,36 +497,49 @@ static xpath_workspace *
 pgxml_xpath(text *document, xmlChar *xpath, PgXmlErrorContext *xmlerrcxt)
 {
 	int32		docsize = VARSIZE_ANY_EXHDR(document);
-	xmlXPathCompExprPtr comppath;
+	xmlXPathCompExprPtr volatile comppath = NULL;
 	xpath_workspace *workspace = palloc0_object(xpath_workspace);
 
 	workspace->doctree = NULL;
 	workspace->ctxt = NULL;
 	workspace->res = NULL;
 
-	workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
-									   docsize, NULL, NULL,
-									   XML_PARSE_NOENT);
-	if (workspace->doctree != NULL)
+	PG_TRY();
 	{
-		workspace->ctxt = xmlXPathNewContext(workspace->doctree);
-		workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
-
-		/* compile the path */
-		comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
-		if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+		workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
+										   docsize, NULL, NULL,
+										   XML_PARSE_NOENT);
+		if (workspace->doctree != NULL)
 		{
-			if (comppath != NULL)
-				xmlXPathFreeCompExpr(comppath);
-			xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
-						"XPath Syntax Error");
-		}
+			workspace->ctxt = xmlXPathNewContext(workspace->doctree);
+			if (workspace->ctxt == NULL)
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_OUT_OF_MEMORY,
+							"could not allocate XPath context");
 
-		/* Now evaluate the path expression. */
-		workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+			workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
+
+			/* compile the path */
+			comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
+			if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
+							"XPath Syntax Error");
+
+			/* Now evaluate the path expression. */
+			workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+
+			xmlXPathFreeCompExpr(comppath);
+			comppath = NULL;
+		}
+	}
+	PG_CATCH();
+	{
+		if (comppath != NULL)
+			xmlXPathFreeCompExpr(comppath);
+		cleanup_workspace(workspace);
 
-		xmlXPathFreeCompExpr(comppath);
+		PG_RE_THROW();
 	}
+	PG_END_TRY();
 
 	return workspace;
 }
-- 
2.54.0


--MP_/LMSk9=uMhuQ1QiIJDarDO8G--





^ permalink  raw  reply  [nested|flat] 611+ messages in thread

* [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths
@ 2026-06-01 22:41 Andrey Chernyy <andrey.cherny@tantorlabs.com>
  0 siblings, 0 replies; 611+ messages in thread

From: Andrey Chernyy @ 2026-06-01 22:41 UTC (permalink / raw)

pgxml_xpath() builds an xpath_workspace before returning it to
callers.  If an ERROR is thrown before the function returns, callers
have not received the workspace pointer yet and cannot run
cleanup_workspace().

Add local error cleanup for the partially built workspace and the
compiled XPath expression.  Also check xmlXPathNewContext() before
dereferencing the returned context.
---
 contrib/xml2/xpath.c | 51 +++++++++++++++++++++++++++-----------------
 1 file changed, 32 insertions(+), 19 deletions(-)

diff --git a/contrib/xml2/xpath.c b/contrib/xml2/xpath.c
index 9fe75cb5ff4..283bb51178d 100644
--- a/contrib/xml2/xpath.c
+++ b/contrib/xml2/xpath.c
@@ -497,36 +497,49 @@ static xpath_workspace *
 pgxml_xpath(text *document, xmlChar *xpath, PgXmlErrorContext *xmlerrcxt)
 {
 	int32		docsize = VARSIZE_ANY_EXHDR(document);
-	xmlXPathCompExprPtr comppath;
+	xmlXPathCompExprPtr volatile comppath = NULL;
 	xpath_workspace *workspace = palloc0_object(xpath_workspace);
 
 	workspace->doctree = NULL;
 	workspace->ctxt = NULL;
 	workspace->res = NULL;
 
-	workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
-									   docsize, NULL, NULL,
-									   XML_PARSE_NOENT);
-	if (workspace->doctree != NULL)
+	PG_TRY();
 	{
-		workspace->ctxt = xmlXPathNewContext(workspace->doctree);
-		workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
-
-		/* compile the path */
-		comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
-		if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+		workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
+										   docsize, NULL, NULL,
+										   XML_PARSE_NOENT);
+		if (workspace->doctree != NULL)
 		{
-			if (comppath != NULL)
-				xmlXPathFreeCompExpr(comppath);
-			xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
-						"XPath Syntax Error");
-		}
+			workspace->ctxt = xmlXPathNewContext(workspace->doctree);
+			if (workspace->ctxt == NULL)
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_OUT_OF_MEMORY,
+							"could not allocate XPath context");
 
-		/* Now evaluate the path expression. */
-		workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+			workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
+
+			/* compile the path */
+			comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
+			if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
+							"XPath Syntax Error");
+
+			/* Now evaluate the path expression. */
+			workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+
+			xmlXPathFreeCompExpr(comppath);
+			comppath = NULL;
+		}
+	}
+	PG_CATCH();
+	{
+		if (comppath != NULL)
+			xmlXPathFreeCompExpr(comppath);
+		cleanup_workspace(workspace);
 
-		xmlXPathFreeCompExpr(comppath);
+		PG_RE_THROW();
 	}
+	PG_END_TRY();
 
 	return workspace;
 }
-- 
2.54.0


--MP_/LMSk9=uMhuQ1QiIJDarDO8G--






^ permalink  raw  reply  [nested|flat] 611+ messages in thread

* [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths
@ 2026-06-01 22:41 Andrey Chernyy <andrey.cherny@tantorlabs.com>
  0 siblings, 0 replies; 611+ messages in thread

From: Andrey Chernyy @ 2026-06-01 22:41 UTC (permalink / raw)

pgxml_xpath() builds an xpath_workspace before returning it to
callers.  If an ERROR is thrown before the function returns, callers
have not received the workspace pointer yet and cannot run
cleanup_workspace().

Add local error cleanup for the partially built workspace and the
compiled XPath expression.  Also check xmlXPathNewContext() before
dereferencing the returned context.
---
 contrib/xml2/xpath.c | 51 +++++++++++++++++++++++++++-----------------
 1 file changed, 32 insertions(+), 19 deletions(-)

diff --git a/contrib/xml2/xpath.c b/contrib/xml2/xpath.c
index 9fe75cb5ff4..283bb51178d 100644
--- a/contrib/xml2/xpath.c
+++ b/contrib/xml2/xpath.c
@@ -497,36 +497,49 @@ static xpath_workspace *
 pgxml_xpath(text *document, xmlChar *xpath, PgXmlErrorContext *xmlerrcxt)
 {
 	int32		docsize = VARSIZE_ANY_EXHDR(document);
-	xmlXPathCompExprPtr comppath;
+	xmlXPathCompExprPtr volatile comppath = NULL;
 	xpath_workspace *workspace = palloc0_object(xpath_workspace);
 
 	workspace->doctree = NULL;
 	workspace->ctxt = NULL;
 	workspace->res = NULL;
 
-	workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
-									   docsize, NULL, NULL,
-									   XML_PARSE_NOENT);
-	if (workspace->doctree != NULL)
+	PG_TRY();
 	{
-		workspace->ctxt = xmlXPathNewContext(workspace->doctree);
-		workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
-
-		/* compile the path */
-		comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
-		if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+		workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
+										   docsize, NULL, NULL,
+										   XML_PARSE_NOENT);
+		if (workspace->doctree != NULL)
 		{
-			if (comppath != NULL)
-				xmlXPathFreeCompExpr(comppath);
-			xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
-						"XPath Syntax Error");
-		}
+			workspace->ctxt = xmlXPathNewContext(workspace->doctree);
+			if (workspace->ctxt == NULL)
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_OUT_OF_MEMORY,
+							"could not allocate XPath context");
 
-		/* Now evaluate the path expression. */
-		workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+			workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
+
+			/* compile the path */
+			comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
+			if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
+							"XPath Syntax Error");
+
+			/* Now evaluate the path expression. */
+			workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+
+			xmlXPathFreeCompExpr(comppath);
+			comppath = NULL;
+		}
+	}
+	PG_CATCH();
+	{
+		if (comppath != NULL)
+			xmlXPathFreeCompExpr(comppath);
+		cleanup_workspace(workspace);
 
-		xmlXPathFreeCompExpr(comppath);
+		PG_RE_THROW();
 	}
+	PG_END_TRY();
 
 	return workspace;
 }
-- 
2.54.0


--MP_/LMSk9=uMhuQ1QiIJDarDO8G--





^ permalink  raw  reply  [nested|flat] 611+ messages in thread

* [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths
@ 2026-06-01 22:41 Andrey Chernyy <andrey.cherny@tantorlabs.com>
  0 siblings, 0 replies; 611+ messages in thread

From: Andrey Chernyy @ 2026-06-01 22:41 UTC (permalink / raw)

pgxml_xpath() builds an xpath_workspace before returning it to
callers.  If an ERROR is thrown before the function returns, callers
have not received the workspace pointer yet and cannot run
cleanup_workspace().

Add local error cleanup for the partially built workspace and the
compiled XPath expression.  Also check xmlXPathNewContext() before
dereferencing the returned context.
---
 contrib/xml2/xpath.c | 51 +++++++++++++++++++++++++++-----------------
 1 file changed, 32 insertions(+), 19 deletions(-)

diff --git a/contrib/xml2/xpath.c b/contrib/xml2/xpath.c
index 9fe75cb5ff4..283bb51178d 100644
--- a/contrib/xml2/xpath.c
+++ b/contrib/xml2/xpath.c
@@ -497,36 +497,49 @@ static xpath_workspace *
 pgxml_xpath(text *document, xmlChar *xpath, PgXmlErrorContext *xmlerrcxt)
 {
 	int32		docsize = VARSIZE_ANY_EXHDR(document);
-	xmlXPathCompExprPtr comppath;
+	xmlXPathCompExprPtr volatile comppath = NULL;
 	xpath_workspace *workspace = palloc0_object(xpath_workspace);
 
 	workspace->doctree = NULL;
 	workspace->ctxt = NULL;
 	workspace->res = NULL;
 
-	workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
-									   docsize, NULL, NULL,
-									   XML_PARSE_NOENT);
-	if (workspace->doctree != NULL)
+	PG_TRY();
 	{
-		workspace->ctxt = xmlXPathNewContext(workspace->doctree);
-		workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
-
-		/* compile the path */
-		comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
-		if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+		workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
+										   docsize, NULL, NULL,
+										   XML_PARSE_NOENT);
+		if (workspace->doctree != NULL)
 		{
-			if (comppath != NULL)
-				xmlXPathFreeCompExpr(comppath);
-			xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
-						"XPath Syntax Error");
-		}
+			workspace->ctxt = xmlXPathNewContext(workspace->doctree);
+			if (workspace->ctxt == NULL)
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_OUT_OF_MEMORY,
+							"could not allocate XPath context");
 
-		/* Now evaluate the path expression. */
-		workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+			workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
+
+			/* compile the path */
+			comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
+			if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
+							"XPath Syntax Error");
+
+			/* Now evaluate the path expression. */
+			workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+
+			xmlXPathFreeCompExpr(comppath);
+			comppath = NULL;
+		}
+	}
+	PG_CATCH();
+	{
+		if (comppath != NULL)
+			xmlXPathFreeCompExpr(comppath);
+		cleanup_workspace(workspace);
 
-		xmlXPathFreeCompExpr(comppath);
+		PG_RE_THROW();
 	}
+	PG_END_TRY();
 
 	return workspace;
 }
-- 
2.54.0


--MP_/LMSk9=uMhuQ1QiIJDarDO8G--






^ permalink  raw  reply  [nested|flat] 611+ messages in thread

* [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths
@ 2026-06-01 22:41 Andrey Chernyy <andrey.cherny@tantorlabs.com>
  0 siblings, 0 replies; 611+ messages in thread

From: Andrey Chernyy @ 2026-06-01 22:41 UTC (permalink / raw)

pgxml_xpath() builds an xpath_workspace before returning it to
callers.  If an ERROR is thrown before the function returns, callers
have not received the workspace pointer yet and cannot run
cleanup_workspace().

Add local error cleanup for the partially built workspace and the
compiled XPath expression.  Also check xmlXPathNewContext() before
dereferencing the returned context.
---
 contrib/xml2/xpath.c | 51 +++++++++++++++++++++++++++-----------------
 1 file changed, 32 insertions(+), 19 deletions(-)

diff --git a/contrib/xml2/xpath.c b/contrib/xml2/xpath.c
index 9fe75cb5ff4..283bb51178d 100644
--- a/contrib/xml2/xpath.c
+++ b/contrib/xml2/xpath.c
@@ -497,36 +497,49 @@ static xpath_workspace *
 pgxml_xpath(text *document, xmlChar *xpath, PgXmlErrorContext *xmlerrcxt)
 {
 	int32		docsize = VARSIZE_ANY_EXHDR(document);
-	xmlXPathCompExprPtr comppath;
+	xmlXPathCompExprPtr volatile comppath = NULL;
 	xpath_workspace *workspace = palloc0_object(xpath_workspace);
 
 	workspace->doctree = NULL;
 	workspace->ctxt = NULL;
 	workspace->res = NULL;
 
-	workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
-									   docsize, NULL, NULL,
-									   XML_PARSE_NOENT);
-	if (workspace->doctree != NULL)
+	PG_TRY();
 	{
-		workspace->ctxt = xmlXPathNewContext(workspace->doctree);
-		workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
-
-		/* compile the path */
-		comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
-		if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+		workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
+										   docsize, NULL, NULL,
+										   XML_PARSE_NOENT);
+		if (workspace->doctree != NULL)
 		{
-			if (comppath != NULL)
-				xmlXPathFreeCompExpr(comppath);
-			xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
-						"XPath Syntax Error");
-		}
+			workspace->ctxt = xmlXPathNewContext(workspace->doctree);
+			if (workspace->ctxt == NULL)
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_OUT_OF_MEMORY,
+							"could not allocate XPath context");
 
-		/* Now evaluate the path expression. */
-		workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+			workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
+
+			/* compile the path */
+			comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
+			if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
+							"XPath Syntax Error");
+
+			/* Now evaluate the path expression. */
+			workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+
+			xmlXPathFreeCompExpr(comppath);
+			comppath = NULL;
+		}
+	}
+	PG_CATCH();
+	{
+		if (comppath != NULL)
+			xmlXPathFreeCompExpr(comppath);
+		cleanup_workspace(workspace);
 
-		xmlXPathFreeCompExpr(comppath);
+		PG_RE_THROW();
 	}
+	PG_END_TRY();
 
 	return workspace;
 }
-- 
2.54.0


--MP_/LMSk9=uMhuQ1QiIJDarDO8G--






^ permalink  raw  reply  [nested|flat] 611+ messages in thread

* [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths
@ 2026-06-01 22:41 Andrey Chernyy <andrey.cherny@tantorlabs.com>
  0 siblings, 0 replies; 611+ messages in thread

From: Andrey Chernyy @ 2026-06-01 22:41 UTC (permalink / raw)

pgxml_xpath() builds an xpath_workspace before returning it to
callers.  If an ERROR is thrown before the function returns, callers
have not received the workspace pointer yet and cannot run
cleanup_workspace().

Add local error cleanup for the partially built workspace and the
compiled XPath expression.  Also check xmlXPathNewContext() before
dereferencing the returned context.
---
 contrib/xml2/xpath.c | 51 +++++++++++++++++++++++++++-----------------
 1 file changed, 32 insertions(+), 19 deletions(-)

diff --git a/contrib/xml2/xpath.c b/contrib/xml2/xpath.c
index 9fe75cb5ff4..283bb51178d 100644
--- a/contrib/xml2/xpath.c
+++ b/contrib/xml2/xpath.c
@@ -497,36 +497,49 @@ static xpath_workspace *
 pgxml_xpath(text *document, xmlChar *xpath, PgXmlErrorContext *xmlerrcxt)
 {
 	int32		docsize = VARSIZE_ANY_EXHDR(document);
-	xmlXPathCompExprPtr comppath;
+	xmlXPathCompExprPtr volatile comppath = NULL;
 	xpath_workspace *workspace = palloc0_object(xpath_workspace);
 
 	workspace->doctree = NULL;
 	workspace->ctxt = NULL;
 	workspace->res = NULL;
 
-	workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
-									   docsize, NULL, NULL,
-									   XML_PARSE_NOENT);
-	if (workspace->doctree != NULL)
+	PG_TRY();
 	{
-		workspace->ctxt = xmlXPathNewContext(workspace->doctree);
-		workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
-
-		/* compile the path */
-		comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
-		if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+		workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
+										   docsize, NULL, NULL,
+										   XML_PARSE_NOENT);
+		if (workspace->doctree != NULL)
 		{
-			if (comppath != NULL)
-				xmlXPathFreeCompExpr(comppath);
-			xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
-						"XPath Syntax Error");
-		}
+			workspace->ctxt = xmlXPathNewContext(workspace->doctree);
+			if (workspace->ctxt == NULL)
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_OUT_OF_MEMORY,
+							"could not allocate XPath context");
 
-		/* Now evaluate the path expression. */
-		workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+			workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
+
+			/* compile the path */
+			comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
+			if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
+							"XPath Syntax Error");
+
+			/* Now evaluate the path expression. */
+			workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+
+			xmlXPathFreeCompExpr(comppath);
+			comppath = NULL;
+		}
+	}
+	PG_CATCH();
+	{
+		if (comppath != NULL)
+			xmlXPathFreeCompExpr(comppath);
+		cleanup_workspace(workspace);
 
-		xmlXPathFreeCompExpr(comppath);
+		PG_RE_THROW();
 	}
+	PG_END_TRY();
 
 	return workspace;
 }
-- 
2.54.0


--MP_/LMSk9=uMhuQ1QiIJDarDO8G--






^ permalink  raw  reply  [nested|flat] 611+ messages in thread

* [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths
@ 2026-06-01 22:41 Andrey Chernyy <andrey.cherny@tantorlabs.com>
  0 siblings, 0 replies; 611+ messages in thread

From: Andrey Chernyy @ 2026-06-01 22:41 UTC (permalink / raw)

pgxml_xpath() builds an xpath_workspace before returning it to
callers.  If an ERROR is thrown before the function returns, callers
have not received the workspace pointer yet and cannot run
cleanup_workspace().

Add local error cleanup for the partially built workspace and the
compiled XPath expression.  Also check xmlXPathNewContext() before
dereferencing the returned context.
---
 contrib/xml2/xpath.c | 51 +++++++++++++++++++++++++++-----------------
 1 file changed, 32 insertions(+), 19 deletions(-)

diff --git a/contrib/xml2/xpath.c b/contrib/xml2/xpath.c
index 9fe75cb5ff4..283bb51178d 100644
--- a/contrib/xml2/xpath.c
+++ b/contrib/xml2/xpath.c
@@ -497,36 +497,49 @@ static xpath_workspace *
 pgxml_xpath(text *document, xmlChar *xpath, PgXmlErrorContext *xmlerrcxt)
 {
 	int32		docsize = VARSIZE_ANY_EXHDR(document);
-	xmlXPathCompExprPtr comppath;
+	xmlXPathCompExprPtr volatile comppath = NULL;
 	xpath_workspace *workspace = palloc0_object(xpath_workspace);
 
 	workspace->doctree = NULL;
 	workspace->ctxt = NULL;
 	workspace->res = NULL;
 
-	workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
-									   docsize, NULL, NULL,
-									   XML_PARSE_NOENT);
-	if (workspace->doctree != NULL)
+	PG_TRY();
 	{
-		workspace->ctxt = xmlXPathNewContext(workspace->doctree);
-		workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
-
-		/* compile the path */
-		comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
-		if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+		workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
+										   docsize, NULL, NULL,
+										   XML_PARSE_NOENT);
+		if (workspace->doctree != NULL)
 		{
-			if (comppath != NULL)
-				xmlXPathFreeCompExpr(comppath);
-			xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
-						"XPath Syntax Error");
-		}
+			workspace->ctxt = xmlXPathNewContext(workspace->doctree);
+			if (workspace->ctxt == NULL)
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_OUT_OF_MEMORY,
+							"could not allocate XPath context");
 
-		/* Now evaluate the path expression. */
-		workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+			workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
+
+			/* compile the path */
+			comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
+			if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
+							"XPath Syntax Error");
+
+			/* Now evaluate the path expression. */
+			workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+
+			xmlXPathFreeCompExpr(comppath);
+			comppath = NULL;
+		}
+	}
+	PG_CATCH();
+	{
+		if (comppath != NULL)
+			xmlXPathFreeCompExpr(comppath);
+		cleanup_workspace(workspace);
 
-		xmlXPathFreeCompExpr(comppath);
+		PG_RE_THROW();
 	}
+	PG_END_TRY();
 
 	return workspace;
 }
-- 
2.54.0


--MP_/LMSk9=uMhuQ1QiIJDarDO8G--





^ permalink  raw  reply  [nested|flat] 611+ messages in thread

* [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths
@ 2026-06-01 22:41 Andrey Chernyy <andrey.cherny@tantorlabs.com>
  0 siblings, 0 replies; 611+ messages in thread

From: Andrey Chernyy @ 2026-06-01 22:41 UTC (permalink / raw)

pgxml_xpath() builds an xpath_workspace before returning it to
callers.  If an ERROR is thrown before the function returns, callers
have not received the workspace pointer yet and cannot run
cleanup_workspace().

Add local error cleanup for the partially built workspace and the
compiled XPath expression.  Also check xmlXPathNewContext() before
dereferencing the returned context.
---
 contrib/xml2/xpath.c | 51 +++++++++++++++++++++++++++-----------------
 1 file changed, 32 insertions(+), 19 deletions(-)

diff --git a/contrib/xml2/xpath.c b/contrib/xml2/xpath.c
index 9fe75cb5ff4..283bb51178d 100644
--- a/contrib/xml2/xpath.c
+++ b/contrib/xml2/xpath.c
@@ -497,36 +497,49 @@ static xpath_workspace *
 pgxml_xpath(text *document, xmlChar *xpath, PgXmlErrorContext *xmlerrcxt)
 {
 	int32		docsize = VARSIZE_ANY_EXHDR(document);
-	xmlXPathCompExprPtr comppath;
+	xmlXPathCompExprPtr volatile comppath = NULL;
 	xpath_workspace *workspace = palloc0_object(xpath_workspace);
 
 	workspace->doctree = NULL;
 	workspace->ctxt = NULL;
 	workspace->res = NULL;
 
-	workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
-									   docsize, NULL, NULL,
-									   XML_PARSE_NOENT);
-	if (workspace->doctree != NULL)
+	PG_TRY();
 	{
-		workspace->ctxt = xmlXPathNewContext(workspace->doctree);
-		workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
-
-		/* compile the path */
-		comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
-		if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+		workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
+										   docsize, NULL, NULL,
+										   XML_PARSE_NOENT);
+		if (workspace->doctree != NULL)
 		{
-			if (comppath != NULL)
-				xmlXPathFreeCompExpr(comppath);
-			xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
-						"XPath Syntax Error");
-		}
+			workspace->ctxt = xmlXPathNewContext(workspace->doctree);
+			if (workspace->ctxt == NULL)
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_OUT_OF_MEMORY,
+							"could not allocate XPath context");
 
-		/* Now evaluate the path expression. */
-		workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+			workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
+
+			/* compile the path */
+			comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
+			if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
+							"XPath Syntax Error");
+
+			/* Now evaluate the path expression. */
+			workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+
+			xmlXPathFreeCompExpr(comppath);
+			comppath = NULL;
+		}
+	}
+	PG_CATCH();
+	{
+		if (comppath != NULL)
+			xmlXPathFreeCompExpr(comppath);
+		cleanup_workspace(workspace);
 
-		xmlXPathFreeCompExpr(comppath);
+		PG_RE_THROW();
 	}
+	PG_END_TRY();
 
 	return workspace;
 }
-- 
2.54.0


--MP_/LMSk9=uMhuQ1QiIJDarDO8G--





^ permalink  raw  reply  [nested|flat] 611+ messages in thread

* [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths
@ 2026-06-01 22:41 Andrey Chernyy <andrey.cherny@tantorlabs.com>
  0 siblings, 0 replies; 611+ messages in thread

From: Andrey Chernyy @ 2026-06-01 22:41 UTC (permalink / raw)

pgxml_xpath() builds an xpath_workspace before returning it to
callers.  If an ERROR is thrown before the function returns, callers
have not received the workspace pointer yet and cannot run
cleanup_workspace().

Add local error cleanup for the partially built workspace and the
compiled XPath expression.  Also check xmlXPathNewContext() before
dereferencing the returned context.
---
 contrib/xml2/xpath.c | 51 +++++++++++++++++++++++++++-----------------
 1 file changed, 32 insertions(+), 19 deletions(-)

diff --git a/contrib/xml2/xpath.c b/contrib/xml2/xpath.c
index 9fe75cb5ff4..283bb51178d 100644
--- a/contrib/xml2/xpath.c
+++ b/contrib/xml2/xpath.c
@@ -497,36 +497,49 @@ static xpath_workspace *
 pgxml_xpath(text *document, xmlChar *xpath, PgXmlErrorContext *xmlerrcxt)
 {
 	int32		docsize = VARSIZE_ANY_EXHDR(document);
-	xmlXPathCompExprPtr comppath;
+	xmlXPathCompExprPtr volatile comppath = NULL;
 	xpath_workspace *workspace = palloc0_object(xpath_workspace);
 
 	workspace->doctree = NULL;
 	workspace->ctxt = NULL;
 	workspace->res = NULL;
 
-	workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
-									   docsize, NULL, NULL,
-									   XML_PARSE_NOENT);
-	if (workspace->doctree != NULL)
+	PG_TRY();
 	{
-		workspace->ctxt = xmlXPathNewContext(workspace->doctree);
-		workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
-
-		/* compile the path */
-		comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
-		if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+		workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
+										   docsize, NULL, NULL,
+										   XML_PARSE_NOENT);
+		if (workspace->doctree != NULL)
 		{
-			if (comppath != NULL)
-				xmlXPathFreeCompExpr(comppath);
-			xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
-						"XPath Syntax Error");
-		}
+			workspace->ctxt = xmlXPathNewContext(workspace->doctree);
+			if (workspace->ctxt == NULL)
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_OUT_OF_MEMORY,
+							"could not allocate XPath context");
 
-		/* Now evaluate the path expression. */
-		workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+			workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
+
+			/* compile the path */
+			comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
+			if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
+							"XPath Syntax Error");
+
+			/* Now evaluate the path expression. */
+			workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+
+			xmlXPathFreeCompExpr(comppath);
+			comppath = NULL;
+		}
+	}
+	PG_CATCH();
+	{
+		if (comppath != NULL)
+			xmlXPathFreeCompExpr(comppath);
+		cleanup_workspace(workspace);
 
-		xmlXPathFreeCompExpr(comppath);
+		PG_RE_THROW();
 	}
+	PG_END_TRY();
 
 	return workspace;
 }
-- 
2.54.0


--MP_/LMSk9=uMhuQ1QiIJDarDO8G--






^ permalink  raw  reply  [nested|flat] 611+ messages in thread

* [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths
@ 2026-06-01 22:41 Andrey Chernyy <andrey.cherny@tantorlabs.com>
  0 siblings, 0 replies; 611+ messages in thread

From: Andrey Chernyy @ 2026-06-01 22:41 UTC (permalink / raw)

pgxml_xpath() builds an xpath_workspace before returning it to
callers.  If an ERROR is thrown before the function returns, callers
have not received the workspace pointer yet and cannot run
cleanup_workspace().

Add local error cleanup for the partially built workspace and the
compiled XPath expression.  Also check xmlXPathNewContext() before
dereferencing the returned context.
---
 contrib/xml2/xpath.c | 51 +++++++++++++++++++++++++++-----------------
 1 file changed, 32 insertions(+), 19 deletions(-)

diff --git a/contrib/xml2/xpath.c b/contrib/xml2/xpath.c
index 9fe75cb5ff4..283bb51178d 100644
--- a/contrib/xml2/xpath.c
+++ b/contrib/xml2/xpath.c
@@ -497,36 +497,49 @@ static xpath_workspace *
 pgxml_xpath(text *document, xmlChar *xpath, PgXmlErrorContext *xmlerrcxt)
 {
 	int32		docsize = VARSIZE_ANY_EXHDR(document);
-	xmlXPathCompExprPtr comppath;
+	xmlXPathCompExprPtr volatile comppath = NULL;
 	xpath_workspace *workspace = palloc0_object(xpath_workspace);
 
 	workspace->doctree = NULL;
 	workspace->ctxt = NULL;
 	workspace->res = NULL;
 
-	workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
-									   docsize, NULL, NULL,
-									   XML_PARSE_NOENT);
-	if (workspace->doctree != NULL)
+	PG_TRY();
 	{
-		workspace->ctxt = xmlXPathNewContext(workspace->doctree);
-		workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
-
-		/* compile the path */
-		comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
-		if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+		workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
+										   docsize, NULL, NULL,
+										   XML_PARSE_NOENT);
+		if (workspace->doctree != NULL)
 		{
-			if (comppath != NULL)
-				xmlXPathFreeCompExpr(comppath);
-			xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
-						"XPath Syntax Error");
-		}
+			workspace->ctxt = xmlXPathNewContext(workspace->doctree);
+			if (workspace->ctxt == NULL)
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_OUT_OF_MEMORY,
+							"could not allocate XPath context");
 
-		/* Now evaluate the path expression. */
-		workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+			workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
+
+			/* compile the path */
+			comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
+			if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
+							"XPath Syntax Error");
+
+			/* Now evaluate the path expression. */
+			workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+
+			xmlXPathFreeCompExpr(comppath);
+			comppath = NULL;
+		}
+	}
+	PG_CATCH();
+	{
+		if (comppath != NULL)
+			xmlXPathFreeCompExpr(comppath);
+		cleanup_workspace(workspace);
 
-		xmlXPathFreeCompExpr(comppath);
+		PG_RE_THROW();
 	}
+	PG_END_TRY();
 
 	return workspace;
 }
-- 
2.54.0


--MP_/LMSk9=uMhuQ1QiIJDarDO8G--





^ permalink  raw  reply  [nested|flat] 611+ messages in thread

* [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths
@ 2026-06-01 22:41 Andrey Chernyy <andrey.cherny@tantorlabs.com>
  0 siblings, 0 replies; 611+ messages in thread

From: Andrey Chernyy @ 2026-06-01 22:41 UTC (permalink / raw)

pgxml_xpath() builds an xpath_workspace before returning it to
callers.  If an ERROR is thrown before the function returns, callers
have not received the workspace pointer yet and cannot run
cleanup_workspace().

Add local error cleanup for the partially built workspace and the
compiled XPath expression.  Also check xmlXPathNewContext() before
dereferencing the returned context.
---
 contrib/xml2/xpath.c | 51 +++++++++++++++++++++++++++-----------------
 1 file changed, 32 insertions(+), 19 deletions(-)

diff --git a/contrib/xml2/xpath.c b/contrib/xml2/xpath.c
index 9fe75cb5ff4..283bb51178d 100644
--- a/contrib/xml2/xpath.c
+++ b/contrib/xml2/xpath.c
@@ -497,36 +497,49 @@ static xpath_workspace *
 pgxml_xpath(text *document, xmlChar *xpath, PgXmlErrorContext *xmlerrcxt)
 {
 	int32		docsize = VARSIZE_ANY_EXHDR(document);
-	xmlXPathCompExprPtr comppath;
+	xmlXPathCompExprPtr volatile comppath = NULL;
 	xpath_workspace *workspace = palloc0_object(xpath_workspace);
 
 	workspace->doctree = NULL;
 	workspace->ctxt = NULL;
 	workspace->res = NULL;
 
-	workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
-									   docsize, NULL, NULL,
-									   XML_PARSE_NOENT);
-	if (workspace->doctree != NULL)
+	PG_TRY();
 	{
-		workspace->ctxt = xmlXPathNewContext(workspace->doctree);
-		workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
-
-		/* compile the path */
-		comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
-		if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+		workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
+										   docsize, NULL, NULL,
+										   XML_PARSE_NOENT);
+		if (workspace->doctree != NULL)
 		{
-			if (comppath != NULL)
-				xmlXPathFreeCompExpr(comppath);
-			xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
-						"XPath Syntax Error");
-		}
+			workspace->ctxt = xmlXPathNewContext(workspace->doctree);
+			if (workspace->ctxt == NULL)
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_OUT_OF_MEMORY,
+							"could not allocate XPath context");
 
-		/* Now evaluate the path expression. */
-		workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+			workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
+
+			/* compile the path */
+			comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
+			if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
+							"XPath Syntax Error");
+
+			/* Now evaluate the path expression. */
+			workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+
+			xmlXPathFreeCompExpr(comppath);
+			comppath = NULL;
+		}
+	}
+	PG_CATCH();
+	{
+		if (comppath != NULL)
+			xmlXPathFreeCompExpr(comppath);
+		cleanup_workspace(workspace);
 
-		xmlXPathFreeCompExpr(comppath);
+		PG_RE_THROW();
 	}
+	PG_END_TRY();
 
 	return workspace;
 }
-- 
2.54.0


--MP_/LMSk9=uMhuQ1QiIJDarDO8G--





^ permalink  raw  reply  [nested|flat] 611+ messages in thread

* [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths
@ 2026-06-01 22:41 Andrey Chernyy <andrey.cherny@tantorlabs.com>
  0 siblings, 0 replies; 611+ messages in thread

From: Andrey Chernyy @ 2026-06-01 22:41 UTC (permalink / raw)

pgxml_xpath() builds an xpath_workspace before returning it to
callers.  If an ERROR is thrown before the function returns, callers
have not received the workspace pointer yet and cannot run
cleanup_workspace().

Add local error cleanup for the partially built workspace and the
compiled XPath expression.  Also check xmlXPathNewContext() before
dereferencing the returned context.
---
 contrib/xml2/xpath.c | 51 +++++++++++++++++++++++++++-----------------
 1 file changed, 32 insertions(+), 19 deletions(-)

diff --git a/contrib/xml2/xpath.c b/contrib/xml2/xpath.c
index 9fe75cb5ff4..283bb51178d 100644
--- a/contrib/xml2/xpath.c
+++ b/contrib/xml2/xpath.c
@@ -497,36 +497,49 @@ static xpath_workspace *
 pgxml_xpath(text *document, xmlChar *xpath, PgXmlErrorContext *xmlerrcxt)
 {
 	int32		docsize = VARSIZE_ANY_EXHDR(document);
-	xmlXPathCompExprPtr comppath;
+	xmlXPathCompExprPtr volatile comppath = NULL;
 	xpath_workspace *workspace = palloc0_object(xpath_workspace);
 
 	workspace->doctree = NULL;
 	workspace->ctxt = NULL;
 	workspace->res = NULL;
 
-	workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
-									   docsize, NULL, NULL,
-									   XML_PARSE_NOENT);
-	if (workspace->doctree != NULL)
+	PG_TRY();
 	{
-		workspace->ctxt = xmlXPathNewContext(workspace->doctree);
-		workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
-
-		/* compile the path */
-		comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
-		if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+		workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
+										   docsize, NULL, NULL,
+										   XML_PARSE_NOENT);
+		if (workspace->doctree != NULL)
 		{
-			if (comppath != NULL)
-				xmlXPathFreeCompExpr(comppath);
-			xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
-						"XPath Syntax Error");
-		}
+			workspace->ctxt = xmlXPathNewContext(workspace->doctree);
+			if (workspace->ctxt == NULL)
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_OUT_OF_MEMORY,
+							"could not allocate XPath context");
 
-		/* Now evaluate the path expression. */
-		workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+			workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
+
+			/* compile the path */
+			comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
+			if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
+							"XPath Syntax Error");
+
+			/* Now evaluate the path expression. */
+			workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+
+			xmlXPathFreeCompExpr(comppath);
+			comppath = NULL;
+		}
+	}
+	PG_CATCH();
+	{
+		if (comppath != NULL)
+			xmlXPathFreeCompExpr(comppath);
+		cleanup_workspace(workspace);
 
-		xmlXPathFreeCompExpr(comppath);
+		PG_RE_THROW();
 	}
+	PG_END_TRY();
 
 	return workspace;
 }
-- 
2.54.0


--MP_/LMSk9=uMhuQ1QiIJDarDO8G--





^ permalink  raw  reply  [nested|flat] 611+ messages in thread

* [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths
@ 2026-06-01 22:41 Andrey Chernyy <andrey.cherny@tantorlabs.com>
  0 siblings, 0 replies; 611+ messages in thread

From: Andrey Chernyy @ 2026-06-01 22:41 UTC (permalink / raw)

pgxml_xpath() builds an xpath_workspace before returning it to
callers.  If an ERROR is thrown before the function returns, callers
have not received the workspace pointer yet and cannot run
cleanup_workspace().

Add local error cleanup for the partially built workspace and the
compiled XPath expression.  Also check xmlXPathNewContext() before
dereferencing the returned context.
---
 contrib/xml2/xpath.c | 51 +++++++++++++++++++++++++++-----------------
 1 file changed, 32 insertions(+), 19 deletions(-)

diff --git a/contrib/xml2/xpath.c b/contrib/xml2/xpath.c
index 9fe75cb5ff4..283bb51178d 100644
--- a/contrib/xml2/xpath.c
+++ b/contrib/xml2/xpath.c
@@ -497,36 +497,49 @@ static xpath_workspace *
 pgxml_xpath(text *document, xmlChar *xpath, PgXmlErrorContext *xmlerrcxt)
 {
 	int32		docsize = VARSIZE_ANY_EXHDR(document);
-	xmlXPathCompExprPtr comppath;
+	xmlXPathCompExprPtr volatile comppath = NULL;
 	xpath_workspace *workspace = palloc0_object(xpath_workspace);
 
 	workspace->doctree = NULL;
 	workspace->ctxt = NULL;
 	workspace->res = NULL;
 
-	workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
-									   docsize, NULL, NULL,
-									   XML_PARSE_NOENT);
-	if (workspace->doctree != NULL)
+	PG_TRY();
 	{
-		workspace->ctxt = xmlXPathNewContext(workspace->doctree);
-		workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
-
-		/* compile the path */
-		comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
-		if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+		workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
+										   docsize, NULL, NULL,
+										   XML_PARSE_NOENT);
+		if (workspace->doctree != NULL)
 		{
-			if (comppath != NULL)
-				xmlXPathFreeCompExpr(comppath);
-			xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
-						"XPath Syntax Error");
-		}
+			workspace->ctxt = xmlXPathNewContext(workspace->doctree);
+			if (workspace->ctxt == NULL)
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_OUT_OF_MEMORY,
+							"could not allocate XPath context");
 
-		/* Now evaluate the path expression. */
-		workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+			workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
+
+			/* compile the path */
+			comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
+			if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
+							"XPath Syntax Error");
+
+			/* Now evaluate the path expression. */
+			workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+
+			xmlXPathFreeCompExpr(comppath);
+			comppath = NULL;
+		}
+	}
+	PG_CATCH();
+	{
+		if (comppath != NULL)
+			xmlXPathFreeCompExpr(comppath);
+		cleanup_workspace(workspace);
 
-		xmlXPathFreeCompExpr(comppath);
+		PG_RE_THROW();
 	}
+	PG_END_TRY();
 
 	return workspace;
 }
-- 
2.54.0


--MP_/LMSk9=uMhuQ1QiIJDarDO8G--






^ permalink  raw  reply  [nested|flat] 611+ messages in thread

* [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths
@ 2026-06-01 22:41 Andrey Chernyy <andrey.cherny@tantorlabs.com>
  0 siblings, 0 replies; 611+ messages in thread

From: Andrey Chernyy @ 2026-06-01 22:41 UTC (permalink / raw)

pgxml_xpath() builds an xpath_workspace before returning it to
callers.  If an ERROR is thrown before the function returns, callers
have not received the workspace pointer yet and cannot run
cleanup_workspace().

Add local error cleanup for the partially built workspace and the
compiled XPath expression.  Also check xmlXPathNewContext() before
dereferencing the returned context.
---
 contrib/xml2/xpath.c | 51 +++++++++++++++++++++++++++-----------------
 1 file changed, 32 insertions(+), 19 deletions(-)

diff --git a/contrib/xml2/xpath.c b/contrib/xml2/xpath.c
index 9fe75cb5ff4..283bb51178d 100644
--- a/contrib/xml2/xpath.c
+++ b/contrib/xml2/xpath.c
@@ -497,36 +497,49 @@ static xpath_workspace *
 pgxml_xpath(text *document, xmlChar *xpath, PgXmlErrorContext *xmlerrcxt)
 {
 	int32		docsize = VARSIZE_ANY_EXHDR(document);
-	xmlXPathCompExprPtr comppath;
+	xmlXPathCompExprPtr volatile comppath = NULL;
 	xpath_workspace *workspace = palloc0_object(xpath_workspace);
 
 	workspace->doctree = NULL;
 	workspace->ctxt = NULL;
 	workspace->res = NULL;
 
-	workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
-									   docsize, NULL, NULL,
-									   XML_PARSE_NOENT);
-	if (workspace->doctree != NULL)
+	PG_TRY();
 	{
-		workspace->ctxt = xmlXPathNewContext(workspace->doctree);
-		workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
-
-		/* compile the path */
-		comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
-		if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+		workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
+										   docsize, NULL, NULL,
+										   XML_PARSE_NOENT);
+		if (workspace->doctree != NULL)
 		{
-			if (comppath != NULL)
-				xmlXPathFreeCompExpr(comppath);
-			xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
-						"XPath Syntax Error");
-		}
+			workspace->ctxt = xmlXPathNewContext(workspace->doctree);
+			if (workspace->ctxt == NULL)
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_OUT_OF_MEMORY,
+							"could not allocate XPath context");
 
-		/* Now evaluate the path expression. */
-		workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+			workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
+
+			/* compile the path */
+			comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
+			if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
+							"XPath Syntax Error");
+
+			/* Now evaluate the path expression. */
+			workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+
+			xmlXPathFreeCompExpr(comppath);
+			comppath = NULL;
+		}
+	}
+	PG_CATCH();
+	{
+		if (comppath != NULL)
+			xmlXPathFreeCompExpr(comppath);
+		cleanup_workspace(workspace);
 
-		xmlXPathFreeCompExpr(comppath);
+		PG_RE_THROW();
 	}
+	PG_END_TRY();
 
 	return workspace;
 }
-- 
2.54.0


--MP_/LMSk9=uMhuQ1QiIJDarDO8G--





^ permalink  raw  reply  [nested|flat] 611+ messages in thread

* [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths
@ 2026-06-01 22:41 Andrey Chernyy <andrey.cherny@tantorlabs.com>
  0 siblings, 0 replies; 611+ messages in thread

From: Andrey Chernyy @ 2026-06-01 22:41 UTC (permalink / raw)

pgxml_xpath() builds an xpath_workspace before returning it to
callers.  If an ERROR is thrown before the function returns, callers
have not received the workspace pointer yet and cannot run
cleanup_workspace().

Add local error cleanup for the partially built workspace and the
compiled XPath expression.  Also check xmlXPathNewContext() before
dereferencing the returned context.
---
 contrib/xml2/xpath.c | 51 +++++++++++++++++++++++++++-----------------
 1 file changed, 32 insertions(+), 19 deletions(-)

diff --git a/contrib/xml2/xpath.c b/contrib/xml2/xpath.c
index 9fe75cb5ff4..283bb51178d 100644
--- a/contrib/xml2/xpath.c
+++ b/contrib/xml2/xpath.c
@@ -497,36 +497,49 @@ static xpath_workspace *
 pgxml_xpath(text *document, xmlChar *xpath, PgXmlErrorContext *xmlerrcxt)
 {
 	int32		docsize = VARSIZE_ANY_EXHDR(document);
-	xmlXPathCompExprPtr comppath;
+	xmlXPathCompExprPtr volatile comppath = NULL;
 	xpath_workspace *workspace = palloc0_object(xpath_workspace);
 
 	workspace->doctree = NULL;
 	workspace->ctxt = NULL;
 	workspace->res = NULL;
 
-	workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
-									   docsize, NULL, NULL,
-									   XML_PARSE_NOENT);
-	if (workspace->doctree != NULL)
+	PG_TRY();
 	{
-		workspace->ctxt = xmlXPathNewContext(workspace->doctree);
-		workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
-
-		/* compile the path */
-		comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
-		if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+		workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
+										   docsize, NULL, NULL,
+										   XML_PARSE_NOENT);
+		if (workspace->doctree != NULL)
 		{
-			if (comppath != NULL)
-				xmlXPathFreeCompExpr(comppath);
-			xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
-						"XPath Syntax Error");
-		}
+			workspace->ctxt = xmlXPathNewContext(workspace->doctree);
+			if (workspace->ctxt == NULL)
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_OUT_OF_MEMORY,
+							"could not allocate XPath context");
 
-		/* Now evaluate the path expression. */
-		workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+			workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
+
+			/* compile the path */
+			comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
+			if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
+							"XPath Syntax Error");
+
+			/* Now evaluate the path expression. */
+			workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+
+			xmlXPathFreeCompExpr(comppath);
+			comppath = NULL;
+		}
+	}
+	PG_CATCH();
+	{
+		if (comppath != NULL)
+			xmlXPathFreeCompExpr(comppath);
+		cleanup_workspace(workspace);
 
-		xmlXPathFreeCompExpr(comppath);
+		PG_RE_THROW();
 	}
+	PG_END_TRY();
 
 	return workspace;
 }
-- 
2.54.0


--MP_/LMSk9=uMhuQ1QiIJDarDO8G--





^ permalink  raw  reply  [nested|flat] 611+ messages in thread

* [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths
@ 2026-06-01 22:41 Andrey Chernyy <andrey.cherny@tantorlabs.com>
  0 siblings, 0 replies; 611+ messages in thread

From: Andrey Chernyy @ 2026-06-01 22:41 UTC (permalink / raw)

pgxml_xpath() builds an xpath_workspace before returning it to
callers.  If an ERROR is thrown before the function returns, callers
have not received the workspace pointer yet and cannot run
cleanup_workspace().

Add local error cleanup for the partially built workspace and the
compiled XPath expression.  Also check xmlXPathNewContext() before
dereferencing the returned context.
---
 contrib/xml2/xpath.c | 51 +++++++++++++++++++++++++++-----------------
 1 file changed, 32 insertions(+), 19 deletions(-)

diff --git a/contrib/xml2/xpath.c b/contrib/xml2/xpath.c
index 9fe75cb5ff4..283bb51178d 100644
--- a/contrib/xml2/xpath.c
+++ b/contrib/xml2/xpath.c
@@ -497,36 +497,49 @@ static xpath_workspace *
 pgxml_xpath(text *document, xmlChar *xpath, PgXmlErrorContext *xmlerrcxt)
 {
 	int32		docsize = VARSIZE_ANY_EXHDR(document);
-	xmlXPathCompExprPtr comppath;
+	xmlXPathCompExprPtr volatile comppath = NULL;
 	xpath_workspace *workspace = palloc0_object(xpath_workspace);
 
 	workspace->doctree = NULL;
 	workspace->ctxt = NULL;
 	workspace->res = NULL;
 
-	workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
-									   docsize, NULL, NULL,
-									   XML_PARSE_NOENT);
-	if (workspace->doctree != NULL)
+	PG_TRY();
 	{
-		workspace->ctxt = xmlXPathNewContext(workspace->doctree);
-		workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
-
-		/* compile the path */
-		comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
-		if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+		workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
+										   docsize, NULL, NULL,
+										   XML_PARSE_NOENT);
+		if (workspace->doctree != NULL)
 		{
-			if (comppath != NULL)
-				xmlXPathFreeCompExpr(comppath);
-			xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
-						"XPath Syntax Error");
-		}
+			workspace->ctxt = xmlXPathNewContext(workspace->doctree);
+			if (workspace->ctxt == NULL)
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_OUT_OF_MEMORY,
+							"could not allocate XPath context");
 
-		/* Now evaluate the path expression. */
-		workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+			workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
+
+			/* compile the path */
+			comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
+			if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
+							"XPath Syntax Error");
+
+			/* Now evaluate the path expression. */
+			workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+
+			xmlXPathFreeCompExpr(comppath);
+			comppath = NULL;
+		}
+	}
+	PG_CATCH();
+	{
+		if (comppath != NULL)
+			xmlXPathFreeCompExpr(comppath);
+		cleanup_workspace(workspace);
 
-		xmlXPathFreeCompExpr(comppath);
+		PG_RE_THROW();
 	}
+	PG_END_TRY();
 
 	return workspace;
 }
-- 
2.54.0


--MP_/LMSk9=uMhuQ1QiIJDarDO8G--





^ permalink  raw  reply  [nested|flat] 611+ messages in thread

* [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths
@ 2026-06-01 22:41 Andrey Chernyy <andrey.cherny@tantorlabs.com>
  0 siblings, 0 replies; 611+ messages in thread

From: Andrey Chernyy @ 2026-06-01 22:41 UTC (permalink / raw)

pgxml_xpath() builds an xpath_workspace before returning it to
callers.  If an ERROR is thrown before the function returns, callers
have not received the workspace pointer yet and cannot run
cleanup_workspace().

Add local error cleanup for the partially built workspace and the
compiled XPath expression.  Also check xmlXPathNewContext() before
dereferencing the returned context.
---
 contrib/xml2/xpath.c | 51 +++++++++++++++++++++++++++-----------------
 1 file changed, 32 insertions(+), 19 deletions(-)

diff --git a/contrib/xml2/xpath.c b/contrib/xml2/xpath.c
index 9fe75cb5ff4..283bb51178d 100644
--- a/contrib/xml2/xpath.c
+++ b/contrib/xml2/xpath.c
@@ -497,36 +497,49 @@ static xpath_workspace *
 pgxml_xpath(text *document, xmlChar *xpath, PgXmlErrorContext *xmlerrcxt)
 {
 	int32		docsize = VARSIZE_ANY_EXHDR(document);
-	xmlXPathCompExprPtr comppath;
+	xmlXPathCompExprPtr volatile comppath = NULL;
 	xpath_workspace *workspace = palloc0_object(xpath_workspace);
 
 	workspace->doctree = NULL;
 	workspace->ctxt = NULL;
 	workspace->res = NULL;
 
-	workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
-									   docsize, NULL, NULL,
-									   XML_PARSE_NOENT);
-	if (workspace->doctree != NULL)
+	PG_TRY();
 	{
-		workspace->ctxt = xmlXPathNewContext(workspace->doctree);
-		workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
-
-		/* compile the path */
-		comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
-		if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+		workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
+										   docsize, NULL, NULL,
+										   XML_PARSE_NOENT);
+		if (workspace->doctree != NULL)
 		{
-			if (comppath != NULL)
-				xmlXPathFreeCompExpr(comppath);
-			xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
-						"XPath Syntax Error");
-		}
+			workspace->ctxt = xmlXPathNewContext(workspace->doctree);
+			if (workspace->ctxt == NULL)
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_OUT_OF_MEMORY,
+							"could not allocate XPath context");
 
-		/* Now evaluate the path expression. */
-		workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+			workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
+
+			/* compile the path */
+			comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
+			if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
+							"XPath Syntax Error");
+
+			/* Now evaluate the path expression. */
+			workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+
+			xmlXPathFreeCompExpr(comppath);
+			comppath = NULL;
+		}
+	}
+	PG_CATCH();
+	{
+		if (comppath != NULL)
+			xmlXPathFreeCompExpr(comppath);
+		cleanup_workspace(workspace);
 
-		xmlXPathFreeCompExpr(comppath);
+		PG_RE_THROW();
 	}
+	PG_END_TRY();
 
 	return workspace;
 }
-- 
2.54.0


--MP_/LMSk9=uMhuQ1QiIJDarDO8G--





^ permalink  raw  reply  [nested|flat] 611+ messages in thread

* [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths
@ 2026-06-01 22:41 Andrey Chernyy <andrey.cherny@tantorlabs.com>
  0 siblings, 0 replies; 611+ messages in thread

From: Andrey Chernyy @ 2026-06-01 22:41 UTC (permalink / raw)

pgxml_xpath() builds an xpath_workspace before returning it to
callers.  If an ERROR is thrown before the function returns, callers
have not received the workspace pointer yet and cannot run
cleanup_workspace().

Add local error cleanup for the partially built workspace and the
compiled XPath expression.  Also check xmlXPathNewContext() before
dereferencing the returned context.
---
 contrib/xml2/xpath.c | 51 +++++++++++++++++++++++++++-----------------
 1 file changed, 32 insertions(+), 19 deletions(-)

diff --git a/contrib/xml2/xpath.c b/contrib/xml2/xpath.c
index 9fe75cb5ff4..283bb51178d 100644
--- a/contrib/xml2/xpath.c
+++ b/contrib/xml2/xpath.c
@@ -497,36 +497,49 @@ static xpath_workspace *
 pgxml_xpath(text *document, xmlChar *xpath, PgXmlErrorContext *xmlerrcxt)
 {
 	int32		docsize = VARSIZE_ANY_EXHDR(document);
-	xmlXPathCompExprPtr comppath;
+	xmlXPathCompExprPtr volatile comppath = NULL;
 	xpath_workspace *workspace = palloc0_object(xpath_workspace);
 
 	workspace->doctree = NULL;
 	workspace->ctxt = NULL;
 	workspace->res = NULL;
 
-	workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
-									   docsize, NULL, NULL,
-									   XML_PARSE_NOENT);
-	if (workspace->doctree != NULL)
+	PG_TRY();
 	{
-		workspace->ctxt = xmlXPathNewContext(workspace->doctree);
-		workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
-
-		/* compile the path */
-		comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
-		if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+		workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
+										   docsize, NULL, NULL,
+										   XML_PARSE_NOENT);
+		if (workspace->doctree != NULL)
 		{
-			if (comppath != NULL)
-				xmlXPathFreeCompExpr(comppath);
-			xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
-						"XPath Syntax Error");
-		}
+			workspace->ctxt = xmlXPathNewContext(workspace->doctree);
+			if (workspace->ctxt == NULL)
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_OUT_OF_MEMORY,
+							"could not allocate XPath context");
 
-		/* Now evaluate the path expression. */
-		workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+			workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
+
+			/* compile the path */
+			comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
+			if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
+							"XPath Syntax Error");
+
+			/* Now evaluate the path expression. */
+			workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+
+			xmlXPathFreeCompExpr(comppath);
+			comppath = NULL;
+		}
+	}
+	PG_CATCH();
+	{
+		if (comppath != NULL)
+			xmlXPathFreeCompExpr(comppath);
+		cleanup_workspace(workspace);
 
-		xmlXPathFreeCompExpr(comppath);
+		PG_RE_THROW();
 	}
+	PG_END_TRY();
 
 	return workspace;
 }
-- 
2.54.0


--MP_/LMSk9=uMhuQ1QiIJDarDO8G--






^ permalink  raw  reply  [nested|flat] 611+ messages in thread

* [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths
@ 2026-06-01 22:41 Andrey Chernyy <andrey.cherny@tantorlabs.com>
  0 siblings, 0 replies; 611+ messages in thread

From: Andrey Chernyy @ 2026-06-01 22:41 UTC (permalink / raw)

pgxml_xpath() builds an xpath_workspace before returning it to
callers.  If an ERROR is thrown before the function returns, callers
have not received the workspace pointer yet and cannot run
cleanup_workspace().

Add local error cleanup for the partially built workspace and the
compiled XPath expression.  Also check xmlXPathNewContext() before
dereferencing the returned context.
---
 contrib/xml2/xpath.c | 51 +++++++++++++++++++++++++++-----------------
 1 file changed, 32 insertions(+), 19 deletions(-)

diff --git a/contrib/xml2/xpath.c b/contrib/xml2/xpath.c
index 9fe75cb5ff4..283bb51178d 100644
--- a/contrib/xml2/xpath.c
+++ b/contrib/xml2/xpath.c
@@ -497,36 +497,49 @@ static xpath_workspace *
 pgxml_xpath(text *document, xmlChar *xpath, PgXmlErrorContext *xmlerrcxt)
 {
 	int32		docsize = VARSIZE_ANY_EXHDR(document);
-	xmlXPathCompExprPtr comppath;
+	xmlXPathCompExprPtr volatile comppath = NULL;
 	xpath_workspace *workspace = palloc0_object(xpath_workspace);
 
 	workspace->doctree = NULL;
 	workspace->ctxt = NULL;
 	workspace->res = NULL;
 
-	workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
-									   docsize, NULL, NULL,
-									   XML_PARSE_NOENT);
-	if (workspace->doctree != NULL)
+	PG_TRY();
 	{
-		workspace->ctxt = xmlXPathNewContext(workspace->doctree);
-		workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
-
-		/* compile the path */
-		comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
-		if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+		workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
+										   docsize, NULL, NULL,
+										   XML_PARSE_NOENT);
+		if (workspace->doctree != NULL)
 		{
-			if (comppath != NULL)
-				xmlXPathFreeCompExpr(comppath);
-			xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
-						"XPath Syntax Error");
-		}
+			workspace->ctxt = xmlXPathNewContext(workspace->doctree);
+			if (workspace->ctxt == NULL)
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_OUT_OF_MEMORY,
+							"could not allocate XPath context");
 
-		/* Now evaluate the path expression. */
-		workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+			workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
+
+			/* compile the path */
+			comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
+			if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
+							"XPath Syntax Error");
+
+			/* Now evaluate the path expression. */
+			workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+
+			xmlXPathFreeCompExpr(comppath);
+			comppath = NULL;
+		}
+	}
+	PG_CATCH();
+	{
+		if (comppath != NULL)
+			xmlXPathFreeCompExpr(comppath);
+		cleanup_workspace(workspace);
 
-		xmlXPathFreeCompExpr(comppath);
+		PG_RE_THROW();
 	}
+	PG_END_TRY();
 
 	return workspace;
 }
-- 
2.54.0


--MP_/LMSk9=uMhuQ1QiIJDarDO8G--





^ permalink  raw  reply  [nested|flat] 611+ messages in thread

* [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths
@ 2026-06-01 22:41 Andrey Chernyy <andrey.cherny@tantorlabs.com>
  0 siblings, 0 replies; 611+ messages in thread

From: Andrey Chernyy @ 2026-06-01 22:41 UTC (permalink / raw)

pgxml_xpath() builds an xpath_workspace before returning it to
callers.  If an ERROR is thrown before the function returns, callers
have not received the workspace pointer yet and cannot run
cleanup_workspace().

Add local error cleanup for the partially built workspace and the
compiled XPath expression.  Also check xmlXPathNewContext() before
dereferencing the returned context.
---
 contrib/xml2/xpath.c | 51 +++++++++++++++++++++++++++-----------------
 1 file changed, 32 insertions(+), 19 deletions(-)

diff --git a/contrib/xml2/xpath.c b/contrib/xml2/xpath.c
index 9fe75cb5ff4..283bb51178d 100644
--- a/contrib/xml2/xpath.c
+++ b/contrib/xml2/xpath.c
@@ -497,36 +497,49 @@ static xpath_workspace *
 pgxml_xpath(text *document, xmlChar *xpath, PgXmlErrorContext *xmlerrcxt)
 {
 	int32		docsize = VARSIZE_ANY_EXHDR(document);
-	xmlXPathCompExprPtr comppath;
+	xmlXPathCompExprPtr volatile comppath = NULL;
 	xpath_workspace *workspace = palloc0_object(xpath_workspace);
 
 	workspace->doctree = NULL;
 	workspace->ctxt = NULL;
 	workspace->res = NULL;
 
-	workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
-									   docsize, NULL, NULL,
-									   XML_PARSE_NOENT);
-	if (workspace->doctree != NULL)
+	PG_TRY();
 	{
-		workspace->ctxt = xmlXPathNewContext(workspace->doctree);
-		workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
-
-		/* compile the path */
-		comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
-		if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+		workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
+										   docsize, NULL, NULL,
+										   XML_PARSE_NOENT);
+		if (workspace->doctree != NULL)
 		{
-			if (comppath != NULL)
-				xmlXPathFreeCompExpr(comppath);
-			xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
-						"XPath Syntax Error");
-		}
+			workspace->ctxt = xmlXPathNewContext(workspace->doctree);
+			if (workspace->ctxt == NULL)
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_OUT_OF_MEMORY,
+							"could not allocate XPath context");
 
-		/* Now evaluate the path expression. */
-		workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+			workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
+
+			/* compile the path */
+			comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
+			if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
+							"XPath Syntax Error");
+
+			/* Now evaluate the path expression. */
+			workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+
+			xmlXPathFreeCompExpr(comppath);
+			comppath = NULL;
+		}
+	}
+	PG_CATCH();
+	{
+		if (comppath != NULL)
+			xmlXPathFreeCompExpr(comppath);
+		cleanup_workspace(workspace);
 
-		xmlXPathFreeCompExpr(comppath);
+		PG_RE_THROW();
 	}
+	PG_END_TRY();
 
 	return workspace;
 }
-- 
2.54.0


--MP_/LMSk9=uMhuQ1QiIJDarDO8G--






^ permalink  raw  reply  [nested|flat] 611+ messages in thread

* [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths
@ 2026-06-01 22:41 Andrey Chernyy <andrey.cherny@tantorlabs.com>
  0 siblings, 0 replies; 611+ messages in thread

From: Andrey Chernyy @ 2026-06-01 22:41 UTC (permalink / raw)

pgxml_xpath() builds an xpath_workspace before returning it to
callers.  If an ERROR is thrown before the function returns, callers
have not received the workspace pointer yet and cannot run
cleanup_workspace().

Add local error cleanup for the partially built workspace and the
compiled XPath expression.  Also check xmlXPathNewContext() before
dereferencing the returned context.
---
 contrib/xml2/xpath.c | 51 +++++++++++++++++++++++++++-----------------
 1 file changed, 32 insertions(+), 19 deletions(-)

diff --git a/contrib/xml2/xpath.c b/contrib/xml2/xpath.c
index 9fe75cb5ff4..283bb51178d 100644
--- a/contrib/xml2/xpath.c
+++ b/contrib/xml2/xpath.c
@@ -497,36 +497,49 @@ static xpath_workspace *
 pgxml_xpath(text *document, xmlChar *xpath, PgXmlErrorContext *xmlerrcxt)
 {
 	int32		docsize = VARSIZE_ANY_EXHDR(document);
-	xmlXPathCompExprPtr comppath;
+	xmlXPathCompExprPtr volatile comppath = NULL;
 	xpath_workspace *workspace = palloc0_object(xpath_workspace);
 
 	workspace->doctree = NULL;
 	workspace->ctxt = NULL;
 	workspace->res = NULL;
 
-	workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
-									   docsize, NULL, NULL,
-									   XML_PARSE_NOENT);
-	if (workspace->doctree != NULL)
+	PG_TRY();
 	{
-		workspace->ctxt = xmlXPathNewContext(workspace->doctree);
-		workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
-
-		/* compile the path */
-		comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
-		if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+		workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
+										   docsize, NULL, NULL,
+										   XML_PARSE_NOENT);
+		if (workspace->doctree != NULL)
 		{
-			if (comppath != NULL)
-				xmlXPathFreeCompExpr(comppath);
-			xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
-						"XPath Syntax Error");
-		}
+			workspace->ctxt = xmlXPathNewContext(workspace->doctree);
+			if (workspace->ctxt == NULL)
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_OUT_OF_MEMORY,
+							"could not allocate XPath context");
 
-		/* Now evaluate the path expression. */
-		workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+			workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
+
+			/* compile the path */
+			comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
+			if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
+							"XPath Syntax Error");
+
+			/* Now evaluate the path expression. */
+			workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+
+			xmlXPathFreeCompExpr(comppath);
+			comppath = NULL;
+		}
+	}
+	PG_CATCH();
+	{
+		if (comppath != NULL)
+			xmlXPathFreeCompExpr(comppath);
+		cleanup_workspace(workspace);
 
-		xmlXPathFreeCompExpr(comppath);
+		PG_RE_THROW();
 	}
+	PG_END_TRY();
 
 	return workspace;
 }
-- 
2.54.0


--MP_/LMSk9=uMhuQ1QiIJDarDO8G--






^ permalink  raw  reply  [nested|flat] 611+ messages in thread

* [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths
@ 2026-06-01 22:41 Andrey Chernyy <andrey.cherny@tantorlabs.com>
  0 siblings, 0 replies; 611+ messages in thread

From: Andrey Chernyy @ 2026-06-01 22:41 UTC (permalink / raw)

pgxml_xpath() builds an xpath_workspace before returning it to
callers.  If an ERROR is thrown before the function returns, callers
have not received the workspace pointer yet and cannot run
cleanup_workspace().

Add local error cleanup for the partially built workspace and the
compiled XPath expression.  Also check xmlXPathNewContext() before
dereferencing the returned context.
---
 contrib/xml2/xpath.c | 51 +++++++++++++++++++++++++++-----------------
 1 file changed, 32 insertions(+), 19 deletions(-)

diff --git a/contrib/xml2/xpath.c b/contrib/xml2/xpath.c
index 9fe75cb5ff4..283bb51178d 100644
--- a/contrib/xml2/xpath.c
+++ b/contrib/xml2/xpath.c
@@ -497,36 +497,49 @@ static xpath_workspace *
 pgxml_xpath(text *document, xmlChar *xpath, PgXmlErrorContext *xmlerrcxt)
 {
 	int32		docsize = VARSIZE_ANY_EXHDR(document);
-	xmlXPathCompExprPtr comppath;
+	xmlXPathCompExprPtr volatile comppath = NULL;
 	xpath_workspace *workspace = palloc0_object(xpath_workspace);
 
 	workspace->doctree = NULL;
 	workspace->ctxt = NULL;
 	workspace->res = NULL;
 
-	workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
-									   docsize, NULL, NULL,
-									   XML_PARSE_NOENT);
-	if (workspace->doctree != NULL)
+	PG_TRY();
 	{
-		workspace->ctxt = xmlXPathNewContext(workspace->doctree);
-		workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
-
-		/* compile the path */
-		comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
-		if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+		workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
+										   docsize, NULL, NULL,
+										   XML_PARSE_NOENT);
+		if (workspace->doctree != NULL)
 		{
-			if (comppath != NULL)
-				xmlXPathFreeCompExpr(comppath);
-			xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
-						"XPath Syntax Error");
-		}
+			workspace->ctxt = xmlXPathNewContext(workspace->doctree);
+			if (workspace->ctxt == NULL)
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_OUT_OF_MEMORY,
+							"could not allocate XPath context");
 
-		/* Now evaluate the path expression. */
-		workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+			workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
+
+			/* compile the path */
+			comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
+			if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
+							"XPath Syntax Error");
+
+			/* Now evaluate the path expression. */
+			workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+
+			xmlXPathFreeCompExpr(comppath);
+			comppath = NULL;
+		}
+	}
+	PG_CATCH();
+	{
+		if (comppath != NULL)
+			xmlXPathFreeCompExpr(comppath);
+		cleanup_workspace(workspace);
 
-		xmlXPathFreeCompExpr(comppath);
+		PG_RE_THROW();
 	}
+	PG_END_TRY();
 
 	return workspace;
 }
-- 
2.54.0


--MP_/LMSk9=uMhuQ1QiIJDarDO8G--






^ permalink  raw  reply  [nested|flat] 611+ messages in thread

* [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths
@ 2026-06-01 22:41 Andrey Chernyy <andrey.cherny@tantorlabs.com>
  0 siblings, 0 replies; 611+ messages in thread

From: Andrey Chernyy @ 2026-06-01 22:41 UTC (permalink / raw)

pgxml_xpath() builds an xpath_workspace before returning it to
callers.  If an ERROR is thrown before the function returns, callers
have not received the workspace pointer yet and cannot run
cleanup_workspace().

Add local error cleanup for the partially built workspace and the
compiled XPath expression.  Also check xmlXPathNewContext() before
dereferencing the returned context.
---
 contrib/xml2/xpath.c | 51 +++++++++++++++++++++++++++-----------------
 1 file changed, 32 insertions(+), 19 deletions(-)

diff --git a/contrib/xml2/xpath.c b/contrib/xml2/xpath.c
index 9fe75cb5ff4..283bb51178d 100644
--- a/contrib/xml2/xpath.c
+++ b/contrib/xml2/xpath.c
@@ -497,36 +497,49 @@ static xpath_workspace *
 pgxml_xpath(text *document, xmlChar *xpath, PgXmlErrorContext *xmlerrcxt)
 {
 	int32		docsize = VARSIZE_ANY_EXHDR(document);
-	xmlXPathCompExprPtr comppath;
+	xmlXPathCompExprPtr volatile comppath = NULL;
 	xpath_workspace *workspace = palloc0_object(xpath_workspace);
 
 	workspace->doctree = NULL;
 	workspace->ctxt = NULL;
 	workspace->res = NULL;
 
-	workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
-									   docsize, NULL, NULL,
-									   XML_PARSE_NOENT);
-	if (workspace->doctree != NULL)
+	PG_TRY();
 	{
-		workspace->ctxt = xmlXPathNewContext(workspace->doctree);
-		workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
-
-		/* compile the path */
-		comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
-		if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+		workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
+										   docsize, NULL, NULL,
+										   XML_PARSE_NOENT);
+		if (workspace->doctree != NULL)
 		{
-			if (comppath != NULL)
-				xmlXPathFreeCompExpr(comppath);
-			xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
-						"XPath Syntax Error");
-		}
+			workspace->ctxt = xmlXPathNewContext(workspace->doctree);
+			if (workspace->ctxt == NULL)
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_OUT_OF_MEMORY,
+							"could not allocate XPath context");
 
-		/* Now evaluate the path expression. */
-		workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+			workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
+
+			/* compile the path */
+			comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
+			if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
+							"XPath Syntax Error");
+
+			/* Now evaluate the path expression. */
+			workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+
+			xmlXPathFreeCompExpr(comppath);
+			comppath = NULL;
+		}
+	}
+	PG_CATCH();
+	{
+		if (comppath != NULL)
+			xmlXPathFreeCompExpr(comppath);
+		cleanup_workspace(workspace);
 
-		xmlXPathFreeCompExpr(comppath);
+		PG_RE_THROW();
 	}
+	PG_END_TRY();
 
 	return workspace;
 }
-- 
2.54.0


--MP_/LMSk9=uMhuQ1QiIJDarDO8G--





^ permalink  raw  reply  [nested|flat] 611+ messages in thread

* [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths
@ 2026-06-01 22:41 Andrey Chernyy <andrey.cherny@tantorlabs.com>
  0 siblings, 0 replies; 611+ messages in thread

From: Andrey Chernyy @ 2026-06-01 22:41 UTC (permalink / raw)

pgxml_xpath() builds an xpath_workspace before returning it to
callers.  If an ERROR is thrown before the function returns, callers
have not received the workspace pointer yet and cannot run
cleanup_workspace().

Add local error cleanup for the partially built workspace and the
compiled XPath expression.  Also check xmlXPathNewContext() before
dereferencing the returned context.
---
 contrib/xml2/xpath.c | 51 +++++++++++++++++++++++++++-----------------
 1 file changed, 32 insertions(+), 19 deletions(-)

diff --git a/contrib/xml2/xpath.c b/contrib/xml2/xpath.c
index 9fe75cb5ff4..283bb51178d 100644
--- a/contrib/xml2/xpath.c
+++ b/contrib/xml2/xpath.c
@@ -497,36 +497,49 @@ static xpath_workspace *
 pgxml_xpath(text *document, xmlChar *xpath, PgXmlErrorContext *xmlerrcxt)
 {
 	int32		docsize = VARSIZE_ANY_EXHDR(document);
-	xmlXPathCompExprPtr comppath;
+	xmlXPathCompExprPtr volatile comppath = NULL;
 	xpath_workspace *workspace = palloc0_object(xpath_workspace);
 
 	workspace->doctree = NULL;
 	workspace->ctxt = NULL;
 	workspace->res = NULL;
 
-	workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
-									   docsize, NULL, NULL,
-									   XML_PARSE_NOENT);
-	if (workspace->doctree != NULL)
+	PG_TRY();
 	{
-		workspace->ctxt = xmlXPathNewContext(workspace->doctree);
-		workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
-
-		/* compile the path */
-		comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
-		if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+		workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
+										   docsize, NULL, NULL,
+										   XML_PARSE_NOENT);
+		if (workspace->doctree != NULL)
 		{
-			if (comppath != NULL)
-				xmlXPathFreeCompExpr(comppath);
-			xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
-						"XPath Syntax Error");
-		}
+			workspace->ctxt = xmlXPathNewContext(workspace->doctree);
+			if (workspace->ctxt == NULL)
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_OUT_OF_MEMORY,
+							"could not allocate XPath context");
 
-		/* Now evaluate the path expression. */
-		workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+			workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
+
+			/* compile the path */
+			comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
+			if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
+							"XPath Syntax Error");
+
+			/* Now evaluate the path expression. */
+			workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+
+			xmlXPathFreeCompExpr(comppath);
+			comppath = NULL;
+		}
+	}
+	PG_CATCH();
+	{
+		if (comppath != NULL)
+			xmlXPathFreeCompExpr(comppath);
+		cleanup_workspace(workspace);
 
-		xmlXPathFreeCompExpr(comppath);
+		PG_RE_THROW();
 	}
+	PG_END_TRY();
 
 	return workspace;
 }
-- 
2.54.0


--MP_/LMSk9=uMhuQ1QiIJDarDO8G--






^ permalink  raw  reply  [nested|flat] 611+ messages in thread

* [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths
@ 2026-06-01 22:41 Andrey Chernyy <andrey.cherny@tantorlabs.com>
  0 siblings, 0 replies; 611+ messages in thread

From: Andrey Chernyy @ 2026-06-01 22:41 UTC (permalink / raw)

pgxml_xpath() builds an xpath_workspace before returning it to
callers.  If an ERROR is thrown before the function returns, callers
have not received the workspace pointer yet and cannot run
cleanup_workspace().

Add local error cleanup for the partially built workspace and the
compiled XPath expression.  Also check xmlXPathNewContext() before
dereferencing the returned context.
---
 contrib/xml2/xpath.c | 51 +++++++++++++++++++++++++++-----------------
 1 file changed, 32 insertions(+), 19 deletions(-)

diff --git a/contrib/xml2/xpath.c b/contrib/xml2/xpath.c
index 9fe75cb5ff4..283bb51178d 100644
--- a/contrib/xml2/xpath.c
+++ b/contrib/xml2/xpath.c
@@ -497,36 +497,49 @@ static xpath_workspace *
 pgxml_xpath(text *document, xmlChar *xpath, PgXmlErrorContext *xmlerrcxt)
 {
 	int32		docsize = VARSIZE_ANY_EXHDR(document);
-	xmlXPathCompExprPtr comppath;
+	xmlXPathCompExprPtr volatile comppath = NULL;
 	xpath_workspace *workspace = palloc0_object(xpath_workspace);
 
 	workspace->doctree = NULL;
 	workspace->ctxt = NULL;
 	workspace->res = NULL;
 
-	workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
-									   docsize, NULL, NULL,
-									   XML_PARSE_NOENT);
-	if (workspace->doctree != NULL)
+	PG_TRY();
 	{
-		workspace->ctxt = xmlXPathNewContext(workspace->doctree);
-		workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
-
-		/* compile the path */
-		comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
-		if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+		workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
+										   docsize, NULL, NULL,
+										   XML_PARSE_NOENT);
+		if (workspace->doctree != NULL)
 		{
-			if (comppath != NULL)
-				xmlXPathFreeCompExpr(comppath);
-			xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
-						"XPath Syntax Error");
-		}
+			workspace->ctxt = xmlXPathNewContext(workspace->doctree);
+			if (workspace->ctxt == NULL)
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_OUT_OF_MEMORY,
+							"could not allocate XPath context");
 
-		/* Now evaluate the path expression. */
-		workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+			workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
+
+			/* compile the path */
+			comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
+			if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
+							"XPath Syntax Error");
+
+			/* Now evaluate the path expression. */
+			workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+
+			xmlXPathFreeCompExpr(comppath);
+			comppath = NULL;
+		}
+	}
+	PG_CATCH();
+	{
+		if (comppath != NULL)
+			xmlXPathFreeCompExpr(comppath);
+		cleanup_workspace(workspace);
 
-		xmlXPathFreeCompExpr(comppath);
+		PG_RE_THROW();
 	}
+	PG_END_TRY();
 
 	return workspace;
 }
-- 
2.54.0


--MP_/LMSk9=uMhuQ1QiIJDarDO8G--





^ permalink  raw  reply  [nested|flat] 611+ messages in thread

* [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths
@ 2026-06-01 22:41 Andrey Chernyy <andrey.cherny@tantorlabs.com>
  0 siblings, 0 replies; 611+ messages in thread

From: Andrey Chernyy @ 2026-06-01 22:41 UTC (permalink / raw)

pgxml_xpath() builds an xpath_workspace before returning it to
callers.  If an ERROR is thrown before the function returns, callers
have not received the workspace pointer yet and cannot run
cleanup_workspace().

Add local error cleanup for the partially built workspace and the
compiled XPath expression.  Also check xmlXPathNewContext() before
dereferencing the returned context.
---
 contrib/xml2/xpath.c | 51 +++++++++++++++++++++++++++-----------------
 1 file changed, 32 insertions(+), 19 deletions(-)

diff --git a/contrib/xml2/xpath.c b/contrib/xml2/xpath.c
index 9fe75cb5ff4..283bb51178d 100644
--- a/contrib/xml2/xpath.c
+++ b/contrib/xml2/xpath.c
@@ -497,36 +497,49 @@ static xpath_workspace *
 pgxml_xpath(text *document, xmlChar *xpath, PgXmlErrorContext *xmlerrcxt)
 {
 	int32		docsize = VARSIZE_ANY_EXHDR(document);
-	xmlXPathCompExprPtr comppath;
+	xmlXPathCompExprPtr volatile comppath = NULL;
 	xpath_workspace *workspace = palloc0_object(xpath_workspace);
 
 	workspace->doctree = NULL;
 	workspace->ctxt = NULL;
 	workspace->res = NULL;
 
-	workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
-									   docsize, NULL, NULL,
-									   XML_PARSE_NOENT);
-	if (workspace->doctree != NULL)
+	PG_TRY();
 	{
-		workspace->ctxt = xmlXPathNewContext(workspace->doctree);
-		workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
-
-		/* compile the path */
-		comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
-		if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+		workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
+										   docsize, NULL, NULL,
+										   XML_PARSE_NOENT);
+		if (workspace->doctree != NULL)
 		{
-			if (comppath != NULL)
-				xmlXPathFreeCompExpr(comppath);
-			xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
-						"XPath Syntax Error");
-		}
+			workspace->ctxt = xmlXPathNewContext(workspace->doctree);
+			if (workspace->ctxt == NULL)
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_OUT_OF_MEMORY,
+							"could not allocate XPath context");
 
-		/* Now evaluate the path expression. */
-		workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+			workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
+
+			/* compile the path */
+			comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
+			if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
+							"XPath Syntax Error");
+
+			/* Now evaluate the path expression. */
+			workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+
+			xmlXPathFreeCompExpr(comppath);
+			comppath = NULL;
+		}
+	}
+	PG_CATCH();
+	{
+		if (comppath != NULL)
+			xmlXPathFreeCompExpr(comppath);
+		cleanup_workspace(workspace);
 
-		xmlXPathFreeCompExpr(comppath);
+		PG_RE_THROW();
 	}
+	PG_END_TRY();
 
 	return workspace;
 }
-- 
2.54.0


--MP_/LMSk9=uMhuQ1QiIJDarDO8G--






^ permalink  raw  reply  [nested|flat] 611+ messages in thread

* [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths
@ 2026-06-01 22:41 Andrey Chernyy <andrey.cherny@tantorlabs.com>
  0 siblings, 0 replies; 611+ messages in thread

From: Andrey Chernyy @ 2026-06-01 22:41 UTC (permalink / raw)

pgxml_xpath() builds an xpath_workspace before returning it to
callers.  If an ERROR is thrown before the function returns, callers
have not received the workspace pointer yet and cannot run
cleanup_workspace().

Add local error cleanup for the partially built workspace and the
compiled XPath expression.  Also check xmlXPathNewContext() before
dereferencing the returned context.
---
 contrib/xml2/xpath.c | 51 +++++++++++++++++++++++++++-----------------
 1 file changed, 32 insertions(+), 19 deletions(-)

diff --git a/contrib/xml2/xpath.c b/contrib/xml2/xpath.c
index 9fe75cb5ff4..283bb51178d 100644
--- a/contrib/xml2/xpath.c
+++ b/contrib/xml2/xpath.c
@@ -497,36 +497,49 @@ static xpath_workspace *
 pgxml_xpath(text *document, xmlChar *xpath, PgXmlErrorContext *xmlerrcxt)
 {
 	int32		docsize = VARSIZE_ANY_EXHDR(document);
-	xmlXPathCompExprPtr comppath;
+	xmlXPathCompExprPtr volatile comppath = NULL;
 	xpath_workspace *workspace = palloc0_object(xpath_workspace);
 
 	workspace->doctree = NULL;
 	workspace->ctxt = NULL;
 	workspace->res = NULL;
 
-	workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
-									   docsize, NULL, NULL,
-									   XML_PARSE_NOENT);
-	if (workspace->doctree != NULL)
+	PG_TRY();
 	{
-		workspace->ctxt = xmlXPathNewContext(workspace->doctree);
-		workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
-
-		/* compile the path */
-		comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
-		if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+		workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
+										   docsize, NULL, NULL,
+										   XML_PARSE_NOENT);
+		if (workspace->doctree != NULL)
 		{
-			if (comppath != NULL)
-				xmlXPathFreeCompExpr(comppath);
-			xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
-						"XPath Syntax Error");
-		}
+			workspace->ctxt = xmlXPathNewContext(workspace->doctree);
+			if (workspace->ctxt == NULL)
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_OUT_OF_MEMORY,
+							"could not allocate XPath context");
 
-		/* Now evaluate the path expression. */
-		workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+			workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
+
+			/* compile the path */
+			comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
+			if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
+							"XPath Syntax Error");
+
+			/* Now evaluate the path expression. */
+			workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+
+			xmlXPathFreeCompExpr(comppath);
+			comppath = NULL;
+		}
+	}
+	PG_CATCH();
+	{
+		if (comppath != NULL)
+			xmlXPathFreeCompExpr(comppath);
+		cleanup_workspace(workspace);
 
-		xmlXPathFreeCompExpr(comppath);
+		PG_RE_THROW();
 	}
+	PG_END_TRY();
 
 	return workspace;
 }
-- 
2.54.0


--MP_/LMSk9=uMhuQ1QiIJDarDO8G--





^ permalink  raw  reply  [nested|flat] 611+ messages in thread

* [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths
@ 2026-06-01 22:41 Andrey Chernyy <andrey.cherny@tantorlabs.com>
  0 siblings, 0 replies; 611+ messages in thread

From: Andrey Chernyy @ 2026-06-01 22:41 UTC (permalink / raw)

pgxml_xpath() builds an xpath_workspace before returning it to
callers.  If an ERROR is thrown before the function returns, callers
have not received the workspace pointer yet and cannot run
cleanup_workspace().

Add local error cleanup for the partially built workspace and the
compiled XPath expression.  Also check xmlXPathNewContext() before
dereferencing the returned context.
---
 contrib/xml2/xpath.c | 51 +++++++++++++++++++++++++++-----------------
 1 file changed, 32 insertions(+), 19 deletions(-)

diff --git a/contrib/xml2/xpath.c b/contrib/xml2/xpath.c
index 9fe75cb5ff4..283bb51178d 100644
--- a/contrib/xml2/xpath.c
+++ b/contrib/xml2/xpath.c
@@ -497,36 +497,49 @@ static xpath_workspace *
 pgxml_xpath(text *document, xmlChar *xpath, PgXmlErrorContext *xmlerrcxt)
 {
 	int32		docsize = VARSIZE_ANY_EXHDR(document);
-	xmlXPathCompExprPtr comppath;
+	xmlXPathCompExprPtr volatile comppath = NULL;
 	xpath_workspace *workspace = palloc0_object(xpath_workspace);
 
 	workspace->doctree = NULL;
 	workspace->ctxt = NULL;
 	workspace->res = NULL;
 
-	workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
-									   docsize, NULL, NULL,
-									   XML_PARSE_NOENT);
-	if (workspace->doctree != NULL)
+	PG_TRY();
 	{
-		workspace->ctxt = xmlXPathNewContext(workspace->doctree);
-		workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
-
-		/* compile the path */
-		comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
-		if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+		workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
+										   docsize, NULL, NULL,
+										   XML_PARSE_NOENT);
+		if (workspace->doctree != NULL)
 		{
-			if (comppath != NULL)
-				xmlXPathFreeCompExpr(comppath);
-			xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
-						"XPath Syntax Error");
-		}
+			workspace->ctxt = xmlXPathNewContext(workspace->doctree);
+			if (workspace->ctxt == NULL)
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_OUT_OF_MEMORY,
+							"could not allocate XPath context");
 
-		/* Now evaluate the path expression. */
-		workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+			workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
+
+			/* compile the path */
+			comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
+			if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
+							"XPath Syntax Error");
+
+			/* Now evaluate the path expression. */
+			workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+
+			xmlXPathFreeCompExpr(comppath);
+			comppath = NULL;
+		}
+	}
+	PG_CATCH();
+	{
+		if (comppath != NULL)
+			xmlXPathFreeCompExpr(comppath);
+		cleanup_workspace(workspace);
 
-		xmlXPathFreeCompExpr(comppath);
+		PG_RE_THROW();
 	}
+	PG_END_TRY();
 
 	return workspace;
 }
-- 
2.54.0


--MP_/LMSk9=uMhuQ1QiIJDarDO8G--





^ permalink  raw  reply  [nested|flat] 611+ messages in thread

* [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths
@ 2026-06-01 22:41 Andrey Chernyy <andrey.cherny@tantorlabs.com>
  0 siblings, 0 replies; 611+ messages in thread

From: Andrey Chernyy @ 2026-06-01 22:41 UTC (permalink / raw)

pgxml_xpath() builds an xpath_workspace before returning it to
callers.  If an ERROR is thrown before the function returns, callers
have not received the workspace pointer yet and cannot run
cleanup_workspace().

Add local error cleanup for the partially built workspace and the
compiled XPath expression.  Also check xmlXPathNewContext() before
dereferencing the returned context.
---
 contrib/xml2/xpath.c | 51 +++++++++++++++++++++++++++-----------------
 1 file changed, 32 insertions(+), 19 deletions(-)

diff --git a/contrib/xml2/xpath.c b/contrib/xml2/xpath.c
index 9fe75cb5ff4..283bb51178d 100644
--- a/contrib/xml2/xpath.c
+++ b/contrib/xml2/xpath.c
@@ -497,36 +497,49 @@ static xpath_workspace *
 pgxml_xpath(text *document, xmlChar *xpath, PgXmlErrorContext *xmlerrcxt)
 {
 	int32		docsize = VARSIZE_ANY_EXHDR(document);
-	xmlXPathCompExprPtr comppath;
+	xmlXPathCompExprPtr volatile comppath = NULL;
 	xpath_workspace *workspace = palloc0_object(xpath_workspace);
 
 	workspace->doctree = NULL;
 	workspace->ctxt = NULL;
 	workspace->res = NULL;
 
-	workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
-									   docsize, NULL, NULL,
-									   XML_PARSE_NOENT);
-	if (workspace->doctree != NULL)
+	PG_TRY();
 	{
-		workspace->ctxt = xmlXPathNewContext(workspace->doctree);
-		workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
-
-		/* compile the path */
-		comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
-		if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+		workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
+										   docsize, NULL, NULL,
+										   XML_PARSE_NOENT);
+		if (workspace->doctree != NULL)
 		{
-			if (comppath != NULL)
-				xmlXPathFreeCompExpr(comppath);
-			xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
-						"XPath Syntax Error");
-		}
+			workspace->ctxt = xmlXPathNewContext(workspace->doctree);
+			if (workspace->ctxt == NULL)
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_OUT_OF_MEMORY,
+							"could not allocate XPath context");
 
-		/* Now evaluate the path expression. */
-		workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+			workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
+
+			/* compile the path */
+			comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
+			if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
+							"XPath Syntax Error");
+
+			/* Now evaluate the path expression. */
+			workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+
+			xmlXPathFreeCompExpr(comppath);
+			comppath = NULL;
+		}
+	}
+	PG_CATCH();
+	{
+		if (comppath != NULL)
+			xmlXPathFreeCompExpr(comppath);
+		cleanup_workspace(workspace);
 
-		xmlXPathFreeCompExpr(comppath);
+		PG_RE_THROW();
 	}
+	PG_END_TRY();
 
 	return workspace;
 }
-- 
2.54.0


--MP_/LMSk9=uMhuQ1QiIJDarDO8G--





^ permalink  raw  reply  [nested|flat] 611+ messages in thread

* [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths
@ 2026-06-01 22:41 Andrey Chernyy <andrey.cherny@tantorlabs.com>
  0 siblings, 0 replies; 611+ messages in thread

From: Andrey Chernyy @ 2026-06-01 22:41 UTC (permalink / raw)

pgxml_xpath() builds an xpath_workspace before returning it to
callers.  If an ERROR is thrown before the function returns, callers
have not received the workspace pointer yet and cannot run
cleanup_workspace().

Add local error cleanup for the partially built workspace and the
compiled XPath expression.  Also check xmlXPathNewContext() before
dereferencing the returned context.
---
 contrib/xml2/xpath.c | 51 +++++++++++++++++++++++++++-----------------
 1 file changed, 32 insertions(+), 19 deletions(-)

diff --git a/contrib/xml2/xpath.c b/contrib/xml2/xpath.c
index 9fe75cb5ff4..283bb51178d 100644
--- a/contrib/xml2/xpath.c
+++ b/contrib/xml2/xpath.c
@@ -497,36 +497,49 @@ static xpath_workspace *
 pgxml_xpath(text *document, xmlChar *xpath, PgXmlErrorContext *xmlerrcxt)
 {
 	int32		docsize = VARSIZE_ANY_EXHDR(document);
-	xmlXPathCompExprPtr comppath;
+	xmlXPathCompExprPtr volatile comppath = NULL;
 	xpath_workspace *workspace = palloc0_object(xpath_workspace);
 
 	workspace->doctree = NULL;
 	workspace->ctxt = NULL;
 	workspace->res = NULL;
 
-	workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
-									   docsize, NULL, NULL,
-									   XML_PARSE_NOENT);
-	if (workspace->doctree != NULL)
+	PG_TRY();
 	{
-		workspace->ctxt = xmlXPathNewContext(workspace->doctree);
-		workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
-
-		/* compile the path */
-		comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
-		if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+		workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
+										   docsize, NULL, NULL,
+										   XML_PARSE_NOENT);
+		if (workspace->doctree != NULL)
 		{
-			if (comppath != NULL)
-				xmlXPathFreeCompExpr(comppath);
-			xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
-						"XPath Syntax Error");
-		}
+			workspace->ctxt = xmlXPathNewContext(workspace->doctree);
+			if (workspace->ctxt == NULL)
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_OUT_OF_MEMORY,
+							"could not allocate XPath context");
 
-		/* Now evaluate the path expression. */
-		workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+			workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
+
+			/* compile the path */
+			comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
+			if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
+							"XPath Syntax Error");
+
+			/* Now evaluate the path expression. */
+			workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+
+			xmlXPathFreeCompExpr(comppath);
+			comppath = NULL;
+		}
+	}
+	PG_CATCH();
+	{
+		if (comppath != NULL)
+			xmlXPathFreeCompExpr(comppath);
+		cleanup_workspace(workspace);
 
-		xmlXPathFreeCompExpr(comppath);
+		PG_RE_THROW();
 	}
+	PG_END_TRY();
 
 	return workspace;
 }
-- 
2.54.0


--MP_/LMSk9=uMhuQ1QiIJDarDO8G--





^ permalink  raw  reply  [nested|flat] 611+ messages in thread

* [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths
@ 2026-06-01 22:41 Andrey Chernyy <andrey.cherny@tantorlabs.com>
  0 siblings, 0 replies; 611+ messages in thread

From: Andrey Chernyy @ 2026-06-01 22:41 UTC (permalink / raw)

pgxml_xpath() builds an xpath_workspace before returning it to
callers.  If an ERROR is thrown before the function returns, callers
have not received the workspace pointer yet and cannot run
cleanup_workspace().

Add local error cleanup for the partially built workspace and the
compiled XPath expression.  Also check xmlXPathNewContext() before
dereferencing the returned context.
---
 contrib/xml2/xpath.c | 51 +++++++++++++++++++++++++++-----------------
 1 file changed, 32 insertions(+), 19 deletions(-)

diff --git a/contrib/xml2/xpath.c b/contrib/xml2/xpath.c
index 9fe75cb5ff4..283bb51178d 100644
--- a/contrib/xml2/xpath.c
+++ b/contrib/xml2/xpath.c
@@ -497,36 +497,49 @@ static xpath_workspace *
 pgxml_xpath(text *document, xmlChar *xpath, PgXmlErrorContext *xmlerrcxt)
 {
 	int32		docsize = VARSIZE_ANY_EXHDR(document);
-	xmlXPathCompExprPtr comppath;
+	xmlXPathCompExprPtr volatile comppath = NULL;
 	xpath_workspace *workspace = palloc0_object(xpath_workspace);
 
 	workspace->doctree = NULL;
 	workspace->ctxt = NULL;
 	workspace->res = NULL;
 
-	workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
-									   docsize, NULL, NULL,
-									   XML_PARSE_NOENT);
-	if (workspace->doctree != NULL)
+	PG_TRY();
 	{
-		workspace->ctxt = xmlXPathNewContext(workspace->doctree);
-		workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
-
-		/* compile the path */
-		comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
-		if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+		workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
+										   docsize, NULL, NULL,
+										   XML_PARSE_NOENT);
+		if (workspace->doctree != NULL)
 		{
-			if (comppath != NULL)
-				xmlXPathFreeCompExpr(comppath);
-			xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
-						"XPath Syntax Error");
-		}
+			workspace->ctxt = xmlXPathNewContext(workspace->doctree);
+			if (workspace->ctxt == NULL)
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_OUT_OF_MEMORY,
+							"could not allocate XPath context");
 
-		/* Now evaluate the path expression. */
-		workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+			workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
+
+			/* compile the path */
+			comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
+			if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
+							"XPath Syntax Error");
+
+			/* Now evaluate the path expression. */
+			workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+
+			xmlXPathFreeCompExpr(comppath);
+			comppath = NULL;
+		}
+	}
+	PG_CATCH();
+	{
+		if (comppath != NULL)
+			xmlXPathFreeCompExpr(comppath);
+		cleanup_workspace(workspace);
 
-		xmlXPathFreeCompExpr(comppath);
+		PG_RE_THROW();
 	}
+	PG_END_TRY();
 
 	return workspace;
 }
-- 
2.54.0


--MP_/LMSk9=uMhuQ1QiIJDarDO8G--






^ permalink  raw  reply  [nested|flat] 611+ messages in thread

* [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths
@ 2026-06-01 22:41 Andrey Chernyy <andrey.cherny@tantorlabs.com>
  0 siblings, 0 replies; 611+ messages in thread

From: Andrey Chernyy @ 2026-06-01 22:41 UTC (permalink / raw)

pgxml_xpath() builds an xpath_workspace before returning it to
callers.  If an ERROR is thrown before the function returns, callers
have not received the workspace pointer yet and cannot run
cleanup_workspace().

Add local error cleanup for the partially built workspace and the
compiled XPath expression.  Also check xmlXPathNewContext() before
dereferencing the returned context.
---
 contrib/xml2/xpath.c | 51 +++++++++++++++++++++++++++-----------------
 1 file changed, 32 insertions(+), 19 deletions(-)

diff --git a/contrib/xml2/xpath.c b/contrib/xml2/xpath.c
index 9fe75cb5ff4..283bb51178d 100644
--- a/contrib/xml2/xpath.c
+++ b/contrib/xml2/xpath.c
@@ -497,36 +497,49 @@ static xpath_workspace *
 pgxml_xpath(text *document, xmlChar *xpath, PgXmlErrorContext *xmlerrcxt)
 {
 	int32		docsize = VARSIZE_ANY_EXHDR(document);
-	xmlXPathCompExprPtr comppath;
+	xmlXPathCompExprPtr volatile comppath = NULL;
 	xpath_workspace *workspace = palloc0_object(xpath_workspace);
 
 	workspace->doctree = NULL;
 	workspace->ctxt = NULL;
 	workspace->res = NULL;
 
-	workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
-									   docsize, NULL, NULL,
-									   XML_PARSE_NOENT);
-	if (workspace->doctree != NULL)
+	PG_TRY();
 	{
-		workspace->ctxt = xmlXPathNewContext(workspace->doctree);
-		workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
-
-		/* compile the path */
-		comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
-		if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+		workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
+										   docsize, NULL, NULL,
+										   XML_PARSE_NOENT);
+		if (workspace->doctree != NULL)
 		{
-			if (comppath != NULL)
-				xmlXPathFreeCompExpr(comppath);
-			xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
-						"XPath Syntax Error");
-		}
+			workspace->ctxt = xmlXPathNewContext(workspace->doctree);
+			if (workspace->ctxt == NULL)
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_OUT_OF_MEMORY,
+							"could not allocate XPath context");
 
-		/* Now evaluate the path expression. */
-		workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+			workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
+
+			/* compile the path */
+			comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
+			if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
+							"XPath Syntax Error");
+
+			/* Now evaluate the path expression. */
+			workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+
+			xmlXPathFreeCompExpr(comppath);
+			comppath = NULL;
+		}
+	}
+	PG_CATCH();
+	{
+		if (comppath != NULL)
+			xmlXPathFreeCompExpr(comppath);
+		cleanup_workspace(workspace);
 
-		xmlXPathFreeCompExpr(comppath);
+		PG_RE_THROW();
 	}
+	PG_END_TRY();
 
 	return workspace;
 }
-- 
2.54.0


--MP_/LMSk9=uMhuQ1QiIJDarDO8G--





^ permalink  raw  reply  [nested|flat] 611+ messages in thread

* [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths
@ 2026-06-01 22:41 Andrey Chernyy <andrey.cherny@tantorlabs.com>
  0 siblings, 0 replies; 611+ messages in thread

From: Andrey Chernyy @ 2026-06-01 22:41 UTC (permalink / raw)

pgxml_xpath() builds an xpath_workspace before returning it to
callers.  If an ERROR is thrown before the function returns, callers
have not received the workspace pointer yet and cannot run
cleanup_workspace().

Add local error cleanup for the partially built workspace and the
compiled XPath expression.  Also check xmlXPathNewContext() before
dereferencing the returned context.
---
 contrib/xml2/xpath.c | 51 +++++++++++++++++++++++++++-----------------
 1 file changed, 32 insertions(+), 19 deletions(-)

diff --git a/contrib/xml2/xpath.c b/contrib/xml2/xpath.c
index 9fe75cb5ff4..283bb51178d 100644
--- a/contrib/xml2/xpath.c
+++ b/contrib/xml2/xpath.c
@@ -497,36 +497,49 @@ static xpath_workspace *
 pgxml_xpath(text *document, xmlChar *xpath, PgXmlErrorContext *xmlerrcxt)
 {
 	int32		docsize = VARSIZE_ANY_EXHDR(document);
-	xmlXPathCompExprPtr comppath;
+	xmlXPathCompExprPtr volatile comppath = NULL;
 	xpath_workspace *workspace = palloc0_object(xpath_workspace);
 
 	workspace->doctree = NULL;
 	workspace->ctxt = NULL;
 	workspace->res = NULL;
 
-	workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
-									   docsize, NULL, NULL,
-									   XML_PARSE_NOENT);
-	if (workspace->doctree != NULL)
+	PG_TRY();
 	{
-		workspace->ctxt = xmlXPathNewContext(workspace->doctree);
-		workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
-
-		/* compile the path */
-		comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
-		if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+		workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
+										   docsize, NULL, NULL,
+										   XML_PARSE_NOENT);
+		if (workspace->doctree != NULL)
 		{
-			if (comppath != NULL)
-				xmlXPathFreeCompExpr(comppath);
-			xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
-						"XPath Syntax Error");
-		}
+			workspace->ctxt = xmlXPathNewContext(workspace->doctree);
+			if (workspace->ctxt == NULL)
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_OUT_OF_MEMORY,
+							"could not allocate XPath context");
 
-		/* Now evaluate the path expression. */
-		workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+			workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
+
+			/* compile the path */
+			comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
+			if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
+							"XPath Syntax Error");
+
+			/* Now evaluate the path expression. */
+			workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+
+			xmlXPathFreeCompExpr(comppath);
+			comppath = NULL;
+		}
+	}
+	PG_CATCH();
+	{
+		if (comppath != NULL)
+			xmlXPathFreeCompExpr(comppath);
+		cleanup_workspace(workspace);
 
-		xmlXPathFreeCompExpr(comppath);
+		PG_RE_THROW();
 	}
+	PG_END_TRY();
 
 	return workspace;
 }
-- 
2.54.0


--MP_/LMSk9=uMhuQ1QiIJDarDO8G--





^ permalink  raw  reply  [nested|flat] 611+ messages in thread

* [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths
@ 2026-06-01 22:41 Andrey Chernyy <andrey.cherny@tantorlabs.com>
  0 siblings, 0 replies; 611+ messages in thread

From: Andrey Chernyy @ 2026-06-01 22:41 UTC (permalink / raw)

pgxml_xpath() builds an xpath_workspace before returning it to
callers.  If an ERROR is thrown before the function returns, callers
have not received the workspace pointer yet and cannot run
cleanup_workspace().

Add local error cleanup for the partially built workspace and the
compiled XPath expression.  Also check xmlXPathNewContext() before
dereferencing the returned context.
---
 contrib/xml2/xpath.c | 51 +++++++++++++++++++++++++++-----------------
 1 file changed, 32 insertions(+), 19 deletions(-)

diff --git a/contrib/xml2/xpath.c b/contrib/xml2/xpath.c
index 9fe75cb5ff4..283bb51178d 100644
--- a/contrib/xml2/xpath.c
+++ b/contrib/xml2/xpath.c
@@ -497,36 +497,49 @@ static xpath_workspace *
 pgxml_xpath(text *document, xmlChar *xpath, PgXmlErrorContext *xmlerrcxt)
 {
 	int32		docsize = VARSIZE_ANY_EXHDR(document);
-	xmlXPathCompExprPtr comppath;
+	xmlXPathCompExprPtr volatile comppath = NULL;
 	xpath_workspace *workspace = palloc0_object(xpath_workspace);
 
 	workspace->doctree = NULL;
 	workspace->ctxt = NULL;
 	workspace->res = NULL;
 
-	workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
-									   docsize, NULL, NULL,
-									   XML_PARSE_NOENT);
-	if (workspace->doctree != NULL)
+	PG_TRY();
 	{
-		workspace->ctxt = xmlXPathNewContext(workspace->doctree);
-		workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
-
-		/* compile the path */
-		comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
-		if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+		workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
+										   docsize, NULL, NULL,
+										   XML_PARSE_NOENT);
+		if (workspace->doctree != NULL)
 		{
-			if (comppath != NULL)
-				xmlXPathFreeCompExpr(comppath);
-			xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
-						"XPath Syntax Error");
-		}
+			workspace->ctxt = xmlXPathNewContext(workspace->doctree);
+			if (workspace->ctxt == NULL)
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_OUT_OF_MEMORY,
+							"could not allocate XPath context");
 
-		/* Now evaluate the path expression. */
-		workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+			workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
+
+			/* compile the path */
+			comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
+			if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
+							"XPath Syntax Error");
+
+			/* Now evaluate the path expression. */
+			workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+
+			xmlXPathFreeCompExpr(comppath);
+			comppath = NULL;
+		}
+	}
+	PG_CATCH();
+	{
+		if (comppath != NULL)
+			xmlXPathFreeCompExpr(comppath);
+		cleanup_workspace(workspace);
 
-		xmlXPathFreeCompExpr(comppath);
+		PG_RE_THROW();
 	}
+	PG_END_TRY();
 
 	return workspace;
 }
-- 
2.54.0


--MP_/LMSk9=uMhuQ1QiIJDarDO8G--





^ permalink  raw  reply  [nested|flat] 611+ messages in thread

* [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths
@ 2026-06-01 22:41 Andrey Chernyy <andrey.cherny@tantorlabs.com>
  0 siblings, 0 replies; 611+ messages in thread

From: Andrey Chernyy @ 2026-06-01 22:41 UTC (permalink / raw)

pgxml_xpath() builds an xpath_workspace before returning it to
callers.  If an ERROR is thrown before the function returns, callers
have not received the workspace pointer yet and cannot run
cleanup_workspace().

Add local error cleanup for the partially built workspace and the
compiled XPath expression.  Also check xmlXPathNewContext() before
dereferencing the returned context.
---
 contrib/xml2/xpath.c | 51 +++++++++++++++++++++++++++-----------------
 1 file changed, 32 insertions(+), 19 deletions(-)

diff --git a/contrib/xml2/xpath.c b/contrib/xml2/xpath.c
index 9fe75cb5ff4..283bb51178d 100644
--- a/contrib/xml2/xpath.c
+++ b/contrib/xml2/xpath.c
@@ -497,36 +497,49 @@ static xpath_workspace *
 pgxml_xpath(text *document, xmlChar *xpath, PgXmlErrorContext *xmlerrcxt)
 {
 	int32		docsize = VARSIZE_ANY_EXHDR(document);
-	xmlXPathCompExprPtr comppath;
+	xmlXPathCompExprPtr volatile comppath = NULL;
 	xpath_workspace *workspace = palloc0_object(xpath_workspace);
 
 	workspace->doctree = NULL;
 	workspace->ctxt = NULL;
 	workspace->res = NULL;
 
-	workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
-									   docsize, NULL, NULL,
-									   XML_PARSE_NOENT);
-	if (workspace->doctree != NULL)
+	PG_TRY();
 	{
-		workspace->ctxt = xmlXPathNewContext(workspace->doctree);
-		workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
-
-		/* compile the path */
-		comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
-		if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+		workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
+										   docsize, NULL, NULL,
+										   XML_PARSE_NOENT);
+		if (workspace->doctree != NULL)
 		{
-			if (comppath != NULL)
-				xmlXPathFreeCompExpr(comppath);
-			xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
-						"XPath Syntax Error");
-		}
+			workspace->ctxt = xmlXPathNewContext(workspace->doctree);
+			if (workspace->ctxt == NULL)
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_OUT_OF_MEMORY,
+							"could not allocate XPath context");
 
-		/* Now evaluate the path expression. */
-		workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+			workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
+
+			/* compile the path */
+			comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
+			if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
+							"XPath Syntax Error");
+
+			/* Now evaluate the path expression. */
+			workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+
+			xmlXPathFreeCompExpr(comppath);
+			comppath = NULL;
+		}
+	}
+	PG_CATCH();
+	{
+		if (comppath != NULL)
+			xmlXPathFreeCompExpr(comppath);
+		cleanup_workspace(workspace);
 
-		xmlXPathFreeCompExpr(comppath);
+		PG_RE_THROW();
 	}
+	PG_END_TRY();
 
 	return workspace;
 }
-- 
2.54.0


--MP_/LMSk9=uMhuQ1QiIJDarDO8G--






^ permalink  raw  reply  [nested|flat] 611+ messages in thread

* [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths
@ 2026-06-01 22:41 Andrey Chernyy <andrey.cherny@tantorlabs.com>
  0 siblings, 0 replies; 611+ messages in thread

From: Andrey Chernyy @ 2026-06-01 22:41 UTC (permalink / raw)

pgxml_xpath() builds an xpath_workspace before returning it to
callers.  If an ERROR is thrown before the function returns, callers
have not received the workspace pointer yet and cannot run
cleanup_workspace().

Add local error cleanup for the partially built workspace and the
compiled XPath expression.  Also check xmlXPathNewContext() before
dereferencing the returned context.
---
 contrib/xml2/xpath.c | 51 +++++++++++++++++++++++++++-----------------
 1 file changed, 32 insertions(+), 19 deletions(-)

diff --git a/contrib/xml2/xpath.c b/contrib/xml2/xpath.c
index 9fe75cb5ff4..283bb51178d 100644
--- a/contrib/xml2/xpath.c
+++ b/contrib/xml2/xpath.c
@@ -497,36 +497,49 @@ static xpath_workspace *
 pgxml_xpath(text *document, xmlChar *xpath, PgXmlErrorContext *xmlerrcxt)
 {
 	int32		docsize = VARSIZE_ANY_EXHDR(document);
-	xmlXPathCompExprPtr comppath;
+	xmlXPathCompExprPtr volatile comppath = NULL;
 	xpath_workspace *workspace = palloc0_object(xpath_workspace);
 
 	workspace->doctree = NULL;
 	workspace->ctxt = NULL;
 	workspace->res = NULL;
 
-	workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
-									   docsize, NULL, NULL,
-									   XML_PARSE_NOENT);
-	if (workspace->doctree != NULL)
+	PG_TRY();
 	{
-		workspace->ctxt = xmlXPathNewContext(workspace->doctree);
-		workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
-
-		/* compile the path */
-		comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
-		if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+		workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
+										   docsize, NULL, NULL,
+										   XML_PARSE_NOENT);
+		if (workspace->doctree != NULL)
 		{
-			if (comppath != NULL)
-				xmlXPathFreeCompExpr(comppath);
-			xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
-						"XPath Syntax Error");
-		}
+			workspace->ctxt = xmlXPathNewContext(workspace->doctree);
+			if (workspace->ctxt == NULL)
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_OUT_OF_MEMORY,
+							"could not allocate XPath context");
 
-		/* Now evaluate the path expression. */
-		workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+			workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
+
+			/* compile the path */
+			comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
+			if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
+							"XPath Syntax Error");
+
+			/* Now evaluate the path expression. */
+			workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+
+			xmlXPathFreeCompExpr(comppath);
+			comppath = NULL;
+		}
+	}
+	PG_CATCH();
+	{
+		if (comppath != NULL)
+			xmlXPathFreeCompExpr(comppath);
+		cleanup_workspace(workspace);
 
-		xmlXPathFreeCompExpr(comppath);
+		PG_RE_THROW();
 	}
+	PG_END_TRY();
 
 	return workspace;
 }
-- 
2.54.0


--MP_/LMSk9=uMhuQ1QiIJDarDO8G--






^ permalink  raw  reply  [nested|flat] 611+ messages in thread

* [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths
@ 2026-06-01 22:41 Andrey Chernyy <andrey.cherny@tantorlabs.com>
  0 siblings, 0 replies; 611+ messages in thread

From: Andrey Chernyy @ 2026-06-01 22:41 UTC (permalink / raw)

pgxml_xpath() builds an xpath_workspace before returning it to
callers.  If an ERROR is thrown before the function returns, callers
have not received the workspace pointer yet and cannot run
cleanup_workspace().

Add local error cleanup for the partially built workspace and the
compiled XPath expression.  Also check xmlXPathNewContext() before
dereferencing the returned context.
---
 contrib/xml2/xpath.c | 51 +++++++++++++++++++++++++++-----------------
 1 file changed, 32 insertions(+), 19 deletions(-)

diff --git a/contrib/xml2/xpath.c b/contrib/xml2/xpath.c
index 9fe75cb5ff4..283bb51178d 100644
--- a/contrib/xml2/xpath.c
+++ b/contrib/xml2/xpath.c
@@ -497,36 +497,49 @@ static xpath_workspace *
 pgxml_xpath(text *document, xmlChar *xpath, PgXmlErrorContext *xmlerrcxt)
 {
 	int32		docsize = VARSIZE_ANY_EXHDR(document);
-	xmlXPathCompExprPtr comppath;
+	xmlXPathCompExprPtr volatile comppath = NULL;
 	xpath_workspace *workspace = palloc0_object(xpath_workspace);
 
 	workspace->doctree = NULL;
 	workspace->ctxt = NULL;
 	workspace->res = NULL;
 
-	workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
-									   docsize, NULL, NULL,
-									   XML_PARSE_NOENT);
-	if (workspace->doctree != NULL)
+	PG_TRY();
 	{
-		workspace->ctxt = xmlXPathNewContext(workspace->doctree);
-		workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
-
-		/* compile the path */
-		comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
-		if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+		workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
+										   docsize, NULL, NULL,
+										   XML_PARSE_NOENT);
+		if (workspace->doctree != NULL)
 		{
-			if (comppath != NULL)
-				xmlXPathFreeCompExpr(comppath);
-			xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
-						"XPath Syntax Error");
-		}
+			workspace->ctxt = xmlXPathNewContext(workspace->doctree);
+			if (workspace->ctxt == NULL)
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_OUT_OF_MEMORY,
+							"could not allocate XPath context");
 
-		/* Now evaluate the path expression. */
-		workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+			workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
+
+			/* compile the path */
+			comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
+			if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
+							"XPath Syntax Error");
+
+			/* Now evaluate the path expression. */
+			workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+
+			xmlXPathFreeCompExpr(comppath);
+			comppath = NULL;
+		}
+	}
+	PG_CATCH();
+	{
+		if (comppath != NULL)
+			xmlXPathFreeCompExpr(comppath);
+		cleanup_workspace(workspace);
 
-		xmlXPathFreeCompExpr(comppath);
+		PG_RE_THROW();
 	}
+	PG_END_TRY();
 
 	return workspace;
 }
-- 
2.54.0


--MP_/LMSk9=uMhuQ1QiIJDarDO8G--






^ permalink  raw  reply  [nested|flat] 611+ messages in thread

* [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths
@ 2026-06-01 22:41 Andrey Chernyy <andrey.cherny@tantorlabs.com>
  0 siblings, 0 replies; 611+ messages in thread

From: Andrey Chernyy @ 2026-06-01 22:41 UTC (permalink / raw)

pgxml_xpath() builds an xpath_workspace before returning it to
callers.  If an ERROR is thrown before the function returns, callers
have not received the workspace pointer yet and cannot run
cleanup_workspace().

Add local error cleanup for the partially built workspace and the
compiled XPath expression.  Also check xmlXPathNewContext() before
dereferencing the returned context.
---
 contrib/xml2/xpath.c | 51 +++++++++++++++++++++++++++-----------------
 1 file changed, 32 insertions(+), 19 deletions(-)

diff --git a/contrib/xml2/xpath.c b/contrib/xml2/xpath.c
index 9fe75cb5ff4..283bb51178d 100644
--- a/contrib/xml2/xpath.c
+++ b/contrib/xml2/xpath.c
@@ -497,36 +497,49 @@ static xpath_workspace *
 pgxml_xpath(text *document, xmlChar *xpath, PgXmlErrorContext *xmlerrcxt)
 {
 	int32		docsize = VARSIZE_ANY_EXHDR(document);
-	xmlXPathCompExprPtr comppath;
+	xmlXPathCompExprPtr volatile comppath = NULL;
 	xpath_workspace *workspace = palloc0_object(xpath_workspace);
 
 	workspace->doctree = NULL;
 	workspace->ctxt = NULL;
 	workspace->res = NULL;
 
-	workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
-									   docsize, NULL, NULL,
-									   XML_PARSE_NOENT);
-	if (workspace->doctree != NULL)
+	PG_TRY();
 	{
-		workspace->ctxt = xmlXPathNewContext(workspace->doctree);
-		workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
-
-		/* compile the path */
-		comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
-		if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+		workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
+										   docsize, NULL, NULL,
+										   XML_PARSE_NOENT);
+		if (workspace->doctree != NULL)
 		{
-			if (comppath != NULL)
-				xmlXPathFreeCompExpr(comppath);
-			xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
-						"XPath Syntax Error");
-		}
+			workspace->ctxt = xmlXPathNewContext(workspace->doctree);
+			if (workspace->ctxt == NULL)
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_OUT_OF_MEMORY,
+							"could not allocate XPath context");
 
-		/* Now evaluate the path expression. */
-		workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+			workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
+
+			/* compile the path */
+			comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
+			if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
+							"XPath Syntax Error");
+
+			/* Now evaluate the path expression. */
+			workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+
+			xmlXPathFreeCompExpr(comppath);
+			comppath = NULL;
+		}
+	}
+	PG_CATCH();
+	{
+		if (comppath != NULL)
+			xmlXPathFreeCompExpr(comppath);
+		cleanup_workspace(workspace);
 
-		xmlXPathFreeCompExpr(comppath);
+		PG_RE_THROW();
 	}
+	PG_END_TRY();
 
 	return workspace;
 }
-- 
2.54.0


--MP_/LMSk9=uMhuQ1QiIJDarDO8G--





^ permalink  raw  reply  [nested|flat] 611+ messages in thread

* [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths
@ 2026-06-01 22:41 Andrey Chernyy <andrey.cherny@tantorlabs.com>
  0 siblings, 0 replies; 611+ messages in thread

From: Andrey Chernyy @ 2026-06-01 22:41 UTC (permalink / raw)

pgxml_xpath() builds an xpath_workspace before returning it to
callers.  If an ERROR is thrown before the function returns, callers
have not received the workspace pointer yet and cannot run
cleanup_workspace().

Add local error cleanup for the partially built workspace and the
compiled XPath expression.  Also check xmlXPathNewContext() before
dereferencing the returned context.
---
 contrib/xml2/xpath.c | 51 +++++++++++++++++++++++++++-----------------
 1 file changed, 32 insertions(+), 19 deletions(-)

diff --git a/contrib/xml2/xpath.c b/contrib/xml2/xpath.c
index 9fe75cb5ff4..283bb51178d 100644
--- a/contrib/xml2/xpath.c
+++ b/contrib/xml2/xpath.c
@@ -497,36 +497,49 @@ static xpath_workspace *
 pgxml_xpath(text *document, xmlChar *xpath, PgXmlErrorContext *xmlerrcxt)
 {
 	int32		docsize = VARSIZE_ANY_EXHDR(document);
-	xmlXPathCompExprPtr comppath;
+	xmlXPathCompExprPtr volatile comppath = NULL;
 	xpath_workspace *workspace = palloc0_object(xpath_workspace);
 
 	workspace->doctree = NULL;
 	workspace->ctxt = NULL;
 	workspace->res = NULL;
 
-	workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
-									   docsize, NULL, NULL,
-									   XML_PARSE_NOENT);
-	if (workspace->doctree != NULL)
+	PG_TRY();
 	{
-		workspace->ctxt = xmlXPathNewContext(workspace->doctree);
-		workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
-
-		/* compile the path */
-		comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
-		if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+		workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
+										   docsize, NULL, NULL,
+										   XML_PARSE_NOENT);
+		if (workspace->doctree != NULL)
 		{
-			if (comppath != NULL)
-				xmlXPathFreeCompExpr(comppath);
-			xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
-						"XPath Syntax Error");
-		}
+			workspace->ctxt = xmlXPathNewContext(workspace->doctree);
+			if (workspace->ctxt == NULL)
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_OUT_OF_MEMORY,
+							"could not allocate XPath context");
 
-		/* Now evaluate the path expression. */
-		workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+			workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
+
+			/* compile the path */
+			comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
+			if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
+							"XPath Syntax Error");
+
+			/* Now evaluate the path expression. */
+			workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+
+			xmlXPathFreeCompExpr(comppath);
+			comppath = NULL;
+		}
+	}
+	PG_CATCH();
+	{
+		if (comppath != NULL)
+			xmlXPathFreeCompExpr(comppath);
+		cleanup_workspace(workspace);
 
-		xmlXPathFreeCompExpr(comppath);
+		PG_RE_THROW();
 	}
+	PG_END_TRY();
 
 	return workspace;
 }
-- 
2.54.0


--MP_/LMSk9=uMhuQ1QiIJDarDO8G--





^ permalink  raw  reply  [nested|flat] 611+ messages in thread

* [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths
@ 2026-06-01 22:41 Andrey Chernyy <andrey.cherny@tantorlabs.com>
  0 siblings, 0 replies; 611+ messages in thread

From: Andrey Chernyy @ 2026-06-01 22:41 UTC (permalink / raw)

pgxml_xpath() builds an xpath_workspace before returning it to
callers.  If an ERROR is thrown before the function returns, callers
have not received the workspace pointer yet and cannot run
cleanup_workspace().

Add local error cleanup for the partially built workspace and the
compiled XPath expression.  Also check xmlXPathNewContext() before
dereferencing the returned context.
---
 contrib/xml2/xpath.c | 51 +++++++++++++++++++++++++++-----------------
 1 file changed, 32 insertions(+), 19 deletions(-)

diff --git a/contrib/xml2/xpath.c b/contrib/xml2/xpath.c
index 9fe75cb5ff4..283bb51178d 100644
--- a/contrib/xml2/xpath.c
+++ b/contrib/xml2/xpath.c
@@ -497,36 +497,49 @@ static xpath_workspace *
 pgxml_xpath(text *document, xmlChar *xpath, PgXmlErrorContext *xmlerrcxt)
 {
 	int32		docsize = VARSIZE_ANY_EXHDR(document);
-	xmlXPathCompExprPtr comppath;
+	xmlXPathCompExprPtr volatile comppath = NULL;
 	xpath_workspace *workspace = palloc0_object(xpath_workspace);
 
 	workspace->doctree = NULL;
 	workspace->ctxt = NULL;
 	workspace->res = NULL;
 
-	workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
-									   docsize, NULL, NULL,
-									   XML_PARSE_NOENT);
-	if (workspace->doctree != NULL)
+	PG_TRY();
 	{
-		workspace->ctxt = xmlXPathNewContext(workspace->doctree);
-		workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
-
-		/* compile the path */
-		comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
-		if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+		workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
+										   docsize, NULL, NULL,
+										   XML_PARSE_NOENT);
+		if (workspace->doctree != NULL)
 		{
-			if (comppath != NULL)
-				xmlXPathFreeCompExpr(comppath);
-			xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
-						"XPath Syntax Error");
-		}
+			workspace->ctxt = xmlXPathNewContext(workspace->doctree);
+			if (workspace->ctxt == NULL)
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_OUT_OF_MEMORY,
+							"could not allocate XPath context");
 
-		/* Now evaluate the path expression. */
-		workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+			workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
+
+			/* compile the path */
+			comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
+			if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
+							"XPath Syntax Error");
+
+			/* Now evaluate the path expression. */
+			workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+
+			xmlXPathFreeCompExpr(comppath);
+			comppath = NULL;
+		}
+	}
+	PG_CATCH();
+	{
+		if (comppath != NULL)
+			xmlXPathFreeCompExpr(comppath);
+		cleanup_workspace(workspace);
 
-		xmlXPathFreeCompExpr(comppath);
+		PG_RE_THROW();
 	}
+	PG_END_TRY();
 
 	return workspace;
 }
-- 
2.54.0


--MP_/LMSk9=uMhuQ1QiIJDarDO8G--






^ permalink  raw  reply  [nested|flat] 611+ messages in thread

* [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths
@ 2026-06-01 22:41 Andrey Chernyy <andrey.cherny@tantorlabs.com>
  0 siblings, 0 replies; 611+ messages in thread

From: Andrey Chernyy @ 2026-06-01 22:41 UTC (permalink / raw)

pgxml_xpath() builds an xpath_workspace before returning it to
callers.  If an ERROR is thrown before the function returns, callers
have not received the workspace pointer yet and cannot run
cleanup_workspace().

Add local error cleanup for the partially built workspace and the
compiled XPath expression.  Also check xmlXPathNewContext() before
dereferencing the returned context.
---
 contrib/xml2/xpath.c | 51 +++++++++++++++++++++++++++-----------------
 1 file changed, 32 insertions(+), 19 deletions(-)

diff --git a/contrib/xml2/xpath.c b/contrib/xml2/xpath.c
index 9fe75cb5ff4..283bb51178d 100644
--- a/contrib/xml2/xpath.c
+++ b/contrib/xml2/xpath.c
@@ -497,36 +497,49 @@ static xpath_workspace *
 pgxml_xpath(text *document, xmlChar *xpath, PgXmlErrorContext *xmlerrcxt)
 {
 	int32		docsize = VARSIZE_ANY_EXHDR(document);
-	xmlXPathCompExprPtr comppath;
+	xmlXPathCompExprPtr volatile comppath = NULL;
 	xpath_workspace *workspace = palloc0_object(xpath_workspace);
 
 	workspace->doctree = NULL;
 	workspace->ctxt = NULL;
 	workspace->res = NULL;
 
-	workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
-									   docsize, NULL, NULL,
-									   XML_PARSE_NOENT);
-	if (workspace->doctree != NULL)
+	PG_TRY();
 	{
-		workspace->ctxt = xmlXPathNewContext(workspace->doctree);
-		workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
-
-		/* compile the path */
-		comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
-		if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+		workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
+										   docsize, NULL, NULL,
+										   XML_PARSE_NOENT);
+		if (workspace->doctree != NULL)
 		{
-			if (comppath != NULL)
-				xmlXPathFreeCompExpr(comppath);
-			xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
-						"XPath Syntax Error");
-		}
+			workspace->ctxt = xmlXPathNewContext(workspace->doctree);
+			if (workspace->ctxt == NULL)
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_OUT_OF_MEMORY,
+							"could not allocate XPath context");
 
-		/* Now evaluate the path expression. */
-		workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+			workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
+
+			/* compile the path */
+			comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
+			if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
+							"XPath Syntax Error");
+
+			/* Now evaluate the path expression. */
+			workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+
+			xmlXPathFreeCompExpr(comppath);
+			comppath = NULL;
+		}
+	}
+	PG_CATCH();
+	{
+		if (comppath != NULL)
+			xmlXPathFreeCompExpr(comppath);
+		cleanup_workspace(workspace);
 
-		xmlXPathFreeCompExpr(comppath);
+		PG_RE_THROW();
 	}
+	PG_END_TRY();
 
 	return workspace;
 }
-- 
2.54.0


--MP_/LMSk9=uMhuQ1QiIJDarDO8G--






^ permalink  raw  reply  [nested|flat] 611+ messages in thread

* [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths
@ 2026-06-01 22:41 Andrey Chernyy <andrey.cherny@tantorlabs.com>
  0 siblings, 0 replies; 611+ messages in thread

From: Andrey Chernyy @ 2026-06-01 22:41 UTC (permalink / raw)

pgxml_xpath() builds an xpath_workspace before returning it to
callers.  If an ERROR is thrown before the function returns, callers
have not received the workspace pointer yet and cannot run
cleanup_workspace().

Add local error cleanup for the partially built workspace and the
compiled XPath expression.  Also check xmlXPathNewContext() before
dereferencing the returned context.
---
 contrib/xml2/xpath.c | 51 +++++++++++++++++++++++++++-----------------
 1 file changed, 32 insertions(+), 19 deletions(-)

diff --git a/contrib/xml2/xpath.c b/contrib/xml2/xpath.c
index 9fe75cb5ff4..283bb51178d 100644
--- a/contrib/xml2/xpath.c
+++ b/contrib/xml2/xpath.c
@@ -497,36 +497,49 @@ static xpath_workspace *
 pgxml_xpath(text *document, xmlChar *xpath, PgXmlErrorContext *xmlerrcxt)
 {
 	int32		docsize = VARSIZE_ANY_EXHDR(document);
-	xmlXPathCompExprPtr comppath;
+	xmlXPathCompExprPtr volatile comppath = NULL;
 	xpath_workspace *workspace = palloc0_object(xpath_workspace);
 
 	workspace->doctree = NULL;
 	workspace->ctxt = NULL;
 	workspace->res = NULL;
 
-	workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
-									   docsize, NULL, NULL,
-									   XML_PARSE_NOENT);
-	if (workspace->doctree != NULL)
+	PG_TRY();
 	{
-		workspace->ctxt = xmlXPathNewContext(workspace->doctree);
-		workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
-
-		/* compile the path */
-		comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
-		if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+		workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
+										   docsize, NULL, NULL,
+										   XML_PARSE_NOENT);
+		if (workspace->doctree != NULL)
 		{
-			if (comppath != NULL)
-				xmlXPathFreeCompExpr(comppath);
-			xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
-						"XPath Syntax Error");
-		}
+			workspace->ctxt = xmlXPathNewContext(workspace->doctree);
+			if (workspace->ctxt == NULL)
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_OUT_OF_MEMORY,
+							"could not allocate XPath context");
 
-		/* Now evaluate the path expression. */
-		workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+			workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
+
+			/* compile the path */
+			comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
+			if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
+							"XPath Syntax Error");
+
+			/* Now evaluate the path expression. */
+			workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+
+			xmlXPathFreeCompExpr(comppath);
+			comppath = NULL;
+		}
+	}
+	PG_CATCH();
+	{
+		if (comppath != NULL)
+			xmlXPathFreeCompExpr(comppath);
+		cleanup_workspace(workspace);
 
-		xmlXPathFreeCompExpr(comppath);
+		PG_RE_THROW();
 	}
+	PG_END_TRY();
 
 	return workspace;
 }
-- 
2.54.0


--MP_/LMSk9=uMhuQ1QiIJDarDO8G--






^ permalink  raw  reply  [nested|flat] 611+ messages in thread

* [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths
@ 2026-06-01 22:41 Andrey Chernyy <andrey.cherny@tantorlabs.com>
  0 siblings, 0 replies; 611+ messages in thread

From: Andrey Chernyy @ 2026-06-01 22:41 UTC (permalink / raw)

pgxml_xpath() builds an xpath_workspace before returning it to
callers.  If an ERROR is thrown before the function returns, callers
have not received the workspace pointer yet and cannot run
cleanup_workspace().

Add local error cleanup for the partially built workspace and the
compiled XPath expression.  Also check xmlXPathNewContext() before
dereferencing the returned context.
---
 contrib/xml2/xpath.c | 51 +++++++++++++++++++++++++++-----------------
 1 file changed, 32 insertions(+), 19 deletions(-)

diff --git a/contrib/xml2/xpath.c b/contrib/xml2/xpath.c
index 9fe75cb5ff4..283bb51178d 100644
--- a/contrib/xml2/xpath.c
+++ b/contrib/xml2/xpath.c
@@ -497,36 +497,49 @@ static xpath_workspace *
 pgxml_xpath(text *document, xmlChar *xpath, PgXmlErrorContext *xmlerrcxt)
 {
 	int32		docsize = VARSIZE_ANY_EXHDR(document);
-	xmlXPathCompExprPtr comppath;
+	xmlXPathCompExprPtr volatile comppath = NULL;
 	xpath_workspace *workspace = palloc0_object(xpath_workspace);
 
 	workspace->doctree = NULL;
 	workspace->ctxt = NULL;
 	workspace->res = NULL;
 
-	workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
-									   docsize, NULL, NULL,
-									   XML_PARSE_NOENT);
-	if (workspace->doctree != NULL)
+	PG_TRY();
 	{
-		workspace->ctxt = xmlXPathNewContext(workspace->doctree);
-		workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
-
-		/* compile the path */
-		comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
-		if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+		workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
+										   docsize, NULL, NULL,
+										   XML_PARSE_NOENT);
+		if (workspace->doctree != NULL)
 		{
-			if (comppath != NULL)
-				xmlXPathFreeCompExpr(comppath);
-			xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
-						"XPath Syntax Error");
-		}
+			workspace->ctxt = xmlXPathNewContext(workspace->doctree);
+			if (workspace->ctxt == NULL)
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_OUT_OF_MEMORY,
+							"could not allocate XPath context");
 
-		/* Now evaluate the path expression. */
-		workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+			workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
+
+			/* compile the path */
+			comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
+			if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
+							"XPath Syntax Error");
+
+			/* Now evaluate the path expression. */
+			workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+
+			xmlXPathFreeCompExpr(comppath);
+			comppath = NULL;
+		}
+	}
+	PG_CATCH();
+	{
+		if (comppath != NULL)
+			xmlXPathFreeCompExpr(comppath);
+		cleanup_workspace(workspace);
 
-		xmlXPathFreeCompExpr(comppath);
+		PG_RE_THROW();
 	}
+	PG_END_TRY();
 
 	return workspace;
 }
-- 
2.54.0


--MP_/LMSk9=uMhuQ1QiIJDarDO8G--





^ permalink  raw  reply  [nested|flat] 611+ messages in thread

* [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths
@ 2026-06-01 22:41 Andrey Chernyy <andrey.cherny@tantorlabs.com>
  0 siblings, 0 replies; 611+ messages in thread

From: Andrey Chernyy @ 2026-06-01 22:41 UTC (permalink / raw)

pgxml_xpath() builds an xpath_workspace before returning it to
callers.  If an ERROR is thrown before the function returns, callers
have not received the workspace pointer yet and cannot run
cleanup_workspace().

Add local error cleanup for the partially built workspace and the
compiled XPath expression.  Also check xmlXPathNewContext() before
dereferencing the returned context.
---
 contrib/xml2/xpath.c | 51 +++++++++++++++++++++++++++-----------------
 1 file changed, 32 insertions(+), 19 deletions(-)

diff --git a/contrib/xml2/xpath.c b/contrib/xml2/xpath.c
index 9fe75cb5ff4..283bb51178d 100644
--- a/contrib/xml2/xpath.c
+++ b/contrib/xml2/xpath.c
@@ -497,36 +497,49 @@ static xpath_workspace *
 pgxml_xpath(text *document, xmlChar *xpath, PgXmlErrorContext *xmlerrcxt)
 {
 	int32		docsize = VARSIZE_ANY_EXHDR(document);
-	xmlXPathCompExprPtr comppath;
+	xmlXPathCompExprPtr volatile comppath = NULL;
 	xpath_workspace *workspace = palloc0_object(xpath_workspace);
 
 	workspace->doctree = NULL;
 	workspace->ctxt = NULL;
 	workspace->res = NULL;
 
-	workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
-									   docsize, NULL, NULL,
-									   XML_PARSE_NOENT);
-	if (workspace->doctree != NULL)
+	PG_TRY();
 	{
-		workspace->ctxt = xmlXPathNewContext(workspace->doctree);
-		workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
-
-		/* compile the path */
-		comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
-		if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+		workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
+										   docsize, NULL, NULL,
+										   XML_PARSE_NOENT);
+		if (workspace->doctree != NULL)
 		{
-			if (comppath != NULL)
-				xmlXPathFreeCompExpr(comppath);
-			xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
-						"XPath Syntax Error");
-		}
+			workspace->ctxt = xmlXPathNewContext(workspace->doctree);
+			if (workspace->ctxt == NULL)
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_OUT_OF_MEMORY,
+							"could not allocate XPath context");
 
-		/* Now evaluate the path expression. */
-		workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+			workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
+
+			/* compile the path */
+			comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
+			if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
+							"XPath Syntax Error");
+
+			/* Now evaluate the path expression. */
+			workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+
+			xmlXPathFreeCompExpr(comppath);
+			comppath = NULL;
+		}
+	}
+	PG_CATCH();
+	{
+		if (comppath != NULL)
+			xmlXPathFreeCompExpr(comppath);
+		cleanup_workspace(workspace);
 
-		xmlXPathFreeCompExpr(comppath);
+		PG_RE_THROW();
 	}
+	PG_END_TRY();
 
 	return workspace;
 }
-- 
2.54.0


--MP_/LMSk9=uMhuQ1QiIJDarDO8G--





^ permalink  raw  reply  [nested|flat] 611+ messages in thread

* [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths
@ 2026-06-01 22:41 Andrey Chernyy <andrey.cherny@tantorlabs.com>
  0 siblings, 0 replies; 611+ messages in thread

From: Andrey Chernyy @ 2026-06-01 22:41 UTC (permalink / raw)

pgxml_xpath() builds an xpath_workspace before returning it to
callers.  If an ERROR is thrown before the function returns, callers
have not received the workspace pointer yet and cannot run
cleanup_workspace().

Add local error cleanup for the partially built workspace and the
compiled XPath expression.  Also check xmlXPathNewContext() before
dereferencing the returned context.
---
 contrib/xml2/xpath.c | 51 +++++++++++++++++++++++++++-----------------
 1 file changed, 32 insertions(+), 19 deletions(-)

diff --git a/contrib/xml2/xpath.c b/contrib/xml2/xpath.c
index 9fe75cb5ff4..283bb51178d 100644
--- a/contrib/xml2/xpath.c
+++ b/contrib/xml2/xpath.c
@@ -497,36 +497,49 @@ static xpath_workspace *
 pgxml_xpath(text *document, xmlChar *xpath, PgXmlErrorContext *xmlerrcxt)
 {
 	int32		docsize = VARSIZE_ANY_EXHDR(document);
-	xmlXPathCompExprPtr comppath;
+	xmlXPathCompExprPtr volatile comppath = NULL;
 	xpath_workspace *workspace = palloc0_object(xpath_workspace);
 
 	workspace->doctree = NULL;
 	workspace->ctxt = NULL;
 	workspace->res = NULL;
 
-	workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
-									   docsize, NULL, NULL,
-									   XML_PARSE_NOENT);
-	if (workspace->doctree != NULL)
+	PG_TRY();
 	{
-		workspace->ctxt = xmlXPathNewContext(workspace->doctree);
-		workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
-
-		/* compile the path */
-		comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
-		if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+		workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
+										   docsize, NULL, NULL,
+										   XML_PARSE_NOENT);
+		if (workspace->doctree != NULL)
 		{
-			if (comppath != NULL)
-				xmlXPathFreeCompExpr(comppath);
-			xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
-						"XPath Syntax Error");
-		}
+			workspace->ctxt = xmlXPathNewContext(workspace->doctree);
+			if (workspace->ctxt == NULL)
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_OUT_OF_MEMORY,
+							"could not allocate XPath context");
 
-		/* Now evaluate the path expression. */
-		workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+			workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
+
+			/* compile the path */
+			comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
+			if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
+							"XPath Syntax Error");
+
+			/* Now evaluate the path expression. */
+			workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+
+			xmlXPathFreeCompExpr(comppath);
+			comppath = NULL;
+		}
+	}
+	PG_CATCH();
+	{
+		if (comppath != NULL)
+			xmlXPathFreeCompExpr(comppath);
+		cleanup_workspace(workspace);
 
-		xmlXPathFreeCompExpr(comppath);
+		PG_RE_THROW();
 	}
+	PG_END_TRY();
 
 	return workspace;
 }
-- 
2.54.0


--MP_/LMSk9=uMhuQ1QiIJDarDO8G--






^ permalink  raw  reply  [nested|flat] 611+ messages in thread

* [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths
@ 2026-06-01 22:41 Andrey Chernyy <andrey.cherny@tantorlabs.com>
  0 siblings, 0 replies; 611+ messages in thread

From: Andrey Chernyy @ 2026-06-01 22:41 UTC (permalink / raw)

pgxml_xpath() builds an xpath_workspace before returning it to
callers.  If an ERROR is thrown before the function returns, callers
have not received the workspace pointer yet and cannot run
cleanup_workspace().

Add local error cleanup for the partially built workspace and the
compiled XPath expression.  Also check xmlXPathNewContext() before
dereferencing the returned context.
---
 contrib/xml2/xpath.c | 51 +++++++++++++++++++++++++++-----------------
 1 file changed, 32 insertions(+), 19 deletions(-)

diff --git a/contrib/xml2/xpath.c b/contrib/xml2/xpath.c
index 9fe75cb5ff4..283bb51178d 100644
--- a/contrib/xml2/xpath.c
+++ b/contrib/xml2/xpath.c
@@ -497,36 +497,49 @@ static xpath_workspace *
 pgxml_xpath(text *document, xmlChar *xpath, PgXmlErrorContext *xmlerrcxt)
 {
 	int32		docsize = VARSIZE_ANY_EXHDR(document);
-	xmlXPathCompExprPtr comppath;
+	xmlXPathCompExprPtr volatile comppath = NULL;
 	xpath_workspace *workspace = palloc0_object(xpath_workspace);
 
 	workspace->doctree = NULL;
 	workspace->ctxt = NULL;
 	workspace->res = NULL;
 
-	workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
-									   docsize, NULL, NULL,
-									   XML_PARSE_NOENT);
-	if (workspace->doctree != NULL)
+	PG_TRY();
 	{
-		workspace->ctxt = xmlXPathNewContext(workspace->doctree);
-		workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
-
-		/* compile the path */
-		comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
-		if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+		workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
+										   docsize, NULL, NULL,
+										   XML_PARSE_NOENT);
+		if (workspace->doctree != NULL)
 		{
-			if (comppath != NULL)
-				xmlXPathFreeCompExpr(comppath);
-			xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
-						"XPath Syntax Error");
-		}
+			workspace->ctxt = xmlXPathNewContext(workspace->doctree);
+			if (workspace->ctxt == NULL)
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_OUT_OF_MEMORY,
+							"could not allocate XPath context");
 
-		/* Now evaluate the path expression. */
-		workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+			workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
+
+			/* compile the path */
+			comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
+			if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
+							"XPath Syntax Error");
+
+			/* Now evaluate the path expression. */
+			workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+
+			xmlXPathFreeCompExpr(comppath);
+			comppath = NULL;
+		}
+	}
+	PG_CATCH();
+	{
+		if (comppath != NULL)
+			xmlXPathFreeCompExpr(comppath);
+		cleanup_workspace(workspace);
 
-		xmlXPathFreeCompExpr(comppath);
+		PG_RE_THROW();
 	}
+	PG_END_TRY();
 
 	return workspace;
 }
-- 
2.54.0


--MP_/LMSk9=uMhuQ1QiIJDarDO8G--





^ permalink  raw  reply  [nested|flat] 611+ messages in thread

* [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths
@ 2026-06-01 22:41 Andrey Chernyy <andrey.cherny@tantorlabs.com>
  0 siblings, 0 replies; 611+ messages in thread

From: Andrey Chernyy @ 2026-06-01 22:41 UTC (permalink / raw)

pgxml_xpath() builds an xpath_workspace before returning it to
callers.  If an ERROR is thrown before the function returns, callers
have not received the workspace pointer yet and cannot run
cleanup_workspace().

Add local error cleanup for the partially built workspace and the
compiled XPath expression.  Also check xmlXPathNewContext() before
dereferencing the returned context.
---
 contrib/xml2/xpath.c | 51 +++++++++++++++++++++++++++-----------------
 1 file changed, 32 insertions(+), 19 deletions(-)

diff --git a/contrib/xml2/xpath.c b/contrib/xml2/xpath.c
index 9fe75cb5ff4..283bb51178d 100644
--- a/contrib/xml2/xpath.c
+++ b/contrib/xml2/xpath.c
@@ -497,36 +497,49 @@ static xpath_workspace *
 pgxml_xpath(text *document, xmlChar *xpath, PgXmlErrorContext *xmlerrcxt)
 {
 	int32		docsize = VARSIZE_ANY_EXHDR(document);
-	xmlXPathCompExprPtr comppath;
+	xmlXPathCompExprPtr volatile comppath = NULL;
 	xpath_workspace *workspace = palloc0_object(xpath_workspace);
 
 	workspace->doctree = NULL;
 	workspace->ctxt = NULL;
 	workspace->res = NULL;
 
-	workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
-									   docsize, NULL, NULL,
-									   XML_PARSE_NOENT);
-	if (workspace->doctree != NULL)
+	PG_TRY();
 	{
-		workspace->ctxt = xmlXPathNewContext(workspace->doctree);
-		workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
-
-		/* compile the path */
-		comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
-		if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+		workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
+										   docsize, NULL, NULL,
+										   XML_PARSE_NOENT);
+		if (workspace->doctree != NULL)
 		{
-			if (comppath != NULL)
-				xmlXPathFreeCompExpr(comppath);
-			xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
-						"XPath Syntax Error");
-		}
+			workspace->ctxt = xmlXPathNewContext(workspace->doctree);
+			if (workspace->ctxt == NULL)
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_OUT_OF_MEMORY,
+							"could not allocate XPath context");
 
-		/* Now evaluate the path expression. */
-		workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+			workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
+
+			/* compile the path */
+			comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
+			if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
+							"XPath Syntax Error");
+
+			/* Now evaluate the path expression. */
+			workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+
+			xmlXPathFreeCompExpr(comppath);
+			comppath = NULL;
+		}
+	}
+	PG_CATCH();
+	{
+		if (comppath != NULL)
+			xmlXPathFreeCompExpr(comppath);
+		cleanup_workspace(workspace);
 
-		xmlXPathFreeCompExpr(comppath);
+		PG_RE_THROW();
 	}
+	PG_END_TRY();
 
 	return workspace;
 }
-- 
2.54.0


--MP_/LMSk9=uMhuQ1QiIJDarDO8G--






^ permalink  raw  reply  [nested|flat] 611+ messages in thread

* [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths
@ 2026-06-01 22:41 Andrey Chernyy <andrey.cherny@tantorlabs.com>
  0 siblings, 0 replies; 611+ messages in thread

From: Andrey Chernyy @ 2026-06-01 22:41 UTC (permalink / raw)

pgxml_xpath() builds an xpath_workspace before returning it to
callers.  If an ERROR is thrown before the function returns, callers
have not received the workspace pointer yet and cannot run
cleanup_workspace().

Add local error cleanup for the partially built workspace and the
compiled XPath expression.  Also check xmlXPathNewContext() before
dereferencing the returned context.
---
 contrib/xml2/xpath.c | 51 +++++++++++++++++++++++++++-----------------
 1 file changed, 32 insertions(+), 19 deletions(-)

diff --git a/contrib/xml2/xpath.c b/contrib/xml2/xpath.c
index 9fe75cb5ff4..283bb51178d 100644
--- a/contrib/xml2/xpath.c
+++ b/contrib/xml2/xpath.c
@@ -497,36 +497,49 @@ static xpath_workspace *
 pgxml_xpath(text *document, xmlChar *xpath, PgXmlErrorContext *xmlerrcxt)
 {
 	int32		docsize = VARSIZE_ANY_EXHDR(document);
-	xmlXPathCompExprPtr comppath;
+	xmlXPathCompExprPtr volatile comppath = NULL;
 	xpath_workspace *workspace = palloc0_object(xpath_workspace);
 
 	workspace->doctree = NULL;
 	workspace->ctxt = NULL;
 	workspace->res = NULL;
 
-	workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
-									   docsize, NULL, NULL,
-									   XML_PARSE_NOENT);
-	if (workspace->doctree != NULL)
+	PG_TRY();
 	{
-		workspace->ctxt = xmlXPathNewContext(workspace->doctree);
-		workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
-
-		/* compile the path */
-		comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
-		if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+		workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
+										   docsize, NULL, NULL,
+										   XML_PARSE_NOENT);
+		if (workspace->doctree != NULL)
 		{
-			if (comppath != NULL)
-				xmlXPathFreeCompExpr(comppath);
-			xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
-						"XPath Syntax Error");
-		}
+			workspace->ctxt = xmlXPathNewContext(workspace->doctree);
+			if (workspace->ctxt == NULL)
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_OUT_OF_MEMORY,
+							"could not allocate XPath context");
 
-		/* Now evaluate the path expression. */
-		workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+			workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
+
+			/* compile the path */
+			comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
+			if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
+							"XPath Syntax Error");
+
+			/* Now evaluate the path expression. */
+			workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+
+			xmlXPathFreeCompExpr(comppath);
+			comppath = NULL;
+		}
+	}
+	PG_CATCH();
+	{
+		if (comppath != NULL)
+			xmlXPathFreeCompExpr(comppath);
+		cleanup_workspace(workspace);
 
-		xmlXPathFreeCompExpr(comppath);
+		PG_RE_THROW();
 	}
+	PG_END_TRY();
 
 	return workspace;
 }
-- 
2.54.0


--MP_/LMSk9=uMhuQ1QiIJDarDO8G--






^ permalink  raw  reply  [nested|flat] 611+ messages in thread

* [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths
@ 2026-06-01 22:41 Andrey Chernyy <andrey.cherny@tantorlabs.com>
  0 siblings, 0 replies; 611+ messages in thread

From: Andrey Chernyy @ 2026-06-01 22:41 UTC (permalink / raw)

pgxml_xpath() builds an xpath_workspace before returning it to
callers.  If an ERROR is thrown before the function returns, callers
have not received the workspace pointer yet and cannot run
cleanup_workspace().

Add local error cleanup for the partially built workspace and the
compiled XPath expression.  Also check xmlXPathNewContext() before
dereferencing the returned context.
---
 contrib/xml2/xpath.c | 51 +++++++++++++++++++++++++++-----------------
 1 file changed, 32 insertions(+), 19 deletions(-)

diff --git a/contrib/xml2/xpath.c b/contrib/xml2/xpath.c
index 9fe75cb5ff4..283bb51178d 100644
--- a/contrib/xml2/xpath.c
+++ b/contrib/xml2/xpath.c
@@ -497,36 +497,49 @@ static xpath_workspace *
 pgxml_xpath(text *document, xmlChar *xpath, PgXmlErrorContext *xmlerrcxt)
 {
 	int32		docsize = VARSIZE_ANY_EXHDR(document);
-	xmlXPathCompExprPtr comppath;
+	xmlXPathCompExprPtr volatile comppath = NULL;
 	xpath_workspace *workspace = palloc0_object(xpath_workspace);
 
 	workspace->doctree = NULL;
 	workspace->ctxt = NULL;
 	workspace->res = NULL;
 
-	workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
-									   docsize, NULL, NULL,
-									   XML_PARSE_NOENT);
-	if (workspace->doctree != NULL)
+	PG_TRY();
 	{
-		workspace->ctxt = xmlXPathNewContext(workspace->doctree);
-		workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
-
-		/* compile the path */
-		comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
-		if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+		workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
+										   docsize, NULL, NULL,
+										   XML_PARSE_NOENT);
+		if (workspace->doctree != NULL)
 		{
-			if (comppath != NULL)
-				xmlXPathFreeCompExpr(comppath);
-			xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
-						"XPath Syntax Error");
-		}
+			workspace->ctxt = xmlXPathNewContext(workspace->doctree);
+			if (workspace->ctxt == NULL)
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_OUT_OF_MEMORY,
+							"could not allocate XPath context");
 
-		/* Now evaluate the path expression. */
-		workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+			workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
+
+			/* compile the path */
+			comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
+			if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
+							"XPath Syntax Error");
+
+			/* Now evaluate the path expression. */
+			workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+
+			xmlXPathFreeCompExpr(comppath);
+			comppath = NULL;
+		}
+	}
+	PG_CATCH();
+	{
+		if (comppath != NULL)
+			xmlXPathFreeCompExpr(comppath);
+		cleanup_workspace(workspace);
 
-		xmlXPathFreeCompExpr(comppath);
+		PG_RE_THROW();
 	}
+	PG_END_TRY();
 
 	return workspace;
 }
-- 
2.54.0


--MP_/LMSk9=uMhuQ1QiIJDarDO8G--





^ permalink  raw  reply  [nested|flat] 611+ messages in thread

* [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths
@ 2026-06-01 22:41 Andrey Chernyy <andrey.cherny@tantorlabs.com>
  0 siblings, 0 replies; 611+ messages in thread

From: Andrey Chernyy @ 2026-06-01 22:41 UTC (permalink / raw)

pgxml_xpath() builds an xpath_workspace before returning it to
callers.  If an ERROR is thrown before the function returns, callers
have not received the workspace pointer yet and cannot run
cleanup_workspace().

Add local error cleanup for the partially built workspace and the
compiled XPath expression.  Also check xmlXPathNewContext() before
dereferencing the returned context.
---
 contrib/xml2/xpath.c | 51 +++++++++++++++++++++++++++-----------------
 1 file changed, 32 insertions(+), 19 deletions(-)

diff --git a/contrib/xml2/xpath.c b/contrib/xml2/xpath.c
index 9fe75cb5ff4..283bb51178d 100644
--- a/contrib/xml2/xpath.c
+++ b/contrib/xml2/xpath.c
@@ -497,36 +497,49 @@ static xpath_workspace *
 pgxml_xpath(text *document, xmlChar *xpath, PgXmlErrorContext *xmlerrcxt)
 {
 	int32		docsize = VARSIZE_ANY_EXHDR(document);
-	xmlXPathCompExprPtr comppath;
+	xmlXPathCompExprPtr volatile comppath = NULL;
 	xpath_workspace *workspace = palloc0_object(xpath_workspace);
 
 	workspace->doctree = NULL;
 	workspace->ctxt = NULL;
 	workspace->res = NULL;
 
-	workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
-									   docsize, NULL, NULL,
-									   XML_PARSE_NOENT);
-	if (workspace->doctree != NULL)
+	PG_TRY();
 	{
-		workspace->ctxt = xmlXPathNewContext(workspace->doctree);
-		workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
-
-		/* compile the path */
-		comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
-		if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+		workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
+										   docsize, NULL, NULL,
+										   XML_PARSE_NOENT);
+		if (workspace->doctree != NULL)
 		{
-			if (comppath != NULL)
-				xmlXPathFreeCompExpr(comppath);
-			xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
-						"XPath Syntax Error");
-		}
+			workspace->ctxt = xmlXPathNewContext(workspace->doctree);
+			if (workspace->ctxt == NULL)
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_OUT_OF_MEMORY,
+							"could not allocate XPath context");
 
-		/* Now evaluate the path expression. */
-		workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+			workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
+
+			/* compile the path */
+			comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
+			if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
+							"XPath Syntax Error");
+
+			/* Now evaluate the path expression. */
+			workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+
+			xmlXPathFreeCompExpr(comppath);
+			comppath = NULL;
+		}
+	}
+	PG_CATCH();
+	{
+		if (comppath != NULL)
+			xmlXPathFreeCompExpr(comppath);
+		cleanup_workspace(workspace);
 
-		xmlXPathFreeCompExpr(comppath);
+		PG_RE_THROW();
 	}
+	PG_END_TRY();
 
 	return workspace;
 }
-- 
2.54.0


--MP_/LMSk9=uMhuQ1QiIJDarDO8G--






^ permalink  raw  reply  [nested|flat] 611+ messages in thread

* [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths
@ 2026-06-01 22:41 Andrey Chernyy <andrey.cherny@tantorlabs.com>
  0 siblings, 0 replies; 611+ messages in thread

From: Andrey Chernyy @ 2026-06-01 22:41 UTC (permalink / raw)

pgxml_xpath() builds an xpath_workspace before returning it to
callers.  If an ERROR is thrown before the function returns, callers
have not received the workspace pointer yet and cannot run
cleanup_workspace().

Add local error cleanup for the partially built workspace and the
compiled XPath expression.  Also check xmlXPathNewContext() before
dereferencing the returned context.
---
 contrib/xml2/xpath.c | 51 +++++++++++++++++++++++++++-----------------
 1 file changed, 32 insertions(+), 19 deletions(-)

diff --git a/contrib/xml2/xpath.c b/contrib/xml2/xpath.c
index 9fe75cb5ff4..283bb51178d 100644
--- a/contrib/xml2/xpath.c
+++ b/contrib/xml2/xpath.c
@@ -497,36 +497,49 @@ static xpath_workspace *
 pgxml_xpath(text *document, xmlChar *xpath, PgXmlErrorContext *xmlerrcxt)
 {
 	int32		docsize = VARSIZE_ANY_EXHDR(document);
-	xmlXPathCompExprPtr comppath;
+	xmlXPathCompExprPtr volatile comppath = NULL;
 	xpath_workspace *workspace = palloc0_object(xpath_workspace);
 
 	workspace->doctree = NULL;
 	workspace->ctxt = NULL;
 	workspace->res = NULL;
 
-	workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
-									   docsize, NULL, NULL,
-									   XML_PARSE_NOENT);
-	if (workspace->doctree != NULL)
+	PG_TRY();
 	{
-		workspace->ctxt = xmlXPathNewContext(workspace->doctree);
-		workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
-
-		/* compile the path */
-		comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
-		if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+		workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
+										   docsize, NULL, NULL,
+										   XML_PARSE_NOENT);
+		if (workspace->doctree != NULL)
 		{
-			if (comppath != NULL)
-				xmlXPathFreeCompExpr(comppath);
-			xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
-						"XPath Syntax Error");
-		}
+			workspace->ctxt = xmlXPathNewContext(workspace->doctree);
+			if (workspace->ctxt == NULL)
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_OUT_OF_MEMORY,
+							"could not allocate XPath context");
 
-		/* Now evaluate the path expression. */
-		workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+			workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
+
+			/* compile the path */
+			comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
+			if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
+							"XPath Syntax Error");
+
+			/* Now evaluate the path expression. */
+			workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+
+			xmlXPathFreeCompExpr(comppath);
+			comppath = NULL;
+		}
+	}
+	PG_CATCH();
+	{
+		if (comppath != NULL)
+			xmlXPathFreeCompExpr(comppath);
+		cleanup_workspace(workspace);
 
-		xmlXPathFreeCompExpr(comppath);
+		PG_RE_THROW();
 	}
+	PG_END_TRY();
 
 	return workspace;
 }
-- 
2.54.0


--MP_/LMSk9=uMhuQ1QiIJDarDO8G--





^ permalink  raw  reply  [nested|flat] 611+ messages in thread

* [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths
@ 2026-06-01 22:41 Andrey Chernyy <andrey.cherny@tantorlabs.com>
  0 siblings, 0 replies; 611+ messages in thread

From: Andrey Chernyy @ 2026-06-01 22:41 UTC (permalink / raw)

pgxml_xpath() builds an xpath_workspace before returning it to
callers.  If an ERROR is thrown before the function returns, callers
have not received the workspace pointer yet and cannot run
cleanup_workspace().

Add local error cleanup for the partially built workspace and the
compiled XPath expression.  Also check xmlXPathNewContext() before
dereferencing the returned context.
---
 contrib/xml2/xpath.c | 51 +++++++++++++++++++++++++++-----------------
 1 file changed, 32 insertions(+), 19 deletions(-)

diff --git a/contrib/xml2/xpath.c b/contrib/xml2/xpath.c
index 9fe75cb5ff4..283bb51178d 100644
--- a/contrib/xml2/xpath.c
+++ b/contrib/xml2/xpath.c
@@ -497,36 +497,49 @@ static xpath_workspace *
 pgxml_xpath(text *document, xmlChar *xpath, PgXmlErrorContext *xmlerrcxt)
 {
 	int32		docsize = VARSIZE_ANY_EXHDR(document);
-	xmlXPathCompExprPtr comppath;
+	xmlXPathCompExprPtr volatile comppath = NULL;
 	xpath_workspace *workspace = palloc0_object(xpath_workspace);
 
 	workspace->doctree = NULL;
 	workspace->ctxt = NULL;
 	workspace->res = NULL;
 
-	workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
-									   docsize, NULL, NULL,
-									   XML_PARSE_NOENT);
-	if (workspace->doctree != NULL)
+	PG_TRY();
 	{
-		workspace->ctxt = xmlXPathNewContext(workspace->doctree);
-		workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
-
-		/* compile the path */
-		comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
-		if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+		workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
+										   docsize, NULL, NULL,
+										   XML_PARSE_NOENT);
+		if (workspace->doctree != NULL)
 		{
-			if (comppath != NULL)
-				xmlXPathFreeCompExpr(comppath);
-			xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
-						"XPath Syntax Error");
-		}
+			workspace->ctxt = xmlXPathNewContext(workspace->doctree);
+			if (workspace->ctxt == NULL)
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_OUT_OF_MEMORY,
+							"could not allocate XPath context");
 
-		/* Now evaluate the path expression. */
-		workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+			workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
+
+			/* compile the path */
+			comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
+			if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
+							"XPath Syntax Error");
+
+			/* Now evaluate the path expression. */
+			workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+
+			xmlXPathFreeCompExpr(comppath);
+			comppath = NULL;
+		}
+	}
+	PG_CATCH();
+	{
+		if (comppath != NULL)
+			xmlXPathFreeCompExpr(comppath);
+		cleanup_workspace(workspace);
 
-		xmlXPathFreeCompExpr(comppath);
+		PG_RE_THROW();
 	}
+	PG_END_TRY();
 
 	return workspace;
 }
-- 
2.54.0


--MP_/LMSk9=uMhuQ1QiIJDarDO8G--






^ permalink  raw  reply  [nested|flat] 611+ messages in thread

* [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths
@ 2026-06-01 22:41 Andrey Chernyy <andrey.cherny@tantorlabs.com>
  0 siblings, 0 replies; 611+ messages in thread

From: Andrey Chernyy @ 2026-06-01 22:41 UTC (permalink / raw)

pgxml_xpath() builds an xpath_workspace before returning it to
callers.  If an ERROR is thrown before the function returns, callers
have not received the workspace pointer yet and cannot run
cleanup_workspace().

Add local error cleanup for the partially built workspace and the
compiled XPath expression.  Also check xmlXPathNewContext() before
dereferencing the returned context.
---
 contrib/xml2/xpath.c | 51 +++++++++++++++++++++++++++-----------------
 1 file changed, 32 insertions(+), 19 deletions(-)

diff --git a/contrib/xml2/xpath.c b/contrib/xml2/xpath.c
index 9fe75cb5ff4..283bb51178d 100644
--- a/contrib/xml2/xpath.c
+++ b/contrib/xml2/xpath.c
@@ -497,36 +497,49 @@ static xpath_workspace *
 pgxml_xpath(text *document, xmlChar *xpath, PgXmlErrorContext *xmlerrcxt)
 {
 	int32		docsize = VARSIZE_ANY_EXHDR(document);
-	xmlXPathCompExprPtr comppath;
+	xmlXPathCompExprPtr volatile comppath = NULL;
 	xpath_workspace *workspace = palloc0_object(xpath_workspace);
 
 	workspace->doctree = NULL;
 	workspace->ctxt = NULL;
 	workspace->res = NULL;
 
-	workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
-									   docsize, NULL, NULL,
-									   XML_PARSE_NOENT);
-	if (workspace->doctree != NULL)
+	PG_TRY();
 	{
-		workspace->ctxt = xmlXPathNewContext(workspace->doctree);
-		workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
-
-		/* compile the path */
-		comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
-		if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+		workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
+										   docsize, NULL, NULL,
+										   XML_PARSE_NOENT);
+		if (workspace->doctree != NULL)
 		{
-			if (comppath != NULL)
-				xmlXPathFreeCompExpr(comppath);
-			xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
-						"XPath Syntax Error");
-		}
+			workspace->ctxt = xmlXPathNewContext(workspace->doctree);
+			if (workspace->ctxt == NULL)
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_OUT_OF_MEMORY,
+							"could not allocate XPath context");
 
-		/* Now evaluate the path expression. */
-		workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+			workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
+
+			/* compile the path */
+			comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
+			if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
+							"XPath Syntax Error");
+
+			/* Now evaluate the path expression. */
+			workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+
+			xmlXPathFreeCompExpr(comppath);
+			comppath = NULL;
+		}
+	}
+	PG_CATCH();
+	{
+		if (comppath != NULL)
+			xmlXPathFreeCompExpr(comppath);
+		cleanup_workspace(workspace);
 
-		xmlXPathFreeCompExpr(comppath);
+		PG_RE_THROW();
 	}
+	PG_END_TRY();
 
 	return workspace;
 }
-- 
2.54.0


--MP_/LMSk9=uMhuQ1QiIJDarDO8G--






^ permalink  raw  reply  [nested|flat] 611+ messages in thread

* [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths
@ 2026-06-01 22:41 Andrey Chernyy <andrey.cherny@tantorlabs.com>
  0 siblings, 0 replies; 611+ messages in thread

From: Andrey Chernyy @ 2026-06-01 22:41 UTC (permalink / raw)

pgxml_xpath() builds an xpath_workspace before returning it to
callers.  If an ERROR is thrown before the function returns, callers
have not received the workspace pointer yet and cannot run
cleanup_workspace().

Add local error cleanup for the partially built workspace and the
compiled XPath expression.  Also check xmlXPathNewContext() before
dereferencing the returned context.
---
 contrib/xml2/xpath.c | 51 +++++++++++++++++++++++++++-----------------
 1 file changed, 32 insertions(+), 19 deletions(-)

diff --git a/contrib/xml2/xpath.c b/contrib/xml2/xpath.c
index 9fe75cb5ff4..283bb51178d 100644
--- a/contrib/xml2/xpath.c
+++ b/contrib/xml2/xpath.c
@@ -497,36 +497,49 @@ static xpath_workspace *
 pgxml_xpath(text *document, xmlChar *xpath, PgXmlErrorContext *xmlerrcxt)
 {
 	int32		docsize = VARSIZE_ANY_EXHDR(document);
-	xmlXPathCompExprPtr comppath;
+	xmlXPathCompExprPtr volatile comppath = NULL;
 	xpath_workspace *workspace = palloc0_object(xpath_workspace);
 
 	workspace->doctree = NULL;
 	workspace->ctxt = NULL;
 	workspace->res = NULL;
 
-	workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
-									   docsize, NULL, NULL,
-									   XML_PARSE_NOENT);
-	if (workspace->doctree != NULL)
+	PG_TRY();
 	{
-		workspace->ctxt = xmlXPathNewContext(workspace->doctree);
-		workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
-
-		/* compile the path */
-		comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
-		if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+		workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
+										   docsize, NULL, NULL,
+										   XML_PARSE_NOENT);
+		if (workspace->doctree != NULL)
 		{
-			if (comppath != NULL)
-				xmlXPathFreeCompExpr(comppath);
-			xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
-						"XPath Syntax Error");
-		}
+			workspace->ctxt = xmlXPathNewContext(workspace->doctree);
+			if (workspace->ctxt == NULL)
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_OUT_OF_MEMORY,
+							"could not allocate XPath context");
 
-		/* Now evaluate the path expression. */
-		workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+			workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
+
+			/* compile the path */
+			comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
+			if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
+							"XPath Syntax Error");
+
+			/* Now evaluate the path expression. */
+			workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+
+			xmlXPathFreeCompExpr(comppath);
+			comppath = NULL;
+		}
+	}
+	PG_CATCH();
+	{
+		if (comppath != NULL)
+			xmlXPathFreeCompExpr(comppath);
+		cleanup_workspace(workspace);
 
-		xmlXPathFreeCompExpr(comppath);
+		PG_RE_THROW();
 	}
+	PG_END_TRY();
 
 	return workspace;
 }
-- 
2.54.0


--MP_/LMSk9=uMhuQ1QiIJDarDO8G--






^ permalink  raw  reply  [nested|flat] 611+ messages in thread

* [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths
@ 2026-06-01 22:41 Andrey Chernyy <andrey.cherny@tantorlabs.com>
  0 siblings, 0 replies; 611+ messages in thread

From: Andrey Chernyy @ 2026-06-01 22:41 UTC (permalink / raw)

pgxml_xpath() builds an xpath_workspace before returning it to
callers.  If an ERROR is thrown before the function returns, callers
have not received the workspace pointer yet and cannot run
cleanup_workspace().

Add local error cleanup for the partially built workspace and the
compiled XPath expression.  Also check xmlXPathNewContext() before
dereferencing the returned context.
---
 contrib/xml2/xpath.c | 51 +++++++++++++++++++++++++++-----------------
 1 file changed, 32 insertions(+), 19 deletions(-)

diff --git a/contrib/xml2/xpath.c b/contrib/xml2/xpath.c
index 9fe75cb5ff4..283bb51178d 100644
--- a/contrib/xml2/xpath.c
+++ b/contrib/xml2/xpath.c
@@ -497,36 +497,49 @@ static xpath_workspace *
 pgxml_xpath(text *document, xmlChar *xpath, PgXmlErrorContext *xmlerrcxt)
 {
 	int32		docsize = VARSIZE_ANY_EXHDR(document);
-	xmlXPathCompExprPtr comppath;
+	xmlXPathCompExprPtr volatile comppath = NULL;
 	xpath_workspace *workspace = palloc0_object(xpath_workspace);
 
 	workspace->doctree = NULL;
 	workspace->ctxt = NULL;
 	workspace->res = NULL;
 
-	workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
-									   docsize, NULL, NULL,
-									   XML_PARSE_NOENT);
-	if (workspace->doctree != NULL)
+	PG_TRY();
 	{
-		workspace->ctxt = xmlXPathNewContext(workspace->doctree);
-		workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
-
-		/* compile the path */
-		comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
-		if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+		workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
+										   docsize, NULL, NULL,
+										   XML_PARSE_NOENT);
+		if (workspace->doctree != NULL)
 		{
-			if (comppath != NULL)
-				xmlXPathFreeCompExpr(comppath);
-			xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
-						"XPath Syntax Error");
-		}
+			workspace->ctxt = xmlXPathNewContext(workspace->doctree);
+			if (workspace->ctxt == NULL)
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_OUT_OF_MEMORY,
+							"could not allocate XPath context");
 
-		/* Now evaluate the path expression. */
-		workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+			workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
+
+			/* compile the path */
+			comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
+			if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
+							"XPath Syntax Error");
+
+			/* Now evaluate the path expression. */
+			workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+
+			xmlXPathFreeCompExpr(comppath);
+			comppath = NULL;
+		}
+	}
+	PG_CATCH();
+	{
+		if (comppath != NULL)
+			xmlXPathFreeCompExpr(comppath);
+		cleanup_workspace(workspace);
 
-		xmlXPathFreeCompExpr(comppath);
+		PG_RE_THROW();
 	}
+	PG_END_TRY();
 
 	return workspace;
 }
-- 
2.54.0


--MP_/LMSk9=uMhuQ1QiIJDarDO8G--






^ permalink  raw  reply  [nested|flat] 611+ messages in thread

* [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths
@ 2026-06-01 22:41 Andrey Chernyy <andrey.cherny@tantorlabs.com>
  0 siblings, 0 replies; 611+ messages in thread

From: Andrey Chernyy @ 2026-06-01 22:41 UTC (permalink / raw)

pgxml_xpath() builds an xpath_workspace before returning it to
callers.  If an ERROR is thrown before the function returns, callers
have not received the workspace pointer yet and cannot run
cleanup_workspace().

Add local error cleanup for the partially built workspace and the
compiled XPath expression.  Also check xmlXPathNewContext() before
dereferencing the returned context.
---
 contrib/xml2/xpath.c | 51 +++++++++++++++++++++++++++-----------------
 1 file changed, 32 insertions(+), 19 deletions(-)

diff --git a/contrib/xml2/xpath.c b/contrib/xml2/xpath.c
index 9fe75cb5ff4..283bb51178d 100644
--- a/contrib/xml2/xpath.c
+++ b/contrib/xml2/xpath.c
@@ -497,36 +497,49 @@ static xpath_workspace *
 pgxml_xpath(text *document, xmlChar *xpath, PgXmlErrorContext *xmlerrcxt)
 {
 	int32		docsize = VARSIZE_ANY_EXHDR(document);
-	xmlXPathCompExprPtr comppath;
+	xmlXPathCompExprPtr volatile comppath = NULL;
 	xpath_workspace *workspace = palloc0_object(xpath_workspace);
 
 	workspace->doctree = NULL;
 	workspace->ctxt = NULL;
 	workspace->res = NULL;
 
-	workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
-									   docsize, NULL, NULL,
-									   XML_PARSE_NOENT);
-	if (workspace->doctree != NULL)
+	PG_TRY();
 	{
-		workspace->ctxt = xmlXPathNewContext(workspace->doctree);
-		workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
-
-		/* compile the path */
-		comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
-		if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+		workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
+										   docsize, NULL, NULL,
+										   XML_PARSE_NOENT);
+		if (workspace->doctree != NULL)
 		{
-			if (comppath != NULL)
-				xmlXPathFreeCompExpr(comppath);
-			xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
-						"XPath Syntax Error");
-		}
+			workspace->ctxt = xmlXPathNewContext(workspace->doctree);
+			if (workspace->ctxt == NULL)
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_OUT_OF_MEMORY,
+							"could not allocate XPath context");
 
-		/* Now evaluate the path expression. */
-		workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+			workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
+
+			/* compile the path */
+			comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
+			if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
+							"XPath Syntax Error");
+
+			/* Now evaluate the path expression. */
+			workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+
+			xmlXPathFreeCompExpr(comppath);
+			comppath = NULL;
+		}
+	}
+	PG_CATCH();
+	{
+		if (comppath != NULL)
+			xmlXPathFreeCompExpr(comppath);
+		cleanup_workspace(workspace);
 
-		xmlXPathFreeCompExpr(comppath);
+		PG_RE_THROW();
 	}
+	PG_END_TRY();
 
 	return workspace;
 }
-- 
2.54.0


--MP_/LMSk9=uMhuQ1QiIJDarDO8G--






^ permalink  raw  reply  [nested|flat] 611+ messages in thread

* [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths
@ 2026-06-01 22:41 Andrey Chernyy <andrey.cherny@tantorlabs.com>
  0 siblings, 0 replies; 611+ messages in thread

From: Andrey Chernyy @ 2026-06-01 22:41 UTC (permalink / raw)

pgxml_xpath() builds an xpath_workspace before returning it to
callers.  If an ERROR is thrown before the function returns, callers
have not received the workspace pointer yet and cannot run
cleanup_workspace().

Add local error cleanup for the partially built workspace and the
compiled XPath expression.  Also check xmlXPathNewContext() before
dereferencing the returned context.
---
 contrib/xml2/xpath.c | 51 +++++++++++++++++++++++++++-----------------
 1 file changed, 32 insertions(+), 19 deletions(-)

diff --git a/contrib/xml2/xpath.c b/contrib/xml2/xpath.c
index 9fe75cb5ff4..283bb51178d 100644
--- a/contrib/xml2/xpath.c
+++ b/contrib/xml2/xpath.c
@@ -497,36 +497,49 @@ static xpath_workspace *
 pgxml_xpath(text *document, xmlChar *xpath, PgXmlErrorContext *xmlerrcxt)
 {
 	int32		docsize = VARSIZE_ANY_EXHDR(document);
-	xmlXPathCompExprPtr comppath;
+	xmlXPathCompExprPtr volatile comppath = NULL;
 	xpath_workspace *workspace = palloc0_object(xpath_workspace);
 
 	workspace->doctree = NULL;
 	workspace->ctxt = NULL;
 	workspace->res = NULL;
 
-	workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
-									   docsize, NULL, NULL,
-									   XML_PARSE_NOENT);
-	if (workspace->doctree != NULL)
+	PG_TRY();
 	{
-		workspace->ctxt = xmlXPathNewContext(workspace->doctree);
-		workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
-
-		/* compile the path */
-		comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
-		if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+		workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
+										   docsize, NULL, NULL,
+										   XML_PARSE_NOENT);
+		if (workspace->doctree != NULL)
 		{
-			if (comppath != NULL)
-				xmlXPathFreeCompExpr(comppath);
-			xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
-						"XPath Syntax Error");
-		}
+			workspace->ctxt = xmlXPathNewContext(workspace->doctree);
+			if (workspace->ctxt == NULL)
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_OUT_OF_MEMORY,
+							"could not allocate XPath context");
 
-		/* Now evaluate the path expression. */
-		workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+			workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
+
+			/* compile the path */
+			comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
+			if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
+							"XPath Syntax Error");
+
+			/* Now evaluate the path expression. */
+			workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+
+			xmlXPathFreeCompExpr(comppath);
+			comppath = NULL;
+		}
+	}
+	PG_CATCH();
+	{
+		if (comppath != NULL)
+			xmlXPathFreeCompExpr(comppath);
+		cleanup_workspace(workspace);
 
-		xmlXPathFreeCompExpr(comppath);
+		PG_RE_THROW();
 	}
+	PG_END_TRY();
 
 	return workspace;
 }
-- 
2.54.0


--MP_/LMSk9=uMhuQ1QiIJDarDO8G--






^ permalink  raw  reply  [nested|flat] 611+ messages in thread

* [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths
@ 2026-06-01 22:41 Andrey Chernyy <andrey.cherny@tantorlabs.com>
  0 siblings, 0 replies; 611+ messages in thread

From: Andrey Chernyy @ 2026-06-01 22:41 UTC (permalink / raw)

pgxml_xpath() builds an xpath_workspace before returning it to
callers.  If an ERROR is thrown before the function returns, callers
have not received the workspace pointer yet and cannot run
cleanup_workspace().

Add local error cleanup for the partially built workspace and the
compiled XPath expression.  Also check xmlXPathNewContext() before
dereferencing the returned context.
---
 contrib/xml2/xpath.c | 51 +++++++++++++++++++++++++++-----------------
 1 file changed, 32 insertions(+), 19 deletions(-)

diff --git a/contrib/xml2/xpath.c b/contrib/xml2/xpath.c
index 9fe75cb5ff4..283bb51178d 100644
--- a/contrib/xml2/xpath.c
+++ b/contrib/xml2/xpath.c
@@ -497,36 +497,49 @@ static xpath_workspace *
 pgxml_xpath(text *document, xmlChar *xpath, PgXmlErrorContext *xmlerrcxt)
 {
 	int32		docsize = VARSIZE_ANY_EXHDR(document);
-	xmlXPathCompExprPtr comppath;
+	xmlXPathCompExprPtr volatile comppath = NULL;
 	xpath_workspace *workspace = palloc0_object(xpath_workspace);
 
 	workspace->doctree = NULL;
 	workspace->ctxt = NULL;
 	workspace->res = NULL;
 
-	workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
-									   docsize, NULL, NULL,
-									   XML_PARSE_NOENT);
-	if (workspace->doctree != NULL)
+	PG_TRY();
 	{
-		workspace->ctxt = xmlXPathNewContext(workspace->doctree);
-		workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
-
-		/* compile the path */
-		comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
-		if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+		workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
+										   docsize, NULL, NULL,
+										   XML_PARSE_NOENT);
+		if (workspace->doctree != NULL)
 		{
-			if (comppath != NULL)
-				xmlXPathFreeCompExpr(comppath);
-			xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
-						"XPath Syntax Error");
-		}
+			workspace->ctxt = xmlXPathNewContext(workspace->doctree);
+			if (workspace->ctxt == NULL)
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_OUT_OF_MEMORY,
+							"could not allocate XPath context");
 
-		/* Now evaluate the path expression. */
-		workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+			workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
+
+			/* compile the path */
+			comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
+			if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
+							"XPath Syntax Error");
+
+			/* Now evaluate the path expression. */
+			workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+
+			xmlXPathFreeCompExpr(comppath);
+			comppath = NULL;
+		}
+	}
+	PG_CATCH();
+	{
+		if (comppath != NULL)
+			xmlXPathFreeCompExpr(comppath);
+		cleanup_workspace(workspace);
 
-		xmlXPathFreeCompExpr(comppath);
+		PG_RE_THROW();
 	}
+	PG_END_TRY();
 
 	return workspace;
 }
-- 
2.54.0


--MP_/LMSk9=uMhuQ1QiIJDarDO8G--






^ permalink  raw  reply  [nested|flat] 611+ messages in thread

* [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths
@ 2026-06-01 22:41 Andrey Chernyy <andrey.cherny@tantorlabs.com>
  0 siblings, 0 replies; 611+ messages in thread

From: Andrey Chernyy @ 2026-06-01 22:41 UTC (permalink / raw)

pgxml_xpath() builds an xpath_workspace before returning it to
callers.  If an ERROR is thrown before the function returns, callers
have not received the workspace pointer yet and cannot run
cleanup_workspace().

Add local error cleanup for the partially built workspace and the
compiled XPath expression.  Also check xmlXPathNewContext() before
dereferencing the returned context.
---
 contrib/xml2/xpath.c | 51 +++++++++++++++++++++++++++-----------------
 1 file changed, 32 insertions(+), 19 deletions(-)

diff --git a/contrib/xml2/xpath.c b/contrib/xml2/xpath.c
index 9fe75cb5ff4..283bb51178d 100644
--- a/contrib/xml2/xpath.c
+++ b/contrib/xml2/xpath.c
@@ -497,36 +497,49 @@ static xpath_workspace *
 pgxml_xpath(text *document, xmlChar *xpath, PgXmlErrorContext *xmlerrcxt)
 {
 	int32		docsize = VARSIZE_ANY_EXHDR(document);
-	xmlXPathCompExprPtr comppath;
+	xmlXPathCompExprPtr volatile comppath = NULL;
 	xpath_workspace *workspace = palloc0_object(xpath_workspace);
 
 	workspace->doctree = NULL;
 	workspace->ctxt = NULL;
 	workspace->res = NULL;
 
-	workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
-									   docsize, NULL, NULL,
-									   XML_PARSE_NOENT);
-	if (workspace->doctree != NULL)
+	PG_TRY();
 	{
-		workspace->ctxt = xmlXPathNewContext(workspace->doctree);
-		workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
-
-		/* compile the path */
-		comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
-		if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+		workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
+										   docsize, NULL, NULL,
+										   XML_PARSE_NOENT);
+		if (workspace->doctree != NULL)
 		{
-			if (comppath != NULL)
-				xmlXPathFreeCompExpr(comppath);
-			xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
-						"XPath Syntax Error");
-		}
+			workspace->ctxt = xmlXPathNewContext(workspace->doctree);
+			if (workspace->ctxt == NULL)
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_OUT_OF_MEMORY,
+							"could not allocate XPath context");
 
-		/* Now evaluate the path expression. */
-		workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+			workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
+
+			/* compile the path */
+			comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
+			if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
+							"XPath Syntax Error");
+
+			/* Now evaluate the path expression. */
+			workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+
+			xmlXPathFreeCompExpr(comppath);
+			comppath = NULL;
+		}
+	}
+	PG_CATCH();
+	{
+		if (comppath != NULL)
+			xmlXPathFreeCompExpr(comppath);
+		cleanup_workspace(workspace);
 
-		xmlXPathFreeCompExpr(comppath);
+		PG_RE_THROW();
 	}
+	PG_END_TRY();
 
 	return workspace;
 }
-- 
2.54.0


--MP_/LMSk9=uMhuQ1QiIJDarDO8G--





^ permalink  raw  reply  [nested|flat] 611+ messages in thread

* [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths
@ 2026-06-01 22:41 Andrey Chernyy <andrey.cherny@tantorlabs.com>
  0 siblings, 0 replies; 611+ messages in thread

From: Andrey Chernyy @ 2026-06-01 22:41 UTC (permalink / raw)

pgxml_xpath() builds an xpath_workspace before returning it to
callers.  If an ERROR is thrown before the function returns, callers
have not received the workspace pointer yet and cannot run
cleanup_workspace().

Add local error cleanup for the partially built workspace and the
compiled XPath expression.  Also check xmlXPathNewContext() before
dereferencing the returned context.
---
 contrib/xml2/xpath.c | 51 +++++++++++++++++++++++++++-----------------
 1 file changed, 32 insertions(+), 19 deletions(-)

diff --git a/contrib/xml2/xpath.c b/contrib/xml2/xpath.c
index 9fe75cb5ff4..283bb51178d 100644
--- a/contrib/xml2/xpath.c
+++ b/contrib/xml2/xpath.c
@@ -497,36 +497,49 @@ static xpath_workspace *
 pgxml_xpath(text *document, xmlChar *xpath, PgXmlErrorContext *xmlerrcxt)
 {
 	int32		docsize = VARSIZE_ANY_EXHDR(document);
-	xmlXPathCompExprPtr comppath;
+	xmlXPathCompExprPtr volatile comppath = NULL;
 	xpath_workspace *workspace = palloc0_object(xpath_workspace);
 
 	workspace->doctree = NULL;
 	workspace->ctxt = NULL;
 	workspace->res = NULL;
 
-	workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
-									   docsize, NULL, NULL,
-									   XML_PARSE_NOENT);
-	if (workspace->doctree != NULL)
+	PG_TRY();
 	{
-		workspace->ctxt = xmlXPathNewContext(workspace->doctree);
-		workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
-
-		/* compile the path */
-		comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
-		if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+		workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
+										   docsize, NULL, NULL,
+										   XML_PARSE_NOENT);
+		if (workspace->doctree != NULL)
 		{
-			if (comppath != NULL)
-				xmlXPathFreeCompExpr(comppath);
-			xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
-						"XPath Syntax Error");
-		}
+			workspace->ctxt = xmlXPathNewContext(workspace->doctree);
+			if (workspace->ctxt == NULL)
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_OUT_OF_MEMORY,
+							"could not allocate XPath context");
 
-		/* Now evaluate the path expression. */
-		workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+			workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
+
+			/* compile the path */
+			comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
+			if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
+							"XPath Syntax Error");
+
+			/* Now evaluate the path expression. */
+			workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+
+			xmlXPathFreeCompExpr(comppath);
+			comppath = NULL;
+		}
+	}
+	PG_CATCH();
+	{
+		if (comppath != NULL)
+			xmlXPathFreeCompExpr(comppath);
+		cleanup_workspace(workspace);
 
-		xmlXPathFreeCompExpr(comppath);
+		PG_RE_THROW();
 	}
+	PG_END_TRY();
 
 	return workspace;
 }
-- 
2.54.0


--MP_/LMSk9=uMhuQ1QiIJDarDO8G--





^ permalink  raw  reply  [nested|flat] 611+ messages in thread

* [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths
@ 2026-06-01 22:41 Andrey Chernyy <andrey.cherny@tantorlabs.com>
  0 siblings, 0 replies; 611+ messages in thread

From: Andrey Chernyy @ 2026-06-01 22:41 UTC (permalink / raw)

pgxml_xpath() builds an xpath_workspace before returning it to
callers.  If an ERROR is thrown before the function returns, callers
have not received the workspace pointer yet and cannot run
cleanup_workspace().

Add local error cleanup for the partially built workspace and the
compiled XPath expression.  Also check xmlXPathNewContext() before
dereferencing the returned context.
---
 contrib/xml2/xpath.c | 51 +++++++++++++++++++++++++++-----------------
 1 file changed, 32 insertions(+), 19 deletions(-)

diff --git a/contrib/xml2/xpath.c b/contrib/xml2/xpath.c
index 9fe75cb5ff4..283bb51178d 100644
--- a/contrib/xml2/xpath.c
+++ b/contrib/xml2/xpath.c
@@ -497,36 +497,49 @@ static xpath_workspace *
 pgxml_xpath(text *document, xmlChar *xpath, PgXmlErrorContext *xmlerrcxt)
 {
 	int32		docsize = VARSIZE_ANY_EXHDR(document);
-	xmlXPathCompExprPtr comppath;
+	xmlXPathCompExprPtr volatile comppath = NULL;
 	xpath_workspace *workspace = palloc0_object(xpath_workspace);
 
 	workspace->doctree = NULL;
 	workspace->ctxt = NULL;
 	workspace->res = NULL;
 
-	workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
-									   docsize, NULL, NULL,
-									   XML_PARSE_NOENT);
-	if (workspace->doctree != NULL)
+	PG_TRY();
 	{
-		workspace->ctxt = xmlXPathNewContext(workspace->doctree);
-		workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
-
-		/* compile the path */
-		comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
-		if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+		workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
+										   docsize, NULL, NULL,
+										   XML_PARSE_NOENT);
+		if (workspace->doctree != NULL)
 		{
-			if (comppath != NULL)
-				xmlXPathFreeCompExpr(comppath);
-			xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
-						"XPath Syntax Error");
-		}
+			workspace->ctxt = xmlXPathNewContext(workspace->doctree);
+			if (workspace->ctxt == NULL)
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_OUT_OF_MEMORY,
+							"could not allocate XPath context");
 
-		/* Now evaluate the path expression. */
-		workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+			workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
+
+			/* compile the path */
+			comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
+			if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
+							"XPath Syntax Error");
+
+			/* Now evaluate the path expression. */
+			workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+
+			xmlXPathFreeCompExpr(comppath);
+			comppath = NULL;
+		}
+	}
+	PG_CATCH();
+	{
+		if (comppath != NULL)
+			xmlXPathFreeCompExpr(comppath);
+		cleanup_workspace(workspace);
 
-		xmlXPathFreeCompExpr(comppath);
+		PG_RE_THROW();
 	}
+	PG_END_TRY();
 
 	return workspace;
 }
-- 
2.54.0


--MP_/LMSk9=uMhuQ1QiIJDarDO8G--





^ permalink  raw  reply  [nested|flat] 611+ messages in thread

* [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths
@ 2026-06-01 22:41 Andrey Chernyy <andrey.cherny@tantorlabs.com>
  0 siblings, 0 replies; 611+ messages in thread

From: Andrey Chernyy @ 2026-06-01 22:41 UTC (permalink / raw)

pgxml_xpath() builds an xpath_workspace before returning it to
callers.  If an ERROR is thrown before the function returns, callers
have not received the workspace pointer yet and cannot run
cleanup_workspace().

Add local error cleanup for the partially built workspace and the
compiled XPath expression.  Also check xmlXPathNewContext() before
dereferencing the returned context.
---
 contrib/xml2/xpath.c | 51 +++++++++++++++++++++++++++-----------------
 1 file changed, 32 insertions(+), 19 deletions(-)

diff --git a/contrib/xml2/xpath.c b/contrib/xml2/xpath.c
index 9fe75cb5ff4..283bb51178d 100644
--- a/contrib/xml2/xpath.c
+++ b/contrib/xml2/xpath.c
@@ -497,36 +497,49 @@ static xpath_workspace *
 pgxml_xpath(text *document, xmlChar *xpath, PgXmlErrorContext *xmlerrcxt)
 {
 	int32		docsize = VARSIZE_ANY_EXHDR(document);
-	xmlXPathCompExprPtr comppath;
+	xmlXPathCompExprPtr volatile comppath = NULL;
 	xpath_workspace *workspace = palloc0_object(xpath_workspace);
 
 	workspace->doctree = NULL;
 	workspace->ctxt = NULL;
 	workspace->res = NULL;
 
-	workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
-									   docsize, NULL, NULL,
-									   XML_PARSE_NOENT);
-	if (workspace->doctree != NULL)
+	PG_TRY();
 	{
-		workspace->ctxt = xmlXPathNewContext(workspace->doctree);
-		workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
-
-		/* compile the path */
-		comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
-		if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+		workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
+										   docsize, NULL, NULL,
+										   XML_PARSE_NOENT);
+		if (workspace->doctree != NULL)
 		{
-			if (comppath != NULL)
-				xmlXPathFreeCompExpr(comppath);
-			xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
-						"XPath Syntax Error");
-		}
+			workspace->ctxt = xmlXPathNewContext(workspace->doctree);
+			if (workspace->ctxt == NULL)
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_OUT_OF_MEMORY,
+							"could not allocate XPath context");
 
-		/* Now evaluate the path expression. */
-		workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+			workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
+
+			/* compile the path */
+			comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
+			if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
+							"XPath Syntax Error");
+
+			/* Now evaluate the path expression. */
+			workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+
+			xmlXPathFreeCompExpr(comppath);
+			comppath = NULL;
+		}
+	}
+	PG_CATCH();
+	{
+		if (comppath != NULL)
+			xmlXPathFreeCompExpr(comppath);
+		cleanup_workspace(workspace);
 
-		xmlXPathFreeCompExpr(comppath);
+		PG_RE_THROW();
 	}
+	PG_END_TRY();
 
 	return workspace;
 }
-- 
2.54.0


--MP_/LMSk9=uMhuQ1QiIJDarDO8G--





^ permalink  raw  reply  [nested|flat] 611+ messages in thread

* [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths
@ 2026-06-01 22:41 Andrey Chernyy <andrey.cherny@tantorlabs.com>
  0 siblings, 0 replies; 611+ messages in thread

From: Andrey Chernyy @ 2026-06-01 22:41 UTC (permalink / raw)

pgxml_xpath() builds an xpath_workspace before returning it to
callers.  If an ERROR is thrown before the function returns, callers
have not received the workspace pointer yet and cannot run
cleanup_workspace().

Add local error cleanup for the partially built workspace and the
compiled XPath expression.  Also check xmlXPathNewContext() before
dereferencing the returned context.
---
 contrib/xml2/xpath.c | 51 +++++++++++++++++++++++++++-----------------
 1 file changed, 32 insertions(+), 19 deletions(-)

diff --git a/contrib/xml2/xpath.c b/contrib/xml2/xpath.c
index 9fe75cb5ff4..283bb51178d 100644
--- a/contrib/xml2/xpath.c
+++ b/contrib/xml2/xpath.c
@@ -497,36 +497,49 @@ static xpath_workspace *
 pgxml_xpath(text *document, xmlChar *xpath, PgXmlErrorContext *xmlerrcxt)
 {
 	int32		docsize = VARSIZE_ANY_EXHDR(document);
-	xmlXPathCompExprPtr comppath;
+	xmlXPathCompExprPtr volatile comppath = NULL;
 	xpath_workspace *workspace = palloc0_object(xpath_workspace);
 
 	workspace->doctree = NULL;
 	workspace->ctxt = NULL;
 	workspace->res = NULL;
 
-	workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
-									   docsize, NULL, NULL,
-									   XML_PARSE_NOENT);
-	if (workspace->doctree != NULL)
+	PG_TRY();
 	{
-		workspace->ctxt = xmlXPathNewContext(workspace->doctree);
-		workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
-
-		/* compile the path */
-		comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
-		if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+		workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
+										   docsize, NULL, NULL,
+										   XML_PARSE_NOENT);
+		if (workspace->doctree != NULL)
 		{
-			if (comppath != NULL)
-				xmlXPathFreeCompExpr(comppath);
-			xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
-						"XPath Syntax Error");
-		}
+			workspace->ctxt = xmlXPathNewContext(workspace->doctree);
+			if (workspace->ctxt == NULL)
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_OUT_OF_MEMORY,
+							"could not allocate XPath context");
 
-		/* Now evaluate the path expression. */
-		workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+			workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
+
+			/* compile the path */
+			comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
+			if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
+							"XPath Syntax Error");
+
+			/* Now evaluate the path expression. */
+			workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+
+			xmlXPathFreeCompExpr(comppath);
+			comppath = NULL;
+		}
+	}
+	PG_CATCH();
+	{
+		if (comppath != NULL)
+			xmlXPathFreeCompExpr(comppath);
+		cleanup_workspace(workspace);
 
-		xmlXPathFreeCompExpr(comppath);
+		PG_RE_THROW();
 	}
+	PG_END_TRY();
 
 	return workspace;
 }
-- 
2.54.0


--MP_/LMSk9=uMhuQ1QiIJDarDO8G--





^ permalink  raw  reply  [nested|flat] 611+ messages in thread

* [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths
@ 2026-06-01 22:41 Andrey Chernyy <andrey.cherny@tantorlabs.com>
  0 siblings, 0 replies; 611+ messages in thread

From: Andrey Chernyy @ 2026-06-01 22:41 UTC (permalink / raw)

pgxml_xpath() builds an xpath_workspace before returning it to
callers.  If an ERROR is thrown before the function returns, callers
have not received the workspace pointer yet and cannot run
cleanup_workspace().

Add local error cleanup for the partially built workspace and the
compiled XPath expression.  Also check xmlXPathNewContext() before
dereferencing the returned context.
---
 contrib/xml2/xpath.c | 51 +++++++++++++++++++++++++++-----------------
 1 file changed, 32 insertions(+), 19 deletions(-)

diff --git a/contrib/xml2/xpath.c b/contrib/xml2/xpath.c
index 9fe75cb5ff4..283bb51178d 100644
--- a/contrib/xml2/xpath.c
+++ b/contrib/xml2/xpath.c
@@ -497,36 +497,49 @@ static xpath_workspace *
 pgxml_xpath(text *document, xmlChar *xpath, PgXmlErrorContext *xmlerrcxt)
 {
 	int32		docsize = VARSIZE_ANY_EXHDR(document);
-	xmlXPathCompExprPtr comppath;
+	xmlXPathCompExprPtr volatile comppath = NULL;
 	xpath_workspace *workspace = palloc0_object(xpath_workspace);
 
 	workspace->doctree = NULL;
 	workspace->ctxt = NULL;
 	workspace->res = NULL;
 
-	workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
-									   docsize, NULL, NULL,
-									   XML_PARSE_NOENT);
-	if (workspace->doctree != NULL)
+	PG_TRY();
 	{
-		workspace->ctxt = xmlXPathNewContext(workspace->doctree);
-		workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
-
-		/* compile the path */
-		comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
-		if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+		workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
+										   docsize, NULL, NULL,
+										   XML_PARSE_NOENT);
+		if (workspace->doctree != NULL)
 		{
-			if (comppath != NULL)
-				xmlXPathFreeCompExpr(comppath);
-			xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
-						"XPath Syntax Error");
-		}
+			workspace->ctxt = xmlXPathNewContext(workspace->doctree);
+			if (workspace->ctxt == NULL)
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_OUT_OF_MEMORY,
+							"could not allocate XPath context");
 
-		/* Now evaluate the path expression. */
-		workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+			workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
+
+			/* compile the path */
+			comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
+			if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
+							"XPath Syntax Error");
+
+			/* Now evaluate the path expression. */
+			workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+
+			xmlXPathFreeCompExpr(comppath);
+			comppath = NULL;
+		}
+	}
+	PG_CATCH();
+	{
+		if (comppath != NULL)
+			xmlXPathFreeCompExpr(comppath);
+		cleanup_workspace(workspace);
 
-		xmlXPathFreeCompExpr(comppath);
+		PG_RE_THROW();
 	}
+	PG_END_TRY();
 
 	return workspace;
 }
-- 
2.54.0


--MP_/LMSk9=uMhuQ1QiIJDarDO8G--





^ permalink  raw  reply  [nested|flat] 611+ messages in thread

* [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths
@ 2026-06-01 22:41 Andrey Chernyy <andrey.cherny@tantorlabs.com>
  0 siblings, 0 replies; 611+ messages in thread

From: Andrey Chernyy @ 2026-06-01 22:41 UTC (permalink / raw)

pgxml_xpath() builds an xpath_workspace before returning it to
callers.  If an ERROR is thrown before the function returns, callers
have not received the workspace pointer yet and cannot run
cleanup_workspace().

Add local error cleanup for the partially built workspace and the
compiled XPath expression.  Also check xmlXPathNewContext() before
dereferencing the returned context.
---
 contrib/xml2/xpath.c | 51 +++++++++++++++++++++++++++-----------------
 1 file changed, 32 insertions(+), 19 deletions(-)

diff --git a/contrib/xml2/xpath.c b/contrib/xml2/xpath.c
index 9fe75cb5ff4..283bb51178d 100644
--- a/contrib/xml2/xpath.c
+++ b/contrib/xml2/xpath.c
@@ -497,36 +497,49 @@ static xpath_workspace *
 pgxml_xpath(text *document, xmlChar *xpath, PgXmlErrorContext *xmlerrcxt)
 {
 	int32		docsize = VARSIZE_ANY_EXHDR(document);
-	xmlXPathCompExprPtr comppath;
+	xmlXPathCompExprPtr volatile comppath = NULL;
 	xpath_workspace *workspace = palloc0_object(xpath_workspace);
 
 	workspace->doctree = NULL;
 	workspace->ctxt = NULL;
 	workspace->res = NULL;
 
-	workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
-									   docsize, NULL, NULL,
-									   XML_PARSE_NOENT);
-	if (workspace->doctree != NULL)
+	PG_TRY();
 	{
-		workspace->ctxt = xmlXPathNewContext(workspace->doctree);
-		workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
-
-		/* compile the path */
-		comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
-		if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+		workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
+										   docsize, NULL, NULL,
+										   XML_PARSE_NOENT);
+		if (workspace->doctree != NULL)
 		{
-			if (comppath != NULL)
-				xmlXPathFreeCompExpr(comppath);
-			xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
-						"XPath Syntax Error");
-		}
+			workspace->ctxt = xmlXPathNewContext(workspace->doctree);
+			if (workspace->ctxt == NULL)
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_OUT_OF_MEMORY,
+							"could not allocate XPath context");
 
-		/* Now evaluate the path expression. */
-		workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+			workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
+
+			/* compile the path */
+			comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
+			if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
+							"XPath Syntax Error");
+
+			/* Now evaluate the path expression. */
+			workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+
+			xmlXPathFreeCompExpr(comppath);
+			comppath = NULL;
+		}
+	}
+	PG_CATCH();
+	{
+		if (comppath != NULL)
+			xmlXPathFreeCompExpr(comppath);
+		cleanup_workspace(workspace);
 
-		xmlXPathFreeCompExpr(comppath);
+		PG_RE_THROW();
 	}
+	PG_END_TRY();
 
 	return workspace;
 }
-- 
2.54.0


--MP_/LMSk9=uMhuQ1QiIJDarDO8G--





^ permalink  raw  reply  [nested|flat] 611+ messages in thread

* [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths
@ 2026-06-01 22:41 Andrey Chernyy <andrey.cherny@tantorlabs.com>
  0 siblings, 0 replies; 611+ messages in thread

From: Andrey Chernyy @ 2026-06-01 22:41 UTC (permalink / raw)

pgxml_xpath() builds an xpath_workspace before returning it to
callers.  If an ERROR is thrown before the function returns, callers
have not received the workspace pointer yet and cannot run
cleanup_workspace().

Add local error cleanup for the partially built workspace and the
compiled XPath expression.  Also check xmlXPathNewContext() before
dereferencing the returned context.
---
 contrib/xml2/xpath.c | 51 +++++++++++++++++++++++++++-----------------
 1 file changed, 32 insertions(+), 19 deletions(-)

diff --git a/contrib/xml2/xpath.c b/contrib/xml2/xpath.c
index 9fe75cb5ff4..283bb51178d 100644
--- a/contrib/xml2/xpath.c
+++ b/contrib/xml2/xpath.c
@@ -497,36 +497,49 @@ static xpath_workspace *
 pgxml_xpath(text *document, xmlChar *xpath, PgXmlErrorContext *xmlerrcxt)
 {
 	int32		docsize = VARSIZE_ANY_EXHDR(document);
-	xmlXPathCompExprPtr comppath;
+	xmlXPathCompExprPtr volatile comppath = NULL;
 	xpath_workspace *workspace = palloc0_object(xpath_workspace);
 
 	workspace->doctree = NULL;
 	workspace->ctxt = NULL;
 	workspace->res = NULL;
 
-	workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
-									   docsize, NULL, NULL,
-									   XML_PARSE_NOENT);
-	if (workspace->doctree != NULL)
+	PG_TRY();
 	{
-		workspace->ctxt = xmlXPathNewContext(workspace->doctree);
-		workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
-
-		/* compile the path */
-		comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
-		if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+		workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
+										   docsize, NULL, NULL,
+										   XML_PARSE_NOENT);
+		if (workspace->doctree != NULL)
 		{
-			if (comppath != NULL)
-				xmlXPathFreeCompExpr(comppath);
-			xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
-						"XPath Syntax Error");
-		}
+			workspace->ctxt = xmlXPathNewContext(workspace->doctree);
+			if (workspace->ctxt == NULL)
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_OUT_OF_MEMORY,
+							"could not allocate XPath context");
 
-		/* Now evaluate the path expression. */
-		workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+			workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
+
+			/* compile the path */
+			comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
+			if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
+							"XPath Syntax Error");
+
+			/* Now evaluate the path expression. */
+			workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+
+			xmlXPathFreeCompExpr(comppath);
+			comppath = NULL;
+		}
+	}
+	PG_CATCH();
+	{
+		if (comppath != NULL)
+			xmlXPathFreeCompExpr(comppath);
+		cleanup_workspace(workspace);
 
-		xmlXPathFreeCompExpr(comppath);
+		PG_RE_THROW();
 	}
+	PG_END_TRY();
 
 	return workspace;
 }
-- 
2.54.0


--MP_/LMSk9=uMhuQ1QiIJDarDO8G--






^ permalink  raw  reply  [nested|flat] 611+ messages in thread

* [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths
@ 2026-06-01 22:41 Andrey Chernyy <andrey.cherny@tantorlabs.com>
  0 siblings, 0 replies; 611+ messages in thread

From: Andrey Chernyy @ 2026-06-01 22:41 UTC (permalink / raw)

pgxml_xpath() builds an xpath_workspace before returning it to
callers.  If an ERROR is thrown before the function returns, callers
have not received the workspace pointer yet and cannot run
cleanup_workspace().

Add local error cleanup for the partially built workspace and the
compiled XPath expression.  Also check xmlXPathNewContext() before
dereferencing the returned context.
---
 contrib/xml2/xpath.c | 51 +++++++++++++++++++++++++++-----------------
 1 file changed, 32 insertions(+), 19 deletions(-)

diff --git a/contrib/xml2/xpath.c b/contrib/xml2/xpath.c
index 9fe75cb5ff4..283bb51178d 100644
--- a/contrib/xml2/xpath.c
+++ b/contrib/xml2/xpath.c
@@ -497,36 +497,49 @@ static xpath_workspace *
 pgxml_xpath(text *document, xmlChar *xpath, PgXmlErrorContext *xmlerrcxt)
 {
 	int32		docsize = VARSIZE_ANY_EXHDR(document);
-	xmlXPathCompExprPtr comppath;
+	xmlXPathCompExprPtr volatile comppath = NULL;
 	xpath_workspace *workspace = palloc0_object(xpath_workspace);
 
 	workspace->doctree = NULL;
 	workspace->ctxt = NULL;
 	workspace->res = NULL;
 
-	workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
-									   docsize, NULL, NULL,
-									   XML_PARSE_NOENT);
-	if (workspace->doctree != NULL)
+	PG_TRY();
 	{
-		workspace->ctxt = xmlXPathNewContext(workspace->doctree);
-		workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
-
-		/* compile the path */
-		comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
-		if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+		workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
+										   docsize, NULL, NULL,
+										   XML_PARSE_NOENT);
+		if (workspace->doctree != NULL)
 		{
-			if (comppath != NULL)
-				xmlXPathFreeCompExpr(comppath);
-			xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
-						"XPath Syntax Error");
-		}
+			workspace->ctxt = xmlXPathNewContext(workspace->doctree);
+			if (workspace->ctxt == NULL)
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_OUT_OF_MEMORY,
+							"could not allocate XPath context");
 
-		/* Now evaluate the path expression. */
-		workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+			workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
+
+			/* compile the path */
+			comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
+			if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
+							"XPath Syntax Error");
+
+			/* Now evaluate the path expression. */
+			workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+
+			xmlXPathFreeCompExpr(comppath);
+			comppath = NULL;
+		}
+	}
+	PG_CATCH();
+	{
+		if (comppath != NULL)
+			xmlXPathFreeCompExpr(comppath);
+		cleanup_workspace(workspace);
 
-		xmlXPathFreeCompExpr(comppath);
+		PG_RE_THROW();
 	}
+	PG_END_TRY();
 
 	return workspace;
 }
-- 
2.54.0


--MP_/LMSk9=uMhuQ1QiIJDarDO8G--






^ permalink  raw  reply  [nested|flat] 611+ messages in thread

* [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths
@ 2026-06-01 22:41 Andrey Chernyy <andrey.cherny@tantorlabs.com>
  0 siblings, 0 replies; 611+ messages in thread

From: Andrey Chernyy @ 2026-06-01 22:41 UTC (permalink / raw)

pgxml_xpath() builds an xpath_workspace before returning it to
callers.  If an ERROR is thrown before the function returns, callers
have not received the workspace pointer yet and cannot run
cleanup_workspace().

Add local error cleanup for the partially built workspace and the
compiled XPath expression.  Also check xmlXPathNewContext() before
dereferencing the returned context.
---
 contrib/xml2/xpath.c | 51 +++++++++++++++++++++++++++-----------------
 1 file changed, 32 insertions(+), 19 deletions(-)

diff --git a/contrib/xml2/xpath.c b/contrib/xml2/xpath.c
index 9fe75cb5ff4..283bb51178d 100644
--- a/contrib/xml2/xpath.c
+++ b/contrib/xml2/xpath.c
@@ -497,36 +497,49 @@ static xpath_workspace *
 pgxml_xpath(text *document, xmlChar *xpath, PgXmlErrorContext *xmlerrcxt)
 {
 	int32		docsize = VARSIZE_ANY_EXHDR(document);
-	xmlXPathCompExprPtr comppath;
+	xmlXPathCompExprPtr volatile comppath = NULL;
 	xpath_workspace *workspace = palloc0_object(xpath_workspace);
 
 	workspace->doctree = NULL;
 	workspace->ctxt = NULL;
 	workspace->res = NULL;
 
-	workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
-									   docsize, NULL, NULL,
-									   XML_PARSE_NOENT);
-	if (workspace->doctree != NULL)
+	PG_TRY();
 	{
-		workspace->ctxt = xmlXPathNewContext(workspace->doctree);
-		workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
-
-		/* compile the path */
-		comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
-		if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+		workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
+										   docsize, NULL, NULL,
+										   XML_PARSE_NOENT);
+		if (workspace->doctree != NULL)
 		{
-			if (comppath != NULL)
-				xmlXPathFreeCompExpr(comppath);
-			xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
-						"XPath Syntax Error");
-		}
+			workspace->ctxt = xmlXPathNewContext(workspace->doctree);
+			if (workspace->ctxt == NULL)
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_OUT_OF_MEMORY,
+							"could not allocate XPath context");
 
-		/* Now evaluate the path expression. */
-		workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+			workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
+
+			/* compile the path */
+			comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
+			if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
+							"XPath Syntax Error");
+
+			/* Now evaluate the path expression. */
+			workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+
+			xmlXPathFreeCompExpr(comppath);
+			comppath = NULL;
+		}
+	}
+	PG_CATCH();
+	{
+		if (comppath != NULL)
+			xmlXPathFreeCompExpr(comppath);
+		cleanup_workspace(workspace);
 
-		xmlXPathFreeCompExpr(comppath);
+		PG_RE_THROW();
 	}
+	PG_END_TRY();
 
 	return workspace;
 }
-- 
2.54.0


--MP_/LMSk9=uMhuQ1QiIJDarDO8G--





^ permalink  raw  reply  [nested|flat] 611+ messages in thread

* [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths
@ 2026-06-01 22:41 Andrey Chernyy <andrey.cherny@tantorlabs.com>
  0 siblings, 0 replies; 611+ messages in thread

From: Andrey Chernyy @ 2026-06-01 22:41 UTC (permalink / raw)

pgxml_xpath() builds an xpath_workspace before returning it to
callers.  If an ERROR is thrown before the function returns, callers
have not received the workspace pointer yet and cannot run
cleanup_workspace().

Add local error cleanup for the partially built workspace and the
compiled XPath expression.  Also check xmlXPathNewContext() before
dereferencing the returned context.
---
 contrib/xml2/xpath.c | 51 +++++++++++++++++++++++++++-----------------
 1 file changed, 32 insertions(+), 19 deletions(-)

diff --git a/contrib/xml2/xpath.c b/contrib/xml2/xpath.c
index 9fe75cb5ff4..283bb51178d 100644
--- a/contrib/xml2/xpath.c
+++ b/contrib/xml2/xpath.c
@@ -497,36 +497,49 @@ static xpath_workspace *
 pgxml_xpath(text *document, xmlChar *xpath, PgXmlErrorContext *xmlerrcxt)
 {
 	int32		docsize = VARSIZE_ANY_EXHDR(document);
-	xmlXPathCompExprPtr comppath;
+	xmlXPathCompExprPtr volatile comppath = NULL;
 	xpath_workspace *workspace = palloc0_object(xpath_workspace);
 
 	workspace->doctree = NULL;
 	workspace->ctxt = NULL;
 	workspace->res = NULL;
 
-	workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
-									   docsize, NULL, NULL,
-									   XML_PARSE_NOENT);
-	if (workspace->doctree != NULL)
+	PG_TRY();
 	{
-		workspace->ctxt = xmlXPathNewContext(workspace->doctree);
-		workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
-
-		/* compile the path */
-		comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
-		if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+		workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
+										   docsize, NULL, NULL,
+										   XML_PARSE_NOENT);
+		if (workspace->doctree != NULL)
 		{
-			if (comppath != NULL)
-				xmlXPathFreeCompExpr(comppath);
-			xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
-						"XPath Syntax Error");
-		}
+			workspace->ctxt = xmlXPathNewContext(workspace->doctree);
+			if (workspace->ctxt == NULL)
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_OUT_OF_MEMORY,
+							"could not allocate XPath context");
 
-		/* Now evaluate the path expression. */
-		workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+			workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
+
+			/* compile the path */
+			comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
+			if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
+							"XPath Syntax Error");
+
+			/* Now evaluate the path expression. */
+			workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+
+			xmlXPathFreeCompExpr(comppath);
+			comppath = NULL;
+		}
+	}
+	PG_CATCH();
+	{
+		if (comppath != NULL)
+			xmlXPathFreeCompExpr(comppath);
+		cleanup_workspace(workspace);
 
-		xmlXPathFreeCompExpr(comppath);
+		PG_RE_THROW();
 	}
+	PG_END_TRY();
 
 	return workspace;
 }
-- 
2.54.0


--MP_/LMSk9=uMhuQ1QiIJDarDO8G--





^ permalink  raw  reply  [nested|flat] 611+ messages in thread

* [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths
@ 2026-06-01 22:41 Andrey Chernyy <andrey.cherny@tantorlabs.com>
  0 siblings, 0 replies; 611+ messages in thread

From: Andrey Chernyy @ 2026-06-01 22:41 UTC (permalink / raw)

pgxml_xpath() builds an xpath_workspace before returning it to
callers.  If an ERROR is thrown before the function returns, callers
have not received the workspace pointer yet and cannot run
cleanup_workspace().

Add local error cleanup for the partially built workspace and the
compiled XPath expression.  Also check xmlXPathNewContext() before
dereferencing the returned context.
---
 contrib/xml2/xpath.c | 51 +++++++++++++++++++++++++++-----------------
 1 file changed, 32 insertions(+), 19 deletions(-)

diff --git a/contrib/xml2/xpath.c b/contrib/xml2/xpath.c
index 9fe75cb5ff4..283bb51178d 100644
--- a/contrib/xml2/xpath.c
+++ b/contrib/xml2/xpath.c
@@ -497,36 +497,49 @@ static xpath_workspace *
 pgxml_xpath(text *document, xmlChar *xpath, PgXmlErrorContext *xmlerrcxt)
 {
 	int32		docsize = VARSIZE_ANY_EXHDR(document);
-	xmlXPathCompExprPtr comppath;
+	xmlXPathCompExprPtr volatile comppath = NULL;
 	xpath_workspace *workspace = palloc0_object(xpath_workspace);
 
 	workspace->doctree = NULL;
 	workspace->ctxt = NULL;
 	workspace->res = NULL;
 
-	workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
-									   docsize, NULL, NULL,
-									   XML_PARSE_NOENT);
-	if (workspace->doctree != NULL)
+	PG_TRY();
 	{
-		workspace->ctxt = xmlXPathNewContext(workspace->doctree);
-		workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
-
-		/* compile the path */
-		comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
-		if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+		workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
+										   docsize, NULL, NULL,
+										   XML_PARSE_NOENT);
+		if (workspace->doctree != NULL)
 		{
-			if (comppath != NULL)
-				xmlXPathFreeCompExpr(comppath);
-			xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
-						"XPath Syntax Error");
-		}
+			workspace->ctxt = xmlXPathNewContext(workspace->doctree);
+			if (workspace->ctxt == NULL)
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_OUT_OF_MEMORY,
+							"could not allocate XPath context");
 
-		/* Now evaluate the path expression. */
-		workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+			workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
+
+			/* compile the path */
+			comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
+			if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
+							"XPath Syntax Error");
+
+			/* Now evaluate the path expression. */
+			workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+
+			xmlXPathFreeCompExpr(comppath);
+			comppath = NULL;
+		}
+	}
+	PG_CATCH();
+	{
+		if (comppath != NULL)
+			xmlXPathFreeCompExpr(comppath);
+		cleanup_workspace(workspace);
 
-		xmlXPathFreeCompExpr(comppath);
+		PG_RE_THROW();
 	}
+	PG_END_TRY();
 
 	return workspace;
 }
-- 
2.54.0


--MP_/LMSk9=uMhuQ1QiIJDarDO8G--





^ permalink  raw  reply  [nested|flat] 611+ messages in thread

* [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths
@ 2026-06-01 22:41 Andrey Chernyy <andrey.cherny@tantorlabs.com>
  0 siblings, 0 replies; 611+ messages in thread

From: Andrey Chernyy @ 2026-06-01 22:41 UTC (permalink / raw)

pgxml_xpath() builds an xpath_workspace before returning it to
callers.  If an ERROR is thrown before the function returns, callers
have not received the workspace pointer yet and cannot run
cleanup_workspace().

Add local error cleanup for the partially built workspace and the
compiled XPath expression.  Also check xmlXPathNewContext() before
dereferencing the returned context.
---
 contrib/xml2/xpath.c | 51 +++++++++++++++++++++++++++-----------------
 1 file changed, 32 insertions(+), 19 deletions(-)

diff --git a/contrib/xml2/xpath.c b/contrib/xml2/xpath.c
index 9fe75cb5ff4..283bb51178d 100644
--- a/contrib/xml2/xpath.c
+++ b/contrib/xml2/xpath.c
@@ -497,36 +497,49 @@ static xpath_workspace *
 pgxml_xpath(text *document, xmlChar *xpath, PgXmlErrorContext *xmlerrcxt)
 {
 	int32		docsize = VARSIZE_ANY_EXHDR(document);
-	xmlXPathCompExprPtr comppath;
+	xmlXPathCompExprPtr volatile comppath = NULL;
 	xpath_workspace *workspace = palloc0_object(xpath_workspace);
 
 	workspace->doctree = NULL;
 	workspace->ctxt = NULL;
 	workspace->res = NULL;
 
-	workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
-									   docsize, NULL, NULL,
-									   XML_PARSE_NOENT);
-	if (workspace->doctree != NULL)
+	PG_TRY();
 	{
-		workspace->ctxt = xmlXPathNewContext(workspace->doctree);
-		workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
-
-		/* compile the path */
-		comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
-		if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+		workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
+										   docsize, NULL, NULL,
+										   XML_PARSE_NOENT);
+		if (workspace->doctree != NULL)
 		{
-			if (comppath != NULL)
-				xmlXPathFreeCompExpr(comppath);
-			xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
-						"XPath Syntax Error");
-		}
+			workspace->ctxt = xmlXPathNewContext(workspace->doctree);
+			if (workspace->ctxt == NULL)
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_OUT_OF_MEMORY,
+							"could not allocate XPath context");
 
-		/* Now evaluate the path expression. */
-		workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+			workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
+
+			/* compile the path */
+			comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
+			if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
+							"XPath Syntax Error");
+
+			/* Now evaluate the path expression. */
+			workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+
+			xmlXPathFreeCompExpr(comppath);
+			comppath = NULL;
+		}
+	}
+	PG_CATCH();
+	{
+		if (comppath != NULL)
+			xmlXPathFreeCompExpr(comppath);
+		cleanup_workspace(workspace);
 
-		xmlXPathFreeCompExpr(comppath);
+		PG_RE_THROW();
 	}
+	PG_END_TRY();
 
 	return workspace;
 }
-- 
2.54.0


--MP_/LMSk9=uMhuQ1QiIJDarDO8G--






^ permalink  raw  reply  [nested|flat] 611+ messages in thread

* [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths
@ 2026-06-01 22:41 Andrey Chernyy <andrey.cherny@tantorlabs.com>
  0 siblings, 0 replies; 611+ messages in thread

From: Andrey Chernyy @ 2026-06-01 22:41 UTC (permalink / raw)

pgxml_xpath() builds an xpath_workspace before returning it to
callers.  If an ERROR is thrown before the function returns, callers
have not received the workspace pointer yet and cannot run
cleanup_workspace().

Add local error cleanup for the partially built workspace and the
compiled XPath expression.  Also check xmlXPathNewContext() before
dereferencing the returned context.
---
 contrib/xml2/xpath.c | 51 +++++++++++++++++++++++++++-----------------
 1 file changed, 32 insertions(+), 19 deletions(-)

diff --git a/contrib/xml2/xpath.c b/contrib/xml2/xpath.c
index 9fe75cb5ff4..283bb51178d 100644
--- a/contrib/xml2/xpath.c
+++ b/contrib/xml2/xpath.c
@@ -497,36 +497,49 @@ static xpath_workspace *
 pgxml_xpath(text *document, xmlChar *xpath, PgXmlErrorContext *xmlerrcxt)
 {
 	int32		docsize = VARSIZE_ANY_EXHDR(document);
-	xmlXPathCompExprPtr comppath;
+	xmlXPathCompExprPtr volatile comppath = NULL;
 	xpath_workspace *workspace = palloc0_object(xpath_workspace);
 
 	workspace->doctree = NULL;
 	workspace->ctxt = NULL;
 	workspace->res = NULL;
 
-	workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
-									   docsize, NULL, NULL,
-									   XML_PARSE_NOENT);
-	if (workspace->doctree != NULL)
+	PG_TRY();
 	{
-		workspace->ctxt = xmlXPathNewContext(workspace->doctree);
-		workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
-
-		/* compile the path */
-		comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
-		if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+		workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
+										   docsize, NULL, NULL,
+										   XML_PARSE_NOENT);
+		if (workspace->doctree != NULL)
 		{
-			if (comppath != NULL)
-				xmlXPathFreeCompExpr(comppath);
-			xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
-						"XPath Syntax Error");
-		}
+			workspace->ctxt = xmlXPathNewContext(workspace->doctree);
+			if (workspace->ctxt == NULL)
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_OUT_OF_MEMORY,
+							"could not allocate XPath context");
 
-		/* Now evaluate the path expression. */
-		workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+			workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
+
+			/* compile the path */
+			comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
+			if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
+							"XPath Syntax Error");
+
+			/* Now evaluate the path expression. */
+			workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+
+			xmlXPathFreeCompExpr(comppath);
+			comppath = NULL;
+		}
+	}
+	PG_CATCH();
+	{
+		if (comppath != NULL)
+			xmlXPathFreeCompExpr(comppath);
+		cleanup_workspace(workspace);
 
-		xmlXPathFreeCompExpr(comppath);
+		PG_RE_THROW();
 	}
+	PG_END_TRY();
 
 	return workspace;
 }
-- 
2.54.0


--MP_/LMSk9=uMhuQ1QiIJDarDO8G--






^ permalink  raw  reply  [nested|flat] 611+ messages in thread

* [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths
@ 2026-06-01 22:41 Andrey Chernyy <andrey.cherny@tantorlabs.com>
  0 siblings, 0 replies; 611+ messages in thread

From: Andrey Chernyy @ 2026-06-01 22:41 UTC (permalink / raw)

pgxml_xpath() builds an xpath_workspace before returning it to
callers.  If an ERROR is thrown before the function returns, callers
have not received the workspace pointer yet and cannot run
cleanup_workspace().

Add local error cleanup for the partially built workspace and the
compiled XPath expression.  Also check xmlXPathNewContext() before
dereferencing the returned context.
---
 contrib/xml2/xpath.c | 51 +++++++++++++++++++++++++++-----------------
 1 file changed, 32 insertions(+), 19 deletions(-)

diff --git a/contrib/xml2/xpath.c b/contrib/xml2/xpath.c
index 9fe75cb5ff4..283bb51178d 100644
--- a/contrib/xml2/xpath.c
+++ b/contrib/xml2/xpath.c
@@ -497,36 +497,49 @@ static xpath_workspace *
 pgxml_xpath(text *document, xmlChar *xpath, PgXmlErrorContext *xmlerrcxt)
 {
 	int32		docsize = VARSIZE_ANY_EXHDR(document);
-	xmlXPathCompExprPtr comppath;
+	xmlXPathCompExprPtr volatile comppath = NULL;
 	xpath_workspace *workspace = palloc0_object(xpath_workspace);
 
 	workspace->doctree = NULL;
 	workspace->ctxt = NULL;
 	workspace->res = NULL;
 
-	workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
-									   docsize, NULL, NULL,
-									   XML_PARSE_NOENT);
-	if (workspace->doctree != NULL)
+	PG_TRY();
 	{
-		workspace->ctxt = xmlXPathNewContext(workspace->doctree);
-		workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
-
-		/* compile the path */
-		comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
-		if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+		workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
+										   docsize, NULL, NULL,
+										   XML_PARSE_NOENT);
+		if (workspace->doctree != NULL)
 		{
-			if (comppath != NULL)
-				xmlXPathFreeCompExpr(comppath);
-			xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
-						"XPath Syntax Error");
-		}
+			workspace->ctxt = xmlXPathNewContext(workspace->doctree);
+			if (workspace->ctxt == NULL)
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_OUT_OF_MEMORY,
+							"could not allocate XPath context");
 
-		/* Now evaluate the path expression. */
-		workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+			workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
+
+			/* compile the path */
+			comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
+			if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
+							"XPath Syntax Error");
+
+			/* Now evaluate the path expression. */
+			workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+
+			xmlXPathFreeCompExpr(comppath);
+			comppath = NULL;
+		}
+	}
+	PG_CATCH();
+	{
+		if (comppath != NULL)
+			xmlXPathFreeCompExpr(comppath);
+		cleanup_workspace(workspace);
 
-		xmlXPathFreeCompExpr(comppath);
+		PG_RE_THROW();
 	}
+	PG_END_TRY();
 
 	return workspace;
 }
-- 
2.54.0


--MP_/LMSk9=uMhuQ1QiIJDarDO8G--






^ permalink  raw  reply  [nested|flat] 611+ messages in thread

* [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths
@ 2026-06-01 22:41 Andrey Chernyy <andrey.cherny@tantorlabs.com>
  0 siblings, 0 replies; 611+ messages in thread

From: Andrey Chernyy @ 2026-06-01 22:41 UTC (permalink / raw)

pgxml_xpath() builds an xpath_workspace before returning it to
callers.  If an ERROR is thrown before the function returns, callers
have not received the workspace pointer yet and cannot run
cleanup_workspace().

Add local error cleanup for the partially built workspace and the
compiled XPath expression.  Also check xmlXPathNewContext() before
dereferencing the returned context.
---
 contrib/xml2/xpath.c | 51 +++++++++++++++++++++++++++-----------------
 1 file changed, 32 insertions(+), 19 deletions(-)

diff --git a/contrib/xml2/xpath.c b/contrib/xml2/xpath.c
index 9fe75cb5ff4..283bb51178d 100644
--- a/contrib/xml2/xpath.c
+++ b/contrib/xml2/xpath.c
@@ -497,36 +497,49 @@ static xpath_workspace *
 pgxml_xpath(text *document, xmlChar *xpath, PgXmlErrorContext *xmlerrcxt)
 {
 	int32		docsize = VARSIZE_ANY_EXHDR(document);
-	xmlXPathCompExprPtr comppath;
+	xmlXPathCompExprPtr volatile comppath = NULL;
 	xpath_workspace *workspace = palloc0_object(xpath_workspace);
 
 	workspace->doctree = NULL;
 	workspace->ctxt = NULL;
 	workspace->res = NULL;
 
-	workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
-									   docsize, NULL, NULL,
-									   XML_PARSE_NOENT);
-	if (workspace->doctree != NULL)
+	PG_TRY();
 	{
-		workspace->ctxt = xmlXPathNewContext(workspace->doctree);
-		workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
-
-		/* compile the path */
-		comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
-		if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+		workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
+										   docsize, NULL, NULL,
+										   XML_PARSE_NOENT);
+		if (workspace->doctree != NULL)
 		{
-			if (comppath != NULL)
-				xmlXPathFreeCompExpr(comppath);
-			xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
-						"XPath Syntax Error");
-		}
+			workspace->ctxt = xmlXPathNewContext(workspace->doctree);
+			if (workspace->ctxt == NULL)
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_OUT_OF_MEMORY,
+							"could not allocate XPath context");
 
-		/* Now evaluate the path expression. */
-		workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+			workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
+
+			/* compile the path */
+			comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
+			if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
+							"XPath Syntax Error");
+
+			/* Now evaluate the path expression. */
+			workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+
+			xmlXPathFreeCompExpr(comppath);
+			comppath = NULL;
+		}
+	}
+	PG_CATCH();
+	{
+		if (comppath != NULL)
+			xmlXPathFreeCompExpr(comppath);
+		cleanup_workspace(workspace);
 
-		xmlXPathFreeCompExpr(comppath);
+		PG_RE_THROW();
 	}
+	PG_END_TRY();
 
 	return workspace;
 }
-- 
2.54.0


--MP_/LMSk9=uMhuQ1QiIJDarDO8G--






^ permalink  raw  reply  [nested|flat] 611+ messages in thread

* [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths
@ 2026-06-01 22:41 Andrey Chernyy <andrey.cherny@tantorlabs.com>
  0 siblings, 0 replies; 611+ messages in thread

From: Andrey Chernyy @ 2026-06-01 22:41 UTC (permalink / raw)

pgxml_xpath() builds an xpath_workspace before returning it to
callers.  If an ERROR is thrown before the function returns, callers
have not received the workspace pointer yet and cannot run
cleanup_workspace().

Add local error cleanup for the partially built workspace and the
compiled XPath expression.  Also check xmlXPathNewContext() before
dereferencing the returned context.
---
 contrib/xml2/xpath.c | 51 +++++++++++++++++++++++++++-----------------
 1 file changed, 32 insertions(+), 19 deletions(-)

diff --git a/contrib/xml2/xpath.c b/contrib/xml2/xpath.c
index 9fe75cb5ff4..283bb51178d 100644
--- a/contrib/xml2/xpath.c
+++ b/contrib/xml2/xpath.c
@@ -497,36 +497,49 @@ static xpath_workspace *
 pgxml_xpath(text *document, xmlChar *xpath, PgXmlErrorContext *xmlerrcxt)
 {
 	int32		docsize = VARSIZE_ANY_EXHDR(document);
-	xmlXPathCompExprPtr comppath;
+	xmlXPathCompExprPtr volatile comppath = NULL;
 	xpath_workspace *workspace = palloc0_object(xpath_workspace);
 
 	workspace->doctree = NULL;
 	workspace->ctxt = NULL;
 	workspace->res = NULL;
 
-	workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
-									   docsize, NULL, NULL,
-									   XML_PARSE_NOENT);
-	if (workspace->doctree != NULL)
+	PG_TRY();
 	{
-		workspace->ctxt = xmlXPathNewContext(workspace->doctree);
-		workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
-
-		/* compile the path */
-		comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
-		if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+		workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
+										   docsize, NULL, NULL,
+										   XML_PARSE_NOENT);
+		if (workspace->doctree != NULL)
 		{
-			if (comppath != NULL)
-				xmlXPathFreeCompExpr(comppath);
-			xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
-						"XPath Syntax Error");
-		}
+			workspace->ctxt = xmlXPathNewContext(workspace->doctree);
+			if (workspace->ctxt == NULL)
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_OUT_OF_MEMORY,
+							"could not allocate XPath context");
 
-		/* Now evaluate the path expression. */
-		workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+			workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
+
+			/* compile the path */
+			comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
+			if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
+							"XPath Syntax Error");
+
+			/* Now evaluate the path expression. */
+			workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+
+			xmlXPathFreeCompExpr(comppath);
+			comppath = NULL;
+		}
+	}
+	PG_CATCH();
+	{
+		if (comppath != NULL)
+			xmlXPathFreeCompExpr(comppath);
+		cleanup_workspace(workspace);
 
-		xmlXPathFreeCompExpr(comppath);
+		PG_RE_THROW();
 	}
+	PG_END_TRY();
 
 	return workspace;
 }
-- 
2.54.0


--MP_/LMSk9=uMhuQ1QiIJDarDO8G--






^ permalink  raw  reply  [nested|flat] 611+ messages in thread

* [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths
@ 2026-06-01 22:41 Andrey Chernyy <andrey.cherny@tantorlabs.com>
  0 siblings, 0 replies; 611+ messages in thread

From: Andrey Chernyy @ 2026-06-01 22:41 UTC (permalink / raw)

pgxml_xpath() builds an xpath_workspace before returning it to
callers.  If an ERROR is thrown before the function returns, callers
have not received the workspace pointer yet and cannot run
cleanup_workspace().

Add local error cleanup for the partially built workspace and the
compiled XPath expression.  Also check xmlXPathNewContext() before
dereferencing the returned context.
---
 contrib/xml2/xpath.c | 51 +++++++++++++++++++++++++++-----------------
 1 file changed, 32 insertions(+), 19 deletions(-)

diff --git a/contrib/xml2/xpath.c b/contrib/xml2/xpath.c
index 9fe75cb5ff4..283bb51178d 100644
--- a/contrib/xml2/xpath.c
+++ b/contrib/xml2/xpath.c
@@ -497,36 +497,49 @@ static xpath_workspace *
 pgxml_xpath(text *document, xmlChar *xpath, PgXmlErrorContext *xmlerrcxt)
 {
 	int32		docsize = VARSIZE_ANY_EXHDR(document);
-	xmlXPathCompExprPtr comppath;
+	xmlXPathCompExprPtr volatile comppath = NULL;
 	xpath_workspace *workspace = palloc0_object(xpath_workspace);
 
 	workspace->doctree = NULL;
 	workspace->ctxt = NULL;
 	workspace->res = NULL;
 
-	workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
-									   docsize, NULL, NULL,
-									   XML_PARSE_NOENT);
-	if (workspace->doctree != NULL)
+	PG_TRY();
 	{
-		workspace->ctxt = xmlXPathNewContext(workspace->doctree);
-		workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
-
-		/* compile the path */
-		comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
-		if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+		workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
+										   docsize, NULL, NULL,
+										   XML_PARSE_NOENT);
+		if (workspace->doctree != NULL)
 		{
-			if (comppath != NULL)
-				xmlXPathFreeCompExpr(comppath);
-			xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
-						"XPath Syntax Error");
-		}
+			workspace->ctxt = xmlXPathNewContext(workspace->doctree);
+			if (workspace->ctxt == NULL)
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_OUT_OF_MEMORY,
+							"could not allocate XPath context");
 
-		/* Now evaluate the path expression. */
-		workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+			workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
+
+			/* compile the path */
+			comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
+			if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
+							"XPath Syntax Error");
+
+			/* Now evaluate the path expression. */
+			workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+
+			xmlXPathFreeCompExpr(comppath);
+			comppath = NULL;
+		}
+	}
+	PG_CATCH();
+	{
+		if (comppath != NULL)
+			xmlXPathFreeCompExpr(comppath);
+		cleanup_workspace(workspace);
 
-		xmlXPathFreeCompExpr(comppath);
+		PG_RE_THROW();
 	}
+	PG_END_TRY();
 
 	return workspace;
 }
-- 
2.54.0


--MP_/LMSk9=uMhuQ1QiIJDarDO8G--






^ permalink  raw  reply  [nested|flat] 611+ messages in thread

* [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths
@ 2026-06-01 22:41 Andrey Chernyy <andrey.cherny@tantorlabs.com>
  0 siblings, 0 replies; 611+ messages in thread

From: Andrey Chernyy @ 2026-06-01 22:41 UTC (permalink / raw)

pgxml_xpath() builds an xpath_workspace before returning it to
callers.  If an ERROR is thrown before the function returns, callers
have not received the workspace pointer yet and cannot run
cleanup_workspace().

Add local error cleanup for the partially built workspace and the
compiled XPath expression.  Also check xmlXPathNewContext() before
dereferencing the returned context.
---
 contrib/xml2/xpath.c | 51 +++++++++++++++++++++++++++-----------------
 1 file changed, 32 insertions(+), 19 deletions(-)

diff --git a/contrib/xml2/xpath.c b/contrib/xml2/xpath.c
index 9fe75cb5ff4..283bb51178d 100644
--- a/contrib/xml2/xpath.c
+++ b/contrib/xml2/xpath.c
@@ -497,36 +497,49 @@ static xpath_workspace *
 pgxml_xpath(text *document, xmlChar *xpath, PgXmlErrorContext *xmlerrcxt)
 {
 	int32		docsize = VARSIZE_ANY_EXHDR(document);
-	xmlXPathCompExprPtr comppath;
+	xmlXPathCompExprPtr volatile comppath = NULL;
 	xpath_workspace *workspace = palloc0_object(xpath_workspace);
 
 	workspace->doctree = NULL;
 	workspace->ctxt = NULL;
 	workspace->res = NULL;
 
-	workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
-									   docsize, NULL, NULL,
-									   XML_PARSE_NOENT);
-	if (workspace->doctree != NULL)
+	PG_TRY();
 	{
-		workspace->ctxt = xmlXPathNewContext(workspace->doctree);
-		workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
-
-		/* compile the path */
-		comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
-		if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+		workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
+										   docsize, NULL, NULL,
+										   XML_PARSE_NOENT);
+		if (workspace->doctree != NULL)
 		{
-			if (comppath != NULL)
-				xmlXPathFreeCompExpr(comppath);
-			xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
-						"XPath Syntax Error");
-		}
+			workspace->ctxt = xmlXPathNewContext(workspace->doctree);
+			if (workspace->ctxt == NULL)
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_OUT_OF_MEMORY,
+							"could not allocate XPath context");
 
-		/* Now evaluate the path expression. */
-		workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+			workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
+
+			/* compile the path */
+			comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
+			if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
+							"XPath Syntax Error");
+
+			/* Now evaluate the path expression. */
+			workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+
+			xmlXPathFreeCompExpr(comppath);
+			comppath = NULL;
+		}
+	}
+	PG_CATCH();
+	{
+		if (comppath != NULL)
+			xmlXPathFreeCompExpr(comppath);
+		cleanup_workspace(workspace);
 
-		xmlXPathFreeCompExpr(comppath);
+		PG_RE_THROW();
 	}
+	PG_END_TRY();
 
 	return workspace;
 }
-- 
2.54.0


--MP_/LMSk9=uMhuQ1QiIJDarDO8G--





^ permalink  raw  reply  [nested|flat] 611+ messages in thread

* [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths
@ 2026-06-01 22:41 Andrey Chernyy <andrey.cherny@tantorlabs.com>
  0 siblings, 0 replies; 611+ messages in thread

From: Andrey Chernyy @ 2026-06-01 22:41 UTC (permalink / raw)

pgxml_xpath() builds an xpath_workspace before returning it to
callers.  If an ERROR is thrown before the function returns, callers
have not received the workspace pointer yet and cannot run
cleanup_workspace().

Add local error cleanup for the partially built workspace and the
compiled XPath expression.  Also check xmlXPathNewContext() before
dereferencing the returned context.
---
 contrib/xml2/xpath.c | 51 +++++++++++++++++++++++++++-----------------
 1 file changed, 32 insertions(+), 19 deletions(-)

diff --git a/contrib/xml2/xpath.c b/contrib/xml2/xpath.c
index 9fe75cb5ff4..283bb51178d 100644
--- a/contrib/xml2/xpath.c
+++ b/contrib/xml2/xpath.c
@@ -497,36 +497,49 @@ static xpath_workspace *
 pgxml_xpath(text *document, xmlChar *xpath, PgXmlErrorContext *xmlerrcxt)
 {
 	int32		docsize = VARSIZE_ANY_EXHDR(document);
-	xmlXPathCompExprPtr comppath;
+	xmlXPathCompExprPtr volatile comppath = NULL;
 	xpath_workspace *workspace = palloc0_object(xpath_workspace);
 
 	workspace->doctree = NULL;
 	workspace->ctxt = NULL;
 	workspace->res = NULL;
 
-	workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
-									   docsize, NULL, NULL,
-									   XML_PARSE_NOENT);
-	if (workspace->doctree != NULL)
+	PG_TRY();
 	{
-		workspace->ctxt = xmlXPathNewContext(workspace->doctree);
-		workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
-
-		/* compile the path */
-		comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
-		if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+		workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
+										   docsize, NULL, NULL,
+										   XML_PARSE_NOENT);
+		if (workspace->doctree != NULL)
 		{
-			if (comppath != NULL)
-				xmlXPathFreeCompExpr(comppath);
-			xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
-						"XPath Syntax Error");
-		}
+			workspace->ctxt = xmlXPathNewContext(workspace->doctree);
+			if (workspace->ctxt == NULL)
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_OUT_OF_MEMORY,
+							"could not allocate XPath context");
 
-		/* Now evaluate the path expression. */
-		workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+			workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
+
+			/* compile the path */
+			comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
+			if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
+							"XPath Syntax Error");
+
+			/* Now evaluate the path expression. */
+			workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+
+			xmlXPathFreeCompExpr(comppath);
+			comppath = NULL;
+		}
+	}
+	PG_CATCH();
+	{
+		if (comppath != NULL)
+			xmlXPathFreeCompExpr(comppath);
+		cleanup_workspace(workspace);
 
-		xmlXPathFreeCompExpr(comppath);
+		PG_RE_THROW();
 	}
+	PG_END_TRY();
 
 	return workspace;
 }
-- 
2.54.0


--MP_/LMSk9=uMhuQ1QiIJDarDO8G--






^ permalink  raw  reply  [nested|flat] 611+ messages in thread

* [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths
@ 2026-06-01 22:41 Andrey Chernyy <andrey.cherny@tantorlabs.com>
  0 siblings, 0 replies; 611+ messages in thread

From: Andrey Chernyy @ 2026-06-01 22:41 UTC (permalink / raw)

pgxml_xpath() builds an xpath_workspace before returning it to
callers.  If an ERROR is thrown before the function returns, callers
have not received the workspace pointer yet and cannot run
cleanup_workspace().

Add local error cleanup for the partially built workspace and the
compiled XPath expression.  Also check xmlXPathNewContext() before
dereferencing the returned context.
---
 contrib/xml2/xpath.c | 51 +++++++++++++++++++++++++++-----------------
 1 file changed, 32 insertions(+), 19 deletions(-)

diff --git a/contrib/xml2/xpath.c b/contrib/xml2/xpath.c
index 9fe75cb5ff4..283bb51178d 100644
--- a/contrib/xml2/xpath.c
+++ b/contrib/xml2/xpath.c
@@ -497,36 +497,49 @@ static xpath_workspace *
 pgxml_xpath(text *document, xmlChar *xpath, PgXmlErrorContext *xmlerrcxt)
 {
 	int32		docsize = VARSIZE_ANY_EXHDR(document);
-	xmlXPathCompExprPtr comppath;
+	xmlXPathCompExprPtr volatile comppath = NULL;
 	xpath_workspace *workspace = palloc0_object(xpath_workspace);
 
 	workspace->doctree = NULL;
 	workspace->ctxt = NULL;
 	workspace->res = NULL;
 
-	workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
-									   docsize, NULL, NULL,
-									   XML_PARSE_NOENT);
-	if (workspace->doctree != NULL)
+	PG_TRY();
 	{
-		workspace->ctxt = xmlXPathNewContext(workspace->doctree);
-		workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
-
-		/* compile the path */
-		comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
-		if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+		workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
+										   docsize, NULL, NULL,
+										   XML_PARSE_NOENT);
+		if (workspace->doctree != NULL)
 		{
-			if (comppath != NULL)
-				xmlXPathFreeCompExpr(comppath);
-			xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
-						"XPath Syntax Error");
-		}
+			workspace->ctxt = xmlXPathNewContext(workspace->doctree);
+			if (workspace->ctxt == NULL)
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_OUT_OF_MEMORY,
+							"could not allocate XPath context");
 
-		/* Now evaluate the path expression. */
-		workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+			workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
+
+			/* compile the path */
+			comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
+			if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
+							"XPath Syntax Error");
+
+			/* Now evaluate the path expression. */
+			workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+
+			xmlXPathFreeCompExpr(comppath);
+			comppath = NULL;
+		}
+	}
+	PG_CATCH();
+	{
+		if (comppath != NULL)
+			xmlXPathFreeCompExpr(comppath);
+		cleanup_workspace(workspace);
 
-		xmlXPathFreeCompExpr(comppath);
+		PG_RE_THROW();
 	}
+	PG_END_TRY();
 
 	return workspace;
 }
-- 
2.54.0


--MP_/LMSk9=uMhuQ1QiIJDarDO8G--





^ permalink  raw  reply  [nested|flat] 611+ messages in thread

* [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths
@ 2026-06-01 22:41 Andrey Chernyy <andrey.cherny@tantorlabs.com>
  0 siblings, 0 replies; 611+ messages in thread

From: Andrey Chernyy @ 2026-06-01 22:41 UTC (permalink / raw)

pgxml_xpath() builds an xpath_workspace before returning it to
callers.  If an ERROR is thrown before the function returns, callers
have not received the workspace pointer yet and cannot run
cleanup_workspace().

Add local error cleanup for the partially built workspace and the
compiled XPath expression.  Also check xmlXPathNewContext() before
dereferencing the returned context.
---
 contrib/xml2/xpath.c | 51 +++++++++++++++++++++++++++-----------------
 1 file changed, 32 insertions(+), 19 deletions(-)

diff --git a/contrib/xml2/xpath.c b/contrib/xml2/xpath.c
index 9fe75cb5ff4..283bb51178d 100644
--- a/contrib/xml2/xpath.c
+++ b/contrib/xml2/xpath.c
@@ -497,36 +497,49 @@ static xpath_workspace *
 pgxml_xpath(text *document, xmlChar *xpath, PgXmlErrorContext *xmlerrcxt)
 {
 	int32		docsize = VARSIZE_ANY_EXHDR(document);
-	xmlXPathCompExprPtr comppath;
+	xmlXPathCompExprPtr volatile comppath = NULL;
 	xpath_workspace *workspace = palloc0_object(xpath_workspace);
 
 	workspace->doctree = NULL;
 	workspace->ctxt = NULL;
 	workspace->res = NULL;
 
-	workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
-									   docsize, NULL, NULL,
-									   XML_PARSE_NOENT);
-	if (workspace->doctree != NULL)
+	PG_TRY();
 	{
-		workspace->ctxt = xmlXPathNewContext(workspace->doctree);
-		workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
-
-		/* compile the path */
-		comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
-		if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+		workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
+										   docsize, NULL, NULL,
+										   XML_PARSE_NOENT);
+		if (workspace->doctree != NULL)
 		{
-			if (comppath != NULL)
-				xmlXPathFreeCompExpr(comppath);
-			xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
-						"XPath Syntax Error");
-		}
+			workspace->ctxt = xmlXPathNewContext(workspace->doctree);
+			if (workspace->ctxt == NULL)
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_OUT_OF_MEMORY,
+							"could not allocate XPath context");
 
-		/* Now evaluate the path expression. */
-		workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+			workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
+
+			/* compile the path */
+			comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
+			if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
+							"XPath Syntax Error");
+
+			/* Now evaluate the path expression. */
+			workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+
+			xmlXPathFreeCompExpr(comppath);
+			comppath = NULL;
+		}
+	}
+	PG_CATCH();
+	{
+		if (comppath != NULL)
+			xmlXPathFreeCompExpr(comppath);
+		cleanup_workspace(workspace);
 
-		xmlXPathFreeCompExpr(comppath);
+		PG_RE_THROW();
 	}
+	PG_END_TRY();
 
 	return workspace;
 }
-- 
2.54.0


--MP_/LMSk9=uMhuQ1QiIJDarDO8G--






^ permalink  raw  reply  [nested|flat] 611+ messages in thread

* [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths
@ 2026-06-01 22:41 Andrey Chernyy <andrey.cherny@tantorlabs.com>
  0 siblings, 0 replies; 611+ messages in thread

From: Andrey Chernyy @ 2026-06-01 22:41 UTC (permalink / raw)

pgxml_xpath() builds an xpath_workspace before returning it to
callers.  If an ERROR is thrown before the function returns, callers
have not received the workspace pointer yet and cannot run
cleanup_workspace().

Add local error cleanup for the partially built workspace and the
compiled XPath expression.  Also check xmlXPathNewContext() before
dereferencing the returned context.
---
 contrib/xml2/xpath.c | 51 +++++++++++++++++++++++++++-----------------
 1 file changed, 32 insertions(+), 19 deletions(-)

diff --git a/contrib/xml2/xpath.c b/contrib/xml2/xpath.c
index 9fe75cb5ff4..283bb51178d 100644
--- a/contrib/xml2/xpath.c
+++ b/contrib/xml2/xpath.c
@@ -497,36 +497,49 @@ static xpath_workspace *
 pgxml_xpath(text *document, xmlChar *xpath, PgXmlErrorContext *xmlerrcxt)
 {
 	int32		docsize = VARSIZE_ANY_EXHDR(document);
-	xmlXPathCompExprPtr comppath;
+	xmlXPathCompExprPtr volatile comppath = NULL;
 	xpath_workspace *workspace = palloc0_object(xpath_workspace);
 
 	workspace->doctree = NULL;
 	workspace->ctxt = NULL;
 	workspace->res = NULL;
 
-	workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
-									   docsize, NULL, NULL,
-									   XML_PARSE_NOENT);
-	if (workspace->doctree != NULL)
+	PG_TRY();
 	{
-		workspace->ctxt = xmlXPathNewContext(workspace->doctree);
-		workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
-
-		/* compile the path */
-		comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
-		if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+		workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
+										   docsize, NULL, NULL,
+										   XML_PARSE_NOENT);
+		if (workspace->doctree != NULL)
 		{
-			if (comppath != NULL)
-				xmlXPathFreeCompExpr(comppath);
-			xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
-						"XPath Syntax Error");
-		}
+			workspace->ctxt = xmlXPathNewContext(workspace->doctree);
+			if (workspace->ctxt == NULL)
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_OUT_OF_MEMORY,
+							"could not allocate XPath context");
 
-		/* Now evaluate the path expression. */
-		workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+			workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
+
+			/* compile the path */
+			comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
+			if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
+							"XPath Syntax Error");
+
+			/* Now evaluate the path expression. */
+			workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+
+			xmlXPathFreeCompExpr(comppath);
+			comppath = NULL;
+		}
+	}
+	PG_CATCH();
+	{
+		if (comppath != NULL)
+			xmlXPathFreeCompExpr(comppath);
+		cleanup_workspace(workspace);
 
-		xmlXPathFreeCompExpr(comppath);
+		PG_RE_THROW();
 	}
+	PG_END_TRY();
 
 	return workspace;
 }
-- 
2.54.0


--MP_/LMSk9=uMhuQ1QiIJDarDO8G--





^ permalink  raw  reply  [nested|flat] 611+ messages in thread

* [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths
@ 2026-06-01 22:41 Andrey Chernyy <andrey.cherny@tantorlabs.com>
  0 siblings, 0 replies; 611+ messages in thread

From: Andrey Chernyy @ 2026-06-01 22:41 UTC (permalink / raw)

pgxml_xpath() builds an xpath_workspace before returning it to
callers.  If an ERROR is thrown before the function returns, callers
have not received the workspace pointer yet and cannot run
cleanup_workspace().

Add local error cleanup for the partially built workspace and the
compiled XPath expression.  Also check xmlXPathNewContext() before
dereferencing the returned context.
---
 contrib/xml2/xpath.c | 51 +++++++++++++++++++++++++++-----------------
 1 file changed, 32 insertions(+), 19 deletions(-)

diff --git a/contrib/xml2/xpath.c b/contrib/xml2/xpath.c
index 9fe75cb5ff4..283bb51178d 100644
--- a/contrib/xml2/xpath.c
+++ b/contrib/xml2/xpath.c
@@ -497,36 +497,49 @@ static xpath_workspace *
 pgxml_xpath(text *document, xmlChar *xpath, PgXmlErrorContext *xmlerrcxt)
 {
 	int32		docsize = VARSIZE_ANY_EXHDR(document);
-	xmlXPathCompExprPtr comppath;
+	xmlXPathCompExprPtr volatile comppath = NULL;
 	xpath_workspace *workspace = palloc0_object(xpath_workspace);
 
 	workspace->doctree = NULL;
 	workspace->ctxt = NULL;
 	workspace->res = NULL;
 
-	workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
-									   docsize, NULL, NULL,
-									   XML_PARSE_NOENT);
-	if (workspace->doctree != NULL)
+	PG_TRY();
 	{
-		workspace->ctxt = xmlXPathNewContext(workspace->doctree);
-		workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
-
-		/* compile the path */
-		comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
-		if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+		workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
+										   docsize, NULL, NULL,
+										   XML_PARSE_NOENT);
+		if (workspace->doctree != NULL)
 		{
-			if (comppath != NULL)
-				xmlXPathFreeCompExpr(comppath);
-			xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
-						"XPath Syntax Error");
-		}
+			workspace->ctxt = xmlXPathNewContext(workspace->doctree);
+			if (workspace->ctxt == NULL)
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_OUT_OF_MEMORY,
+							"could not allocate XPath context");
 
-		/* Now evaluate the path expression. */
-		workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+			workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
+
+			/* compile the path */
+			comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
+			if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
+							"XPath Syntax Error");
+
+			/* Now evaluate the path expression. */
+			workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+
+			xmlXPathFreeCompExpr(comppath);
+			comppath = NULL;
+		}
+	}
+	PG_CATCH();
+	{
+		if (comppath != NULL)
+			xmlXPathFreeCompExpr(comppath);
+		cleanup_workspace(workspace);
 
-		xmlXPathFreeCompExpr(comppath);
+		PG_RE_THROW();
 	}
+	PG_END_TRY();
 
 	return workspace;
 }
-- 
2.54.0


--MP_/LMSk9=uMhuQ1QiIJDarDO8G--





^ permalink  raw  reply  [nested|flat] 611+ messages in thread

* [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths
@ 2026-06-01 22:41 Andrey Chernyy <andrey.cherny@tantorlabs.com>
  0 siblings, 0 replies; 611+ messages in thread

From: Andrey Chernyy @ 2026-06-01 22:41 UTC (permalink / raw)

pgxml_xpath() builds an xpath_workspace before returning it to
callers.  If an ERROR is thrown before the function returns, callers
have not received the workspace pointer yet and cannot run
cleanup_workspace().

Add local error cleanup for the partially built workspace and the
compiled XPath expression.  Also check xmlXPathNewContext() before
dereferencing the returned context.
---
 contrib/xml2/xpath.c | 51 +++++++++++++++++++++++++++-----------------
 1 file changed, 32 insertions(+), 19 deletions(-)

diff --git a/contrib/xml2/xpath.c b/contrib/xml2/xpath.c
index 9fe75cb5ff4..283bb51178d 100644
--- a/contrib/xml2/xpath.c
+++ b/contrib/xml2/xpath.c
@@ -497,36 +497,49 @@ static xpath_workspace *
 pgxml_xpath(text *document, xmlChar *xpath, PgXmlErrorContext *xmlerrcxt)
 {
 	int32		docsize = VARSIZE_ANY_EXHDR(document);
-	xmlXPathCompExprPtr comppath;
+	xmlXPathCompExprPtr volatile comppath = NULL;
 	xpath_workspace *workspace = palloc0_object(xpath_workspace);
 
 	workspace->doctree = NULL;
 	workspace->ctxt = NULL;
 	workspace->res = NULL;
 
-	workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
-									   docsize, NULL, NULL,
-									   XML_PARSE_NOENT);
-	if (workspace->doctree != NULL)
+	PG_TRY();
 	{
-		workspace->ctxt = xmlXPathNewContext(workspace->doctree);
-		workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
-
-		/* compile the path */
-		comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
-		if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+		workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
+										   docsize, NULL, NULL,
+										   XML_PARSE_NOENT);
+		if (workspace->doctree != NULL)
 		{
-			if (comppath != NULL)
-				xmlXPathFreeCompExpr(comppath);
-			xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
-						"XPath Syntax Error");
-		}
+			workspace->ctxt = xmlXPathNewContext(workspace->doctree);
+			if (workspace->ctxt == NULL)
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_OUT_OF_MEMORY,
+							"could not allocate XPath context");
 
-		/* Now evaluate the path expression. */
-		workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+			workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
+
+			/* compile the path */
+			comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
+			if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
+							"XPath Syntax Error");
+
+			/* Now evaluate the path expression. */
+			workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+
+			xmlXPathFreeCompExpr(comppath);
+			comppath = NULL;
+		}
+	}
+	PG_CATCH();
+	{
+		if (comppath != NULL)
+			xmlXPathFreeCompExpr(comppath);
+		cleanup_workspace(workspace);
 
-		xmlXPathFreeCompExpr(comppath);
+		PG_RE_THROW();
 	}
+	PG_END_TRY();
 
 	return workspace;
 }
-- 
2.54.0


--MP_/LMSk9=uMhuQ1QiIJDarDO8G--






^ permalink  raw  reply  [nested|flat] 611+ messages in thread

* [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths
@ 2026-06-01 22:41 Andrey Chernyy <andrey.cherny@tantorlabs.com>
  0 siblings, 0 replies; 611+ messages in thread

From: Andrey Chernyy @ 2026-06-01 22:41 UTC (permalink / raw)

pgxml_xpath() builds an xpath_workspace before returning it to
callers.  If an ERROR is thrown before the function returns, callers
have not received the workspace pointer yet and cannot run
cleanup_workspace().

Add local error cleanup for the partially built workspace and the
compiled XPath expression.  Also check xmlXPathNewContext() before
dereferencing the returned context.
---
 contrib/xml2/xpath.c | 51 +++++++++++++++++++++++++++-----------------
 1 file changed, 32 insertions(+), 19 deletions(-)

diff --git a/contrib/xml2/xpath.c b/contrib/xml2/xpath.c
index 9fe75cb5ff4..283bb51178d 100644
--- a/contrib/xml2/xpath.c
+++ b/contrib/xml2/xpath.c
@@ -497,36 +497,49 @@ static xpath_workspace *
 pgxml_xpath(text *document, xmlChar *xpath, PgXmlErrorContext *xmlerrcxt)
 {
 	int32		docsize = VARSIZE_ANY_EXHDR(document);
-	xmlXPathCompExprPtr comppath;
+	xmlXPathCompExprPtr volatile comppath = NULL;
 	xpath_workspace *workspace = palloc0_object(xpath_workspace);
 
 	workspace->doctree = NULL;
 	workspace->ctxt = NULL;
 	workspace->res = NULL;
 
-	workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
-									   docsize, NULL, NULL,
-									   XML_PARSE_NOENT);
-	if (workspace->doctree != NULL)
+	PG_TRY();
 	{
-		workspace->ctxt = xmlXPathNewContext(workspace->doctree);
-		workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
-
-		/* compile the path */
-		comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
-		if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+		workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
+										   docsize, NULL, NULL,
+										   XML_PARSE_NOENT);
+		if (workspace->doctree != NULL)
 		{
-			if (comppath != NULL)
-				xmlXPathFreeCompExpr(comppath);
-			xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
-						"XPath Syntax Error");
-		}
+			workspace->ctxt = xmlXPathNewContext(workspace->doctree);
+			if (workspace->ctxt == NULL)
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_OUT_OF_MEMORY,
+							"could not allocate XPath context");
 
-		/* Now evaluate the path expression. */
-		workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+			workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
+
+			/* compile the path */
+			comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
+			if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
+							"XPath Syntax Error");
+
+			/* Now evaluate the path expression. */
+			workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+
+			xmlXPathFreeCompExpr(comppath);
+			comppath = NULL;
+		}
+	}
+	PG_CATCH();
+	{
+		if (comppath != NULL)
+			xmlXPathFreeCompExpr(comppath);
+		cleanup_workspace(workspace);
 
-		xmlXPathFreeCompExpr(comppath);
+		PG_RE_THROW();
 	}
+	PG_END_TRY();
 
 	return workspace;
 }
-- 
2.54.0


--MP_/LMSk9=uMhuQ1QiIJDarDO8G--





^ permalink  raw  reply  [nested|flat] 611+ messages in thread

* [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths
@ 2026-06-01 22:41 Andrey Chernyy <andrey.cherny@tantorlabs.com>
  0 siblings, 0 replies; 611+ messages in thread

From: Andrey Chernyy @ 2026-06-01 22:41 UTC (permalink / raw)

pgxml_xpath() builds an xpath_workspace before returning it to
callers.  If an ERROR is thrown before the function returns, callers
have not received the workspace pointer yet and cannot run
cleanup_workspace().

Add local error cleanup for the partially built workspace and the
compiled XPath expression.  Also check xmlXPathNewContext() before
dereferencing the returned context.
---
 contrib/xml2/xpath.c | 51 +++++++++++++++++++++++++++-----------------
 1 file changed, 32 insertions(+), 19 deletions(-)

diff --git a/contrib/xml2/xpath.c b/contrib/xml2/xpath.c
index 9fe75cb5ff4..283bb51178d 100644
--- a/contrib/xml2/xpath.c
+++ b/contrib/xml2/xpath.c
@@ -497,36 +497,49 @@ static xpath_workspace *
 pgxml_xpath(text *document, xmlChar *xpath, PgXmlErrorContext *xmlerrcxt)
 {
 	int32		docsize = VARSIZE_ANY_EXHDR(document);
-	xmlXPathCompExprPtr comppath;
+	xmlXPathCompExprPtr volatile comppath = NULL;
 	xpath_workspace *workspace = palloc0_object(xpath_workspace);
 
 	workspace->doctree = NULL;
 	workspace->ctxt = NULL;
 	workspace->res = NULL;
 
-	workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
-									   docsize, NULL, NULL,
-									   XML_PARSE_NOENT);
-	if (workspace->doctree != NULL)
+	PG_TRY();
 	{
-		workspace->ctxt = xmlXPathNewContext(workspace->doctree);
-		workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
-
-		/* compile the path */
-		comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
-		if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+		workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
+										   docsize, NULL, NULL,
+										   XML_PARSE_NOENT);
+		if (workspace->doctree != NULL)
 		{
-			if (comppath != NULL)
-				xmlXPathFreeCompExpr(comppath);
-			xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
-						"XPath Syntax Error");
-		}
+			workspace->ctxt = xmlXPathNewContext(workspace->doctree);
+			if (workspace->ctxt == NULL)
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_OUT_OF_MEMORY,
+							"could not allocate XPath context");
 
-		/* Now evaluate the path expression. */
-		workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+			workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
+
+			/* compile the path */
+			comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
+			if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
+							"XPath Syntax Error");
+
+			/* Now evaluate the path expression. */
+			workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+
+			xmlXPathFreeCompExpr(comppath);
+			comppath = NULL;
+		}
+	}
+	PG_CATCH();
+	{
+		if (comppath != NULL)
+			xmlXPathFreeCompExpr(comppath);
+		cleanup_workspace(workspace);
 
-		xmlXPathFreeCompExpr(comppath);
+		PG_RE_THROW();
 	}
+	PG_END_TRY();
 
 	return workspace;
 }
-- 
2.54.0


--MP_/LMSk9=uMhuQ1QiIJDarDO8G--






^ permalink  raw  reply  [nested|flat] 611+ messages in thread

* [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths
@ 2026-06-01 22:41 Andrey Chernyy <andrey.cherny@tantorlabs.com>
  0 siblings, 0 replies; 611+ messages in thread

From: Andrey Chernyy @ 2026-06-01 22:41 UTC (permalink / raw)

pgxml_xpath() builds an xpath_workspace before returning it to
callers.  If an ERROR is thrown before the function returns, callers
have not received the workspace pointer yet and cannot run
cleanup_workspace().

Add local error cleanup for the partially built workspace and the
compiled XPath expression.  Also check xmlXPathNewContext() before
dereferencing the returned context.
---
 contrib/xml2/xpath.c | 51 +++++++++++++++++++++++++++-----------------
 1 file changed, 32 insertions(+), 19 deletions(-)

diff --git a/contrib/xml2/xpath.c b/contrib/xml2/xpath.c
index 9fe75cb5ff4..283bb51178d 100644
--- a/contrib/xml2/xpath.c
+++ b/contrib/xml2/xpath.c
@@ -497,36 +497,49 @@ static xpath_workspace *
 pgxml_xpath(text *document, xmlChar *xpath, PgXmlErrorContext *xmlerrcxt)
 {
 	int32		docsize = VARSIZE_ANY_EXHDR(document);
-	xmlXPathCompExprPtr comppath;
+	xmlXPathCompExprPtr volatile comppath = NULL;
 	xpath_workspace *workspace = palloc0_object(xpath_workspace);
 
 	workspace->doctree = NULL;
 	workspace->ctxt = NULL;
 	workspace->res = NULL;
 
-	workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
-									   docsize, NULL, NULL,
-									   XML_PARSE_NOENT);
-	if (workspace->doctree != NULL)
+	PG_TRY();
 	{
-		workspace->ctxt = xmlXPathNewContext(workspace->doctree);
-		workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
-
-		/* compile the path */
-		comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
-		if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+		workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
+										   docsize, NULL, NULL,
+										   XML_PARSE_NOENT);
+		if (workspace->doctree != NULL)
 		{
-			if (comppath != NULL)
-				xmlXPathFreeCompExpr(comppath);
-			xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
-						"XPath Syntax Error");
-		}
+			workspace->ctxt = xmlXPathNewContext(workspace->doctree);
+			if (workspace->ctxt == NULL)
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_OUT_OF_MEMORY,
+							"could not allocate XPath context");
 
-		/* Now evaluate the path expression. */
-		workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+			workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
+
+			/* compile the path */
+			comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
+			if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
+							"XPath Syntax Error");
+
+			/* Now evaluate the path expression. */
+			workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+
+			xmlXPathFreeCompExpr(comppath);
+			comppath = NULL;
+		}
+	}
+	PG_CATCH();
+	{
+		if (comppath != NULL)
+			xmlXPathFreeCompExpr(comppath);
+		cleanup_workspace(workspace);
 
-		xmlXPathFreeCompExpr(comppath);
+		PG_RE_THROW();
 	}
+	PG_END_TRY();
 
 	return workspace;
 }
-- 
2.54.0


--MP_/LMSk9=uMhuQ1QiIJDarDO8G--






^ permalink  raw  reply  [nested|flat] 611+ messages in thread

* [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths
@ 2026-06-01 22:41 Andrey Chernyy <andrey.cherny@tantorlabs.com>
  0 siblings, 0 replies; 611+ messages in thread

From: Andrey Chernyy @ 2026-06-01 22:41 UTC (permalink / raw)

pgxml_xpath() builds an xpath_workspace before returning it to
callers.  If an ERROR is thrown before the function returns, callers
have not received the workspace pointer yet and cannot run
cleanup_workspace().

Add local error cleanup for the partially built workspace and the
compiled XPath expression.  Also check xmlXPathNewContext() before
dereferencing the returned context.
---
 contrib/xml2/xpath.c | 51 +++++++++++++++++++++++++++-----------------
 1 file changed, 32 insertions(+), 19 deletions(-)

diff --git a/contrib/xml2/xpath.c b/contrib/xml2/xpath.c
index 9fe75cb5ff4..283bb51178d 100644
--- a/contrib/xml2/xpath.c
+++ b/contrib/xml2/xpath.c
@@ -497,36 +497,49 @@ static xpath_workspace *
 pgxml_xpath(text *document, xmlChar *xpath, PgXmlErrorContext *xmlerrcxt)
 {
 	int32		docsize = VARSIZE_ANY_EXHDR(document);
-	xmlXPathCompExprPtr comppath;
+	xmlXPathCompExprPtr volatile comppath = NULL;
 	xpath_workspace *workspace = palloc0_object(xpath_workspace);
 
 	workspace->doctree = NULL;
 	workspace->ctxt = NULL;
 	workspace->res = NULL;
 
-	workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
-									   docsize, NULL, NULL,
-									   XML_PARSE_NOENT);
-	if (workspace->doctree != NULL)
+	PG_TRY();
 	{
-		workspace->ctxt = xmlXPathNewContext(workspace->doctree);
-		workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
-
-		/* compile the path */
-		comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
-		if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+		workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
+										   docsize, NULL, NULL,
+										   XML_PARSE_NOENT);
+		if (workspace->doctree != NULL)
 		{
-			if (comppath != NULL)
-				xmlXPathFreeCompExpr(comppath);
-			xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
-						"XPath Syntax Error");
-		}
+			workspace->ctxt = xmlXPathNewContext(workspace->doctree);
+			if (workspace->ctxt == NULL)
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_OUT_OF_MEMORY,
+							"could not allocate XPath context");
 
-		/* Now evaluate the path expression. */
-		workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+			workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
+
+			/* compile the path */
+			comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
+			if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
+							"XPath Syntax Error");
+
+			/* Now evaluate the path expression. */
+			workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+
+			xmlXPathFreeCompExpr(comppath);
+			comppath = NULL;
+		}
+	}
+	PG_CATCH();
+	{
+		if (comppath != NULL)
+			xmlXPathFreeCompExpr(comppath);
+		cleanup_workspace(workspace);
 
-		xmlXPathFreeCompExpr(comppath);
+		PG_RE_THROW();
 	}
+	PG_END_TRY();
 
 	return workspace;
 }
-- 
2.54.0


--MP_/LMSk9=uMhuQ1QiIJDarDO8G--






^ permalink  raw  reply  [nested|flat] 611+ messages in thread

* [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths
@ 2026-06-01 22:41 Andrey Chernyy <andrey.cherny@tantorlabs.com>
  0 siblings, 0 replies; 611+ messages in thread

From: Andrey Chernyy @ 2026-06-01 22:41 UTC (permalink / raw)

pgxml_xpath() builds an xpath_workspace before returning it to
callers.  If an ERROR is thrown before the function returns, callers
have not received the workspace pointer yet and cannot run
cleanup_workspace().

Add local error cleanup for the partially built workspace and the
compiled XPath expression.  Also check xmlXPathNewContext() before
dereferencing the returned context.
---
 contrib/xml2/xpath.c | 51 +++++++++++++++++++++++++++-----------------
 1 file changed, 32 insertions(+), 19 deletions(-)

diff --git a/contrib/xml2/xpath.c b/contrib/xml2/xpath.c
index 9fe75cb5ff4..283bb51178d 100644
--- a/contrib/xml2/xpath.c
+++ b/contrib/xml2/xpath.c
@@ -497,36 +497,49 @@ static xpath_workspace *
 pgxml_xpath(text *document, xmlChar *xpath, PgXmlErrorContext *xmlerrcxt)
 {
 	int32		docsize = VARSIZE_ANY_EXHDR(document);
-	xmlXPathCompExprPtr comppath;
+	xmlXPathCompExprPtr volatile comppath = NULL;
 	xpath_workspace *workspace = palloc0_object(xpath_workspace);
 
 	workspace->doctree = NULL;
 	workspace->ctxt = NULL;
 	workspace->res = NULL;
 
-	workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
-									   docsize, NULL, NULL,
-									   XML_PARSE_NOENT);
-	if (workspace->doctree != NULL)
+	PG_TRY();
 	{
-		workspace->ctxt = xmlXPathNewContext(workspace->doctree);
-		workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
-
-		/* compile the path */
-		comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
-		if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+		workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
+										   docsize, NULL, NULL,
+										   XML_PARSE_NOENT);
+		if (workspace->doctree != NULL)
 		{
-			if (comppath != NULL)
-				xmlXPathFreeCompExpr(comppath);
-			xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
-						"XPath Syntax Error");
-		}
+			workspace->ctxt = xmlXPathNewContext(workspace->doctree);
+			if (workspace->ctxt == NULL)
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_OUT_OF_MEMORY,
+							"could not allocate XPath context");
 
-		/* Now evaluate the path expression. */
-		workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+			workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
+
+			/* compile the path */
+			comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
+			if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
+							"XPath Syntax Error");
+
+			/* Now evaluate the path expression. */
+			workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+
+			xmlXPathFreeCompExpr(comppath);
+			comppath = NULL;
+		}
+	}
+	PG_CATCH();
+	{
+		if (comppath != NULL)
+			xmlXPathFreeCompExpr(comppath);
+		cleanup_workspace(workspace);
 
-		xmlXPathFreeCompExpr(comppath);
+		PG_RE_THROW();
 	}
+	PG_END_TRY();
 
 	return workspace;
 }
-- 
2.54.0


--MP_/LMSk9=uMhuQ1QiIJDarDO8G--






^ permalink  raw  reply  [nested|flat] 611+ messages in thread

* [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths
@ 2026-06-01 22:41 Andrey Chernyy <andrey.cherny@tantorlabs.com>
  0 siblings, 0 replies; 611+ messages in thread

From: Andrey Chernyy @ 2026-06-01 22:41 UTC (permalink / raw)

pgxml_xpath() builds an xpath_workspace before returning it to
callers.  If an ERROR is thrown before the function returns, callers
have not received the workspace pointer yet and cannot run
cleanup_workspace().

Add local error cleanup for the partially built workspace and the
compiled XPath expression.  Also check xmlXPathNewContext() before
dereferencing the returned context.
---
 contrib/xml2/xpath.c | 51 +++++++++++++++++++++++++++-----------------
 1 file changed, 32 insertions(+), 19 deletions(-)

diff --git a/contrib/xml2/xpath.c b/contrib/xml2/xpath.c
index 9fe75cb5ff4..283bb51178d 100644
--- a/contrib/xml2/xpath.c
+++ b/contrib/xml2/xpath.c
@@ -497,36 +497,49 @@ static xpath_workspace *
 pgxml_xpath(text *document, xmlChar *xpath, PgXmlErrorContext *xmlerrcxt)
 {
 	int32		docsize = VARSIZE_ANY_EXHDR(document);
-	xmlXPathCompExprPtr comppath;
+	xmlXPathCompExprPtr volatile comppath = NULL;
 	xpath_workspace *workspace = palloc0_object(xpath_workspace);
 
 	workspace->doctree = NULL;
 	workspace->ctxt = NULL;
 	workspace->res = NULL;
 
-	workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
-									   docsize, NULL, NULL,
-									   XML_PARSE_NOENT);
-	if (workspace->doctree != NULL)
+	PG_TRY();
 	{
-		workspace->ctxt = xmlXPathNewContext(workspace->doctree);
-		workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
-
-		/* compile the path */
-		comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
-		if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+		workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
+										   docsize, NULL, NULL,
+										   XML_PARSE_NOENT);
+		if (workspace->doctree != NULL)
 		{
-			if (comppath != NULL)
-				xmlXPathFreeCompExpr(comppath);
-			xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
-						"XPath Syntax Error");
-		}
+			workspace->ctxt = xmlXPathNewContext(workspace->doctree);
+			if (workspace->ctxt == NULL)
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_OUT_OF_MEMORY,
+							"could not allocate XPath context");
 
-		/* Now evaluate the path expression. */
-		workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+			workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
+
+			/* compile the path */
+			comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
+			if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
+							"XPath Syntax Error");
+
+			/* Now evaluate the path expression. */
+			workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+
+			xmlXPathFreeCompExpr(comppath);
+			comppath = NULL;
+		}
+	}
+	PG_CATCH();
+	{
+		if (comppath != NULL)
+			xmlXPathFreeCompExpr(comppath);
+		cleanup_workspace(workspace);
 
-		xmlXPathFreeCompExpr(comppath);
+		PG_RE_THROW();
 	}
+	PG_END_TRY();
 
 	return workspace;
 }
-- 
2.54.0


--MP_/LMSk9=uMhuQ1QiIJDarDO8G--





^ permalink  raw  reply  [nested|flat] 611+ messages in thread

* [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths
@ 2026-06-01 22:41 Andrey Chernyy <andrey.cherny@tantorlabs.com>
  0 siblings, 0 replies; 611+ messages in thread

From: Andrey Chernyy @ 2026-06-01 22:41 UTC (permalink / raw)

pgxml_xpath() builds an xpath_workspace before returning it to
callers.  If an ERROR is thrown before the function returns, callers
have not received the workspace pointer yet and cannot run
cleanup_workspace().

Add local error cleanup for the partially built workspace and the
compiled XPath expression.  Also check xmlXPathNewContext() before
dereferencing the returned context.
---
 contrib/xml2/xpath.c | 51 +++++++++++++++++++++++++++-----------------
 1 file changed, 32 insertions(+), 19 deletions(-)

diff --git a/contrib/xml2/xpath.c b/contrib/xml2/xpath.c
index 9fe75cb5ff4..283bb51178d 100644
--- a/contrib/xml2/xpath.c
+++ b/contrib/xml2/xpath.c
@@ -497,36 +497,49 @@ static xpath_workspace *
 pgxml_xpath(text *document, xmlChar *xpath, PgXmlErrorContext *xmlerrcxt)
 {
 	int32		docsize = VARSIZE_ANY_EXHDR(document);
-	xmlXPathCompExprPtr comppath;
+	xmlXPathCompExprPtr volatile comppath = NULL;
 	xpath_workspace *workspace = palloc0_object(xpath_workspace);
 
 	workspace->doctree = NULL;
 	workspace->ctxt = NULL;
 	workspace->res = NULL;
 
-	workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
-									   docsize, NULL, NULL,
-									   XML_PARSE_NOENT);
-	if (workspace->doctree != NULL)
+	PG_TRY();
 	{
-		workspace->ctxt = xmlXPathNewContext(workspace->doctree);
-		workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
-
-		/* compile the path */
-		comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
-		if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+		workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
+										   docsize, NULL, NULL,
+										   XML_PARSE_NOENT);
+		if (workspace->doctree != NULL)
 		{
-			if (comppath != NULL)
-				xmlXPathFreeCompExpr(comppath);
-			xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
-						"XPath Syntax Error");
-		}
+			workspace->ctxt = xmlXPathNewContext(workspace->doctree);
+			if (workspace->ctxt == NULL)
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_OUT_OF_MEMORY,
+							"could not allocate XPath context");
 
-		/* Now evaluate the path expression. */
-		workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+			workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
+
+			/* compile the path */
+			comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
+			if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
+							"XPath Syntax Error");
+
+			/* Now evaluate the path expression. */
+			workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+
+			xmlXPathFreeCompExpr(comppath);
+			comppath = NULL;
+		}
+	}
+	PG_CATCH();
+	{
+		if (comppath != NULL)
+			xmlXPathFreeCompExpr(comppath);
+		cleanup_workspace(workspace);
 
-		xmlXPathFreeCompExpr(comppath);
+		PG_RE_THROW();
 	}
+	PG_END_TRY();
 
 	return workspace;
 }
-- 
2.54.0


--MP_/LMSk9=uMhuQ1QiIJDarDO8G--






^ permalink  raw  reply  [nested|flat] 611+ messages in thread

* [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths
@ 2026-06-01 22:41 Andrey Chernyy <andrey.cherny@tantorlabs.com>
  0 siblings, 0 replies; 611+ messages in thread

From: Andrey Chernyy @ 2026-06-01 22:41 UTC (permalink / raw)

pgxml_xpath() builds an xpath_workspace before returning it to
callers.  If an ERROR is thrown before the function returns, callers
have not received the workspace pointer yet and cannot run
cleanup_workspace().

Add local error cleanup for the partially built workspace and the
compiled XPath expression.  Also check xmlXPathNewContext() before
dereferencing the returned context.
---
 contrib/xml2/xpath.c | 51 +++++++++++++++++++++++++++-----------------
 1 file changed, 32 insertions(+), 19 deletions(-)

diff --git a/contrib/xml2/xpath.c b/contrib/xml2/xpath.c
index 9fe75cb5ff4..283bb51178d 100644
--- a/contrib/xml2/xpath.c
+++ b/contrib/xml2/xpath.c
@@ -497,36 +497,49 @@ static xpath_workspace *
 pgxml_xpath(text *document, xmlChar *xpath, PgXmlErrorContext *xmlerrcxt)
 {
 	int32		docsize = VARSIZE_ANY_EXHDR(document);
-	xmlXPathCompExprPtr comppath;
+	xmlXPathCompExprPtr volatile comppath = NULL;
 	xpath_workspace *workspace = palloc0_object(xpath_workspace);
 
 	workspace->doctree = NULL;
 	workspace->ctxt = NULL;
 	workspace->res = NULL;
 
-	workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
-									   docsize, NULL, NULL,
-									   XML_PARSE_NOENT);
-	if (workspace->doctree != NULL)
+	PG_TRY();
 	{
-		workspace->ctxt = xmlXPathNewContext(workspace->doctree);
-		workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
-
-		/* compile the path */
-		comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
-		if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+		workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
+										   docsize, NULL, NULL,
+										   XML_PARSE_NOENT);
+		if (workspace->doctree != NULL)
 		{
-			if (comppath != NULL)
-				xmlXPathFreeCompExpr(comppath);
-			xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
-						"XPath Syntax Error");
-		}
+			workspace->ctxt = xmlXPathNewContext(workspace->doctree);
+			if (workspace->ctxt == NULL)
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_OUT_OF_MEMORY,
+							"could not allocate XPath context");
 
-		/* Now evaluate the path expression. */
-		workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+			workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
+
+			/* compile the path */
+			comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
+			if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
+							"XPath Syntax Error");
+
+			/* Now evaluate the path expression. */
+			workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+
+			xmlXPathFreeCompExpr(comppath);
+			comppath = NULL;
+		}
+	}
+	PG_CATCH();
+	{
+		if (comppath != NULL)
+			xmlXPathFreeCompExpr(comppath);
+		cleanup_workspace(workspace);
 
-		xmlXPathFreeCompExpr(comppath);
+		PG_RE_THROW();
 	}
+	PG_END_TRY();
 
 	return workspace;
 }
-- 
2.54.0


--MP_/LMSk9=uMhuQ1QiIJDarDO8G--






^ permalink  raw  reply  [nested|flat] 611+ messages in thread

* [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths
@ 2026-06-01 22:41 Andrey Chernyy <andrey.cherny@tantorlabs.com>
  0 siblings, 0 replies; 611+ messages in thread

From: Andrey Chernyy @ 2026-06-01 22:41 UTC (permalink / raw)

pgxml_xpath() builds an xpath_workspace before returning it to
callers.  If an ERROR is thrown before the function returns, callers
have not received the workspace pointer yet and cannot run
cleanup_workspace().

Add local error cleanup for the partially built workspace and the
compiled XPath expression.  Also check xmlXPathNewContext() before
dereferencing the returned context.
---
 contrib/xml2/xpath.c | 51 +++++++++++++++++++++++++++-----------------
 1 file changed, 32 insertions(+), 19 deletions(-)

diff --git a/contrib/xml2/xpath.c b/contrib/xml2/xpath.c
index 9fe75cb5ff4..283bb51178d 100644
--- a/contrib/xml2/xpath.c
+++ b/contrib/xml2/xpath.c
@@ -497,36 +497,49 @@ static xpath_workspace *
 pgxml_xpath(text *document, xmlChar *xpath, PgXmlErrorContext *xmlerrcxt)
 {
 	int32		docsize = VARSIZE_ANY_EXHDR(document);
-	xmlXPathCompExprPtr comppath;
+	xmlXPathCompExprPtr volatile comppath = NULL;
 	xpath_workspace *workspace = palloc0_object(xpath_workspace);
 
 	workspace->doctree = NULL;
 	workspace->ctxt = NULL;
 	workspace->res = NULL;
 
-	workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
-									   docsize, NULL, NULL,
-									   XML_PARSE_NOENT);
-	if (workspace->doctree != NULL)
+	PG_TRY();
 	{
-		workspace->ctxt = xmlXPathNewContext(workspace->doctree);
-		workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
-
-		/* compile the path */
-		comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
-		if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+		workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
+										   docsize, NULL, NULL,
+										   XML_PARSE_NOENT);
+		if (workspace->doctree != NULL)
 		{
-			if (comppath != NULL)
-				xmlXPathFreeCompExpr(comppath);
-			xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
-						"XPath Syntax Error");
-		}
+			workspace->ctxt = xmlXPathNewContext(workspace->doctree);
+			if (workspace->ctxt == NULL)
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_OUT_OF_MEMORY,
+							"could not allocate XPath context");
 
-		/* Now evaluate the path expression. */
-		workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+			workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
+
+			/* compile the path */
+			comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
+			if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
+							"XPath Syntax Error");
+
+			/* Now evaluate the path expression. */
+			workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+
+			xmlXPathFreeCompExpr(comppath);
+			comppath = NULL;
+		}
+	}
+	PG_CATCH();
+	{
+		if (comppath != NULL)
+			xmlXPathFreeCompExpr(comppath);
+		cleanup_workspace(workspace);
 
-		xmlXPathFreeCompExpr(comppath);
+		PG_RE_THROW();
 	}
+	PG_END_TRY();
 
 	return workspace;
 }
-- 
2.54.0


--MP_/LMSk9=uMhuQ1QiIJDarDO8G--





^ permalink  raw  reply  [nested|flat] 611+ messages in thread

* [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths
@ 2026-06-01 22:41 Andrey Chernyy <andrey.cherny@tantorlabs.com>
  0 siblings, 0 replies; 611+ messages in thread

From: Andrey Chernyy @ 2026-06-01 22:41 UTC (permalink / raw)

pgxml_xpath() builds an xpath_workspace before returning it to
callers.  If an ERROR is thrown before the function returns, callers
have not received the workspace pointer yet and cannot run
cleanup_workspace().

Add local error cleanup for the partially built workspace and the
compiled XPath expression.  Also check xmlXPathNewContext() before
dereferencing the returned context.
---
 contrib/xml2/xpath.c | 51 +++++++++++++++++++++++++++-----------------
 1 file changed, 32 insertions(+), 19 deletions(-)

diff --git a/contrib/xml2/xpath.c b/contrib/xml2/xpath.c
index 9fe75cb5ff4..283bb51178d 100644
--- a/contrib/xml2/xpath.c
+++ b/contrib/xml2/xpath.c
@@ -497,36 +497,49 @@ static xpath_workspace *
 pgxml_xpath(text *document, xmlChar *xpath, PgXmlErrorContext *xmlerrcxt)
 {
 	int32		docsize = VARSIZE_ANY_EXHDR(document);
-	xmlXPathCompExprPtr comppath;
+	xmlXPathCompExprPtr volatile comppath = NULL;
 	xpath_workspace *workspace = palloc0_object(xpath_workspace);
 
 	workspace->doctree = NULL;
 	workspace->ctxt = NULL;
 	workspace->res = NULL;
 
-	workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
-									   docsize, NULL, NULL,
-									   XML_PARSE_NOENT);
-	if (workspace->doctree != NULL)
+	PG_TRY();
 	{
-		workspace->ctxt = xmlXPathNewContext(workspace->doctree);
-		workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
-
-		/* compile the path */
-		comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
-		if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+		workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
+										   docsize, NULL, NULL,
+										   XML_PARSE_NOENT);
+		if (workspace->doctree != NULL)
 		{
-			if (comppath != NULL)
-				xmlXPathFreeCompExpr(comppath);
-			xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
-						"XPath Syntax Error");
-		}
+			workspace->ctxt = xmlXPathNewContext(workspace->doctree);
+			if (workspace->ctxt == NULL)
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_OUT_OF_MEMORY,
+							"could not allocate XPath context");
 
-		/* Now evaluate the path expression. */
-		workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+			workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
+
+			/* compile the path */
+			comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
+			if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
+							"XPath Syntax Error");
+
+			/* Now evaluate the path expression. */
+			workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+
+			xmlXPathFreeCompExpr(comppath);
+			comppath = NULL;
+		}
+	}
+	PG_CATCH();
+	{
+		if (comppath != NULL)
+			xmlXPathFreeCompExpr(comppath);
+		cleanup_workspace(workspace);
 
-		xmlXPathFreeCompExpr(comppath);
+		PG_RE_THROW();
 	}
+	PG_END_TRY();
 
 	return workspace;
 }
-- 
2.54.0


--MP_/LMSk9=uMhuQ1QiIJDarDO8G--






^ permalink  raw  reply  [nested|flat] 611+ messages in thread

* [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths
@ 2026-06-01 22:41 Andrey Chernyy <andrey.cherny@tantorlabs.com>
  0 siblings, 0 replies; 611+ messages in thread

From: Andrey Chernyy @ 2026-06-01 22:41 UTC (permalink / raw)

pgxml_xpath() builds an xpath_workspace before returning it to
callers.  If an ERROR is thrown before the function returns, callers
have not received the workspace pointer yet and cannot run
cleanup_workspace().

Add local error cleanup for the partially built workspace and the
compiled XPath expression.  Also check xmlXPathNewContext() before
dereferencing the returned context.
---
 contrib/xml2/xpath.c | 51 +++++++++++++++++++++++++++-----------------
 1 file changed, 32 insertions(+), 19 deletions(-)

diff --git a/contrib/xml2/xpath.c b/contrib/xml2/xpath.c
index 9fe75cb5ff4..283bb51178d 100644
--- a/contrib/xml2/xpath.c
+++ b/contrib/xml2/xpath.c
@@ -497,36 +497,49 @@ static xpath_workspace *
 pgxml_xpath(text *document, xmlChar *xpath, PgXmlErrorContext *xmlerrcxt)
 {
 	int32		docsize = VARSIZE_ANY_EXHDR(document);
-	xmlXPathCompExprPtr comppath;
+	xmlXPathCompExprPtr volatile comppath = NULL;
 	xpath_workspace *workspace = palloc0_object(xpath_workspace);
 
 	workspace->doctree = NULL;
 	workspace->ctxt = NULL;
 	workspace->res = NULL;
 
-	workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
-									   docsize, NULL, NULL,
-									   XML_PARSE_NOENT);
-	if (workspace->doctree != NULL)
+	PG_TRY();
 	{
-		workspace->ctxt = xmlXPathNewContext(workspace->doctree);
-		workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
-
-		/* compile the path */
-		comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
-		if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+		workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
+										   docsize, NULL, NULL,
+										   XML_PARSE_NOENT);
+		if (workspace->doctree != NULL)
 		{
-			if (comppath != NULL)
-				xmlXPathFreeCompExpr(comppath);
-			xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
-						"XPath Syntax Error");
-		}
+			workspace->ctxt = xmlXPathNewContext(workspace->doctree);
+			if (workspace->ctxt == NULL)
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_OUT_OF_MEMORY,
+							"could not allocate XPath context");
 
-		/* Now evaluate the path expression. */
-		workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+			workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
+
+			/* compile the path */
+			comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
+			if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
+							"XPath Syntax Error");
+
+			/* Now evaluate the path expression. */
+			workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+
+			xmlXPathFreeCompExpr(comppath);
+			comppath = NULL;
+		}
+	}
+	PG_CATCH();
+	{
+		if (comppath != NULL)
+			xmlXPathFreeCompExpr(comppath);
+		cleanup_workspace(workspace);
 
-		xmlXPathFreeCompExpr(comppath);
+		PG_RE_THROW();
 	}
+	PG_END_TRY();
 
 	return workspace;
 }
-- 
2.54.0


--MP_/LMSk9=uMhuQ1QiIJDarDO8G--





^ permalink  raw  reply  [nested|flat] 611+ messages in thread

* [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths
@ 2026-06-01 22:41 Andrey Chernyy <andrey.cherny@tantorlabs.com>
  0 siblings, 0 replies; 611+ messages in thread

From: Andrey Chernyy @ 2026-06-01 22:41 UTC (permalink / raw)

pgxml_xpath() builds an xpath_workspace before returning it to
callers.  If an ERROR is thrown before the function returns, callers
have not received the workspace pointer yet and cannot run
cleanup_workspace().

Add local error cleanup for the partially built workspace and the
compiled XPath expression.  Also check xmlXPathNewContext() before
dereferencing the returned context.
---
 contrib/xml2/xpath.c | 51 +++++++++++++++++++++++++++-----------------
 1 file changed, 32 insertions(+), 19 deletions(-)

diff --git a/contrib/xml2/xpath.c b/contrib/xml2/xpath.c
index 9fe75cb5ff4..283bb51178d 100644
--- a/contrib/xml2/xpath.c
+++ b/contrib/xml2/xpath.c
@@ -497,36 +497,49 @@ static xpath_workspace *
 pgxml_xpath(text *document, xmlChar *xpath, PgXmlErrorContext *xmlerrcxt)
 {
 	int32		docsize = VARSIZE_ANY_EXHDR(document);
-	xmlXPathCompExprPtr comppath;
+	xmlXPathCompExprPtr volatile comppath = NULL;
 	xpath_workspace *workspace = palloc0_object(xpath_workspace);
 
 	workspace->doctree = NULL;
 	workspace->ctxt = NULL;
 	workspace->res = NULL;
 
-	workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
-									   docsize, NULL, NULL,
-									   XML_PARSE_NOENT);
-	if (workspace->doctree != NULL)
+	PG_TRY();
 	{
-		workspace->ctxt = xmlXPathNewContext(workspace->doctree);
-		workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
-
-		/* compile the path */
-		comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
-		if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+		workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
+										   docsize, NULL, NULL,
+										   XML_PARSE_NOENT);
+		if (workspace->doctree != NULL)
 		{
-			if (comppath != NULL)
-				xmlXPathFreeCompExpr(comppath);
-			xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
-						"XPath Syntax Error");
-		}
+			workspace->ctxt = xmlXPathNewContext(workspace->doctree);
+			if (workspace->ctxt == NULL)
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_OUT_OF_MEMORY,
+							"could not allocate XPath context");
 
-		/* Now evaluate the path expression. */
-		workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+			workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
+
+			/* compile the path */
+			comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
+			if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
+							"XPath Syntax Error");
+
+			/* Now evaluate the path expression. */
+			workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+
+			xmlXPathFreeCompExpr(comppath);
+			comppath = NULL;
+		}
+	}
+	PG_CATCH();
+	{
+		if (comppath != NULL)
+			xmlXPathFreeCompExpr(comppath);
+		cleanup_workspace(workspace);
 
-		xmlXPathFreeCompExpr(comppath);
+		PG_RE_THROW();
 	}
+	PG_END_TRY();
 
 	return workspace;
 }
-- 
2.54.0


--MP_/LMSk9=uMhuQ1QiIJDarDO8G--






^ permalink  raw  reply  [nested|flat] 611+ messages in thread

* [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths
@ 2026-06-01 22:41 Andrey Chernyy <andrey.cherny@tantorlabs.com>
  0 siblings, 0 replies; 611+ messages in thread

From: Andrey Chernyy @ 2026-06-01 22:41 UTC (permalink / raw)

pgxml_xpath() builds an xpath_workspace before returning it to
callers.  If an ERROR is thrown before the function returns, callers
have not received the workspace pointer yet and cannot run
cleanup_workspace().

Add local error cleanup for the partially built workspace and the
compiled XPath expression.  Also check xmlXPathNewContext() before
dereferencing the returned context.
---
 contrib/xml2/xpath.c | 51 +++++++++++++++++++++++++++-----------------
 1 file changed, 32 insertions(+), 19 deletions(-)

diff --git a/contrib/xml2/xpath.c b/contrib/xml2/xpath.c
index 9fe75cb5ff4..283bb51178d 100644
--- a/contrib/xml2/xpath.c
+++ b/contrib/xml2/xpath.c
@@ -497,36 +497,49 @@ static xpath_workspace *
 pgxml_xpath(text *document, xmlChar *xpath, PgXmlErrorContext *xmlerrcxt)
 {
 	int32		docsize = VARSIZE_ANY_EXHDR(document);
-	xmlXPathCompExprPtr comppath;
+	xmlXPathCompExprPtr volatile comppath = NULL;
 	xpath_workspace *workspace = palloc0_object(xpath_workspace);
 
 	workspace->doctree = NULL;
 	workspace->ctxt = NULL;
 	workspace->res = NULL;
 
-	workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
-									   docsize, NULL, NULL,
-									   XML_PARSE_NOENT);
-	if (workspace->doctree != NULL)
+	PG_TRY();
 	{
-		workspace->ctxt = xmlXPathNewContext(workspace->doctree);
-		workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
-
-		/* compile the path */
-		comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
-		if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+		workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
+										   docsize, NULL, NULL,
+										   XML_PARSE_NOENT);
+		if (workspace->doctree != NULL)
 		{
-			if (comppath != NULL)
-				xmlXPathFreeCompExpr(comppath);
-			xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
-						"XPath Syntax Error");
-		}
+			workspace->ctxt = xmlXPathNewContext(workspace->doctree);
+			if (workspace->ctxt == NULL)
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_OUT_OF_MEMORY,
+							"could not allocate XPath context");
 
-		/* Now evaluate the path expression. */
-		workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+			workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
+
+			/* compile the path */
+			comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
+			if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
+							"XPath Syntax Error");
+
+			/* Now evaluate the path expression. */
+			workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+
+			xmlXPathFreeCompExpr(comppath);
+			comppath = NULL;
+		}
+	}
+	PG_CATCH();
+	{
+		if (comppath != NULL)
+			xmlXPathFreeCompExpr(comppath);
+		cleanup_workspace(workspace);
 
-		xmlXPathFreeCompExpr(comppath);
+		PG_RE_THROW();
 	}
+	PG_END_TRY();
 
 	return workspace;
 }
-- 
2.54.0


--MP_/LMSk9=uMhuQ1QiIJDarDO8G--





^ permalink  raw  reply  [nested|flat] 611+ messages in thread

* [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths
@ 2026-06-01 22:41 Andrey Chernyy <andrey.cherny@tantorlabs.com>
  0 siblings, 0 replies; 611+ messages in thread

From: Andrey Chernyy @ 2026-06-01 22:41 UTC (permalink / raw)

pgxml_xpath() builds an xpath_workspace before returning it to
callers.  If an ERROR is thrown before the function returns, callers
have not received the workspace pointer yet and cannot run
cleanup_workspace().

Add local error cleanup for the partially built workspace and the
compiled XPath expression.  Also check xmlXPathNewContext() before
dereferencing the returned context.
---
 contrib/xml2/xpath.c | 51 +++++++++++++++++++++++++++-----------------
 1 file changed, 32 insertions(+), 19 deletions(-)

diff --git a/contrib/xml2/xpath.c b/contrib/xml2/xpath.c
index 9fe75cb5ff4..283bb51178d 100644
--- a/contrib/xml2/xpath.c
+++ b/contrib/xml2/xpath.c
@@ -497,36 +497,49 @@ static xpath_workspace *
 pgxml_xpath(text *document, xmlChar *xpath, PgXmlErrorContext *xmlerrcxt)
 {
 	int32		docsize = VARSIZE_ANY_EXHDR(document);
-	xmlXPathCompExprPtr comppath;
+	xmlXPathCompExprPtr volatile comppath = NULL;
 	xpath_workspace *workspace = palloc0_object(xpath_workspace);
 
 	workspace->doctree = NULL;
 	workspace->ctxt = NULL;
 	workspace->res = NULL;
 
-	workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
-									   docsize, NULL, NULL,
-									   XML_PARSE_NOENT);
-	if (workspace->doctree != NULL)
+	PG_TRY();
 	{
-		workspace->ctxt = xmlXPathNewContext(workspace->doctree);
-		workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
-
-		/* compile the path */
-		comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
-		if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+		workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
+										   docsize, NULL, NULL,
+										   XML_PARSE_NOENT);
+		if (workspace->doctree != NULL)
 		{
-			if (comppath != NULL)
-				xmlXPathFreeCompExpr(comppath);
-			xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
-						"XPath Syntax Error");
-		}
+			workspace->ctxt = xmlXPathNewContext(workspace->doctree);
+			if (workspace->ctxt == NULL)
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_OUT_OF_MEMORY,
+							"could not allocate XPath context");
 
-		/* Now evaluate the path expression. */
-		workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+			workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
+
+			/* compile the path */
+			comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
+			if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
+							"XPath Syntax Error");
+
+			/* Now evaluate the path expression. */
+			workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+
+			xmlXPathFreeCompExpr(comppath);
+			comppath = NULL;
+		}
+	}
+	PG_CATCH();
+	{
+		if (comppath != NULL)
+			xmlXPathFreeCompExpr(comppath);
+		cleanup_workspace(workspace);
 
-		xmlXPathFreeCompExpr(comppath);
+		PG_RE_THROW();
 	}
+	PG_END_TRY();
 
 	return workspace;
 }
-- 
2.54.0


--MP_/LMSk9=uMhuQ1QiIJDarDO8G--





^ permalink  raw  reply  [nested|flat] 611+ messages in thread

* [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths
@ 2026-06-01 22:41 Andrey Chernyy <andrey.cherny@tantorlabs.com>
  0 siblings, 0 replies; 611+ messages in thread

From: Andrey Chernyy @ 2026-06-01 22:41 UTC (permalink / raw)

pgxml_xpath() builds an xpath_workspace before returning it to
callers.  If an ERROR is thrown before the function returns, callers
have not received the workspace pointer yet and cannot run
cleanup_workspace().

Add local error cleanup for the partially built workspace and the
compiled XPath expression.  Also check xmlXPathNewContext() before
dereferencing the returned context.
---
 contrib/xml2/xpath.c | 51 +++++++++++++++++++++++++++-----------------
 1 file changed, 32 insertions(+), 19 deletions(-)

diff --git a/contrib/xml2/xpath.c b/contrib/xml2/xpath.c
index 9fe75cb5ff4..283bb51178d 100644
--- a/contrib/xml2/xpath.c
+++ b/contrib/xml2/xpath.c
@@ -497,36 +497,49 @@ static xpath_workspace *
 pgxml_xpath(text *document, xmlChar *xpath, PgXmlErrorContext *xmlerrcxt)
 {
 	int32		docsize = VARSIZE_ANY_EXHDR(document);
-	xmlXPathCompExprPtr comppath;
+	xmlXPathCompExprPtr volatile comppath = NULL;
 	xpath_workspace *workspace = palloc0_object(xpath_workspace);
 
 	workspace->doctree = NULL;
 	workspace->ctxt = NULL;
 	workspace->res = NULL;
 
-	workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
-									   docsize, NULL, NULL,
-									   XML_PARSE_NOENT);
-	if (workspace->doctree != NULL)
+	PG_TRY();
 	{
-		workspace->ctxt = xmlXPathNewContext(workspace->doctree);
-		workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
-
-		/* compile the path */
-		comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
-		if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+		workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
+										   docsize, NULL, NULL,
+										   XML_PARSE_NOENT);
+		if (workspace->doctree != NULL)
 		{
-			if (comppath != NULL)
-				xmlXPathFreeCompExpr(comppath);
-			xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
-						"XPath Syntax Error");
-		}
+			workspace->ctxt = xmlXPathNewContext(workspace->doctree);
+			if (workspace->ctxt == NULL)
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_OUT_OF_MEMORY,
+							"could not allocate XPath context");
 
-		/* Now evaluate the path expression. */
-		workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+			workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
+
+			/* compile the path */
+			comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
+			if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
+							"XPath Syntax Error");
+
+			/* Now evaluate the path expression. */
+			workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+
+			xmlXPathFreeCompExpr(comppath);
+			comppath = NULL;
+		}
+	}
+	PG_CATCH();
+	{
+		if (comppath != NULL)
+			xmlXPathFreeCompExpr(comppath);
+		cleanup_workspace(workspace);
 
-		xmlXPathFreeCompExpr(comppath);
+		PG_RE_THROW();
 	}
+	PG_END_TRY();
 
 	return workspace;
 }
-- 
2.54.0


--MP_/LMSk9=uMhuQ1QiIJDarDO8G--





^ permalink  raw  reply  [nested|flat] 611+ messages in thread

* [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths
@ 2026-06-01 22:41 Andrey Chernyy <andrey.cherny@tantorlabs.com>
  0 siblings, 0 replies; 611+ messages in thread

From: Andrey Chernyy @ 2026-06-01 22:41 UTC (permalink / raw)

pgxml_xpath() builds an xpath_workspace before returning it to
callers.  If an ERROR is thrown before the function returns, callers
have not received the workspace pointer yet and cannot run
cleanup_workspace().

Add local error cleanup for the partially built workspace and the
compiled XPath expression.  Also check xmlXPathNewContext() before
dereferencing the returned context.
---
 contrib/xml2/xpath.c | 51 +++++++++++++++++++++++++++-----------------
 1 file changed, 32 insertions(+), 19 deletions(-)

diff --git a/contrib/xml2/xpath.c b/contrib/xml2/xpath.c
index 9fe75cb5ff4..283bb51178d 100644
--- a/contrib/xml2/xpath.c
+++ b/contrib/xml2/xpath.c
@@ -497,36 +497,49 @@ static xpath_workspace *
 pgxml_xpath(text *document, xmlChar *xpath, PgXmlErrorContext *xmlerrcxt)
 {
 	int32		docsize = VARSIZE_ANY_EXHDR(document);
-	xmlXPathCompExprPtr comppath;
+	xmlXPathCompExprPtr volatile comppath = NULL;
 	xpath_workspace *workspace = palloc0_object(xpath_workspace);
 
 	workspace->doctree = NULL;
 	workspace->ctxt = NULL;
 	workspace->res = NULL;
 
-	workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
-									   docsize, NULL, NULL,
-									   XML_PARSE_NOENT);
-	if (workspace->doctree != NULL)
+	PG_TRY();
 	{
-		workspace->ctxt = xmlXPathNewContext(workspace->doctree);
-		workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
-
-		/* compile the path */
-		comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
-		if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+		workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
+										   docsize, NULL, NULL,
+										   XML_PARSE_NOENT);
+		if (workspace->doctree != NULL)
 		{
-			if (comppath != NULL)
-				xmlXPathFreeCompExpr(comppath);
-			xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
-						"XPath Syntax Error");
-		}
+			workspace->ctxt = xmlXPathNewContext(workspace->doctree);
+			if (workspace->ctxt == NULL)
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_OUT_OF_MEMORY,
+							"could not allocate XPath context");
 
-		/* Now evaluate the path expression. */
-		workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+			workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
+
+			/* compile the path */
+			comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
+			if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
+							"XPath Syntax Error");
+
+			/* Now evaluate the path expression. */
+			workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+
+			xmlXPathFreeCompExpr(comppath);
+			comppath = NULL;
+		}
+	}
+	PG_CATCH();
+	{
+		if (comppath != NULL)
+			xmlXPathFreeCompExpr(comppath);
+		cleanup_workspace(workspace);
 
-		xmlXPathFreeCompExpr(comppath);
+		PG_RE_THROW();
 	}
+	PG_END_TRY();
 
 	return workspace;
 }
-- 
2.54.0


--MP_/LMSk9=uMhuQ1QiIJDarDO8G--






^ permalink  raw  reply  [nested|flat] 611+ messages in thread

* [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths
@ 2026-06-01 22:41 Andrey Chernyy <andrey.cherny@tantorlabs.com>
  0 siblings, 0 replies; 611+ messages in thread

From: Andrey Chernyy @ 2026-06-01 22:41 UTC (permalink / raw)

pgxml_xpath() builds an xpath_workspace before returning it to
callers.  If an ERROR is thrown before the function returns, callers
have not received the workspace pointer yet and cannot run
cleanup_workspace().

Add local error cleanup for the partially built workspace and the
compiled XPath expression.  Also check xmlXPathNewContext() before
dereferencing the returned context.
---
 contrib/xml2/xpath.c | 51 +++++++++++++++++++++++++++-----------------
 1 file changed, 32 insertions(+), 19 deletions(-)

diff --git a/contrib/xml2/xpath.c b/contrib/xml2/xpath.c
index 9fe75cb5ff4..283bb51178d 100644
--- a/contrib/xml2/xpath.c
+++ b/contrib/xml2/xpath.c
@@ -497,36 +497,49 @@ static xpath_workspace *
 pgxml_xpath(text *document, xmlChar *xpath, PgXmlErrorContext *xmlerrcxt)
 {
 	int32		docsize = VARSIZE_ANY_EXHDR(document);
-	xmlXPathCompExprPtr comppath;
+	xmlXPathCompExprPtr volatile comppath = NULL;
 	xpath_workspace *workspace = palloc0_object(xpath_workspace);
 
 	workspace->doctree = NULL;
 	workspace->ctxt = NULL;
 	workspace->res = NULL;
 
-	workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
-									   docsize, NULL, NULL,
-									   XML_PARSE_NOENT);
-	if (workspace->doctree != NULL)
+	PG_TRY();
 	{
-		workspace->ctxt = xmlXPathNewContext(workspace->doctree);
-		workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
-
-		/* compile the path */
-		comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
-		if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+		workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
+										   docsize, NULL, NULL,
+										   XML_PARSE_NOENT);
+		if (workspace->doctree != NULL)
 		{
-			if (comppath != NULL)
-				xmlXPathFreeCompExpr(comppath);
-			xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
-						"XPath Syntax Error");
-		}
+			workspace->ctxt = xmlXPathNewContext(workspace->doctree);
+			if (workspace->ctxt == NULL)
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_OUT_OF_MEMORY,
+							"could not allocate XPath context");
 
-		/* Now evaluate the path expression. */
-		workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+			workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
+
+			/* compile the path */
+			comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
+			if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
+							"XPath Syntax Error");
+
+			/* Now evaluate the path expression. */
+			workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+
+			xmlXPathFreeCompExpr(comppath);
+			comppath = NULL;
+		}
+	}
+	PG_CATCH();
+	{
+		if (comppath != NULL)
+			xmlXPathFreeCompExpr(comppath);
+		cleanup_workspace(workspace);
 
-		xmlXPathFreeCompExpr(comppath);
+		PG_RE_THROW();
 	}
+	PG_END_TRY();
 
 	return workspace;
 }
-- 
2.54.0


--MP_/LMSk9=uMhuQ1QiIJDarDO8G--






^ permalink  raw  reply  [nested|flat] 611+ messages in thread

* [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths
@ 2026-06-01 22:41 Andrey Chernyy <andrey.cherny@tantorlabs.com>
  0 siblings, 0 replies; 611+ messages in thread

From: Andrey Chernyy @ 2026-06-01 22:41 UTC (permalink / raw)

pgxml_xpath() builds an xpath_workspace before returning it to
callers.  If an ERROR is thrown before the function returns, callers
have not received the workspace pointer yet and cannot run
cleanup_workspace().

Add local error cleanup for the partially built workspace and the
compiled XPath expression.  Also check xmlXPathNewContext() before
dereferencing the returned context.
---
 contrib/xml2/xpath.c | 51 +++++++++++++++++++++++++++-----------------
 1 file changed, 32 insertions(+), 19 deletions(-)

diff --git a/contrib/xml2/xpath.c b/contrib/xml2/xpath.c
index 9fe75cb5ff4..283bb51178d 100644
--- a/contrib/xml2/xpath.c
+++ b/contrib/xml2/xpath.c
@@ -497,36 +497,49 @@ static xpath_workspace *
 pgxml_xpath(text *document, xmlChar *xpath, PgXmlErrorContext *xmlerrcxt)
 {
 	int32		docsize = VARSIZE_ANY_EXHDR(document);
-	xmlXPathCompExprPtr comppath;
+	xmlXPathCompExprPtr volatile comppath = NULL;
 	xpath_workspace *workspace = palloc0_object(xpath_workspace);
 
 	workspace->doctree = NULL;
 	workspace->ctxt = NULL;
 	workspace->res = NULL;
 
-	workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
-									   docsize, NULL, NULL,
-									   XML_PARSE_NOENT);
-	if (workspace->doctree != NULL)
+	PG_TRY();
 	{
-		workspace->ctxt = xmlXPathNewContext(workspace->doctree);
-		workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
-
-		/* compile the path */
-		comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
-		if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+		workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
+										   docsize, NULL, NULL,
+										   XML_PARSE_NOENT);
+		if (workspace->doctree != NULL)
 		{
-			if (comppath != NULL)
-				xmlXPathFreeCompExpr(comppath);
-			xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
-						"XPath Syntax Error");
-		}
+			workspace->ctxt = xmlXPathNewContext(workspace->doctree);
+			if (workspace->ctxt == NULL)
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_OUT_OF_MEMORY,
+							"could not allocate XPath context");
 
-		/* Now evaluate the path expression. */
-		workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+			workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
+
+			/* compile the path */
+			comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
+			if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
+							"XPath Syntax Error");
+
+			/* Now evaluate the path expression. */
+			workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+
+			xmlXPathFreeCompExpr(comppath);
+			comppath = NULL;
+		}
+	}
+	PG_CATCH();
+	{
+		if (comppath != NULL)
+			xmlXPathFreeCompExpr(comppath);
+		cleanup_workspace(workspace);
 
-		xmlXPathFreeCompExpr(comppath);
+		PG_RE_THROW();
 	}
+	PG_END_TRY();
 
 	return workspace;
 }
-- 
2.54.0


--MP_/LMSk9=uMhuQ1QiIJDarDO8G--





^ permalink  raw  reply  [nested|flat] 611+ messages in thread

* [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths
@ 2026-06-01 22:41 Andrey Chernyy <andrey.cherny@tantorlabs.com>
  0 siblings, 0 replies; 611+ messages in thread

From: Andrey Chernyy @ 2026-06-01 22:41 UTC (permalink / raw)

pgxml_xpath() builds an xpath_workspace before returning it to
callers.  If an ERROR is thrown before the function returns, callers
have not received the workspace pointer yet and cannot run
cleanup_workspace().

Add local error cleanup for the partially built workspace and the
compiled XPath expression.  Also check xmlXPathNewContext() before
dereferencing the returned context.
---
 contrib/xml2/xpath.c | 51 +++++++++++++++++++++++++++-----------------
 1 file changed, 32 insertions(+), 19 deletions(-)

diff --git a/contrib/xml2/xpath.c b/contrib/xml2/xpath.c
index 9fe75cb5ff4..283bb51178d 100644
--- a/contrib/xml2/xpath.c
+++ b/contrib/xml2/xpath.c
@@ -497,36 +497,49 @@ static xpath_workspace *
 pgxml_xpath(text *document, xmlChar *xpath, PgXmlErrorContext *xmlerrcxt)
 {
 	int32		docsize = VARSIZE_ANY_EXHDR(document);
-	xmlXPathCompExprPtr comppath;
+	xmlXPathCompExprPtr volatile comppath = NULL;
 	xpath_workspace *workspace = palloc0_object(xpath_workspace);
 
 	workspace->doctree = NULL;
 	workspace->ctxt = NULL;
 	workspace->res = NULL;
 
-	workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
-									   docsize, NULL, NULL,
-									   XML_PARSE_NOENT);
-	if (workspace->doctree != NULL)
+	PG_TRY();
 	{
-		workspace->ctxt = xmlXPathNewContext(workspace->doctree);
-		workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
-
-		/* compile the path */
-		comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
-		if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+		workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
+										   docsize, NULL, NULL,
+										   XML_PARSE_NOENT);
+		if (workspace->doctree != NULL)
 		{
-			if (comppath != NULL)
-				xmlXPathFreeCompExpr(comppath);
-			xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
-						"XPath Syntax Error");
-		}
+			workspace->ctxt = xmlXPathNewContext(workspace->doctree);
+			if (workspace->ctxt == NULL)
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_OUT_OF_MEMORY,
+							"could not allocate XPath context");
 
-		/* Now evaluate the path expression. */
-		workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+			workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
+
+			/* compile the path */
+			comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
+			if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
+							"XPath Syntax Error");
+
+			/* Now evaluate the path expression. */
+			workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+
+			xmlXPathFreeCompExpr(comppath);
+			comppath = NULL;
+		}
+	}
+	PG_CATCH();
+	{
+		if (comppath != NULL)
+			xmlXPathFreeCompExpr(comppath);
+		cleanup_workspace(workspace);
 
-		xmlXPathFreeCompExpr(comppath);
+		PG_RE_THROW();
 	}
+	PG_END_TRY();
 
 	return workspace;
 }
-- 
2.54.0


--MP_/LMSk9=uMhuQ1QiIJDarDO8G--





^ permalink  raw  reply  [nested|flat] 611+ messages in thread

* [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths
@ 2026-06-01 22:41 Andrey Chernyy <andrey.cherny@tantorlabs.com>
  0 siblings, 0 replies; 611+ messages in thread

From: Andrey Chernyy @ 2026-06-01 22:41 UTC (permalink / raw)

pgxml_xpath() builds an xpath_workspace before returning it to
callers.  If an ERROR is thrown before the function returns, callers
have not received the workspace pointer yet and cannot run
cleanup_workspace().

Add local error cleanup for the partially built workspace and the
compiled XPath expression.  Also check xmlXPathNewContext() before
dereferencing the returned context.
---
 contrib/xml2/xpath.c | 51 +++++++++++++++++++++++++++-----------------
 1 file changed, 32 insertions(+), 19 deletions(-)

diff --git a/contrib/xml2/xpath.c b/contrib/xml2/xpath.c
index 9fe75cb5ff4..283bb51178d 100644
--- a/contrib/xml2/xpath.c
+++ b/contrib/xml2/xpath.c
@@ -497,36 +497,49 @@ static xpath_workspace *
 pgxml_xpath(text *document, xmlChar *xpath, PgXmlErrorContext *xmlerrcxt)
 {
 	int32		docsize = VARSIZE_ANY_EXHDR(document);
-	xmlXPathCompExprPtr comppath;
+	xmlXPathCompExprPtr volatile comppath = NULL;
 	xpath_workspace *workspace = palloc0_object(xpath_workspace);
 
 	workspace->doctree = NULL;
 	workspace->ctxt = NULL;
 	workspace->res = NULL;
 
-	workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
-									   docsize, NULL, NULL,
-									   XML_PARSE_NOENT);
-	if (workspace->doctree != NULL)
+	PG_TRY();
 	{
-		workspace->ctxt = xmlXPathNewContext(workspace->doctree);
-		workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
-
-		/* compile the path */
-		comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
-		if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+		workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
+										   docsize, NULL, NULL,
+										   XML_PARSE_NOENT);
+		if (workspace->doctree != NULL)
 		{
-			if (comppath != NULL)
-				xmlXPathFreeCompExpr(comppath);
-			xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
-						"XPath Syntax Error");
-		}
+			workspace->ctxt = xmlXPathNewContext(workspace->doctree);
+			if (workspace->ctxt == NULL)
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_OUT_OF_MEMORY,
+							"could not allocate XPath context");
 
-		/* Now evaluate the path expression. */
-		workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+			workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
+
+			/* compile the path */
+			comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
+			if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
+							"XPath Syntax Error");
+
+			/* Now evaluate the path expression. */
+			workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+
+			xmlXPathFreeCompExpr(comppath);
+			comppath = NULL;
+		}
+	}
+	PG_CATCH();
+	{
+		if (comppath != NULL)
+			xmlXPathFreeCompExpr(comppath);
+		cleanup_workspace(workspace);
 
-		xmlXPathFreeCompExpr(comppath);
+		PG_RE_THROW();
 	}
+	PG_END_TRY();
 
 	return workspace;
 }
-- 
2.54.0


--MP_/LMSk9=uMhuQ1QiIJDarDO8G--





^ permalink  raw  reply  [nested|flat] 611+ messages in thread

* [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths
@ 2026-06-01 22:41 Andrey Chernyy <andrey.cherny@tantorlabs.com>
  0 siblings, 0 replies; 611+ messages in thread

From: Andrey Chernyy @ 2026-06-01 22:41 UTC (permalink / raw)

pgxml_xpath() builds an xpath_workspace before returning it to
callers.  If an ERROR is thrown before the function returns, callers
have not received the workspace pointer yet and cannot run
cleanup_workspace().

Add local error cleanup for the partially built workspace and the
compiled XPath expression.  Also check xmlXPathNewContext() before
dereferencing the returned context.
---
 contrib/xml2/xpath.c | 51 +++++++++++++++++++++++++++-----------------
 1 file changed, 32 insertions(+), 19 deletions(-)

diff --git a/contrib/xml2/xpath.c b/contrib/xml2/xpath.c
index 9fe75cb5ff4..283bb51178d 100644
--- a/contrib/xml2/xpath.c
+++ b/contrib/xml2/xpath.c
@@ -497,36 +497,49 @@ static xpath_workspace *
 pgxml_xpath(text *document, xmlChar *xpath, PgXmlErrorContext *xmlerrcxt)
 {
 	int32		docsize = VARSIZE_ANY_EXHDR(document);
-	xmlXPathCompExprPtr comppath;
+	xmlXPathCompExprPtr volatile comppath = NULL;
 	xpath_workspace *workspace = palloc0_object(xpath_workspace);
 
 	workspace->doctree = NULL;
 	workspace->ctxt = NULL;
 	workspace->res = NULL;
 
-	workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
-									   docsize, NULL, NULL,
-									   XML_PARSE_NOENT);
-	if (workspace->doctree != NULL)
+	PG_TRY();
 	{
-		workspace->ctxt = xmlXPathNewContext(workspace->doctree);
-		workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
-
-		/* compile the path */
-		comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
-		if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+		workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
+										   docsize, NULL, NULL,
+										   XML_PARSE_NOENT);
+		if (workspace->doctree != NULL)
 		{
-			if (comppath != NULL)
-				xmlXPathFreeCompExpr(comppath);
-			xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
-						"XPath Syntax Error");
-		}
+			workspace->ctxt = xmlXPathNewContext(workspace->doctree);
+			if (workspace->ctxt == NULL)
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_OUT_OF_MEMORY,
+							"could not allocate XPath context");
 
-		/* Now evaluate the path expression. */
-		workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+			workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
+
+			/* compile the path */
+			comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
+			if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
+							"XPath Syntax Error");
+
+			/* Now evaluate the path expression. */
+			workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+
+			xmlXPathFreeCompExpr(comppath);
+			comppath = NULL;
+		}
+	}
+	PG_CATCH();
+	{
+		if (comppath != NULL)
+			xmlXPathFreeCompExpr(comppath);
+		cleanup_workspace(workspace);
 
-		xmlXPathFreeCompExpr(comppath);
+		PG_RE_THROW();
 	}
+	PG_END_TRY();
 
 	return workspace;
 }
-- 
2.54.0


--MP_/LMSk9=uMhuQ1QiIJDarDO8G--






^ permalink  raw  reply  [nested|flat] 611+ messages in thread

* [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths
@ 2026-06-01 22:41 Andrey Chernyy <andrey.cherny@tantorlabs.com>
  0 siblings, 0 replies; 611+ messages in thread

From: Andrey Chernyy @ 2026-06-01 22:41 UTC (permalink / raw)

pgxml_xpath() builds an xpath_workspace before returning it to
callers.  If an ERROR is thrown before the function returns, callers
have not received the workspace pointer yet and cannot run
cleanup_workspace().

Add local error cleanup for the partially built workspace and the
compiled XPath expression.  Also check xmlXPathNewContext() before
dereferencing the returned context.
---
 contrib/xml2/xpath.c | 51 +++++++++++++++++++++++++++-----------------
 1 file changed, 32 insertions(+), 19 deletions(-)

diff --git a/contrib/xml2/xpath.c b/contrib/xml2/xpath.c
index 9fe75cb5ff4..283bb51178d 100644
--- a/contrib/xml2/xpath.c
+++ b/contrib/xml2/xpath.c
@@ -497,36 +497,49 @@ static xpath_workspace *
 pgxml_xpath(text *document, xmlChar *xpath, PgXmlErrorContext *xmlerrcxt)
 {
 	int32		docsize = VARSIZE_ANY_EXHDR(document);
-	xmlXPathCompExprPtr comppath;
+	xmlXPathCompExprPtr volatile comppath = NULL;
 	xpath_workspace *workspace = palloc0_object(xpath_workspace);
 
 	workspace->doctree = NULL;
 	workspace->ctxt = NULL;
 	workspace->res = NULL;
 
-	workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
-									   docsize, NULL, NULL,
-									   XML_PARSE_NOENT);
-	if (workspace->doctree != NULL)
+	PG_TRY();
 	{
-		workspace->ctxt = xmlXPathNewContext(workspace->doctree);
-		workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
-
-		/* compile the path */
-		comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
-		if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+		workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
+										   docsize, NULL, NULL,
+										   XML_PARSE_NOENT);
+		if (workspace->doctree != NULL)
 		{
-			if (comppath != NULL)
-				xmlXPathFreeCompExpr(comppath);
-			xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
-						"XPath Syntax Error");
-		}
+			workspace->ctxt = xmlXPathNewContext(workspace->doctree);
+			if (workspace->ctxt == NULL)
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_OUT_OF_MEMORY,
+							"could not allocate XPath context");
 
-		/* Now evaluate the path expression. */
-		workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+			workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
+
+			/* compile the path */
+			comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
+			if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
+							"XPath Syntax Error");
+
+			/* Now evaluate the path expression. */
+			workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+
+			xmlXPathFreeCompExpr(comppath);
+			comppath = NULL;
+		}
+	}
+	PG_CATCH();
+	{
+		if (comppath != NULL)
+			xmlXPathFreeCompExpr(comppath);
+		cleanup_workspace(workspace);
 
-		xmlXPathFreeCompExpr(comppath);
+		PG_RE_THROW();
 	}
+	PG_END_TRY();
 
 	return workspace;
 }
-- 
2.54.0


--MP_/LMSk9=uMhuQ1QiIJDarDO8G--





^ permalink  raw  reply  [nested|flat] 611+ messages in thread

* [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths
@ 2026-06-01 22:41 Andrey Chernyy <andrey.cherny@tantorlabs.com>
  0 siblings, 0 replies; 611+ messages in thread

From: Andrey Chernyy @ 2026-06-01 22:41 UTC (permalink / raw)

pgxml_xpath() builds an xpath_workspace before returning it to
callers.  If an ERROR is thrown before the function returns, callers
have not received the workspace pointer yet and cannot run
cleanup_workspace().

Add local error cleanup for the partially built workspace and the
compiled XPath expression.  Also check xmlXPathNewContext() before
dereferencing the returned context.
---
 contrib/xml2/xpath.c | 51 +++++++++++++++++++++++++++-----------------
 1 file changed, 32 insertions(+), 19 deletions(-)

diff --git a/contrib/xml2/xpath.c b/contrib/xml2/xpath.c
index 9fe75cb5ff4..283bb51178d 100644
--- a/contrib/xml2/xpath.c
+++ b/contrib/xml2/xpath.c
@@ -497,36 +497,49 @@ static xpath_workspace *
 pgxml_xpath(text *document, xmlChar *xpath, PgXmlErrorContext *xmlerrcxt)
 {
 	int32		docsize = VARSIZE_ANY_EXHDR(document);
-	xmlXPathCompExprPtr comppath;
+	xmlXPathCompExprPtr volatile comppath = NULL;
 	xpath_workspace *workspace = palloc0_object(xpath_workspace);
 
 	workspace->doctree = NULL;
 	workspace->ctxt = NULL;
 	workspace->res = NULL;
 
-	workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
-									   docsize, NULL, NULL,
-									   XML_PARSE_NOENT);
-	if (workspace->doctree != NULL)
+	PG_TRY();
 	{
-		workspace->ctxt = xmlXPathNewContext(workspace->doctree);
-		workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
-
-		/* compile the path */
-		comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
-		if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+		workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
+										   docsize, NULL, NULL,
+										   XML_PARSE_NOENT);
+		if (workspace->doctree != NULL)
 		{
-			if (comppath != NULL)
-				xmlXPathFreeCompExpr(comppath);
-			xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
-						"XPath Syntax Error");
-		}
+			workspace->ctxt = xmlXPathNewContext(workspace->doctree);
+			if (workspace->ctxt == NULL)
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_OUT_OF_MEMORY,
+							"could not allocate XPath context");
 
-		/* Now evaluate the path expression. */
-		workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+			workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
+
+			/* compile the path */
+			comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
+			if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
+							"XPath Syntax Error");
+
+			/* Now evaluate the path expression. */
+			workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+
+			xmlXPathFreeCompExpr(comppath);
+			comppath = NULL;
+		}
+	}
+	PG_CATCH();
+	{
+		if (comppath != NULL)
+			xmlXPathFreeCompExpr(comppath);
+		cleanup_workspace(workspace);
 
-		xmlXPathFreeCompExpr(comppath);
+		PG_RE_THROW();
 	}
+	PG_END_TRY();
 
 	return workspace;
 }
-- 
2.54.0


--MP_/LMSk9=uMhuQ1QiIJDarDO8G--






^ permalink  raw  reply  [nested|flat] 611+ messages in thread

* [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths
@ 2026-06-01 22:41 Andrey Chernyy <andrey.cherny@tantorlabs.com>
  0 siblings, 0 replies; 611+ messages in thread

From: Andrey Chernyy @ 2026-06-01 22:41 UTC (permalink / raw)

pgxml_xpath() builds an xpath_workspace before returning it to
callers.  If an ERROR is thrown before the function returns, callers
have not received the workspace pointer yet and cannot run
cleanup_workspace().

Add local error cleanup for the partially built workspace and the
compiled XPath expression.  Also check xmlXPathNewContext() before
dereferencing the returned context.
---
 contrib/xml2/xpath.c | 51 +++++++++++++++++++++++++++-----------------
 1 file changed, 32 insertions(+), 19 deletions(-)

diff --git a/contrib/xml2/xpath.c b/contrib/xml2/xpath.c
index 9fe75cb5ff4..283bb51178d 100644
--- a/contrib/xml2/xpath.c
+++ b/contrib/xml2/xpath.c
@@ -497,36 +497,49 @@ static xpath_workspace *
 pgxml_xpath(text *document, xmlChar *xpath, PgXmlErrorContext *xmlerrcxt)
 {
 	int32		docsize = VARSIZE_ANY_EXHDR(document);
-	xmlXPathCompExprPtr comppath;
+	xmlXPathCompExprPtr volatile comppath = NULL;
 	xpath_workspace *workspace = palloc0_object(xpath_workspace);
 
 	workspace->doctree = NULL;
 	workspace->ctxt = NULL;
 	workspace->res = NULL;
 
-	workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
-									   docsize, NULL, NULL,
-									   XML_PARSE_NOENT);
-	if (workspace->doctree != NULL)
+	PG_TRY();
 	{
-		workspace->ctxt = xmlXPathNewContext(workspace->doctree);
-		workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
-
-		/* compile the path */
-		comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
-		if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+		workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
+										   docsize, NULL, NULL,
+										   XML_PARSE_NOENT);
+		if (workspace->doctree != NULL)
 		{
-			if (comppath != NULL)
-				xmlXPathFreeCompExpr(comppath);
-			xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
-						"XPath Syntax Error");
-		}
+			workspace->ctxt = xmlXPathNewContext(workspace->doctree);
+			if (workspace->ctxt == NULL)
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_OUT_OF_MEMORY,
+							"could not allocate XPath context");
 
-		/* Now evaluate the path expression. */
-		workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+			workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
+
+			/* compile the path */
+			comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
+			if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
+							"XPath Syntax Error");
+
+			/* Now evaluate the path expression. */
+			workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+
+			xmlXPathFreeCompExpr(comppath);
+			comppath = NULL;
+		}
+	}
+	PG_CATCH();
+	{
+		if (comppath != NULL)
+			xmlXPathFreeCompExpr(comppath);
+		cleanup_workspace(workspace);
 
-		xmlXPathFreeCompExpr(comppath);
+		PG_RE_THROW();
 	}
+	PG_END_TRY();
 
 	return workspace;
 }
-- 
2.54.0


--MP_/LMSk9=uMhuQ1QiIJDarDO8G--





^ permalink  raw  reply  [nested|flat] 611+ messages in thread

* [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths
@ 2026-06-01 22:41 Andrey Chernyy <andrey.cherny@tantorlabs.com>
  0 siblings, 0 replies; 611+ messages in thread

From: Andrey Chernyy @ 2026-06-01 22:41 UTC (permalink / raw)

pgxml_xpath() builds an xpath_workspace before returning it to
callers.  If an ERROR is thrown before the function returns, callers
have not received the workspace pointer yet and cannot run
cleanup_workspace().

Add local error cleanup for the partially built workspace and the
compiled XPath expression.  Also check xmlXPathNewContext() before
dereferencing the returned context.
---
 contrib/xml2/xpath.c | 51 +++++++++++++++++++++++++++-----------------
 1 file changed, 32 insertions(+), 19 deletions(-)

diff --git a/contrib/xml2/xpath.c b/contrib/xml2/xpath.c
index 9fe75cb5ff4..283bb51178d 100644
--- a/contrib/xml2/xpath.c
+++ b/contrib/xml2/xpath.c
@@ -497,36 +497,49 @@ static xpath_workspace *
 pgxml_xpath(text *document, xmlChar *xpath, PgXmlErrorContext *xmlerrcxt)
 {
 	int32		docsize = VARSIZE_ANY_EXHDR(document);
-	xmlXPathCompExprPtr comppath;
+	xmlXPathCompExprPtr volatile comppath = NULL;
 	xpath_workspace *workspace = palloc0_object(xpath_workspace);
 
 	workspace->doctree = NULL;
 	workspace->ctxt = NULL;
 	workspace->res = NULL;
 
-	workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
-									   docsize, NULL, NULL,
-									   XML_PARSE_NOENT);
-	if (workspace->doctree != NULL)
+	PG_TRY();
 	{
-		workspace->ctxt = xmlXPathNewContext(workspace->doctree);
-		workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
-
-		/* compile the path */
-		comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
-		if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+		workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
+										   docsize, NULL, NULL,
+										   XML_PARSE_NOENT);
+		if (workspace->doctree != NULL)
 		{
-			if (comppath != NULL)
-				xmlXPathFreeCompExpr(comppath);
-			xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
-						"XPath Syntax Error");
-		}
+			workspace->ctxt = xmlXPathNewContext(workspace->doctree);
+			if (workspace->ctxt == NULL)
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_OUT_OF_MEMORY,
+							"could not allocate XPath context");
 
-		/* Now evaluate the path expression. */
-		workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+			workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
+
+			/* compile the path */
+			comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
+			if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
+							"XPath Syntax Error");
+
+			/* Now evaluate the path expression. */
+			workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+
+			xmlXPathFreeCompExpr(comppath);
+			comppath = NULL;
+		}
+	}
+	PG_CATCH();
+	{
+		if (comppath != NULL)
+			xmlXPathFreeCompExpr(comppath);
+		cleanup_workspace(workspace);
 
-		xmlXPathFreeCompExpr(comppath);
+		PG_RE_THROW();
 	}
+	PG_END_TRY();
 
 	return workspace;
 }
-- 
2.54.0


--MP_/LMSk9=uMhuQ1QiIJDarDO8G--






^ permalink  raw  reply  [nested|flat] 611+ messages in thread

* [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths
@ 2026-06-01 22:41 Andrey Chernyy <andrey.cherny@tantorlabs.com>
  0 siblings, 0 replies; 611+ messages in thread

From: Andrey Chernyy @ 2026-06-01 22:41 UTC (permalink / raw)

pgxml_xpath() builds an xpath_workspace before returning it to
callers.  If an ERROR is thrown before the function returns, callers
have not received the workspace pointer yet and cannot run
cleanup_workspace().

Add local error cleanup for the partially built workspace and the
compiled XPath expression.  Also check xmlXPathNewContext() before
dereferencing the returned context.
---
 contrib/xml2/xpath.c | 51 +++++++++++++++++++++++++++-----------------
 1 file changed, 32 insertions(+), 19 deletions(-)

diff --git a/contrib/xml2/xpath.c b/contrib/xml2/xpath.c
index 9fe75cb5ff4..283bb51178d 100644
--- a/contrib/xml2/xpath.c
+++ b/contrib/xml2/xpath.c
@@ -497,36 +497,49 @@ static xpath_workspace *
 pgxml_xpath(text *document, xmlChar *xpath, PgXmlErrorContext *xmlerrcxt)
 {
 	int32		docsize = VARSIZE_ANY_EXHDR(document);
-	xmlXPathCompExprPtr comppath;
+	xmlXPathCompExprPtr volatile comppath = NULL;
 	xpath_workspace *workspace = palloc0_object(xpath_workspace);
 
 	workspace->doctree = NULL;
 	workspace->ctxt = NULL;
 	workspace->res = NULL;
 
-	workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
-									   docsize, NULL, NULL,
-									   XML_PARSE_NOENT);
-	if (workspace->doctree != NULL)
+	PG_TRY();
 	{
-		workspace->ctxt = xmlXPathNewContext(workspace->doctree);
-		workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
-
-		/* compile the path */
-		comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
-		if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+		workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
+										   docsize, NULL, NULL,
+										   XML_PARSE_NOENT);
+		if (workspace->doctree != NULL)
 		{
-			if (comppath != NULL)
-				xmlXPathFreeCompExpr(comppath);
-			xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
-						"XPath Syntax Error");
-		}
+			workspace->ctxt = xmlXPathNewContext(workspace->doctree);
+			if (workspace->ctxt == NULL)
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_OUT_OF_MEMORY,
+							"could not allocate XPath context");
 
-		/* Now evaluate the path expression. */
-		workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+			workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
+
+			/* compile the path */
+			comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
+			if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
+							"XPath Syntax Error");
+
+			/* Now evaluate the path expression. */
+			workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+
+			xmlXPathFreeCompExpr(comppath);
+			comppath = NULL;
+		}
+	}
+	PG_CATCH();
+	{
+		if (comppath != NULL)
+			xmlXPathFreeCompExpr(comppath);
+		cleanup_workspace(workspace);
 
-		xmlXPathFreeCompExpr(comppath);
+		PG_RE_THROW();
 	}
+	PG_END_TRY();
 
 	return workspace;
 }
-- 
2.54.0


--MP_/LMSk9=uMhuQ1QiIJDarDO8G--





^ permalink  raw  reply  [nested|flat] 611+ messages in thread

* [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths
@ 2026-06-01 22:41 Andrey Chernyy <andrey.cherny@tantorlabs.com>
  0 siblings, 0 replies; 611+ messages in thread

From: Andrey Chernyy @ 2026-06-01 22:41 UTC (permalink / raw)

pgxml_xpath() builds an xpath_workspace before returning it to
callers.  If an ERROR is thrown before the function returns, callers
have not received the workspace pointer yet and cannot run
cleanup_workspace().

Add local error cleanup for the partially built workspace and the
compiled XPath expression.  Also check xmlXPathNewContext() before
dereferencing the returned context.
---
 contrib/xml2/xpath.c | 51 +++++++++++++++++++++++++++-----------------
 1 file changed, 32 insertions(+), 19 deletions(-)

diff --git a/contrib/xml2/xpath.c b/contrib/xml2/xpath.c
index 9fe75cb5ff4..283bb51178d 100644
--- a/contrib/xml2/xpath.c
+++ b/contrib/xml2/xpath.c
@@ -497,36 +497,49 @@ static xpath_workspace *
 pgxml_xpath(text *document, xmlChar *xpath, PgXmlErrorContext *xmlerrcxt)
 {
 	int32		docsize = VARSIZE_ANY_EXHDR(document);
-	xmlXPathCompExprPtr comppath;
+	xmlXPathCompExprPtr volatile comppath = NULL;
 	xpath_workspace *workspace = palloc0_object(xpath_workspace);
 
 	workspace->doctree = NULL;
 	workspace->ctxt = NULL;
 	workspace->res = NULL;
 
-	workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
-									   docsize, NULL, NULL,
-									   XML_PARSE_NOENT);
-	if (workspace->doctree != NULL)
+	PG_TRY();
 	{
-		workspace->ctxt = xmlXPathNewContext(workspace->doctree);
-		workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
-
-		/* compile the path */
-		comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
-		if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+		workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
+										   docsize, NULL, NULL,
+										   XML_PARSE_NOENT);
+		if (workspace->doctree != NULL)
 		{
-			if (comppath != NULL)
-				xmlXPathFreeCompExpr(comppath);
-			xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
-						"XPath Syntax Error");
-		}
+			workspace->ctxt = xmlXPathNewContext(workspace->doctree);
+			if (workspace->ctxt == NULL)
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_OUT_OF_MEMORY,
+							"could not allocate XPath context");
 
-		/* Now evaluate the path expression. */
-		workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+			workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
+
+			/* compile the path */
+			comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
+			if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
+							"XPath Syntax Error");
+
+			/* Now evaluate the path expression. */
+			workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+
+			xmlXPathFreeCompExpr(comppath);
+			comppath = NULL;
+		}
+	}
+	PG_CATCH();
+	{
+		if (comppath != NULL)
+			xmlXPathFreeCompExpr(comppath);
+		cleanup_workspace(workspace);
 
-		xmlXPathFreeCompExpr(comppath);
+		PG_RE_THROW();
 	}
+	PG_END_TRY();
 
 	return workspace;
 }
-- 
2.54.0


--MP_/LMSk9=uMhuQ1QiIJDarDO8G--





^ permalink  raw  reply  [nested|flat] 611+ messages in thread

* [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths
@ 2026-06-01 22:41 Andrey Chernyy <andrey.cherny@tantorlabs.com>
  0 siblings, 0 replies; 611+ messages in thread

From: Andrey Chernyy @ 2026-06-01 22:41 UTC (permalink / raw)

pgxml_xpath() builds an xpath_workspace before returning it to
callers.  If an ERROR is thrown before the function returns, callers
have not received the workspace pointer yet and cannot run
cleanup_workspace().

Add local error cleanup for the partially built workspace and the
compiled XPath expression.  Also check xmlXPathNewContext() before
dereferencing the returned context.
---
 contrib/xml2/xpath.c | 51 +++++++++++++++++++++++++++-----------------
 1 file changed, 32 insertions(+), 19 deletions(-)

diff --git a/contrib/xml2/xpath.c b/contrib/xml2/xpath.c
index 9fe75cb5ff4..283bb51178d 100644
--- a/contrib/xml2/xpath.c
+++ b/contrib/xml2/xpath.c
@@ -497,36 +497,49 @@ static xpath_workspace *
 pgxml_xpath(text *document, xmlChar *xpath, PgXmlErrorContext *xmlerrcxt)
 {
 	int32		docsize = VARSIZE_ANY_EXHDR(document);
-	xmlXPathCompExprPtr comppath;
+	xmlXPathCompExprPtr volatile comppath = NULL;
 	xpath_workspace *workspace = palloc0_object(xpath_workspace);
 
 	workspace->doctree = NULL;
 	workspace->ctxt = NULL;
 	workspace->res = NULL;
 
-	workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
-									   docsize, NULL, NULL,
-									   XML_PARSE_NOENT);
-	if (workspace->doctree != NULL)
+	PG_TRY();
 	{
-		workspace->ctxt = xmlXPathNewContext(workspace->doctree);
-		workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
-
-		/* compile the path */
-		comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
-		if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+		workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
+										   docsize, NULL, NULL,
+										   XML_PARSE_NOENT);
+		if (workspace->doctree != NULL)
 		{
-			if (comppath != NULL)
-				xmlXPathFreeCompExpr(comppath);
-			xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
-						"XPath Syntax Error");
-		}
+			workspace->ctxt = xmlXPathNewContext(workspace->doctree);
+			if (workspace->ctxt == NULL)
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_OUT_OF_MEMORY,
+							"could not allocate XPath context");
 
-		/* Now evaluate the path expression. */
-		workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+			workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
+
+			/* compile the path */
+			comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
+			if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
+							"XPath Syntax Error");
+
+			/* Now evaluate the path expression. */
+			workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+
+			xmlXPathFreeCompExpr(comppath);
+			comppath = NULL;
+		}
+	}
+	PG_CATCH();
+	{
+		if (comppath != NULL)
+			xmlXPathFreeCompExpr(comppath);
+		cleanup_workspace(workspace);
 
-		xmlXPathFreeCompExpr(comppath);
+		PG_RE_THROW();
 	}
+	PG_END_TRY();
 
 	return workspace;
 }
-- 
2.54.0


--MP_/LMSk9=uMhuQ1QiIJDarDO8G--





^ permalink  raw  reply  [nested|flat] 611+ messages in thread

* [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths
@ 2026-06-01 22:41 Andrey Chernyy <andrey.cherny@tantorlabs.com>
  0 siblings, 0 replies; 611+ messages in thread

From: Andrey Chernyy @ 2026-06-01 22:41 UTC (permalink / raw)

pgxml_xpath() builds an xpath_workspace before returning it to
callers.  If an ERROR is thrown before the function returns, callers
have not received the workspace pointer yet and cannot run
cleanup_workspace().

Add local error cleanup for the partially built workspace and the
compiled XPath expression.  Also check xmlXPathNewContext() before
dereferencing the returned context.
---
 contrib/xml2/xpath.c | 51 +++++++++++++++++++++++++++-----------------
 1 file changed, 32 insertions(+), 19 deletions(-)

diff --git a/contrib/xml2/xpath.c b/contrib/xml2/xpath.c
index 9fe75cb5ff4..283bb51178d 100644
--- a/contrib/xml2/xpath.c
+++ b/contrib/xml2/xpath.c
@@ -497,36 +497,49 @@ static xpath_workspace *
 pgxml_xpath(text *document, xmlChar *xpath, PgXmlErrorContext *xmlerrcxt)
 {
 	int32		docsize = VARSIZE_ANY_EXHDR(document);
-	xmlXPathCompExprPtr comppath;
+	xmlXPathCompExprPtr volatile comppath = NULL;
 	xpath_workspace *workspace = palloc0_object(xpath_workspace);
 
 	workspace->doctree = NULL;
 	workspace->ctxt = NULL;
 	workspace->res = NULL;
 
-	workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
-									   docsize, NULL, NULL,
-									   XML_PARSE_NOENT);
-	if (workspace->doctree != NULL)
+	PG_TRY();
 	{
-		workspace->ctxt = xmlXPathNewContext(workspace->doctree);
-		workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
-
-		/* compile the path */
-		comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
-		if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+		workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
+										   docsize, NULL, NULL,
+										   XML_PARSE_NOENT);
+		if (workspace->doctree != NULL)
 		{
-			if (comppath != NULL)
-				xmlXPathFreeCompExpr(comppath);
-			xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
-						"XPath Syntax Error");
-		}
+			workspace->ctxt = xmlXPathNewContext(workspace->doctree);
+			if (workspace->ctxt == NULL)
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_OUT_OF_MEMORY,
+							"could not allocate XPath context");
 
-		/* Now evaluate the path expression. */
-		workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+			workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
+
+			/* compile the path */
+			comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
+			if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
+							"XPath Syntax Error");
+
+			/* Now evaluate the path expression. */
+			workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+
+			xmlXPathFreeCompExpr(comppath);
+			comppath = NULL;
+		}
+	}
+	PG_CATCH();
+	{
+		if (comppath != NULL)
+			xmlXPathFreeCompExpr(comppath);
+		cleanup_workspace(workspace);
 
-		xmlXPathFreeCompExpr(comppath);
+		PG_RE_THROW();
 	}
+	PG_END_TRY();
 
 	return workspace;
 }
-- 
2.54.0


--MP_/LMSk9=uMhuQ1QiIJDarDO8G--





^ permalink  raw  reply  [nested|flat] 611+ messages in thread

* [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths
@ 2026-06-01 22:41 Andrey Chernyy <andrey.cherny@tantorlabs.com>
  0 siblings, 0 replies; 611+ messages in thread

From: Andrey Chernyy @ 2026-06-01 22:41 UTC (permalink / raw)

pgxml_xpath() builds an xpath_workspace before returning it to
callers.  If an ERROR is thrown before the function returns, callers
have not received the workspace pointer yet and cannot run
cleanup_workspace().

Add local error cleanup for the partially built workspace and the
compiled XPath expression.  Also check xmlXPathNewContext() before
dereferencing the returned context.
---
 contrib/xml2/xpath.c | 51 +++++++++++++++++++++++++++-----------------
 1 file changed, 32 insertions(+), 19 deletions(-)

diff --git a/contrib/xml2/xpath.c b/contrib/xml2/xpath.c
index 9fe75cb5ff4..283bb51178d 100644
--- a/contrib/xml2/xpath.c
+++ b/contrib/xml2/xpath.c
@@ -497,36 +497,49 @@ static xpath_workspace *
 pgxml_xpath(text *document, xmlChar *xpath, PgXmlErrorContext *xmlerrcxt)
 {
 	int32		docsize = VARSIZE_ANY_EXHDR(document);
-	xmlXPathCompExprPtr comppath;
+	xmlXPathCompExprPtr volatile comppath = NULL;
 	xpath_workspace *workspace = palloc0_object(xpath_workspace);
 
 	workspace->doctree = NULL;
 	workspace->ctxt = NULL;
 	workspace->res = NULL;
 
-	workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
-									   docsize, NULL, NULL,
-									   XML_PARSE_NOENT);
-	if (workspace->doctree != NULL)
+	PG_TRY();
 	{
-		workspace->ctxt = xmlXPathNewContext(workspace->doctree);
-		workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
-
-		/* compile the path */
-		comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
-		if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+		workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
+										   docsize, NULL, NULL,
+										   XML_PARSE_NOENT);
+		if (workspace->doctree != NULL)
 		{
-			if (comppath != NULL)
-				xmlXPathFreeCompExpr(comppath);
-			xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
-						"XPath Syntax Error");
-		}
+			workspace->ctxt = xmlXPathNewContext(workspace->doctree);
+			if (workspace->ctxt == NULL)
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_OUT_OF_MEMORY,
+							"could not allocate XPath context");
 
-		/* Now evaluate the path expression. */
-		workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+			workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
+
+			/* compile the path */
+			comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
+			if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
+							"XPath Syntax Error");
+
+			/* Now evaluate the path expression. */
+			workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+
+			xmlXPathFreeCompExpr(comppath);
+			comppath = NULL;
+		}
+	}
+	PG_CATCH();
+	{
+		if (comppath != NULL)
+			xmlXPathFreeCompExpr(comppath);
+		cleanup_workspace(workspace);
 
-		xmlXPathFreeCompExpr(comppath);
+		PG_RE_THROW();
 	}
+	PG_END_TRY();
 
 	return workspace;
 }
-- 
2.54.0


--MP_/LMSk9=uMhuQ1QiIJDarDO8G--






^ permalink  raw  reply  [nested|flat] 611+ messages in thread

* [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths
@ 2026-06-01 22:41 Andrey Chernyy <andrey.cherny@tantorlabs.com>
  0 siblings, 0 replies; 611+ messages in thread

From: Andrey Chernyy @ 2026-06-01 22:41 UTC (permalink / raw)

pgxml_xpath() builds an xpath_workspace before returning it to
callers.  If an ERROR is thrown before the function returns, callers
have not received the workspace pointer yet and cannot run
cleanup_workspace().

Add local error cleanup for the partially built workspace and the
compiled XPath expression.  Also check xmlXPathNewContext() before
dereferencing the returned context.
---
 contrib/xml2/xpath.c | 51 +++++++++++++++++++++++++++-----------------
 1 file changed, 32 insertions(+), 19 deletions(-)

diff --git a/contrib/xml2/xpath.c b/contrib/xml2/xpath.c
index 9fe75cb5ff4..283bb51178d 100644
--- a/contrib/xml2/xpath.c
+++ b/contrib/xml2/xpath.c
@@ -497,36 +497,49 @@ static xpath_workspace *
 pgxml_xpath(text *document, xmlChar *xpath, PgXmlErrorContext *xmlerrcxt)
 {
 	int32		docsize = VARSIZE_ANY_EXHDR(document);
-	xmlXPathCompExprPtr comppath;
+	xmlXPathCompExprPtr volatile comppath = NULL;
 	xpath_workspace *workspace = palloc0_object(xpath_workspace);
 
 	workspace->doctree = NULL;
 	workspace->ctxt = NULL;
 	workspace->res = NULL;
 
-	workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
-									   docsize, NULL, NULL,
-									   XML_PARSE_NOENT);
-	if (workspace->doctree != NULL)
+	PG_TRY();
 	{
-		workspace->ctxt = xmlXPathNewContext(workspace->doctree);
-		workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
-
-		/* compile the path */
-		comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
-		if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+		workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
+										   docsize, NULL, NULL,
+										   XML_PARSE_NOENT);
+		if (workspace->doctree != NULL)
 		{
-			if (comppath != NULL)
-				xmlXPathFreeCompExpr(comppath);
-			xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
-						"XPath Syntax Error");
-		}
+			workspace->ctxt = xmlXPathNewContext(workspace->doctree);
+			if (workspace->ctxt == NULL)
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_OUT_OF_MEMORY,
+							"could not allocate XPath context");
 
-		/* Now evaluate the path expression. */
-		workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+			workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
+
+			/* compile the path */
+			comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
+			if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
+							"XPath Syntax Error");
+
+			/* Now evaluate the path expression. */
+			workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+
+			xmlXPathFreeCompExpr(comppath);
+			comppath = NULL;
+		}
+	}
+	PG_CATCH();
+	{
+		if (comppath != NULL)
+			xmlXPathFreeCompExpr(comppath);
+		cleanup_workspace(workspace);
 
-		xmlXPathFreeCompExpr(comppath);
+		PG_RE_THROW();
 	}
+	PG_END_TRY();
 
 	return workspace;
 }
-- 
2.54.0


--MP_/LMSk9=uMhuQ1QiIJDarDO8G--





^ permalink  raw  reply  [nested|flat] 611+ messages in thread

* [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths
@ 2026-06-01 22:41 Andrey Chernyy <andrey.cherny@tantorlabs.com>
  0 siblings, 0 replies; 611+ messages in thread

From: Andrey Chernyy @ 2026-06-01 22:41 UTC (permalink / raw)

pgxml_xpath() builds an xpath_workspace before returning it to
callers.  If an ERROR is thrown before the function returns, callers
have not received the workspace pointer yet and cannot run
cleanup_workspace().

Add local error cleanup for the partially built workspace and the
compiled XPath expression.  Also check xmlXPathNewContext() before
dereferencing the returned context.
---
 contrib/xml2/xpath.c | 51 +++++++++++++++++++++++++++-----------------
 1 file changed, 32 insertions(+), 19 deletions(-)

diff --git a/contrib/xml2/xpath.c b/contrib/xml2/xpath.c
index 9fe75cb5ff4..283bb51178d 100644
--- a/contrib/xml2/xpath.c
+++ b/contrib/xml2/xpath.c
@@ -497,36 +497,49 @@ static xpath_workspace *
 pgxml_xpath(text *document, xmlChar *xpath, PgXmlErrorContext *xmlerrcxt)
 {
 	int32		docsize = VARSIZE_ANY_EXHDR(document);
-	xmlXPathCompExprPtr comppath;
+	xmlXPathCompExprPtr volatile comppath = NULL;
 	xpath_workspace *workspace = palloc0_object(xpath_workspace);
 
 	workspace->doctree = NULL;
 	workspace->ctxt = NULL;
 	workspace->res = NULL;
 
-	workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
-									   docsize, NULL, NULL,
-									   XML_PARSE_NOENT);
-	if (workspace->doctree != NULL)
+	PG_TRY();
 	{
-		workspace->ctxt = xmlXPathNewContext(workspace->doctree);
-		workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
-
-		/* compile the path */
-		comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
-		if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+		workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
+										   docsize, NULL, NULL,
+										   XML_PARSE_NOENT);
+		if (workspace->doctree != NULL)
 		{
-			if (comppath != NULL)
-				xmlXPathFreeCompExpr(comppath);
-			xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
-						"XPath Syntax Error");
-		}
+			workspace->ctxt = xmlXPathNewContext(workspace->doctree);
+			if (workspace->ctxt == NULL)
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_OUT_OF_MEMORY,
+							"could not allocate XPath context");
 
-		/* Now evaluate the path expression. */
-		workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+			workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
+
+			/* compile the path */
+			comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
+			if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
+							"XPath Syntax Error");
+
+			/* Now evaluate the path expression. */
+			workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+
+			xmlXPathFreeCompExpr(comppath);
+			comppath = NULL;
+		}
+	}
+	PG_CATCH();
+	{
+		if (comppath != NULL)
+			xmlXPathFreeCompExpr(comppath);
+		cleanup_workspace(workspace);
 
-		xmlXPathFreeCompExpr(comppath);
+		PG_RE_THROW();
 	}
+	PG_END_TRY();
 
 	return workspace;
 }
-- 
2.54.0


--MP_/LMSk9=uMhuQ1QiIJDarDO8G--





^ permalink  raw  reply  [nested|flat] 611+ messages in thread

* [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths
@ 2026-06-01 22:41 Andrey Chernyy <andrey.cherny@tantorlabs.com>
  0 siblings, 0 replies; 611+ messages in thread

From: Andrey Chernyy @ 2026-06-01 22:41 UTC (permalink / raw)

pgxml_xpath() builds an xpath_workspace before returning it to
callers.  If an ERROR is thrown before the function returns, callers
have not received the workspace pointer yet and cannot run
cleanup_workspace().

Add local error cleanup for the partially built workspace and the
compiled XPath expression.  Also check xmlXPathNewContext() before
dereferencing the returned context.
---
 contrib/xml2/xpath.c | 51 +++++++++++++++++++++++++++-----------------
 1 file changed, 32 insertions(+), 19 deletions(-)

diff --git a/contrib/xml2/xpath.c b/contrib/xml2/xpath.c
index 9fe75cb5ff4..283bb51178d 100644
--- a/contrib/xml2/xpath.c
+++ b/contrib/xml2/xpath.c
@@ -497,36 +497,49 @@ static xpath_workspace *
 pgxml_xpath(text *document, xmlChar *xpath, PgXmlErrorContext *xmlerrcxt)
 {
 	int32		docsize = VARSIZE_ANY_EXHDR(document);
-	xmlXPathCompExprPtr comppath;
+	xmlXPathCompExprPtr volatile comppath = NULL;
 	xpath_workspace *workspace = palloc0_object(xpath_workspace);
 
 	workspace->doctree = NULL;
 	workspace->ctxt = NULL;
 	workspace->res = NULL;
 
-	workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
-									   docsize, NULL, NULL,
-									   XML_PARSE_NOENT);
-	if (workspace->doctree != NULL)
+	PG_TRY();
 	{
-		workspace->ctxt = xmlXPathNewContext(workspace->doctree);
-		workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
-
-		/* compile the path */
-		comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
-		if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+		workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
+										   docsize, NULL, NULL,
+										   XML_PARSE_NOENT);
+		if (workspace->doctree != NULL)
 		{
-			if (comppath != NULL)
-				xmlXPathFreeCompExpr(comppath);
-			xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
-						"XPath Syntax Error");
-		}
+			workspace->ctxt = xmlXPathNewContext(workspace->doctree);
+			if (workspace->ctxt == NULL)
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_OUT_OF_MEMORY,
+							"could not allocate XPath context");
 
-		/* Now evaluate the path expression. */
-		workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+			workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
+
+			/* compile the path */
+			comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
+			if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
+							"XPath Syntax Error");
+
+			/* Now evaluate the path expression. */
+			workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+
+			xmlXPathFreeCompExpr(comppath);
+			comppath = NULL;
+		}
+	}
+	PG_CATCH();
+	{
+		if (comppath != NULL)
+			xmlXPathFreeCompExpr(comppath);
+		cleanup_workspace(workspace);
 
-		xmlXPathFreeCompExpr(comppath);
+		PG_RE_THROW();
 	}
+	PG_END_TRY();
 
 	return workspace;
 }
-- 
2.54.0


--MP_/LMSk9=uMhuQ1QiIJDarDO8G--






^ permalink  raw  reply  [nested|flat] 611+ messages in thread

* [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths
@ 2026-06-01 22:41 Andrey Chernyy <andrey.cherny@tantorlabs.com>
  0 siblings, 0 replies; 611+ messages in thread

From: Andrey Chernyy @ 2026-06-01 22:41 UTC (permalink / raw)

pgxml_xpath() builds an xpath_workspace before returning it to
callers.  If an ERROR is thrown before the function returns, callers
have not received the workspace pointer yet and cannot run
cleanup_workspace().

Add local error cleanup for the partially built workspace and the
compiled XPath expression.  Also check xmlXPathNewContext() before
dereferencing the returned context.
---
 contrib/xml2/xpath.c | 51 +++++++++++++++++++++++++++-----------------
 1 file changed, 32 insertions(+), 19 deletions(-)

diff --git a/contrib/xml2/xpath.c b/contrib/xml2/xpath.c
index 9fe75cb5ff4..283bb51178d 100644
--- a/contrib/xml2/xpath.c
+++ b/contrib/xml2/xpath.c
@@ -497,36 +497,49 @@ static xpath_workspace *
 pgxml_xpath(text *document, xmlChar *xpath, PgXmlErrorContext *xmlerrcxt)
 {
 	int32		docsize = VARSIZE_ANY_EXHDR(document);
-	xmlXPathCompExprPtr comppath;
+	xmlXPathCompExprPtr volatile comppath = NULL;
 	xpath_workspace *workspace = palloc0_object(xpath_workspace);
 
 	workspace->doctree = NULL;
 	workspace->ctxt = NULL;
 	workspace->res = NULL;
 
-	workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
-									   docsize, NULL, NULL,
-									   XML_PARSE_NOENT);
-	if (workspace->doctree != NULL)
+	PG_TRY();
 	{
-		workspace->ctxt = xmlXPathNewContext(workspace->doctree);
-		workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
-
-		/* compile the path */
-		comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
-		if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+		workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
+										   docsize, NULL, NULL,
+										   XML_PARSE_NOENT);
+		if (workspace->doctree != NULL)
 		{
-			if (comppath != NULL)
-				xmlXPathFreeCompExpr(comppath);
-			xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
-						"XPath Syntax Error");
-		}
+			workspace->ctxt = xmlXPathNewContext(workspace->doctree);
+			if (workspace->ctxt == NULL)
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_OUT_OF_MEMORY,
+							"could not allocate XPath context");
 
-		/* Now evaluate the path expression. */
-		workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+			workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
+
+			/* compile the path */
+			comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
+			if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
+							"XPath Syntax Error");
+
+			/* Now evaluate the path expression. */
+			workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+
+			xmlXPathFreeCompExpr(comppath);
+			comppath = NULL;
+		}
+	}
+	PG_CATCH();
+	{
+		if (comppath != NULL)
+			xmlXPathFreeCompExpr(comppath);
+		cleanup_workspace(workspace);
 
-		xmlXPathFreeCompExpr(comppath);
+		PG_RE_THROW();
 	}
+	PG_END_TRY();
 
 	return workspace;
 }
-- 
2.54.0


--MP_/LMSk9=uMhuQ1QiIJDarDO8G--





^ permalink  raw  reply  [nested|flat] 611+ messages in thread

* [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths
@ 2026-06-01 22:41 Andrey Chernyy <andrey.cherny@tantorlabs.com>
  0 siblings, 0 replies; 611+ messages in thread

From: Andrey Chernyy @ 2026-06-01 22:41 UTC (permalink / raw)

pgxml_xpath() builds an xpath_workspace before returning it to
callers.  If an ERROR is thrown before the function returns, callers
have not received the workspace pointer yet and cannot run
cleanup_workspace().

Add local error cleanup for the partially built workspace and the
compiled XPath expression.  Also check xmlXPathNewContext() before
dereferencing the returned context.
---
 contrib/xml2/xpath.c | 51 +++++++++++++++++++++++++++-----------------
 1 file changed, 32 insertions(+), 19 deletions(-)

diff --git a/contrib/xml2/xpath.c b/contrib/xml2/xpath.c
index 9fe75cb5ff4..283bb51178d 100644
--- a/contrib/xml2/xpath.c
+++ b/contrib/xml2/xpath.c
@@ -497,36 +497,49 @@ static xpath_workspace *
 pgxml_xpath(text *document, xmlChar *xpath, PgXmlErrorContext *xmlerrcxt)
 {
 	int32		docsize = VARSIZE_ANY_EXHDR(document);
-	xmlXPathCompExprPtr comppath;
+	xmlXPathCompExprPtr volatile comppath = NULL;
 	xpath_workspace *workspace = palloc0_object(xpath_workspace);
 
 	workspace->doctree = NULL;
 	workspace->ctxt = NULL;
 	workspace->res = NULL;
 
-	workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
-									   docsize, NULL, NULL,
-									   XML_PARSE_NOENT);
-	if (workspace->doctree != NULL)
+	PG_TRY();
 	{
-		workspace->ctxt = xmlXPathNewContext(workspace->doctree);
-		workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
-
-		/* compile the path */
-		comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
-		if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+		workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
+										   docsize, NULL, NULL,
+										   XML_PARSE_NOENT);
+		if (workspace->doctree != NULL)
 		{
-			if (comppath != NULL)
-				xmlXPathFreeCompExpr(comppath);
-			xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
-						"XPath Syntax Error");
-		}
+			workspace->ctxt = xmlXPathNewContext(workspace->doctree);
+			if (workspace->ctxt == NULL)
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_OUT_OF_MEMORY,
+							"could not allocate XPath context");
 
-		/* Now evaluate the path expression. */
-		workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+			workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
+
+			/* compile the path */
+			comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
+			if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
+							"XPath Syntax Error");
+
+			/* Now evaluate the path expression. */
+			workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+
+			xmlXPathFreeCompExpr(comppath);
+			comppath = NULL;
+		}
+	}
+	PG_CATCH();
+	{
+		if (comppath != NULL)
+			xmlXPathFreeCompExpr(comppath);
+		cleanup_workspace(workspace);
 
-		xmlXPathFreeCompExpr(comppath);
+		PG_RE_THROW();
 	}
+	PG_END_TRY();
 
 	return workspace;
 }
-- 
2.54.0


--MP_/LMSk9=uMhuQ1QiIJDarDO8G--





^ permalink  raw  reply  [nested|flat] 611+ messages in thread

* [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths
@ 2026-06-01 22:41 Andrey Chernyy <andrey.cherny@tantorlabs.com>
  0 siblings, 0 replies; 611+ messages in thread

From: Andrey Chernyy @ 2026-06-01 22:41 UTC (permalink / raw)

pgxml_xpath() builds an xpath_workspace before returning it to
callers.  If an ERROR is thrown before the function returns, callers
have not received the workspace pointer yet and cannot run
cleanup_workspace().

Add local error cleanup for the partially built workspace and the
compiled XPath expression.  Also check xmlXPathNewContext() before
dereferencing the returned context.
---
 contrib/xml2/xpath.c | 51 +++++++++++++++++++++++++++-----------------
 1 file changed, 32 insertions(+), 19 deletions(-)

diff --git a/contrib/xml2/xpath.c b/contrib/xml2/xpath.c
index 9fe75cb5ff4..283bb51178d 100644
--- a/contrib/xml2/xpath.c
+++ b/contrib/xml2/xpath.c
@@ -497,36 +497,49 @@ static xpath_workspace *
 pgxml_xpath(text *document, xmlChar *xpath, PgXmlErrorContext *xmlerrcxt)
 {
 	int32		docsize = VARSIZE_ANY_EXHDR(document);
-	xmlXPathCompExprPtr comppath;
+	xmlXPathCompExprPtr volatile comppath = NULL;
 	xpath_workspace *workspace = palloc0_object(xpath_workspace);
 
 	workspace->doctree = NULL;
 	workspace->ctxt = NULL;
 	workspace->res = NULL;
 
-	workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
-									   docsize, NULL, NULL,
-									   XML_PARSE_NOENT);
-	if (workspace->doctree != NULL)
+	PG_TRY();
 	{
-		workspace->ctxt = xmlXPathNewContext(workspace->doctree);
-		workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
-
-		/* compile the path */
-		comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
-		if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+		workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
+										   docsize, NULL, NULL,
+										   XML_PARSE_NOENT);
+		if (workspace->doctree != NULL)
 		{
-			if (comppath != NULL)
-				xmlXPathFreeCompExpr(comppath);
-			xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
-						"XPath Syntax Error");
-		}
+			workspace->ctxt = xmlXPathNewContext(workspace->doctree);
+			if (workspace->ctxt == NULL)
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_OUT_OF_MEMORY,
+							"could not allocate XPath context");
 
-		/* Now evaluate the path expression. */
-		workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+			workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
+
+			/* compile the path */
+			comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
+			if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
+							"XPath Syntax Error");
+
+			/* Now evaluate the path expression. */
+			workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+
+			xmlXPathFreeCompExpr(comppath);
+			comppath = NULL;
+		}
+	}
+	PG_CATCH();
+	{
+		if (comppath != NULL)
+			xmlXPathFreeCompExpr(comppath);
+		cleanup_workspace(workspace);
 
-		xmlXPathFreeCompExpr(comppath);
+		PG_RE_THROW();
 	}
+	PG_END_TRY();
 
 	return workspace;
 }
-- 
2.54.0


--MP_/LMSk9=uMhuQ1QiIJDarDO8G--






^ permalink  raw  reply  [nested|flat] 611+ messages in thread

* [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths
@ 2026-06-01 22:41 Andrey Chernyy <andrey.cherny@tantorlabs.com>
  0 siblings, 0 replies; 611+ messages in thread

From: Andrey Chernyy @ 2026-06-01 22:41 UTC (permalink / raw)

pgxml_xpath() builds an xpath_workspace before returning it to
callers.  If an ERROR is thrown before the function returns, callers
have not received the workspace pointer yet and cannot run
cleanup_workspace().

Add local error cleanup for the partially built workspace and the
compiled XPath expression.  Also check xmlXPathNewContext() before
dereferencing the returned context.
---
 contrib/xml2/xpath.c | 51 +++++++++++++++++++++++++++-----------------
 1 file changed, 32 insertions(+), 19 deletions(-)

diff --git a/contrib/xml2/xpath.c b/contrib/xml2/xpath.c
index 9fe75cb5ff4..283bb51178d 100644
--- a/contrib/xml2/xpath.c
+++ b/contrib/xml2/xpath.c
@@ -497,36 +497,49 @@ static xpath_workspace *
 pgxml_xpath(text *document, xmlChar *xpath, PgXmlErrorContext *xmlerrcxt)
 {
 	int32		docsize = VARSIZE_ANY_EXHDR(document);
-	xmlXPathCompExprPtr comppath;
+	xmlXPathCompExprPtr volatile comppath = NULL;
 	xpath_workspace *workspace = palloc0_object(xpath_workspace);
 
 	workspace->doctree = NULL;
 	workspace->ctxt = NULL;
 	workspace->res = NULL;
 
-	workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
-									   docsize, NULL, NULL,
-									   XML_PARSE_NOENT);
-	if (workspace->doctree != NULL)
+	PG_TRY();
 	{
-		workspace->ctxt = xmlXPathNewContext(workspace->doctree);
-		workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
-
-		/* compile the path */
-		comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
-		if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+		workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
+										   docsize, NULL, NULL,
+										   XML_PARSE_NOENT);
+		if (workspace->doctree != NULL)
 		{
-			if (comppath != NULL)
-				xmlXPathFreeCompExpr(comppath);
-			xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
-						"XPath Syntax Error");
-		}
+			workspace->ctxt = xmlXPathNewContext(workspace->doctree);
+			if (workspace->ctxt == NULL)
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_OUT_OF_MEMORY,
+							"could not allocate XPath context");
 
-		/* Now evaluate the path expression. */
-		workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+			workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
+
+			/* compile the path */
+			comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
+			if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
+							"XPath Syntax Error");
+
+			/* Now evaluate the path expression. */
+			workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+
+			xmlXPathFreeCompExpr(comppath);
+			comppath = NULL;
+		}
+	}
+	PG_CATCH();
+	{
+		if (comppath != NULL)
+			xmlXPathFreeCompExpr(comppath);
+		cleanup_workspace(workspace);
 
-		xmlXPathFreeCompExpr(comppath);
+		PG_RE_THROW();
 	}
+	PG_END_TRY();
 
 	return workspace;
 }
-- 
2.54.0


--MP_/LMSk9=uMhuQ1QiIJDarDO8G--






^ permalink  raw  reply  [nested|flat] 611+ messages in thread

* [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths
@ 2026-06-01 22:41 Andrey Chernyy <andrey.cherny@tantorlabs.com>
  0 siblings, 0 replies; 611+ messages in thread

From: Andrey Chernyy @ 2026-06-01 22:41 UTC (permalink / raw)

pgxml_xpath() builds an xpath_workspace before returning it to
callers.  If an ERROR is thrown before the function returns, callers
have not received the workspace pointer yet and cannot run
cleanup_workspace().

Add local error cleanup for the partially built workspace and the
compiled XPath expression.  Also check xmlXPathNewContext() before
dereferencing the returned context.
---
 contrib/xml2/xpath.c | 51 +++++++++++++++++++++++++++-----------------
 1 file changed, 32 insertions(+), 19 deletions(-)

diff --git a/contrib/xml2/xpath.c b/contrib/xml2/xpath.c
index 9fe75cb5ff4..283bb51178d 100644
--- a/contrib/xml2/xpath.c
+++ b/contrib/xml2/xpath.c
@@ -497,36 +497,49 @@ static xpath_workspace *
 pgxml_xpath(text *document, xmlChar *xpath, PgXmlErrorContext *xmlerrcxt)
 {
 	int32		docsize = VARSIZE_ANY_EXHDR(document);
-	xmlXPathCompExprPtr comppath;
+	xmlXPathCompExprPtr volatile comppath = NULL;
 	xpath_workspace *workspace = palloc0_object(xpath_workspace);
 
 	workspace->doctree = NULL;
 	workspace->ctxt = NULL;
 	workspace->res = NULL;
 
-	workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
-									   docsize, NULL, NULL,
-									   XML_PARSE_NOENT);
-	if (workspace->doctree != NULL)
+	PG_TRY();
 	{
-		workspace->ctxt = xmlXPathNewContext(workspace->doctree);
-		workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
-
-		/* compile the path */
-		comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
-		if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+		workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
+										   docsize, NULL, NULL,
+										   XML_PARSE_NOENT);
+		if (workspace->doctree != NULL)
 		{
-			if (comppath != NULL)
-				xmlXPathFreeCompExpr(comppath);
-			xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
-						"XPath Syntax Error");
-		}
+			workspace->ctxt = xmlXPathNewContext(workspace->doctree);
+			if (workspace->ctxt == NULL)
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_OUT_OF_MEMORY,
+							"could not allocate XPath context");
 
-		/* Now evaluate the path expression. */
-		workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+			workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
+
+			/* compile the path */
+			comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
+			if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
+							"XPath Syntax Error");
+
+			/* Now evaluate the path expression. */
+			workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+
+			xmlXPathFreeCompExpr(comppath);
+			comppath = NULL;
+		}
+	}
+	PG_CATCH();
+	{
+		if (comppath != NULL)
+			xmlXPathFreeCompExpr(comppath);
+		cleanup_workspace(workspace);
 
-		xmlXPathFreeCompExpr(comppath);
+		PG_RE_THROW();
 	}
+	PG_END_TRY();
 
 	return workspace;
 }
-- 
2.54.0


--MP_/LMSk9=uMhuQ1QiIJDarDO8G--





^ permalink  raw  reply  [nested|flat] 611+ messages in thread

* [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths
@ 2026-06-01 22:41 Andrey Chernyy <andrey.cherny@tantorlabs.com>
  0 siblings, 0 replies; 611+ messages in thread

From: Andrey Chernyy @ 2026-06-01 22:41 UTC (permalink / raw)

pgxml_xpath() builds an xpath_workspace before returning it to
callers.  If an ERROR is thrown before the function returns, callers
have not received the workspace pointer yet and cannot run
cleanup_workspace().

Add local error cleanup for the partially built workspace and the
compiled XPath expression.  Also check xmlXPathNewContext() before
dereferencing the returned context.
---
 contrib/xml2/xpath.c | 51 +++++++++++++++++++++++++++-----------------
 1 file changed, 32 insertions(+), 19 deletions(-)

diff --git a/contrib/xml2/xpath.c b/contrib/xml2/xpath.c
index 9fe75cb5ff4..283bb51178d 100644
--- a/contrib/xml2/xpath.c
+++ b/contrib/xml2/xpath.c
@@ -497,36 +497,49 @@ static xpath_workspace *
 pgxml_xpath(text *document, xmlChar *xpath, PgXmlErrorContext *xmlerrcxt)
 {
 	int32		docsize = VARSIZE_ANY_EXHDR(document);
-	xmlXPathCompExprPtr comppath;
+	xmlXPathCompExprPtr volatile comppath = NULL;
 	xpath_workspace *workspace = palloc0_object(xpath_workspace);
 
 	workspace->doctree = NULL;
 	workspace->ctxt = NULL;
 	workspace->res = NULL;
 
-	workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
-									   docsize, NULL, NULL,
-									   XML_PARSE_NOENT);
-	if (workspace->doctree != NULL)
+	PG_TRY();
 	{
-		workspace->ctxt = xmlXPathNewContext(workspace->doctree);
-		workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
-
-		/* compile the path */
-		comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
-		if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+		workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
+										   docsize, NULL, NULL,
+										   XML_PARSE_NOENT);
+		if (workspace->doctree != NULL)
 		{
-			if (comppath != NULL)
-				xmlXPathFreeCompExpr(comppath);
-			xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
-						"XPath Syntax Error");
-		}
+			workspace->ctxt = xmlXPathNewContext(workspace->doctree);
+			if (workspace->ctxt == NULL)
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_OUT_OF_MEMORY,
+							"could not allocate XPath context");
 
-		/* Now evaluate the path expression. */
-		workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+			workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
+
+			/* compile the path */
+			comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
+			if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
+							"XPath Syntax Error");
+
+			/* Now evaluate the path expression. */
+			workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+
+			xmlXPathFreeCompExpr(comppath);
+			comppath = NULL;
+		}
+	}
+	PG_CATCH();
+	{
+		if (comppath != NULL)
+			xmlXPathFreeCompExpr(comppath);
+		cleanup_workspace(workspace);
 
-		xmlXPathFreeCompExpr(comppath);
+		PG_RE_THROW();
 	}
+	PG_END_TRY();
 
 	return workspace;
 }
-- 
2.54.0


--MP_/LMSk9=uMhuQ1QiIJDarDO8G--





^ permalink  raw  reply  [nested|flat] 611+ messages in thread

* [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths
@ 2026-06-01 22:41 Andrey Chernyy <andrey.cherny@tantorlabs.com>
  0 siblings, 0 replies; 611+ messages in thread

From: Andrey Chernyy @ 2026-06-01 22:41 UTC (permalink / raw)

pgxml_xpath() builds an xpath_workspace before returning it to
callers.  If an ERROR is thrown before the function returns, callers
have not received the workspace pointer yet and cannot run
cleanup_workspace().

Add local error cleanup for the partially built workspace and the
compiled XPath expression.  Also check xmlXPathNewContext() before
dereferencing the returned context.
---
 contrib/xml2/xpath.c | 51 +++++++++++++++++++++++++++-----------------
 1 file changed, 32 insertions(+), 19 deletions(-)

diff --git a/contrib/xml2/xpath.c b/contrib/xml2/xpath.c
index 9fe75cb5ff4..283bb51178d 100644
--- a/contrib/xml2/xpath.c
+++ b/contrib/xml2/xpath.c
@@ -497,36 +497,49 @@ static xpath_workspace *
 pgxml_xpath(text *document, xmlChar *xpath, PgXmlErrorContext *xmlerrcxt)
 {
 	int32		docsize = VARSIZE_ANY_EXHDR(document);
-	xmlXPathCompExprPtr comppath;
+	xmlXPathCompExprPtr volatile comppath = NULL;
 	xpath_workspace *workspace = palloc0_object(xpath_workspace);
 
 	workspace->doctree = NULL;
 	workspace->ctxt = NULL;
 	workspace->res = NULL;
 
-	workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
-									   docsize, NULL, NULL,
-									   XML_PARSE_NOENT);
-	if (workspace->doctree != NULL)
+	PG_TRY();
 	{
-		workspace->ctxt = xmlXPathNewContext(workspace->doctree);
-		workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
-
-		/* compile the path */
-		comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
-		if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+		workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
+										   docsize, NULL, NULL,
+										   XML_PARSE_NOENT);
+		if (workspace->doctree != NULL)
 		{
-			if (comppath != NULL)
-				xmlXPathFreeCompExpr(comppath);
-			xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
-						"XPath Syntax Error");
-		}
+			workspace->ctxt = xmlXPathNewContext(workspace->doctree);
+			if (workspace->ctxt == NULL)
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_OUT_OF_MEMORY,
+							"could not allocate XPath context");
 
-		/* Now evaluate the path expression. */
-		workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+			workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
+
+			/* compile the path */
+			comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
+			if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
+							"XPath Syntax Error");
+
+			/* Now evaluate the path expression. */
+			workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+
+			xmlXPathFreeCompExpr(comppath);
+			comppath = NULL;
+		}
+	}
+	PG_CATCH();
+	{
+		if (comppath != NULL)
+			xmlXPathFreeCompExpr(comppath);
+		cleanup_workspace(workspace);
 
-		xmlXPathFreeCompExpr(comppath);
+		PG_RE_THROW();
 	}
+	PG_END_TRY();
 
 	return workspace;
 }
-- 
2.54.0


--MP_/LMSk9=uMhuQ1QiIJDarDO8G--






^ permalink  raw  reply  [nested|flat] 611+ messages in thread

* [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths
@ 2026-06-01 22:41 Andrey Chernyy <andrey.cherny@tantorlabs.com>
  0 siblings, 0 replies; 611+ messages in thread

From: Andrey Chernyy @ 2026-06-01 22:41 UTC (permalink / raw)

pgxml_xpath() builds an xpath_workspace before returning it to
callers.  If an ERROR is thrown before the function returns, callers
have not received the workspace pointer yet and cannot run
cleanup_workspace().

Add local error cleanup for the partially built workspace and the
compiled XPath expression.  Also check xmlXPathNewContext() before
dereferencing the returned context.
---
 contrib/xml2/xpath.c | 51 +++++++++++++++++++++++++++-----------------
 1 file changed, 32 insertions(+), 19 deletions(-)

diff --git a/contrib/xml2/xpath.c b/contrib/xml2/xpath.c
index 9fe75cb5ff4..283bb51178d 100644
--- a/contrib/xml2/xpath.c
+++ b/contrib/xml2/xpath.c
@@ -497,36 +497,49 @@ static xpath_workspace *
 pgxml_xpath(text *document, xmlChar *xpath, PgXmlErrorContext *xmlerrcxt)
 {
 	int32		docsize = VARSIZE_ANY_EXHDR(document);
-	xmlXPathCompExprPtr comppath;
+	xmlXPathCompExprPtr volatile comppath = NULL;
 	xpath_workspace *workspace = palloc0_object(xpath_workspace);
 
 	workspace->doctree = NULL;
 	workspace->ctxt = NULL;
 	workspace->res = NULL;
 
-	workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
-									   docsize, NULL, NULL,
-									   XML_PARSE_NOENT);
-	if (workspace->doctree != NULL)
+	PG_TRY();
 	{
-		workspace->ctxt = xmlXPathNewContext(workspace->doctree);
-		workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
-
-		/* compile the path */
-		comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
-		if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+		workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
+										   docsize, NULL, NULL,
+										   XML_PARSE_NOENT);
+		if (workspace->doctree != NULL)
 		{
-			if (comppath != NULL)
-				xmlXPathFreeCompExpr(comppath);
-			xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
-						"XPath Syntax Error");
-		}
+			workspace->ctxt = xmlXPathNewContext(workspace->doctree);
+			if (workspace->ctxt == NULL)
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_OUT_OF_MEMORY,
+							"could not allocate XPath context");
 
-		/* Now evaluate the path expression. */
-		workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+			workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
+
+			/* compile the path */
+			comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
+			if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
+							"XPath Syntax Error");
+
+			/* Now evaluate the path expression. */
+			workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+
+			xmlXPathFreeCompExpr(comppath);
+			comppath = NULL;
+		}
+	}
+	PG_CATCH();
+	{
+		if (comppath != NULL)
+			xmlXPathFreeCompExpr(comppath);
+		cleanup_workspace(workspace);
 
-		xmlXPathFreeCompExpr(comppath);
+		PG_RE_THROW();
 	}
+	PG_END_TRY();
 
 	return workspace;
 }
-- 
2.54.0


--MP_/LMSk9=uMhuQ1QiIJDarDO8G--






^ permalink  raw  reply  [nested|flat] 611+ messages in thread

* [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths
@ 2026-06-01 22:41 Andrey Chernyy <andrey.cherny@tantorlabs.com>
  0 siblings, 0 replies; 611+ messages in thread

From: Andrey Chernyy @ 2026-06-01 22:41 UTC (permalink / raw)

pgxml_xpath() builds an xpath_workspace before returning it to
callers.  If an ERROR is thrown before the function returns, callers
have not received the workspace pointer yet and cannot run
cleanup_workspace().

Add local error cleanup for the partially built workspace and the
compiled XPath expression.  Also check xmlXPathNewContext() before
dereferencing the returned context.
---
 contrib/xml2/xpath.c | 51 +++++++++++++++++++++++++++-----------------
 1 file changed, 32 insertions(+), 19 deletions(-)

diff --git a/contrib/xml2/xpath.c b/contrib/xml2/xpath.c
index 9fe75cb5ff4..283bb51178d 100644
--- a/contrib/xml2/xpath.c
+++ b/contrib/xml2/xpath.c
@@ -497,36 +497,49 @@ static xpath_workspace *
 pgxml_xpath(text *document, xmlChar *xpath, PgXmlErrorContext *xmlerrcxt)
 {
 	int32		docsize = VARSIZE_ANY_EXHDR(document);
-	xmlXPathCompExprPtr comppath;
+	xmlXPathCompExprPtr volatile comppath = NULL;
 	xpath_workspace *workspace = palloc0_object(xpath_workspace);
 
 	workspace->doctree = NULL;
 	workspace->ctxt = NULL;
 	workspace->res = NULL;
 
-	workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
-									   docsize, NULL, NULL,
-									   XML_PARSE_NOENT);
-	if (workspace->doctree != NULL)
+	PG_TRY();
 	{
-		workspace->ctxt = xmlXPathNewContext(workspace->doctree);
-		workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
-
-		/* compile the path */
-		comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
-		if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+		workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
+										   docsize, NULL, NULL,
+										   XML_PARSE_NOENT);
+		if (workspace->doctree != NULL)
 		{
-			if (comppath != NULL)
-				xmlXPathFreeCompExpr(comppath);
-			xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
-						"XPath Syntax Error");
-		}
+			workspace->ctxt = xmlXPathNewContext(workspace->doctree);
+			if (workspace->ctxt == NULL)
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_OUT_OF_MEMORY,
+							"could not allocate XPath context");
 
-		/* Now evaluate the path expression. */
-		workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+			workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
+
+			/* compile the path */
+			comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
+			if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
+							"XPath Syntax Error");
+
+			/* Now evaluate the path expression. */
+			workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+
+			xmlXPathFreeCompExpr(comppath);
+			comppath = NULL;
+		}
+	}
+	PG_CATCH();
+	{
+		if (comppath != NULL)
+			xmlXPathFreeCompExpr(comppath);
+		cleanup_workspace(workspace);
 
-		xmlXPathFreeCompExpr(comppath);
+		PG_RE_THROW();
 	}
+	PG_END_TRY();
 
 	return workspace;
 }
-- 
2.54.0


--MP_/LMSk9=uMhuQ1QiIJDarDO8G--






^ permalink  raw  reply  [nested|flat] 611+ messages in thread

* [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths
@ 2026-06-01 22:41 Andrey Chernyy <andrey.cherny@tantorlabs.com>
  0 siblings, 0 replies; 611+ messages in thread

From: Andrey Chernyy @ 2026-06-01 22:41 UTC (permalink / raw)

pgxml_xpath() builds an xpath_workspace before returning it to
callers.  If an ERROR is thrown before the function returns, callers
have not received the workspace pointer yet and cannot run
cleanup_workspace().

Add local error cleanup for the partially built workspace and the
compiled XPath expression.  Also check xmlXPathNewContext() before
dereferencing the returned context.
---
 contrib/xml2/xpath.c | 51 +++++++++++++++++++++++++++-----------------
 1 file changed, 32 insertions(+), 19 deletions(-)

diff --git a/contrib/xml2/xpath.c b/contrib/xml2/xpath.c
index 9fe75cb5ff4..283bb51178d 100644
--- a/contrib/xml2/xpath.c
+++ b/contrib/xml2/xpath.c
@@ -497,36 +497,49 @@ static xpath_workspace *
 pgxml_xpath(text *document, xmlChar *xpath, PgXmlErrorContext *xmlerrcxt)
 {
 	int32		docsize = VARSIZE_ANY_EXHDR(document);
-	xmlXPathCompExprPtr comppath;
+	xmlXPathCompExprPtr volatile comppath = NULL;
 	xpath_workspace *workspace = palloc0_object(xpath_workspace);
 
 	workspace->doctree = NULL;
 	workspace->ctxt = NULL;
 	workspace->res = NULL;
 
-	workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
-									   docsize, NULL, NULL,
-									   XML_PARSE_NOENT);
-	if (workspace->doctree != NULL)
+	PG_TRY();
 	{
-		workspace->ctxt = xmlXPathNewContext(workspace->doctree);
-		workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
-
-		/* compile the path */
-		comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
-		if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+		workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
+										   docsize, NULL, NULL,
+										   XML_PARSE_NOENT);
+		if (workspace->doctree != NULL)
 		{
-			if (comppath != NULL)
-				xmlXPathFreeCompExpr(comppath);
-			xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
-						"XPath Syntax Error");
-		}
+			workspace->ctxt = xmlXPathNewContext(workspace->doctree);
+			if (workspace->ctxt == NULL)
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_OUT_OF_MEMORY,
+							"could not allocate XPath context");
 
-		/* Now evaluate the path expression. */
-		workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+			workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
+
+			/* compile the path */
+			comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
+			if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
+							"XPath Syntax Error");
+
+			/* Now evaluate the path expression. */
+			workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+
+			xmlXPathFreeCompExpr(comppath);
+			comppath = NULL;
+		}
+	}
+	PG_CATCH();
+	{
+		if (comppath != NULL)
+			xmlXPathFreeCompExpr(comppath);
+		cleanup_workspace(workspace);
 
-		xmlXPathFreeCompExpr(comppath);
+		PG_RE_THROW();
 	}
+	PG_END_TRY();
 
 	return workspace;
 }
-- 
2.54.0


--MP_/LMSk9=uMhuQ1QiIJDarDO8G--





^ permalink  raw  reply  [nested|flat] 611+ messages in thread

* [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths
@ 2026-06-01 22:41 Andrey Chernyy <andrey.cherny@tantorlabs.com>
  0 siblings, 0 replies; 611+ messages in thread

From: Andrey Chernyy @ 2026-06-01 22:41 UTC (permalink / raw)

pgxml_xpath() builds an xpath_workspace before returning it to
callers.  If an ERROR is thrown before the function returns, callers
have not received the workspace pointer yet and cannot run
cleanup_workspace().

Add local error cleanup for the partially built workspace and the
compiled XPath expression.  Also check xmlXPathNewContext() before
dereferencing the returned context.
---
 contrib/xml2/xpath.c | 51 +++++++++++++++++++++++++++-----------------
 1 file changed, 32 insertions(+), 19 deletions(-)

diff --git a/contrib/xml2/xpath.c b/contrib/xml2/xpath.c
index 9fe75cb5ff4..283bb51178d 100644
--- a/contrib/xml2/xpath.c
+++ b/contrib/xml2/xpath.c
@@ -497,36 +497,49 @@ static xpath_workspace *
 pgxml_xpath(text *document, xmlChar *xpath, PgXmlErrorContext *xmlerrcxt)
 {
 	int32		docsize = VARSIZE_ANY_EXHDR(document);
-	xmlXPathCompExprPtr comppath;
+	xmlXPathCompExprPtr volatile comppath = NULL;
 	xpath_workspace *workspace = palloc0_object(xpath_workspace);
 
 	workspace->doctree = NULL;
 	workspace->ctxt = NULL;
 	workspace->res = NULL;
 
-	workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
-									   docsize, NULL, NULL,
-									   XML_PARSE_NOENT);
-	if (workspace->doctree != NULL)
+	PG_TRY();
 	{
-		workspace->ctxt = xmlXPathNewContext(workspace->doctree);
-		workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
-
-		/* compile the path */
-		comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
-		if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+		workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
+										   docsize, NULL, NULL,
+										   XML_PARSE_NOENT);
+		if (workspace->doctree != NULL)
 		{
-			if (comppath != NULL)
-				xmlXPathFreeCompExpr(comppath);
-			xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
-						"XPath Syntax Error");
-		}
+			workspace->ctxt = xmlXPathNewContext(workspace->doctree);
+			if (workspace->ctxt == NULL)
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_OUT_OF_MEMORY,
+							"could not allocate XPath context");
 
-		/* Now evaluate the path expression. */
-		workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+			workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
+
+			/* compile the path */
+			comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
+			if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
+							"XPath Syntax Error");
+
+			/* Now evaluate the path expression. */
+			workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+
+			xmlXPathFreeCompExpr(comppath);
+			comppath = NULL;
+		}
+	}
+	PG_CATCH();
+	{
+		if (comppath != NULL)
+			xmlXPathFreeCompExpr(comppath);
+		cleanup_workspace(workspace);
 
-		xmlXPathFreeCompExpr(comppath);
+		PG_RE_THROW();
 	}
+	PG_END_TRY();
 
 	return workspace;
 }
-- 
2.54.0


--MP_/LMSk9=uMhuQ1QiIJDarDO8G--





^ permalink  raw  reply  [nested|flat] 611+ messages in thread

* [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths
@ 2026-06-01 22:41 Andrey Chernyy <andrey.cherny@tantorlabs.com>
  0 siblings, 0 replies; 611+ messages in thread

From: Andrey Chernyy @ 2026-06-01 22:41 UTC (permalink / raw)

pgxml_xpath() builds an xpath_workspace before returning it to
callers.  If an ERROR is thrown before the function returns, callers
have not received the workspace pointer yet and cannot run
cleanup_workspace().

Add local error cleanup for the partially built workspace and the
compiled XPath expression.  Also check xmlXPathNewContext() before
dereferencing the returned context.
---
 contrib/xml2/xpath.c | 51 +++++++++++++++++++++++++++-----------------
 1 file changed, 32 insertions(+), 19 deletions(-)

diff --git a/contrib/xml2/xpath.c b/contrib/xml2/xpath.c
index 9fe75cb5ff4..283bb51178d 100644
--- a/contrib/xml2/xpath.c
+++ b/contrib/xml2/xpath.c
@@ -497,36 +497,49 @@ static xpath_workspace *
 pgxml_xpath(text *document, xmlChar *xpath, PgXmlErrorContext *xmlerrcxt)
 {
 	int32		docsize = VARSIZE_ANY_EXHDR(document);
-	xmlXPathCompExprPtr comppath;
+	xmlXPathCompExprPtr volatile comppath = NULL;
 	xpath_workspace *workspace = palloc0_object(xpath_workspace);
 
 	workspace->doctree = NULL;
 	workspace->ctxt = NULL;
 	workspace->res = NULL;
 
-	workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
-									   docsize, NULL, NULL,
-									   XML_PARSE_NOENT);
-	if (workspace->doctree != NULL)
+	PG_TRY();
 	{
-		workspace->ctxt = xmlXPathNewContext(workspace->doctree);
-		workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
-
-		/* compile the path */
-		comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
-		if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+		workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
+										   docsize, NULL, NULL,
+										   XML_PARSE_NOENT);
+		if (workspace->doctree != NULL)
 		{
-			if (comppath != NULL)
-				xmlXPathFreeCompExpr(comppath);
-			xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
-						"XPath Syntax Error");
-		}
+			workspace->ctxt = xmlXPathNewContext(workspace->doctree);
+			if (workspace->ctxt == NULL)
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_OUT_OF_MEMORY,
+							"could not allocate XPath context");
 
-		/* Now evaluate the path expression. */
-		workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+			workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
+
+			/* compile the path */
+			comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
+			if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
+							"XPath Syntax Error");
+
+			/* Now evaluate the path expression. */
+			workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+
+			xmlXPathFreeCompExpr(comppath);
+			comppath = NULL;
+		}
+	}
+	PG_CATCH();
+	{
+		if (comppath != NULL)
+			xmlXPathFreeCompExpr(comppath);
+		cleanup_workspace(workspace);
 
-		xmlXPathFreeCompExpr(comppath);
+		PG_RE_THROW();
 	}
+	PG_END_TRY();
 
 	return workspace;
 }
-- 
2.54.0


--MP_/LMSk9=uMhuQ1QiIJDarDO8G--






^ permalink  raw  reply  [nested|flat] 611+ messages in thread

* [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths
@ 2026-06-01 22:41 Andrey Chernyy <andrey.cherny@tantorlabs.com>
  0 siblings, 0 replies; 611+ messages in thread

From: Andrey Chernyy @ 2026-06-01 22:41 UTC (permalink / raw)

pgxml_xpath() builds an xpath_workspace before returning it to
callers.  If an ERROR is thrown before the function returns, callers
have not received the workspace pointer yet and cannot run
cleanup_workspace().

Add local error cleanup for the partially built workspace and the
compiled XPath expression.  Also check xmlXPathNewContext() before
dereferencing the returned context.
---
 contrib/xml2/xpath.c | 51 +++++++++++++++++++++++++++-----------------
 1 file changed, 32 insertions(+), 19 deletions(-)

diff --git a/contrib/xml2/xpath.c b/contrib/xml2/xpath.c
index 9fe75cb5ff4..283bb51178d 100644
--- a/contrib/xml2/xpath.c
+++ b/contrib/xml2/xpath.c
@@ -497,36 +497,49 @@ static xpath_workspace *
 pgxml_xpath(text *document, xmlChar *xpath, PgXmlErrorContext *xmlerrcxt)
 {
 	int32		docsize = VARSIZE_ANY_EXHDR(document);
-	xmlXPathCompExprPtr comppath;
+	xmlXPathCompExprPtr volatile comppath = NULL;
 	xpath_workspace *workspace = palloc0_object(xpath_workspace);
 
 	workspace->doctree = NULL;
 	workspace->ctxt = NULL;
 	workspace->res = NULL;
 
-	workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
-									   docsize, NULL, NULL,
-									   XML_PARSE_NOENT);
-	if (workspace->doctree != NULL)
+	PG_TRY();
 	{
-		workspace->ctxt = xmlXPathNewContext(workspace->doctree);
-		workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
-
-		/* compile the path */
-		comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
-		if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+		workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
+										   docsize, NULL, NULL,
+										   XML_PARSE_NOENT);
+		if (workspace->doctree != NULL)
 		{
-			if (comppath != NULL)
-				xmlXPathFreeCompExpr(comppath);
-			xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
-						"XPath Syntax Error");
-		}
+			workspace->ctxt = xmlXPathNewContext(workspace->doctree);
+			if (workspace->ctxt == NULL)
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_OUT_OF_MEMORY,
+							"could not allocate XPath context");
 
-		/* Now evaluate the path expression. */
-		workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+			workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
+
+			/* compile the path */
+			comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
+			if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
+							"XPath Syntax Error");
+
+			/* Now evaluate the path expression. */
+			workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+
+			xmlXPathFreeCompExpr(comppath);
+			comppath = NULL;
+		}
+	}
+	PG_CATCH();
+	{
+		if (comppath != NULL)
+			xmlXPathFreeCompExpr(comppath);
+		cleanup_workspace(workspace);
 
-		xmlXPathFreeCompExpr(comppath);
+		PG_RE_THROW();
 	}
+	PG_END_TRY();
 
 	return workspace;
 }
-- 
2.54.0


--MP_/LMSk9=uMhuQ1QiIJDarDO8G--





^ permalink  raw  reply  [nested|flat] 611+ messages in thread

* [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths
@ 2026-06-01 22:41 Andrey Chernyy <andrey.cherny@tantorlabs.com>
  0 siblings, 0 replies; 611+ messages in thread

From: Andrey Chernyy @ 2026-06-01 22:41 UTC (permalink / raw)

pgxml_xpath() builds an xpath_workspace before returning it to
callers.  If an ERROR is thrown before the function returns, callers
have not received the workspace pointer yet and cannot run
cleanup_workspace().

Add local error cleanup for the partially built workspace and the
compiled XPath expression.  Also check xmlXPathNewContext() before
dereferencing the returned context.
---
 contrib/xml2/xpath.c | 51 +++++++++++++++++++++++++++-----------------
 1 file changed, 32 insertions(+), 19 deletions(-)

diff --git a/contrib/xml2/xpath.c b/contrib/xml2/xpath.c
index 9fe75cb5ff4..283bb51178d 100644
--- a/contrib/xml2/xpath.c
+++ b/contrib/xml2/xpath.c
@@ -497,36 +497,49 @@ static xpath_workspace *
 pgxml_xpath(text *document, xmlChar *xpath, PgXmlErrorContext *xmlerrcxt)
 {
 	int32		docsize = VARSIZE_ANY_EXHDR(document);
-	xmlXPathCompExprPtr comppath;
+	xmlXPathCompExprPtr volatile comppath = NULL;
 	xpath_workspace *workspace = palloc0_object(xpath_workspace);
 
 	workspace->doctree = NULL;
 	workspace->ctxt = NULL;
 	workspace->res = NULL;
 
-	workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
-									   docsize, NULL, NULL,
-									   XML_PARSE_NOENT);
-	if (workspace->doctree != NULL)
+	PG_TRY();
 	{
-		workspace->ctxt = xmlXPathNewContext(workspace->doctree);
-		workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
-
-		/* compile the path */
-		comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
-		if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+		workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
+										   docsize, NULL, NULL,
+										   XML_PARSE_NOENT);
+		if (workspace->doctree != NULL)
 		{
-			if (comppath != NULL)
-				xmlXPathFreeCompExpr(comppath);
-			xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
-						"XPath Syntax Error");
-		}
+			workspace->ctxt = xmlXPathNewContext(workspace->doctree);
+			if (workspace->ctxt == NULL)
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_OUT_OF_MEMORY,
+							"could not allocate XPath context");
 
-		/* Now evaluate the path expression. */
-		workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+			workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
+
+			/* compile the path */
+			comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
+			if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
+							"XPath Syntax Error");
+
+			/* Now evaluate the path expression. */
+			workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+
+			xmlXPathFreeCompExpr(comppath);
+			comppath = NULL;
+		}
+	}
+	PG_CATCH();
+	{
+		if (comppath != NULL)
+			xmlXPathFreeCompExpr(comppath);
+		cleanup_workspace(workspace);
 
-		xmlXPathFreeCompExpr(comppath);
+		PG_RE_THROW();
 	}
+	PG_END_TRY();
 
 	return workspace;
 }
-- 
2.54.0


--MP_/LMSk9=uMhuQ1QiIJDarDO8G--





^ permalink  raw  reply  [nested|flat] 611+ messages in thread

* [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths
@ 2026-06-01 22:41 Andrey Chernyy <andrey.cherny@tantorlabs.com>
  0 siblings, 0 replies; 611+ messages in thread

From: Andrey Chernyy @ 2026-06-01 22:41 UTC (permalink / raw)

pgxml_xpath() builds an xpath_workspace before returning it to
callers.  If an ERROR is thrown before the function returns, callers
have not received the workspace pointer yet and cannot run
cleanup_workspace().

Add local error cleanup for the partially built workspace and the
compiled XPath expression.  Also check xmlXPathNewContext() before
dereferencing the returned context.
---
 contrib/xml2/xpath.c | 51 +++++++++++++++++++++++++++-----------------
 1 file changed, 32 insertions(+), 19 deletions(-)

diff --git a/contrib/xml2/xpath.c b/contrib/xml2/xpath.c
index 9fe75cb5ff4..283bb51178d 100644
--- a/contrib/xml2/xpath.c
+++ b/contrib/xml2/xpath.c
@@ -497,36 +497,49 @@ static xpath_workspace *
 pgxml_xpath(text *document, xmlChar *xpath, PgXmlErrorContext *xmlerrcxt)
 {
 	int32		docsize = VARSIZE_ANY_EXHDR(document);
-	xmlXPathCompExprPtr comppath;
+	xmlXPathCompExprPtr volatile comppath = NULL;
 	xpath_workspace *workspace = palloc0_object(xpath_workspace);
 
 	workspace->doctree = NULL;
 	workspace->ctxt = NULL;
 	workspace->res = NULL;
 
-	workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
-									   docsize, NULL, NULL,
-									   XML_PARSE_NOENT);
-	if (workspace->doctree != NULL)
+	PG_TRY();
 	{
-		workspace->ctxt = xmlXPathNewContext(workspace->doctree);
-		workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
-
-		/* compile the path */
-		comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
-		if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+		workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
+										   docsize, NULL, NULL,
+										   XML_PARSE_NOENT);
+		if (workspace->doctree != NULL)
 		{
-			if (comppath != NULL)
-				xmlXPathFreeCompExpr(comppath);
-			xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
-						"XPath Syntax Error");
-		}
+			workspace->ctxt = xmlXPathNewContext(workspace->doctree);
+			if (workspace->ctxt == NULL)
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_OUT_OF_MEMORY,
+							"could not allocate XPath context");
 
-		/* Now evaluate the path expression. */
-		workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+			workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
+
+			/* compile the path */
+			comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
+			if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
+							"XPath Syntax Error");
+
+			/* Now evaluate the path expression. */
+			workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+
+			xmlXPathFreeCompExpr(comppath);
+			comppath = NULL;
+		}
+	}
+	PG_CATCH();
+	{
+		if (comppath != NULL)
+			xmlXPathFreeCompExpr(comppath);
+		cleanup_workspace(workspace);
 
-		xmlXPathFreeCompExpr(comppath);
+		PG_RE_THROW();
 	}
+	PG_END_TRY();
 
 	return workspace;
 }
-- 
2.54.0


--MP_/LMSk9=uMhuQ1QiIJDarDO8G--






^ permalink  raw  reply  [nested|flat] 611+ messages in thread

* [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths
@ 2026-06-01 22:41 Andrey Chernyy <andrey.cherny@tantorlabs.com>
  0 siblings, 0 replies; 611+ messages in thread

From: Andrey Chernyy @ 2026-06-01 22:41 UTC (permalink / raw)

pgxml_xpath() builds an xpath_workspace before returning it to
callers.  If an ERROR is thrown before the function returns, callers
have not received the workspace pointer yet and cannot run
cleanup_workspace().

Add local error cleanup for the partially built workspace and the
compiled XPath expression.  Also check xmlXPathNewContext() before
dereferencing the returned context.
---
 contrib/xml2/xpath.c | 51 +++++++++++++++++++++++++++-----------------
 1 file changed, 32 insertions(+), 19 deletions(-)

diff --git a/contrib/xml2/xpath.c b/contrib/xml2/xpath.c
index 9fe75cb5ff4..283bb51178d 100644
--- a/contrib/xml2/xpath.c
+++ b/contrib/xml2/xpath.c
@@ -497,36 +497,49 @@ static xpath_workspace *
 pgxml_xpath(text *document, xmlChar *xpath, PgXmlErrorContext *xmlerrcxt)
 {
 	int32		docsize = VARSIZE_ANY_EXHDR(document);
-	xmlXPathCompExprPtr comppath;
+	xmlXPathCompExprPtr volatile comppath = NULL;
 	xpath_workspace *workspace = palloc0_object(xpath_workspace);
 
 	workspace->doctree = NULL;
 	workspace->ctxt = NULL;
 	workspace->res = NULL;
 
-	workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
-									   docsize, NULL, NULL,
-									   XML_PARSE_NOENT);
-	if (workspace->doctree != NULL)
+	PG_TRY();
 	{
-		workspace->ctxt = xmlXPathNewContext(workspace->doctree);
-		workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
-
-		/* compile the path */
-		comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
-		if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+		workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
+										   docsize, NULL, NULL,
+										   XML_PARSE_NOENT);
+		if (workspace->doctree != NULL)
 		{
-			if (comppath != NULL)
-				xmlXPathFreeCompExpr(comppath);
-			xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
-						"XPath Syntax Error");
-		}
+			workspace->ctxt = xmlXPathNewContext(workspace->doctree);
+			if (workspace->ctxt == NULL)
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_OUT_OF_MEMORY,
+							"could not allocate XPath context");
 
-		/* Now evaluate the path expression. */
-		workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+			workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
+
+			/* compile the path */
+			comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
+			if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
+							"XPath Syntax Error");
+
+			/* Now evaluate the path expression. */
+			workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+
+			xmlXPathFreeCompExpr(comppath);
+			comppath = NULL;
+		}
+	}
+	PG_CATCH();
+	{
+		if (comppath != NULL)
+			xmlXPathFreeCompExpr(comppath);
+		cleanup_workspace(workspace);
 
-		xmlXPathFreeCompExpr(comppath);
+		PG_RE_THROW();
 	}
+	PG_END_TRY();
 
 	return workspace;
 }
-- 
2.54.0


--MP_/LMSk9=uMhuQ1QiIJDarDO8G--






^ permalink  raw  reply  [nested|flat] 611+ messages in thread

* [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths
@ 2026-06-01 22:41 Andrey Chernyy <andrey.cherny@tantorlabs.com>
  0 siblings, 0 replies; 611+ messages in thread

From: Andrey Chernyy @ 2026-06-01 22:41 UTC (permalink / raw)

pgxml_xpath() builds an xpath_workspace before returning it to
callers.  If an ERROR is thrown before the function returns, callers
have not received the workspace pointer yet and cannot run
cleanup_workspace().

Add local error cleanup for the partially built workspace and the
compiled XPath expression.  Also check xmlXPathNewContext() before
dereferencing the returned context.
---
 contrib/xml2/xpath.c | 51 +++++++++++++++++++++++++++-----------------
 1 file changed, 32 insertions(+), 19 deletions(-)

diff --git a/contrib/xml2/xpath.c b/contrib/xml2/xpath.c
index 9fe75cb5ff4..283bb51178d 100644
--- a/contrib/xml2/xpath.c
+++ b/contrib/xml2/xpath.c
@@ -497,36 +497,49 @@ static xpath_workspace *
 pgxml_xpath(text *document, xmlChar *xpath, PgXmlErrorContext *xmlerrcxt)
 {
 	int32		docsize = VARSIZE_ANY_EXHDR(document);
-	xmlXPathCompExprPtr comppath;
+	xmlXPathCompExprPtr volatile comppath = NULL;
 	xpath_workspace *workspace = palloc0_object(xpath_workspace);
 
 	workspace->doctree = NULL;
 	workspace->ctxt = NULL;
 	workspace->res = NULL;
 
-	workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
-									   docsize, NULL, NULL,
-									   XML_PARSE_NOENT);
-	if (workspace->doctree != NULL)
+	PG_TRY();
 	{
-		workspace->ctxt = xmlXPathNewContext(workspace->doctree);
-		workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
-
-		/* compile the path */
-		comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
-		if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+		workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
+										   docsize, NULL, NULL,
+										   XML_PARSE_NOENT);
+		if (workspace->doctree != NULL)
 		{
-			if (comppath != NULL)
-				xmlXPathFreeCompExpr(comppath);
-			xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
-						"XPath Syntax Error");
-		}
+			workspace->ctxt = xmlXPathNewContext(workspace->doctree);
+			if (workspace->ctxt == NULL)
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_OUT_OF_MEMORY,
+							"could not allocate XPath context");
 
-		/* Now evaluate the path expression. */
-		workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+			workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
+
+			/* compile the path */
+			comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
+			if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
+							"XPath Syntax Error");
+
+			/* Now evaluate the path expression. */
+			workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+
+			xmlXPathFreeCompExpr(comppath);
+			comppath = NULL;
+		}
+	}
+	PG_CATCH();
+	{
+		if (comppath != NULL)
+			xmlXPathFreeCompExpr(comppath);
+		cleanup_workspace(workspace);
 
-		xmlXPathFreeCompExpr(comppath);
+		PG_RE_THROW();
 	}
+	PG_END_TRY();
 
 	return workspace;
 }
-- 
2.54.0


--MP_/LMSk9=uMhuQ1QiIJDarDO8G--






^ permalink  raw  reply  [nested|flat] 611+ messages in thread

* [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths
@ 2026-06-01 22:41 Andrey Chernyy <andrey.cherny@tantorlabs.com>
  0 siblings, 0 replies; 611+ messages in thread

From: Andrey Chernyy @ 2026-06-01 22:41 UTC (permalink / raw)

pgxml_xpath() builds an xpath_workspace before returning it to
callers.  If an ERROR is thrown before the function returns, callers
have not received the workspace pointer yet and cannot run
cleanup_workspace().

Add local error cleanup for the partially built workspace and the
compiled XPath expression.  Also check xmlXPathNewContext() before
dereferencing the returned context.
---
 contrib/xml2/xpath.c | 51 +++++++++++++++++++++++++++-----------------
 1 file changed, 32 insertions(+), 19 deletions(-)

diff --git a/contrib/xml2/xpath.c b/contrib/xml2/xpath.c
index 9fe75cb5ff4..283bb51178d 100644
--- a/contrib/xml2/xpath.c
+++ b/contrib/xml2/xpath.c
@@ -497,36 +497,49 @@ static xpath_workspace *
 pgxml_xpath(text *document, xmlChar *xpath, PgXmlErrorContext *xmlerrcxt)
 {
 	int32		docsize = VARSIZE_ANY_EXHDR(document);
-	xmlXPathCompExprPtr comppath;
+	xmlXPathCompExprPtr volatile comppath = NULL;
 	xpath_workspace *workspace = palloc0_object(xpath_workspace);
 
 	workspace->doctree = NULL;
 	workspace->ctxt = NULL;
 	workspace->res = NULL;
 
-	workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
-									   docsize, NULL, NULL,
-									   XML_PARSE_NOENT);
-	if (workspace->doctree != NULL)
+	PG_TRY();
 	{
-		workspace->ctxt = xmlXPathNewContext(workspace->doctree);
-		workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
-
-		/* compile the path */
-		comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
-		if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+		workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
+										   docsize, NULL, NULL,
+										   XML_PARSE_NOENT);
+		if (workspace->doctree != NULL)
 		{
-			if (comppath != NULL)
-				xmlXPathFreeCompExpr(comppath);
-			xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
-						"XPath Syntax Error");
-		}
+			workspace->ctxt = xmlXPathNewContext(workspace->doctree);
+			if (workspace->ctxt == NULL)
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_OUT_OF_MEMORY,
+							"could not allocate XPath context");
 
-		/* Now evaluate the path expression. */
-		workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+			workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
+
+			/* compile the path */
+			comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
+			if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
+							"XPath Syntax Error");
+
+			/* Now evaluate the path expression. */
+			workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+
+			xmlXPathFreeCompExpr(comppath);
+			comppath = NULL;
+		}
+	}
+	PG_CATCH();
+	{
+		if (comppath != NULL)
+			xmlXPathFreeCompExpr(comppath);
+		cleanup_workspace(workspace);
 
-		xmlXPathFreeCompExpr(comppath);
+		PG_RE_THROW();
 	}
+	PG_END_TRY();
 
 	return workspace;
 }
-- 
2.54.0


--MP_/LMSk9=uMhuQ1QiIJDarDO8G--






^ permalink  raw  reply  [nested|flat] 611+ messages in thread

* [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths
@ 2026-06-01 22:41 Andrey Chernyy <andrey.cherny@tantorlabs.com>
  0 siblings, 0 replies; 611+ messages in thread

From: Andrey Chernyy @ 2026-06-01 22:41 UTC (permalink / raw)

pgxml_xpath() builds an xpath_workspace before returning it to
callers.  If an ERROR is thrown before the function returns, callers
have not received the workspace pointer yet and cannot run
cleanup_workspace().

Add local error cleanup for the partially built workspace and the
compiled XPath expression.  Also check xmlXPathNewContext() before
dereferencing the returned context.
---
 contrib/xml2/xpath.c | 51 +++++++++++++++++++++++++++-----------------
 1 file changed, 32 insertions(+), 19 deletions(-)

diff --git a/contrib/xml2/xpath.c b/contrib/xml2/xpath.c
index 9fe75cb5ff4..283bb51178d 100644
--- a/contrib/xml2/xpath.c
+++ b/contrib/xml2/xpath.c
@@ -497,36 +497,49 @@ static xpath_workspace *
 pgxml_xpath(text *document, xmlChar *xpath, PgXmlErrorContext *xmlerrcxt)
 {
 	int32		docsize = VARSIZE_ANY_EXHDR(document);
-	xmlXPathCompExprPtr comppath;
+	xmlXPathCompExprPtr volatile comppath = NULL;
 	xpath_workspace *workspace = palloc0_object(xpath_workspace);
 
 	workspace->doctree = NULL;
 	workspace->ctxt = NULL;
 	workspace->res = NULL;
 
-	workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
-									   docsize, NULL, NULL,
-									   XML_PARSE_NOENT);
-	if (workspace->doctree != NULL)
+	PG_TRY();
 	{
-		workspace->ctxt = xmlXPathNewContext(workspace->doctree);
-		workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
-
-		/* compile the path */
-		comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
-		if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+		workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
+										   docsize, NULL, NULL,
+										   XML_PARSE_NOENT);
+		if (workspace->doctree != NULL)
 		{
-			if (comppath != NULL)
-				xmlXPathFreeCompExpr(comppath);
-			xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
-						"XPath Syntax Error");
-		}
+			workspace->ctxt = xmlXPathNewContext(workspace->doctree);
+			if (workspace->ctxt == NULL)
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_OUT_OF_MEMORY,
+							"could not allocate XPath context");
 
-		/* Now evaluate the path expression. */
-		workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+			workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
+
+			/* compile the path */
+			comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
+			if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
+							"XPath Syntax Error");
+
+			/* Now evaluate the path expression. */
+			workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+
+			xmlXPathFreeCompExpr(comppath);
+			comppath = NULL;
+		}
+	}
+	PG_CATCH();
+	{
+		if (comppath != NULL)
+			xmlXPathFreeCompExpr(comppath);
+		cleanup_workspace(workspace);
 
-		xmlXPathFreeCompExpr(comppath);
+		PG_RE_THROW();
 	}
+	PG_END_TRY();
 
 	return workspace;
 }
-- 
2.54.0


--MP_/LMSk9=uMhuQ1QiIJDarDO8G--





^ permalink  raw  reply  [nested|flat] 611+ messages in thread

* [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths
@ 2026-06-01 22:41 Andrey Chernyy <andrey.cherny@tantorlabs.com>
  0 siblings, 0 replies; 611+ messages in thread

From: Andrey Chernyy @ 2026-06-01 22:41 UTC (permalink / raw)

pgxml_xpath() builds an xpath_workspace before returning it to
callers.  If an ERROR is thrown before the function returns, callers
have not received the workspace pointer yet and cannot run
cleanup_workspace().

Add local error cleanup for the partially built workspace and the
compiled XPath expression.  Also check xmlXPathNewContext() before
dereferencing the returned context.
---
 contrib/xml2/xpath.c | 51 +++++++++++++++++++++++++++-----------------
 1 file changed, 32 insertions(+), 19 deletions(-)

diff --git a/contrib/xml2/xpath.c b/contrib/xml2/xpath.c
index 9fe75cb5ff4..283bb51178d 100644
--- a/contrib/xml2/xpath.c
+++ b/contrib/xml2/xpath.c
@@ -497,36 +497,49 @@ static xpath_workspace *
 pgxml_xpath(text *document, xmlChar *xpath, PgXmlErrorContext *xmlerrcxt)
 {
 	int32		docsize = VARSIZE_ANY_EXHDR(document);
-	xmlXPathCompExprPtr comppath;
+	xmlXPathCompExprPtr volatile comppath = NULL;
 	xpath_workspace *workspace = palloc0_object(xpath_workspace);
 
 	workspace->doctree = NULL;
 	workspace->ctxt = NULL;
 	workspace->res = NULL;
 
-	workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
-									   docsize, NULL, NULL,
-									   XML_PARSE_NOENT);
-	if (workspace->doctree != NULL)
+	PG_TRY();
 	{
-		workspace->ctxt = xmlXPathNewContext(workspace->doctree);
-		workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
-
-		/* compile the path */
-		comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
-		if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+		workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
+										   docsize, NULL, NULL,
+										   XML_PARSE_NOENT);
+		if (workspace->doctree != NULL)
 		{
-			if (comppath != NULL)
-				xmlXPathFreeCompExpr(comppath);
-			xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
-						"XPath Syntax Error");
-		}
+			workspace->ctxt = xmlXPathNewContext(workspace->doctree);
+			if (workspace->ctxt == NULL)
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_OUT_OF_MEMORY,
+							"could not allocate XPath context");
 
-		/* Now evaluate the path expression. */
-		workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+			workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
+
+			/* compile the path */
+			comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
+			if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
+							"XPath Syntax Error");
+
+			/* Now evaluate the path expression. */
+			workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+
+			xmlXPathFreeCompExpr(comppath);
+			comppath = NULL;
+		}
+	}
+	PG_CATCH();
+	{
+		if (comppath != NULL)
+			xmlXPathFreeCompExpr(comppath);
+		cleanup_workspace(workspace);
 
-		xmlXPathFreeCompExpr(comppath);
+		PG_RE_THROW();
 	}
+	PG_END_TRY();
 
 	return workspace;
 }
-- 
2.54.0


--MP_/LMSk9=uMhuQ1QiIJDarDO8G--





^ permalink  raw  reply  [nested|flat] 611+ messages in thread

* [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths
@ 2026-06-01 22:41 Andrey Chernyy <andrey.cherny@tantorlabs.com>
  0 siblings, 0 replies; 611+ messages in thread

From: Andrey Chernyy @ 2026-06-01 22:41 UTC (permalink / raw)

pgxml_xpath() builds an xpath_workspace before returning it to
callers.  If an ERROR is thrown before the function returns, callers
have not received the workspace pointer yet and cannot run
cleanup_workspace().

Add local error cleanup for the partially built workspace and the
compiled XPath expression.  Also check xmlXPathNewContext() before
dereferencing the returned context.
---
 contrib/xml2/xpath.c | 51 +++++++++++++++++++++++++++-----------------
 1 file changed, 32 insertions(+), 19 deletions(-)

diff --git a/contrib/xml2/xpath.c b/contrib/xml2/xpath.c
index 9fe75cb5ff4..283bb51178d 100644
--- a/contrib/xml2/xpath.c
+++ b/contrib/xml2/xpath.c
@@ -497,36 +497,49 @@ static xpath_workspace *
 pgxml_xpath(text *document, xmlChar *xpath, PgXmlErrorContext *xmlerrcxt)
 {
 	int32		docsize = VARSIZE_ANY_EXHDR(document);
-	xmlXPathCompExprPtr comppath;
+	xmlXPathCompExprPtr volatile comppath = NULL;
 	xpath_workspace *workspace = palloc0_object(xpath_workspace);
 
 	workspace->doctree = NULL;
 	workspace->ctxt = NULL;
 	workspace->res = NULL;
 
-	workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
-									   docsize, NULL, NULL,
-									   XML_PARSE_NOENT);
-	if (workspace->doctree != NULL)
+	PG_TRY();
 	{
-		workspace->ctxt = xmlXPathNewContext(workspace->doctree);
-		workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
-
-		/* compile the path */
-		comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
-		if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+		workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
+										   docsize, NULL, NULL,
+										   XML_PARSE_NOENT);
+		if (workspace->doctree != NULL)
 		{
-			if (comppath != NULL)
-				xmlXPathFreeCompExpr(comppath);
-			xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
-						"XPath Syntax Error");
-		}
+			workspace->ctxt = xmlXPathNewContext(workspace->doctree);
+			if (workspace->ctxt == NULL)
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_OUT_OF_MEMORY,
+							"could not allocate XPath context");
 
-		/* Now evaluate the path expression. */
-		workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+			workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
+
+			/* compile the path */
+			comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
+			if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
+							"XPath Syntax Error");
+
+			/* Now evaluate the path expression. */
+			workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+
+			xmlXPathFreeCompExpr(comppath);
+			comppath = NULL;
+		}
+	}
+	PG_CATCH();
+	{
+		if (comppath != NULL)
+			xmlXPathFreeCompExpr(comppath);
+		cleanup_workspace(workspace);
 
-		xmlXPathFreeCompExpr(comppath);
+		PG_RE_THROW();
 	}
+	PG_END_TRY();
 
 	return workspace;
 }
-- 
2.54.0


--MP_/LMSk9=uMhuQ1QiIJDarDO8G--





^ permalink  raw  reply  [nested|flat] 611+ messages in thread

* [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths
@ 2026-06-01 22:41 Andrey Chernyy <andrey.cherny@tantorlabs.com>
  0 siblings, 0 replies; 611+ messages in thread

From: Andrey Chernyy @ 2026-06-01 22:41 UTC (permalink / raw)

pgxml_xpath() builds an xpath_workspace before returning it to
callers.  If an ERROR is thrown before the function returns, callers
have not received the workspace pointer yet and cannot run
cleanup_workspace().

Add local error cleanup for the partially built workspace and the
compiled XPath expression.  Also check xmlXPathNewContext() before
dereferencing the returned context.
---
 contrib/xml2/xpath.c | 51 +++++++++++++++++++++++++++-----------------
 1 file changed, 32 insertions(+), 19 deletions(-)

diff --git a/contrib/xml2/xpath.c b/contrib/xml2/xpath.c
index 9fe75cb5ff4..283bb51178d 100644
--- a/contrib/xml2/xpath.c
+++ b/contrib/xml2/xpath.c
@@ -497,36 +497,49 @@ static xpath_workspace *
 pgxml_xpath(text *document, xmlChar *xpath, PgXmlErrorContext *xmlerrcxt)
 {
 	int32		docsize = VARSIZE_ANY_EXHDR(document);
-	xmlXPathCompExprPtr comppath;
+	xmlXPathCompExprPtr volatile comppath = NULL;
 	xpath_workspace *workspace = palloc0_object(xpath_workspace);
 
 	workspace->doctree = NULL;
 	workspace->ctxt = NULL;
 	workspace->res = NULL;
 
-	workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
-									   docsize, NULL, NULL,
-									   XML_PARSE_NOENT);
-	if (workspace->doctree != NULL)
+	PG_TRY();
 	{
-		workspace->ctxt = xmlXPathNewContext(workspace->doctree);
-		workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
-
-		/* compile the path */
-		comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
-		if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+		workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
+										   docsize, NULL, NULL,
+										   XML_PARSE_NOENT);
+		if (workspace->doctree != NULL)
 		{
-			if (comppath != NULL)
-				xmlXPathFreeCompExpr(comppath);
-			xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
-						"XPath Syntax Error");
-		}
+			workspace->ctxt = xmlXPathNewContext(workspace->doctree);
+			if (workspace->ctxt == NULL)
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_OUT_OF_MEMORY,
+							"could not allocate XPath context");
 
-		/* Now evaluate the path expression. */
-		workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+			workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
+
+			/* compile the path */
+			comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
+			if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
+							"XPath Syntax Error");
+
+			/* Now evaluate the path expression. */
+			workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+
+			xmlXPathFreeCompExpr(comppath);
+			comppath = NULL;
+		}
+	}
+	PG_CATCH();
+	{
+		if (comppath != NULL)
+			xmlXPathFreeCompExpr(comppath);
+		cleanup_workspace(workspace);
 
-		xmlXPathFreeCompExpr(comppath);
+		PG_RE_THROW();
 	}
+	PG_END_TRY();
 
 	return workspace;
 }
-- 
2.54.0


--MP_/LMSk9=uMhuQ1QiIJDarDO8G--






^ permalink  raw  reply  [nested|flat] 611+ messages in thread

* [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths
@ 2026-06-01 22:41 Andrey Chernyy <andrey.cherny@tantorlabs.com>
  0 siblings, 0 replies; 611+ messages in thread

From: Andrey Chernyy @ 2026-06-01 22:41 UTC (permalink / raw)

pgxml_xpath() builds an xpath_workspace before returning it to
callers.  If an ERROR is thrown before the function returns, callers
have not received the workspace pointer yet and cannot run
cleanup_workspace().

Add local error cleanup for the partially built workspace and the
compiled XPath expression.  Also check xmlXPathNewContext() before
dereferencing the returned context.
---
 contrib/xml2/xpath.c | 51 +++++++++++++++++++++++++++-----------------
 1 file changed, 32 insertions(+), 19 deletions(-)

diff --git a/contrib/xml2/xpath.c b/contrib/xml2/xpath.c
index 9fe75cb5ff4..283bb51178d 100644
--- a/contrib/xml2/xpath.c
+++ b/contrib/xml2/xpath.c
@@ -497,36 +497,49 @@ static xpath_workspace *
 pgxml_xpath(text *document, xmlChar *xpath, PgXmlErrorContext *xmlerrcxt)
 {
 	int32		docsize = VARSIZE_ANY_EXHDR(document);
-	xmlXPathCompExprPtr comppath;
+	xmlXPathCompExprPtr volatile comppath = NULL;
 	xpath_workspace *workspace = palloc0_object(xpath_workspace);
 
 	workspace->doctree = NULL;
 	workspace->ctxt = NULL;
 	workspace->res = NULL;
 
-	workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
-									   docsize, NULL, NULL,
-									   XML_PARSE_NOENT);
-	if (workspace->doctree != NULL)
+	PG_TRY();
 	{
-		workspace->ctxt = xmlXPathNewContext(workspace->doctree);
-		workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
-
-		/* compile the path */
-		comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
-		if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+		workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
+										   docsize, NULL, NULL,
+										   XML_PARSE_NOENT);
+		if (workspace->doctree != NULL)
 		{
-			if (comppath != NULL)
-				xmlXPathFreeCompExpr(comppath);
-			xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
-						"XPath Syntax Error");
-		}
+			workspace->ctxt = xmlXPathNewContext(workspace->doctree);
+			if (workspace->ctxt == NULL)
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_OUT_OF_MEMORY,
+							"could not allocate XPath context");
 
-		/* Now evaluate the path expression. */
-		workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+			workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
+
+			/* compile the path */
+			comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
+			if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
+							"XPath Syntax Error");
+
+			/* Now evaluate the path expression. */
+			workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+
+			xmlXPathFreeCompExpr(comppath);
+			comppath = NULL;
+		}
+	}
+	PG_CATCH();
+	{
+		if (comppath != NULL)
+			xmlXPathFreeCompExpr(comppath);
+		cleanup_workspace(workspace);
 
-		xmlXPathFreeCompExpr(comppath);
+		PG_RE_THROW();
 	}
+	PG_END_TRY();
 
 	return workspace;
 }
-- 
2.54.0


--MP_/LMSk9=uMhuQ1QiIJDarDO8G--






^ permalink  raw  reply  [nested|flat] 611+ messages in thread

* [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths
@ 2026-06-01 22:41 Andrey Chernyy <andrey.cherny@tantorlabs.com>
  0 siblings, 0 replies; 611+ messages in thread

From: Andrey Chernyy @ 2026-06-01 22:41 UTC (permalink / raw)

pgxml_xpath() builds an xpath_workspace before returning it to
callers.  If an ERROR is thrown before the function returns, callers
have not received the workspace pointer yet and cannot run
cleanup_workspace().

Add local error cleanup for the partially built workspace and the
compiled XPath expression.  Also check xmlXPathNewContext() before
dereferencing the returned context.
---
 contrib/xml2/xpath.c | 51 +++++++++++++++++++++++++++-----------------
 1 file changed, 32 insertions(+), 19 deletions(-)

diff --git a/contrib/xml2/xpath.c b/contrib/xml2/xpath.c
index 9fe75cb5ff4..283bb51178d 100644
--- a/contrib/xml2/xpath.c
+++ b/contrib/xml2/xpath.c
@@ -497,36 +497,49 @@ static xpath_workspace *
 pgxml_xpath(text *document, xmlChar *xpath, PgXmlErrorContext *xmlerrcxt)
 {
 	int32		docsize = VARSIZE_ANY_EXHDR(document);
-	xmlXPathCompExprPtr comppath;
+	xmlXPathCompExprPtr volatile comppath = NULL;
 	xpath_workspace *workspace = palloc0_object(xpath_workspace);
 
 	workspace->doctree = NULL;
 	workspace->ctxt = NULL;
 	workspace->res = NULL;
 
-	workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
-									   docsize, NULL, NULL,
-									   XML_PARSE_NOENT);
-	if (workspace->doctree != NULL)
+	PG_TRY();
 	{
-		workspace->ctxt = xmlXPathNewContext(workspace->doctree);
-		workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
-
-		/* compile the path */
-		comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
-		if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+		workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
+										   docsize, NULL, NULL,
+										   XML_PARSE_NOENT);
+		if (workspace->doctree != NULL)
 		{
-			if (comppath != NULL)
-				xmlXPathFreeCompExpr(comppath);
-			xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
-						"XPath Syntax Error");
-		}
+			workspace->ctxt = xmlXPathNewContext(workspace->doctree);
+			if (workspace->ctxt == NULL)
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_OUT_OF_MEMORY,
+							"could not allocate XPath context");
 
-		/* Now evaluate the path expression. */
-		workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+			workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
+
+			/* compile the path */
+			comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
+			if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
+							"XPath Syntax Error");
+
+			/* Now evaluate the path expression. */
+			workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+
+			xmlXPathFreeCompExpr(comppath);
+			comppath = NULL;
+		}
+	}
+	PG_CATCH();
+	{
+		if (comppath != NULL)
+			xmlXPathFreeCompExpr(comppath);
+		cleanup_workspace(workspace);
 
-		xmlXPathFreeCompExpr(comppath);
+		PG_RE_THROW();
 	}
+	PG_END_TRY();
 
 	return workspace;
 }
-- 
2.54.0


--MP_/LMSk9=uMhuQ1QiIJDarDO8G--






^ permalink  raw  reply  [nested|flat] 611+ messages in thread

* [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths
@ 2026-06-01 22:41 Andrey Chernyy <andrey.cherny@tantorlabs.com>
  0 siblings, 0 replies; 611+ messages in thread

From: Andrey Chernyy @ 2026-06-01 22:41 UTC (permalink / raw)

pgxml_xpath() builds an xpath_workspace before returning it to
callers.  If an ERROR is thrown before the function returns, callers
have not received the workspace pointer yet and cannot run
cleanup_workspace().

Add local error cleanup for the partially built workspace and the
compiled XPath expression.  Also check xmlXPathNewContext() before
dereferencing the returned context.
---
 contrib/xml2/xpath.c | 51 +++++++++++++++++++++++++++-----------------
 1 file changed, 32 insertions(+), 19 deletions(-)

diff --git a/contrib/xml2/xpath.c b/contrib/xml2/xpath.c
index 9fe75cb5ff4..283bb51178d 100644
--- a/contrib/xml2/xpath.c
+++ b/contrib/xml2/xpath.c
@@ -497,36 +497,49 @@ static xpath_workspace *
 pgxml_xpath(text *document, xmlChar *xpath, PgXmlErrorContext *xmlerrcxt)
 {
 	int32		docsize = VARSIZE_ANY_EXHDR(document);
-	xmlXPathCompExprPtr comppath;
+	xmlXPathCompExprPtr volatile comppath = NULL;
 	xpath_workspace *workspace = palloc0_object(xpath_workspace);
 
 	workspace->doctree = NULL;
 	workspace->ctxt = NULL;
 	workspace->res = NULL;
 
-	workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
-									   docsize, NULL, NULL,
-									   XML_PARSE_NOENT);
-	if (workspace->doctree != NULL)
+	PG_TRY();
 	{
-		workspace->ctxt = xmlXPathNewContext(workspace->doctree);
-		workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
-
-		/* compile the path */
-		comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
-		if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+		workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
+										   docsize, NULL, NULL,
+										   XML_PARSE_NOENT);
+		if (workspace->doctree != NULL)
 		{
-			if (comppath != NULL)
-				xmlXPathFreeCompExpr(comppath);
-			xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
-						"XPath Syntax Error");
-		}
+			workspace->ctxt = xmlXPathNewContext(workspace->doctree);
+			if (workspace->ctxt == NULL)
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_OUT_OF_MEMORY,
+							"could not allocate XPath context");
 
-		/* Now evaluate the path expression. */
-		workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+			workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
+
+			/* compile the path */
+			comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
+			if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
+							"XPath Syntax Error");
+
+			/* Now evaluate the path expression. */
+			workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+
+			xmlXPathFreeCompExpr(comppath);
+			comppath = NULL;
+		}
+	}
+	PG_CATCH();
+	{
+		if (comppath != NULL)
+			xmlXPathFreeCompExpr(comppath);
+		cleanup_workspace(workspace);
 
-		xmlXPathFreeCompExpr(comppath);
+		PG_RE_THROW();
 	}
+	PG_END_TRY();
 
 	return workspace;
 }
-- 
2.54.0


--MP_/LMSk9=uMhuQ1QiIJDarDO8G--






^ permalink  raw  reply  [nested|flat] 611+ messages in thread

* [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths
@ 2026-06-01 22:41 Andrey Chernyy <andrey.cherny@tantorlabs.com>
  0 siblings, 0 replies; 611+ messages in thread

From: Andrey Chernyy @ 2026-06-01 22:41 UTC (permalink / raw)

pgxml_xpath() builds an xpath_workspace before returning it to
callers.  If an ERROR is thrown before the function returns, callers
have not received the workspace pointer yet and cannot run
cleanup_workspace().

Add local error cleanup for the partially built workspace and the
compiled XPath expression.  Also check xmlXPathNewContext() before
dereferencing the returned context.
---
 contrib/xml2/xpath.c | 51 +++++++++++++++++++++++++++-----------------
 1 file changed, 32 insertions(+), 19 deletions(-)

diff --git a/contrib/xml2/xpath.c b/contrib/xml2/xpath.c
index 9fe75cb5ff4..283bb51178d 100644
--- a/contrib/xml2/xpath.c
+++ b/contrib/xml2/xpath.c
@@ -497,36 +497,49 @@ static xpath_workspace *
 pgxml_xpath(text *document, xmlChar *xpath, PgXmlErrorContext *xmlerrcxt)
 {
 	int32		docsize = VARSIZE_ANY_EXHDR(document);
-	xmlXPathCompExprPtr comppath;
+	xmlXPathCompExprPtr volatile comppath = NULL;
 	xpath_workspace *workspace = palloc0_object(xpath_workspace);
 
 	workspace->doctree = NULL;
 	workspace->ctxt = NULL;
 	workspace->res = NULL;
 
-	workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
-									   docsize, NULL, NULL,
-									   XML_PARSE_NOENT);
-	if (workspace->doctree != NULL)
+	PG_TRY();
 	{
-		workspace->ctxt = xmlXPathNewContext(workspace->doctree);
-		workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
-
-		/* compile the path */
-		comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
-		if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+		workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
+										   docsize, NULL, NULL,
+										   XML_PARSE_NOENT);
+		if (workspace->doctree != NULL)
 		{
-			if (comppath != NULL)
-				xmlXPathFreeCompExpr(comppath);
-			xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
-						"XPath Syntax Error");
-		}
+			workspace->ctxt = xmlXPathNewContext(workspace->doctree);
+			if (workspace->ctxt == NULL)
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_OUT_OF_MEMORY,
+							"could not allocate XPath context");
 
-		/* Now evaluate the path expression. */
-		workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+			workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
+
+			/* compile the path */
+			comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
+			if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
+							"XPath Syntax Error");
+
+			/* Now evaluate the path expression. */
+			workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+
+			xmlXPathFreeCompExpr(comppath);
+			comppath = NULL;
+		}
+	}
+	PG_CATCH();
+	{
+		if (comppath != NULL)
+			xmlXPathFreeCompExpr(comppath);
+		cleanup_workspace(workspace);
 
-		xmlXPathFreeCompExpr(comppath);
+		PG_RE_THROW();
 	}
+	PG_END_TRY();
 
 	return workspace;
 }
-- 
2.54.0


--MP_/LMSk9=uMhuQ1QiIJDarDO8G--





^ permalink  raw  reply  [nested|flat] 611+ messages in thread

* [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths
@ 2026-06-01 22:41 Andrey Chernyy <andrey.cherny@tantorlabs.com>
  0 siblings, 0 replies; 611+ messages in thread

From: Andrey Chernyy @ 2026-06-01 22:41 UTC (permalink / raw)

pgxml_xpath() builds an xpath_workspace before returning it to
callers.  If an ERROR is thrown before the function returns, callers
have not received the workspace pointer yet and cannot run
cleanup_workspace().

Add local error cleanup for the partially built workspace and the
compiled XPath expression.  Also check xmlXPathNewContext() before
dereferencing the returned context.
---
 contrib/xml2/xpath.c | 51 +++++++++++++++++++++++++++-----------------
 1 file changed, 32 insertions(+), 19 deletions(-)

diff --git a/contrib/xml2/xpath.c b/contrib/xml2/xpath.c
index 9fe75cb5ff4..283bb51178d 100644
--- a/contrib/xml2/xpath.c
+++ b/contrib/xml2/xpath.c
@@ -497,36 +497,49 @@ static xpath_workspace *
 pgxml_xpath(text *document, xmlChar *xpath, PgXmlErrorContext *xmlerrcxt)
 {
 	int32		docsize = VARSIZE_ANY_EXHDR(document);
-	xmlXPathCompExprPtr comppath;
+	xmlXPathCompExprPtr volatile comppath = NULL;
 	xpath_workspace *workspace = palloc0_object(xpath_workspace);
 
 	workspace->doctree = NULL;
 	workspace->ctxt = NULL;
 	workspace->res = NULL;
 
-	workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
-									   docsize, NULL, NULL,
-									   XML_PARSE_NOENT);
-	if (workspace->doctree != NULL)
+	PG_TRY();
 	{
-		workspace->ctxt = xmlXPathNewContext(workspace->doctree);
-		workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
-
-		/* compile the path */
-		comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
-		if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+		workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
+										   docsize, NULL, NULL,
+										   XML_PARSE_NOENT);
+		if (workspace->doctree != NULL)
 		{
-			if (comppath != NULL)
-				xmlXPathFreeCompExpr(comppath);
-			xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
-						"XPath Syntax Error");
-		}
+			workspace->ctxt = xmlXPathNewContext(workspace->doctree);
+			if (workspace->ctxt == NULL)
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_OUT_OF_MEMORY,
+							"could not allocate XPath context");
 
-		/* Now evaluate the path expression. */
-		workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+			workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
+
+			/* compile the path */
+			comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
+			if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
+							"XPath Syntax Error");
+
+			/* Now evaluate the path expression. */
+			workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+
+			xmlXPathFreeCompExpr(comppath);
+			comppath = NULL;
+		}
+	}
+	PG_CATCH();
+	{
+		if (comppath != NULL)
+			xmlXPathFreeCompExpr(comppath);
+		cleanup_workspace(workspace);
 
-		xmlXPathFreeCompExpr(comppath);
+		PG_RE_THROW();
 	}
+	PG_END_TRY();
 
 	return workspace;
 }
-- 
2.54.0


--MP_/LMSk9=uMhuQ1QiIJDarDO8G--






^ permalink  raw  reply  [nested|flat] 611+ messages in thread

* [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths
@ 2026-06-01 22:41 Andrey Chernyy <andrey.cherny@tantorlabs.com>
  0 siblings, 0 replies; 611+ messages in thread

From: Andrey Chernyy @ 2026-06-01 22:41 UTC (permalink / raw)

pgxml_xpath() builds an xpath_workspace before returning it to
callers.  If an ERROR is thrown before the function returns, callers
have not received the workspace pointer yet and cannot run
cleanup_workspace().

Add local error cleanup for the partially built workspace and the
compiled XPath expression.  Also check xmlXPathNewContext() before
dereferencing the returned context.
---
 contrib/xml2/xpath.c | 51 +++++++++++++++++++++++++++-----------------
 1 file changed, 32 insertions(+), 19 deletions(-)

diff --git a/contrib/xml2/xpath.c b/contrib/xml2/xpath.c
index 9fe75cb5ff4..283bb51178d 100644
--- a/contrib/xml2/xpath.c
+++ b/contrib/xml2/xpath.c
@@ -497,36 +497,49 @@ static xpath_workspace *
 pgxml_xpath(text *document, xmlChar *xpath, PgXmlErrorContext *xmlerrcxt)
 {
 	int32		docsize = VARSIZE_ANY_EXHDR(document);
-	xmlXPathCompExprPtr comppath;
+	xmlXPathCompExprPtr volatile comppath = NULL;
 	xpath_workspace *workspace = palloc0_object(xpath_workspace);
 
 	workspace->doctree = NULL;
 	workspace->ctxt = NULL;
 	workspace->res = NULL;
 
-	workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
-									   docsize, NULL, NULL,
-									   XML_PARSE_NOENT);
-	if (workspace->doctree != NULL)
+	PG_TRY();
 	{
-		workspace->ctxt = xmlXPathNewContext(workspace->doctree);
-		workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
-
-		/* compile the path */
-		comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
-		if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+		workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
+										   docsize, NULL, NULL,
+										   XML_PARSE_NOENT);
+		if (workspace->doctree != NULL)
 		{
-			if (comppath != NULL)
-				xmlXPathFreeCompExpr(comppath);
-			xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
-						"XPath Syntax Error");
-		}
+			workspace->ctxt = xmlXPathNewContext(workspace->doctree);
+			if (workspace->ctxt == NULL)
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_OUT_OF_MEMORY,
+							"could not allocate XPath context");
 
-		/* Now evaluate the path expression. */
-		workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+			workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
+
+			/* compile the path */
+			comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
+			if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
+							"XPath Syntax Error");
+
+			/* Now evaluate the path expression. */
+			workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+
+			xmlXPathFreeCompExpr(comppath);
+			comppath = NULL;
+		}
+	}
+	PG_CATCH();
+	{
+		if (comppath != NULL)
+			xmlXPathFreeCompExpr(comppath);
+		cleanup_workspace(workspace);
 
-		xmlXPathFreeCompExpr(comppath);
+		PG_RE_THROW();
 	}
+	PG_END_TRY();
 
 	return workspace;
 }
-- 
2.54.0


--MP_/LMSk9=uMhuQ1QiIJDarDO8G--





^ permalink  raw  reply  [nested|flat] 611+ messages in thread

* [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths
@ 2026-06-01 22:41 Andrey Chernyy <andrey.cherny@tantorlabs.com>
  0 siblings, 0 replies; 611+ messages in thread

From: Andrey Chernyy @ 2026-06-01 22:41 UTC (permalink / raw)

pgxml_xpath() builds an xpath_workspace before returning it to
callers.  If an ERROR is thrown before the function returns, callers
have not received the workspace pointer yet and cannot run
cleanup_workspace().

Add local error cleanup for the partially built workspace and the
compiled XPath expression.  Also check xmlXPathNewContext() before
dereferencing the returned context.
---
 contrib/xml2/xpath.c | 51 +++++++++++++++++++++++++++-----------------
 1 file changed, 32 insertions(+), 19 deletions(-)

diff --git a/contrib/xml2/xpath.c b/contrib/xml2/xpath.c
index 9fe75cb5ff4..283bb51178d 100644
--- a/contrib/xml2/xpath.c
+++ b/contrib/xml2/xpath.c
@@ -497,36 +497,49 @@ static xpath_workspace *
 pgxml_xpath(text *document, xmlChar *xpath, PgXmlErrorContext *xmlerrcxt)
 {
 	int32		docsize = VARSIZE_ANY_EXHDR(document);
-	xmlXPathCompExprPtr comppath;
+	xmlXPathCompExprPtr volatile comppath = NULL;
 	xpath_workspace *workspace = palloc0_object(xpath_workspace);
 
 	workspace->doctree = NULL;
 	workspace->ctxt = NULL;
 	workspace->res = NULL;
 
-	workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
-									   docsize, NULL, NULL,
-									   XML_PARSE_NOENT);
-	if (workspace->doctree != NULL)
+	PG_TRY();
 	{
-		workspace->ctxt = xmlXPathNewContext(workspace->doctree);
-		workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
-
-		/* compile the path */
-		comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
-		if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+		workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
+										   docsize, NULL, NULL,
+										   XML_PARSE_NOENT);
+		if (workspace->doctree != NULL)
 		{
-			if (comppath != NULL)
-				xmlXPathFreeCompExpr(comppath);
-			xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
-						"XPath Syntax Error");
-		}
+			workspace->ctxt = xmlXPathNewContext(workspace->doctree);
+			if (workspace->ctxt == NULL)
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_OUT_OF_MEMORY,
+							"could not allocate XPath context");
 
-		/* Now evaluate the path expression. */
-		workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+			workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
+
+			/* compile the path */
+			comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
+			if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
+							"XPath Syntax Error");
+
+			/* Now evaluate the path expression. */
+			workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+
+			xmlXPathFreeCompExpr(comppath);
+			comppath = NULL;
+		}
+	}
+	PG_CATCH();
+	{
+		if (comppath != NULL)
+			xmlXPathFreeCompExpr(comppath);
+		cleanup_workspace(workspace);
 
-		xmlXPathFreeCompExpr(comppath);
+		PG_RE_THROW();
 	}
+	PG_END_TRY();
 
 	return workspace;
 }
-- 
2.54.0


--MP_/LMSk9=uMhuQ1QiIJDarDO8G--





^ permalink  raw  reply  [nested|flat] 611+ messages in thread

* [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths
@ 2026-06-01 22:41 Andrey Chernyy <andrey.cherny@tantorlabs.com>
  0 siblings, 0 replies; 611+ messages in thread

From: Andrey Chernyy @ 2026-06-01 22:41 UTC (permalink / raw)

pgxml_xpath() builds an xpath_workspace before returning it to
callers.  If an ERROR is thrown before the function returns, callers
have not received the workspace pointer yet and cannot run
cleanup_workspace().

Add local error cleanup for the partially built workspace and the
compiled XPath expression.  Also check xmlXPathNewContext() before
dereferencing the returned context.
---
 contrib/xml2/xpath.c | 51 +++++++++++++++++++++++++++-----------------
 1 file changed, 32 insertions(+), 19 deletions(-)

diff --git a/contrib/xml2/xpath.c b/contrib/xml2/xpath.c
index 9fe75cb5ff4..283bb51178d 100644
--- a/contrib/xml2/xpath.c
+++ b/contrib/xml2/xpath.c
@@ -497,36 +497,49 @@ static xpath_workspace *
 pgxml_xpath(text *document, xmlChar *xpath, PgXmlErrorContext *xmlerrcxt)
 {
 	int32		docsize = VARSIZE_ANY_EXHDR(document);
-	xmlXPathCompExprPtr comppath;
+	xmlXPathCompExprPtr volatile comppath = NULL;
 	xpath_workspace *workspace = palloc0_object(xpath_workspace);
 
 	workspace->doctree = NULL;
 	workspace->ctxt = NULL;
 	workspace->res = NULL;
 
-	workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
-									   docsize, NULL, NULL,
-									   XML_PARSE_NOENT);
-	if (workspace->doctree != NULL)
+	PG_TRY();
 	{
-		workspace->ctxt = xmlXPathNewContext(workspace->doctree);
-		workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
-
-		/* compile the path */
-		comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
-		if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+		workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
+										   docsize, NULL, NULL,
+										   XML_PARSE_NOENT);
+		if (workspace->doctree != NULL)
 		{
-			if (comppath != NULL)
-				xmlXPathFreeCompExpr(comppath);
-			xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
-						"XPath Syntax Error");
-		}
+			workspace->ctxt = xmlXPathNewContext(workspace->doctree);
+			if (workspace->ctxt == NULL)
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_OUT_OF_MEMORY,
+							"could not allocate XPath context");
 
-		/* Now evaluate the path expression. */
-		workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+			workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
+
+			/* compile the path */
+			comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
+			if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
+							"XPath Syntax Error");
+
+			/* Now evaluate the path expression. */
+			workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+
+			xmlXPathFreeCompExpr(comppath);
+			comppath = NULL;
+		}
+	}
+	PG_CATCH();
+	{
+		if (comppath != NULL)
+			xmlXPathFreeCompExpr(comppath);
+		cleanup_workspace(workspace);
 
-		xmlXPathFreeCompExpr(comppath);
+		PG_RE_THROW();
 	}
+	PG_END_TRY();
 
 	return workspace;
 }
-- 
2.54.0


--MP_/LMSk9=uMhuQ1QiIJDarDO8G--






^ permalink  raw  reply  [nested|flat] 611+ messages in thread

* [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths
@ 2026-06-01 22:41 Andrey Chernyy <andrey.cherny@tantorlabs.com>
  0 siblings, 0 replies; 611+ messages in thread

From: Andrey Chernyy @ 2026-06-01 22:41 UTC (permalink / raw)

pgxml_xpath() builds an xpath_workspace before returning it to
callers.  If an ERROR is thrown before the function returns, callers
have not received the workspace pointer yet and cannot run
cleanup_workspace().

Add local error cleanup for the partially built workspace and the
compiled XPath expression.  Also check xmlXPathNewContext() before
dereferencing the returned context.
---
 contrib/xml2/xpath.c | 51 +++++++++++++++++++++++++++-----------------
 1 file changed, 32 insertions(+), 19 deletions(-)

diff --git a/contrib/xml2/xpath.c b/contrib/xml2/xpath.c
index 9fe75cb5ff4..283bb51178d 100644
--- a/contrib/xml2/xpath.c
+++ b/contrib/xml2/xpath.c
@@ -497,36 +497,49 @@ static xpath_workspace *
 pgxml_xpath(text *document, xmlChar *xpath, PgXmlErrorContext *xmlerrcxt)
 {
 	int32		docsize = VARSIZE_ANY_EXHDR(document);
-	xmlXPathCompExprPtr comppath;
+	xmlXPathCompExprPtr volatile comppath = NULL;
 	xpath_workspace *workspace = palloc0_object(xpath_workspace);
 
 	workspace->doctree = NULL;
 	workspace->ctxt = NULL;
 	workspace->res = NULL;
 
-	workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
-									   docsize, NULL, NULL,
-									   XML_PARSE_NOENT);
-	if (workspace->doctree != NULL)
+	PG_TRY();
 	{
-		workspace->ctxt = xmlXPathNewContext(workspace->doctree);
-		workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
-
-		/* compile the path */
-		comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
-		if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+		workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
+										   docsize, NULL, NULL,
+										   XML_PARSE_NOENT);
+		if (workspace->doctree != NULL)
 		{
-			if (comppath != NULL)
-				xmlXPathFreeCompExpr(comppath);
-			xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
-						"XPath Syntax Error");
-		}
+			workspace->ctxt = xmlXPathNewContext(workspace->doctree);
+			if (workspace->ctxt == NULL)
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_OUT_OF_MEMORY,
+							"could not allocate XPath context");
 
-		/* Now evaluate the path expression. */
-		workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+			workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
+
+			/* compile the path */
+			comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
+			if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
+							"XPath Syntax Error");
+
+			/* Now evaluate the path expression. */
+			workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+
+			xmlXPathFreeCompExpr(comppath);
+			comppath = NULL;
+		}
+	}
+	PG_CATCH();
+	{
+		if (comppath != NULL)
+			xmlXPathFreeCompExpr(comppath);
+		cleanup_workspace(workspace);
 
-		xmlXPathFreeCompExpr(comppath);
+		PG_RE_THROW();
 	}
+	PG_END_TRY();
 
 	return workspace;
 }
-- 
2.54.0


--MP_/LMSk9=uMhuQ1QiIJDarDO8G--





^ permalink  raw  reply  [nested|flat] 611+ messages in thread

* [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths
@ 2026-06-01 22:41 Andrey Chernyy <andrey.cherny@tantorlabs.com>
  0 siblings, 0 replies; 611+ messages in thread

From: Andrey Chernyy @ 2026-06-01 22:41 UTC (permalink / raw)

pgxml_xpath() builds an xpath_workspace before returning it to
callers.  If an ERROR is thrown before the function returns, callers
have not received the workspace pointer yet and cannot run
cleanup_workspace().

Add local error cleanup for the partially built workspace and the
compiled XPath expression.  Also check xmlXPathNewContext() before
dereferencing the returned context.
---
 contrib/xml2/xpath.c | 51 +++++++++++++++++++++++++++-----------------
 1 file changed, 32 insertions(+), 19 deletions(-)

diff --git a/contrib/xml2/xpath.c b/contrib/xml2/xpath.c
index 9fe75cb5ff4..283bb51178d 100644
--- a/contrib/xml2/xpath.c
+++ b/contrib/xml2/xpath.c
@@ -497,36 +497,49 @@ static xpath_workspace *
 pgxml_xpath(text *document, xmlChar *xpath, PgXmlErrorContext *xmlerrcxt)
 {
 	int32		docsize = VARSIZE_ANY_EXHDR(document);
-	xmlXPathCompExprPtr comppath;
+	xmlXPathCompExprPtr volatile comppath = NULL;
 	xpath_workspace *workspace = palloc0_object(xpath_workspace);
 
 	workspace->doctree = NULL;
 	workspace->ctxt = NULL;
 	workspace->res = NULL;
 
-	workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
-									   docsize, NULL, NULL,
-									   XML_PARSE_NOENT);
-	if (workspace->doctree != NULL)
+	PG_TRY();
 	{
-		workspace->ctxt = xmlXPathNewContext(workspace->doctree);
-		workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
-
-		/* compile the path */
-		comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
-		if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+		workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
+										   docsize, NULL, NULL,
+										   XML_PARSE_NOENT);
+		if (workspace->doctree != NULL)
 		{
-			if (comppath != NULL)
-				xmlXPathFreeCompExpr(comppath);
-			xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
-						"XPath Syntax Error");
-		}
+			workspace->ctxt = xmlXPathNewContext(workspace->doctree);
+			if (workspace->ctxt == NULL)
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_OUT_OF_MEMORY,
+							"could not allocate XPath context");
 
-		/* Now evaluate the path expression. */
-		workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+			workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
+
+			/* compile the path */
+			comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
+			if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
+							"XPath Syntax Error");
+
+			/* Now evaluate the path expression. */
+			workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+
+			xmlXPathFreeCompExpr(comppath);
+			comppath = NULL;
+		}
+	}
+	PG_CATCH();
+	{
+		if (comppath != NULL)
+			xmlXPathFreeCompExpr(comppath);
+		cleanup_workspace(workspace);
 
-		xmlXPathFreeCompExpr(comppath);
+		PG_RE_THROW();
 	}
+	PG_END_TRY();
 
 	return workspace;
 }
-- 
2.54.0


--MP_/LMSk9=uMhuQ1QiIJDarDO8G--






^ permalink  raw  reply  [nested|flat] 611+ messages in thread

* [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths
@ 2026-06-01 22:41 Andrey Chernyy <andrey.cherny@tantorlabs.com>
  0 siblings, 0 replies; 611+ messages in thread

From: Andrey Chernyy @ 2026-06-01 22:41 UTC (permalink / raw)

pgxml_xpath() builds an xpath_workspace before returning it to
callers.  If an ERROR is thrown before the function returns, callers
have not received the workspace pointer yet and cannot run
cleanup_workspace().

Add local error cleanup for the partially built workspace and the
compiled XPath expression.  Also check xmlXPathNewContext() before
dereferencing the returned context.
---
 contrib/xml2/xpath.c | 51 +++++++++++++++++++++++++++-----------------
 1 file changed, 32 insertions(+), 19 deletions(-)

diff --git a/contrib/xml2/xpath.c b/contrib/xml2/xpath.c
index 9fe75cb5ff4..283bb51178d 100644
--- a/contrib/xml2/xpath.c
+++ b/contrib/xml2/xpath.c
@@ -497,36 +497,49 @@ static xpath_workspace *
 pgxml_xpath(text *document, xmlChar *xpath, PgXmlErrorContext *xmlerrcxt)
 {
 	int32		docsize = VARSIZE_ANY_EXHDR(document);
-	xmlXPathCompExprPtr comppath;
+	xmlXPathCompExprPtr volatile comppath = NULL;
 	xpath_workspace *workspace = palloc0_object(xpath_workspace);
 
 	workspace->doctree = NULL;
 	workspace->ctxt = NULL;
 	workspace->res = NULL;
 
-	workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
-									   docsize, NULL, NULL,
-									   XML_PARSE_NOENT);
-	if (workspace->doctree != NULL)
+	PG_TRY();
 	{
-		workspace->ctxt = xmlXPathNewContext(workspace->doctree);
-		workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
-
-		/* compile the path */
-		comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
-		if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+		workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
+										   docsize, NULL, NULL,
+										   XML_PARSE_NOENT);
+		if (workspace->doctree != NULL)
 		{
-			if (comppath != NULL)
-				xmlXPathFreeCompExpr(comppath);
-			xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
-						"XPath Syntax Error");
-		}
+			workspace->ctxt = xmlXPathNewContext(workspace->doctree);
+			if (workspace->ctxt == NULL)
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_OUT_OF_MEMORY,
+							"could not allocate XPath context");
 
-		/* Now evaluate the path expression. */
-		workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+			workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
+
+			/* compile the path */
+			comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
+			if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
+							"XPath Syntax Error");
+
+			/* Now evaluate the path expression. */
+			workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+
+			xmlXPathFreeCompExpr(comppath);
+			comppath = NULL;
+		}
+	}
+	PG_CATCH();
+	{
+		if (comppath != NULL)
+			xmlXPathFreeCompExpr(comppath);
+		cleanup_workspace(workspace);
 
-		xmlXPathFreeCompExpr(comppath);
+		PG_RE_THROW();
 	}
+	PG_END_TRY();
 
 	return workspace;
 }
-- 
2.54.0


--MP_/LMSk9=uMhuQ1QiIJDarDO8G--






^ permalink  raw  reply  [nested|flat] 611+ messages in thread

* [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths
@ 2026-06-01 22:41 Andrey Chernyy <andrey.cherny@tantorlabs.com>
  0 siblings, 0 replies; 611+ messages in thread

From: Andrey Chernyy @ 2026-06-01 22:41 UTC (permalink / raw)

pgxml_xpath() builds an xpath_workspace before returning it to
callers.  If an ERROR is thrown before the function returns, callers
have not received the workspace pointer yet and cannot run
cleanup_workspace().

Add local error cleanup for the partially built workspace and the
compiled XPath expression.  Also check xmlXPathNewContext() before
dereferencing the returned context.
---
 contrib/xml2/xpath.c | 51 +++++++++++++++++++++++++++-----------------
 1 file changed, 32 insertions(+), 19 deletions(-)

diff --git a/contrib/xml2/xpath.c b/contrib/xml2/xpath.c
index 9fe75cb5ff4..283bb51178d 100644
--- a/contrib/xml2/xpath.c
+++ b/contrib/xml2/xpath.c
@@ -497,36 +497,49 @@ static xpath_workspace *
 pgxml_xpath(text *document, xmlChar *xpath, PgXmlErrorContext *xmlerrcxt)
 {
 	int32		docsize = VARSIZE_ANY_EXHDR(document);
-	xmlXPathCompExprPtr comppath;
+	xmlXPathCompExprPtr volatile comppath = NULL;
 	xpath_workspace *workspace = palloc0_object(xpath_workspace);
 
 	workspace->doctree = NULL;
 	workspace->ctxt = NULL;
 	workspace->res = NULL;
 
-	workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
-									   docsize, NULL, NULL,
-									   XML_PARSE_NOENT);
-	if (workspace->doctree != NULL)
+	PG_TRY();
 	{
-		workspace->ctxt = xmlXPathNewContext(workspace->doctree);
-		workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
-
-		/* compile the path */
-		comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
-		if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+		workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
+										   docsize, NULL, NULL,
+										   XML_PARSE_NOENT);
+		if (workspace->doctree != NULL)
 		{
-			if (comppath != NULL)
-				xmlXPathFreeCompExpr(comppath);
-			xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
-						"XPath Syntax Error");
-		}
+			workspace->ctxt = xmlXPathNewContext(workspace->doctree);
+			if (workspace->ctxt == NULL)
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_OUT_OF_MEMORY,
+							"could not allocate XPath context");
 
-		/* Now evaluate the path expression. */
-		workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+			workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
+
+			/* compile the path */
+			comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
+			if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
+							"XPath Syntax Error");
+
+			/* Now evaluate the path expression. */
+			workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+
+			xmlXPathFreeCompExpr(comppath);
+			comppath = NULL;
+		}
+	}
+	PG_CATCH();
+	{
+		if (comppath != NULL)
+			xmlXPathFreeCompExpr(comppath);
+		cleanup_workspace(workspace);
 
-		xmlXPathFreeCompExpr(comppath);
+		PG_RE_THROW();
 	}
+	PG_END_TRY();
 
 	return workspace;
 }
-- 
2.54.0


--MP_/LMSk9=uMhuQ1QiIJDarDO8G--





^ permalink  raw  reply  [nested|flat] 611+ messages in thread

* [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths
@ 2026-06-01 22:41 Andrey Chernyy <andrey.cherny@tantorlabs.com>
  0 siblings, 0 replies; 611+ messages in thread

From: Andrey Chernyy @ 2026-06-01 22:41 UTC (permalink / raw)

pgxml_xpath() builds an xpath_workspace before returning it to
callers.  If an ERROR is thrown before the function returns, callers
have not received the workspace pointer yet and cannot run
cleanup_workspace().

Add local error cleanup for the partially built workspace and the
compiled XPath expression.  Also check xmlXPathNewContext() before
dereferencing the returned context.
---
 contrib/xml2/xpath.c | 51 +++++++++++++++++++++++++++-----------------
 1 file changed, 32 insertions(+), 19 deletions(-)

diff --git a/contrib/xml2/xpath.c b/contrib/xml2/xpath.c
index 9fe75cb5ff4..283bb51178d 100644
--- a/contrib/xml2/xpath.c
+++ b/contrib/xml2/xpath.c
@@ -497,36 +497,49 @@ static xpath_workspace *
 pgxml_xpath(text *document, xmlChar *xpath, PgXmlErrorContext *xmlerrcxt)
 {
 	int32		docsize = VARSIZE_ANY_EXHDR(document);
-	xmlXPathCompExprPtr comppath;
+	xmlXPathCompExprPtr volatile comppath = NULL;
 	xpath_workspace *workspace = palloc0_object(xpath_workspace);
 
 	workspace->doctree = NULL;
 	workspace->ctxt = NULL;
 	workspace->res = NULL;
 
-	workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
-									   docsize, NULL, NULL,
-									   XML_PARSE_NOENT);
-	if (workspace->doctree != NULL)
+	PG_TRY();
 	{
-		workspace->ctxt = xmlXPathNewContext(workspace->doctree);
-		workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
-
-		/* compile the path */
-		comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
-		if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+		workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
+										   docsize, NULL, NULL,
+										   XML_PARSE_NOENT);
+		if (workspace->doctree != NULL)
 		{
-			if (comppath != NULL)
-				xmlXPathFreeCompExpr(comppath);
-			xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
-						"XPath Syntax Error");
-		}
+			workspace->ctxt = xmlXPathNewContext(workspace->doctree);
+			if (workspace->ctxt == NULL)
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_OUT_OF_MEMORY,
+							"could not allocate XPath context");
 
-		/* Now evaluate the path expression. */
-		workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+			workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
+
+			/* compile the path */
+			comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
+			if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
+							"XPath Syntax Error");
+
+			/* Now evaluate the path expression. */
+			workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+
+			xmlXPathFreeCompExpr(comppath);
+			comppath = NULL;
+		}
+	}
+	PG_CATCH();
+	{
+		if (comppath != NULL)
+			xmlXPathFreeCompExpr(comppath);
+		cleanup_workspace(workspace);
 
-		xmlXPathFreeCompExpr(comppath);
+		PG_RE_THROW();
 	}
+	PG_END_TRY();
 
 	return workspace;
 }
-- 
2.54.0


--MP_/LMSk9=uMhuQ1QiIJDarDO8G--






^ permalink  raw  reply  [nested|flat] 611+ messages in thread

* [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths
@ 2026-06-01 22:41 Andrey Chernyy <andrey.cherny@tantorlabs.com>
  0 siblings, 0 replies; 611+ messages in thread

From: Andrey Chernyy @ 2026-06-01 22:41 UTC (permalink / raw)

pgxml_xpath() builds an xpath_workspace before returning it to
callers.  If an ERROR is thrown before the function returns, callers
have not received the workspace pointer yet and cannot run
cleanup_workspace().

Add local error cleanup for the partially built workspace and the
compiled XPath expression.  Also check xmlXPathNewContext() before
dereferencing the returned context.
---
 contrib/xml2/xpath.c | 51 +++++++++++++++++++++++++++-----------------
 1 file changed, 32 insertions(+), 19 deletions(-)

diff --git a/contrib/xml2/xpath.c b/contrib/xml2/xpath.c
index 9fe75cb5ff4..283bb51178d 100644
--- a/contrib/xml2/xpath.c
+++ b/contrib/xml2/xpath.c
@@ -497,36 +497,49 @@ static xpath_workspace *
 pgxml_xpath(text *document, xmlChar *xpath, PgXmlErrorContext *xmlerrcxt)
 {
 	int32		docsize = VARSIZE_ANY_EXHDR(document);
-	xmlXPathCompExprPtr comppath;
+	xmlXPathCompExprPtr volatile comppath = NULL;
 	xpath_workspace *workspace = palloc0_object(xpath_workspace);
 
 	workspace->doctree = NULL;
 	workspace->ctxt = NULL;
 	workspace->res = NULL;
 
-	workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
-									   docsize, NULL, NULL,
-									   XML_PARSE_NOENT);
-	if (workspace->doctree != NULL)
+	PG_TRY();
 	{
-		workspace->ctxt = xmlXPathNewContext(workspace->doctree);
-		workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
-
-		/* compile the path */
-		comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
-		if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+		workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
+										   docsize, NULL, NULL,
+										   XML_PARSE_NOENT);
+		if (workspace->doctree != NULL)
 		{
-			if (comppath != NULL)
-				xmlXPathFreeCompExpr(comppath);
-			xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
-						"XPath Syntax Error");
-		}
+			workspace->ctxt = xmlXPathNewContext(workspace->doctree);
+			if (workspace->ctxt == NULL)
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_OUT_OF_MEMORY,
+							"could not allocate XPath context");
 
-		/* Now evaluate the path expression. */
-		workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+			workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
+
+			/* compile the path */
+			comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
+			if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
+							"XPath Syntax Error");
+
+			/* Now evaluate the path expression. */
+			workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+
+			xmlXPathFreeCompExpr(comppath);
+			comppath = NULL;
+		}
+	}
+	PG_CATCH();
+	{
+		if (comppath != NULL)
+			xmlXPathFreeCompExpr(comppath);
+		cleanup_workspace(workspace);
 
-		xmlXPathFreeCompExpr(comppath);
+		PG_RE_THROW();
 	}
+	PG_END_TRY();
 
 	return workspace;
 }
-- 
2.54.0


--MP_/LMSk9=uMhuQ1QiIJDarDO8G--






^ permalink  raw  reply  [nested|flat] 611+ messages in thread

* [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths
@ 2026-06-01 22:41 Andrey Chernyy <andrey.cherny@tantorlabs.com>
  0 siblings, 0 replies; 611+ messages in thread

From: Andrey Chernyy @ 2026-06-01 22:41 UTC (permalink / raw)

pgxml_xpath() builds an xpath_workspace before returning it to
callers.  If an ERROR is thrown before the function returns, callers
have not received the workspace pointer yet and cannot run
cleanup_workspace().

Add local error cleanup for the partially built workspace and the
compiled XPath expression.  Also check xmlXPathNewContext() before
dereferencing the returned context.
---
 contrib/xml2/xpath.c | 51 +++++++++++++++++++++++++++-----------------
 1 file changed, 32 insertions(+), 19 deletions(-)

diff --git a/contrib/xml2/xpath.c b/contrib/xml2/xpath.c
index 9fe75cb5ff4..283bb51178d 100644
--- a/contrib/xml2/xpath.c
+++ b/contrib/xml2/xpath.c
@@ -497,36 +497,49 @@ static xpath_workspace *
 pgxml_xpath(text *document, xmlChar *xpath, PgXmlErrorContext *xmlerrcxt)
 {
 	int32		docsize = VARSIZE_ANY_EXHDR(document);
-	xmlXPathCompExprPtr comppath;
+	xmlXPathCompExprPtr volatile comppath = NULL;
 	xpath_workspace *workspace = palloc0_object(xpath_workspace);
 
 	workspace->doctree = NULL;
 	workspace->ctxt = NULL;
 	workspace->res = NULL;
 
-	workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
-									   docsize, NULL, NULL,
-									   XML_PARSE_NOENT);
-	if (workspace->doctree != NULL)
+	PG_TRY();
 	{
-		workspace->ctxt = xmlXPathNewContext(workspace->doctree);
-		workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
-
-		/* compile the path */
-		comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
-		if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+		workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
+										   docsize, NULL, NULL,
+										   XML_PARSE_NOENT);
+		if (workspace->doctree != NULL)
 		{
-			if (comppath != NULL)
-				xmlXPathFreeCompExpr(comppath);
-			xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
-						"XPath Syntax Error");
-		}
+			workspace->ctxt = xmlXPathNewContext(workspace->doctree);
+			if (workspace->ctxt == NULL)
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_OUT_OF_MEMORY,
+							"could not allocate XPath context");
 
-		/* Now evaluate the path expression. */
-		workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+			workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
+
+			/* compile the path */
+			comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
+			if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
+							"XPath Syntax Error");
+
+			/* Now evaluate the path expression. */
+			workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+
+			xmlXPathFreeCompExpr(comppath);
+			comppath = NULL;
+		}
+	}
+	PG_CATCH();
+	{
+		if (comppath != NULL)
+			xmlXPathFreeCompExpr(comppath);
+		cleanup_workspace(workspace);
 
-		xmlXPathFreeCompExpr(comppath);
+		PG_RE_THROW();
 	}
+	PG_END_TRY();
 
 	return workspace;
 }
-- 
2.54.0


--MP_/LMSk9=uMhuQ1QiIJDarDO8G--






^ permalink  raw  reply  [nested|flat] 611+ messages in thread

* [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths
@ 2026-06-01 22:41 Andrey Chernyy <andrey.cherny@tantorlabs.com>
  0 siblings, 0 replies; 611+ messages in thread

From: Andrey Chernyy @ 2026-06-01 22:41 UTC (permalink / raw)

pgxml_xpath() builds an xpath_workspace before returning it to
callers.  If an ERROR is thrown before the function returns, callers
have not received the workspace pointer yet and cannot run
cleanup_workspace().

Add local error cleanup for the partially built workspace and the
compiled XPath expression.  Also check xmlXPathNewContext() before
dereferencing the returned context.
---
 contrib/xml2/xpath.c | 51 +++++++++++++++++++++++++++-----------------
 1 file changed, 32 insertions(+), 19 deletions(-)

diff --git a/contrib/xml2/xpath.c b/contrib/xml2/xpath.c
index 9fe75cb5ff4..283bb51178d 100644
--- a/contrib/xml2/xpath.c
+++ b/contrib/xml2/xpath.c
@@ -497,36 +497,49 @@ static xpath_workspace *
 pgxml_xpath(text *document, xmlChar *xpath, PgXmlErrorContext *xmlerrcxt)
 {
 	int32		docsize = VARSIZE_ANY_EXHDR(document);
-	xmlXPathCompExprPtr comppath;
+	xmlXPathCompExprPtr volatile comppath = NULL;
 	xpath_workspace *workspace = palloc0_object(xpath_workspace);
 
 	workspace->doctree = NULL;
 	workspace->ctxt = NULL;
 	workspace->res = NULL;
 
-	workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
-									   docsize, NULL, NULL,
-									   XML_PARSE_NOENT);
-	if (workspace->doctree != NULL)
+	PG_TRY();
 	{
-		workspace->ctxt = xmlXPathNewContext(workspace->doctree);
-		workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
-
-		/* compile the path */
-		comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
-		if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+		workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
+										   docsize, NULL, NULL,
+										   XML_PARSE_NOENT);
+		if (workspace->doctree != NULL)
 		{
-			if (comppath != NULL)
-				xmlXPathFreeCompExpr(comppath);
-			xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
-						"XPath Syntax Error");
-		}
+			workspace->ctxt = xmlXPathNewContext(workspace->doctree);
+			if (workspace->ctxt == NULL)
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_OUT_OF_MEMORY,
+							"could not allocate XPath context");
 
-		/* Now evaluate the path expression. */
-		workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+			workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
+
+			/* compile the path */
+			comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
+			if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
+							"XPath Syntax Error");
+
+			/* Now evaluate the path expression. */
+			workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+
+			xmlXPathFreeCompExpr(comppath);
+			comppath = NULL;
+		}
+	}
+	PG_CATCH();
+	{
+		if (comppath != NULL)
+			xmlXPathFreeCompExpr(comppath);
+		cleanup_workspace(workspace);
 
-		xmlXPathFreeCompExpr(comppath);
+		PG_RE_THROW();
 	}
+	PG_END_TRY();
 
 	return workspace;
 }
-- 
2.54.0


--MP_/LMSk9=uMhuQ1QiIJDarDO8G--





^ permalink  raw  reply  [nested|flat] 611+ messages in thread

* [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths
@ 2026-06-01 22:41 Andrey Chernyy <andrey.cherny@tantorlabs.com>
  0 siblings, 0 replies; 611+ messages in thread

From: Andrey Chernyy @ 2026-06-01 22:41 UTC (permalink / raw)

pgxml_xpath() builds an xpath_workspace before returning it to
callers.  If an ERROR is thrown before the function returns, callers
have not received the workspace pointer yet and cannot run
cleanup_workspace().

Add local error cleanup for the partially built workspace and the
compiled XPath expression.  Also check xmlXPathNewContext() before
dereferencing the returned context.
---
 contrib/xml2/xpath.c | 51 +++++++++++++++++++++++++++-----------------
 1 file changed, 32 insertions(+), 19 deletions(-)

diff --git a/contrib/xml2/xpath.c b/contrib/xml2/xpath.c
index 9fe75cb5ff4..283bb51178d 100644
--- a/contrib/xml2/xpath.c
+++ b/contrib/xml2/xpath.c
@@ -497,36 +497,49 @@ static xpath_workspace *
 pgxml_xpath(text *document, xmlChar *xpath, PgXmlErrorContext *xmlerrcxt)
 {
 	int32		docsize = VARSIZE_ANY_EXHDR(document);
-	xmlXPathCompExprPtr comppath;
+	xmlXPathCompExprPtr volatile comppath = NULL;
 	xpath_workspace *workspace = palloc0_object(xpath_workspace);
 
 	workspace->doctree = NULL;
 	workspace->ctxt = NULL;
 	workspace->res = NULL;
 
-	workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
-									   docsize, NULL, NULL,
-									   XML_PARSE_NOENT);
-	if (workspace->doctree != NULL)
+	PG_TRY();
 	{
-		workspace->ctxt = xmlXPathNewContext(workspace->doctree);
-		workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
-
-		/* compile the path */
-		comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
-		if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+		workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
+										   docsize, NULL, NULL,
+										   XML_PARSE_NOENT);
+		if (workspace->doctree != NULL)
 		{
-			if (comppath != NULL)
-				xmlXPathFreeCompExpr(comppath);
-			xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
-						"XPath Syntax Error");
-		}
+			workspace->ctxt = xmlXPathNewContext(workspace->doctree);
+			if (workspace->ctxt == NULL)
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_OUT_OF_MEMORY,
+							"could not allocate XPath context");
 
-		/* Now evaluate the path expression. */
-		workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+			workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
+
+			/* compile the path */
+			comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
+			if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
+							"XPath Syntax Error");
+
+			/* Now evaluate the path expression. */
+			workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+
+			xmlXPathFreeCompExpr(comppath);
+			comppath = NULL;
+		}
+	}
+	PG_CATCH();
+	{
+		if (comppath != NULL)
+			xmlXPathFreeCompExpr(comppath);
+		cleanup_workspace(workspace);
 
-		xmlXPathFreeCompExpr(comppath);
+		PG_RE_THROW();
 	}
+	PG_END_TRY();
 
 	return workspace;
 }
-- 
2.54.0


--MP_/LMSk9=uMhuQ1QiIJDarDO8G--






^ permalink  raw  reply  [nested|flat] 611+ messages in thread

* [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths
@ 2026-06-01 22:41 Andrey Chernyy <andrey.cherny@tantorlabs.com>
  0 siblings, 0 replies; 611+ messages in thread

From: Andrey Chernyy @ 2026-06-01 22:41 UTC (permalink / raw)

pgxml_xpath() builds an xpath_workspace before returning it to
callers.  If an ERROR is thrown before the function returns, callers
have not received the workspace pointer yet and cannot run
cleanup_workspace().

Add local error cleanup for the partially built workspace and the
compiled XPath expression.  Also check xmlXPathNewContext() before
dereferencing the returned context.
---
 contrib/xml2/xpath.c | 51 +++++++++++++++++++++++++++-----------------
 1 file changed, 32 insertions(+), 19 deletions(-)

diff --git a/contrib/xml2/xpath.c b/contrib/xml2/xpath.c
index 9fe75cb5ff4..283bb51178d 100644
--- a/contrib/xml2/xpath.c
+++ b/contrib/xml2/xpath.c
@@ -497,36 +497,49 @@ static xpath_workspace *
 pgxml_xpath(text *document, xmlChar *xpath, PgXmlErrorContext *xmlerrcxt)
 {
 	int32		docsize = VARSIZE_ANY_EXHDR(document);
-	xmlXPathCompExprPtr comppath;
+	xmlXPathCompExprPtr volatile comppath = NULL;
 	xpath_workspace *workspace = palloc0_object(xpath_workspace);
 
 	workspace->doctree = NULL;
 	workspace->ctxt = NULL;
 	workspace->res = NULL;
 
-	workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
-									   docsize, NULL, NULL,
-									   XML_PARSE_NOENT);
-	if (workspace->doctree != NULL)
+	PG_TRY();
 	{
-		workspace->ctxt = xmlXPathNewContext(workspace->doctree);
-		workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
-
-		/* compile the path */
-		comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
-		if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+		workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
+										   docsize, NULL, NULL,
+										   XML_PARSE_NOENT);
+		if (workspace->doctree != NULL)
 		{
-			if (comppath != NULL)
-				xmlXPathFreeCompExpr(comppath);
-			xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
-						"XPath Syntax Error");
-		}
+			workspace->ctxt = xmlXPathNewContext(workspace->doctree);
+			if (workspace->ctxt == NULL)
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_OUT_OF_MEMORY,
+							"could not allocate XPath context");
 
-		/* Now evaluate the path expression. */
-		workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+			workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
+
+			/* compile the path */
+			comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
+			if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
+							"XPath Syntax Error");
+
+			/* Now evaluate the path expression. */
+			workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+
+			xmlXPathFreeCompExpr(comppath);
+			comppath = NULL;
+		}
+	}
+	PG_CATCH();
+	{
+		if (comppath != NULL)
+			xmlXPathFreeCompExpr(comppath);
+		cleanup_workspace(workspace);
 
-		xmlXPathFreeCompExpr(comppath);
+		PG_RE_THROW();
 	}
+	PG_END_TRY();
 
 	return workspace;
 }
-- 
2.54.0


--MP_/LMSk9=uMhuQ1QiIJDarDO8G--






^ permalink  raw  reply  [nested|flat] 611+ messages in thread

* [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths
@ 2026-06-01 22:41 Andrey Chernyy <andrey.cherny@tantorlabs.com>
  0 siblings, 0 replies; 611+ messages in thread

From: Andrey Chernyy @ 2026-06-01 22:41 UTC (permalink / raw)

pgxml_xpath() builds an xpath_workspace before returning it to
callers.  If an ERROR is thrown before the function returns, callers
have not received the workspace pointer yet and cannot run
cleanup_workspace().

Add local error cleanup for the partially built workspace and the
compiled XPath expression.  Also check xmlXPathNewContext() before
dereferencing the returned context.
---
 contrib/xml2/xpath.c | 51 +++++++++++++++++++++++++++-----------------
 1 file changed, 32 insertions(+), 19 deletions(-)

diff --git a/contrib/xml2/xpath.c b/contrib/xml2/xpath.c
index 9fe75cb5ff4..283bb51178d 100644
--- a/contrib/xml2/xpath.c
+++ b/contrib/xml2/xpath.c
@@ -497,36 +497,49 @@ static xpath_workspace *
 pgxml_xpath(text *document, xmlChar *xpath, PgXmlErrorContext *xmlerrcxt)
 {
 	int32		docsize = VARSIZE_ANY_EXHDR(document);
-	xmlXPathCompExprPtr comppath;
+	xmlXPathCompExprPtr volatile comppath = NULL;
 	xpath_workspace *workspace = palloc0_object(xpath_workspace);
 
 	workspace->doctree = NULL;
 	workspace->ctxt = NULL;
 	workspace->res = NULL;
 
-	workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
-									   docsize, NULL, NULL,
-									   XML_PARSE_NOENT);
-	if (workspace->doctree != NULL)
+	PG_TRY();
 	{
-		workspace->ctxt = xmlXPathNewContext(workspace->doctree);
-		workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
-
-		/* compile the path */
-		comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
-		if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+		workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
+										   docsize, NULL, NULL,
+										   XML_PARSE_NOENT);
+		if (workspace->doctree != NULL)
 		{
-			if (comppath != NULL)
-				xmlXPathFreeCompExpr(comppath);
-			xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
-						"XPath Syntax Error");
-		}
+			workspace->ctxt = xmlXPathNewContext(workspace->doctree);
+			if (workspace->ctxt == NULL)
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_OUT_OF_MEMORY,
+							"could not allocate XPath context");
 
-		/* Now evaluate the path expression. */
-		workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+			workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
+
+			/* compile the path */
+			comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
+			if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
+							"XPath Syntax Error");
+
+			/* Now evaluate the path expression. */
+			workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+
+			xmlXPathFreeCompExpr(comppath);
+			comppath = NULL;
+		}
+	}
+	PG_CATCH();
+	{
+		if (comppath != NULL)
+			xmlXPathFreeCompExpr(comppath);
+		cleanup_workspace(workspace);
 
-		xmlXPathFreeCompExpr(comppath);
+		PG_RE_THROW();
 	}
+	PG_END_TRY();
 
 	return workspace;
 }
-- 
2.54.0


--MP_/LMSk9=uMhuQ1QiIJDarDO8G--






^ permalink  raw  reply  [nested|flat] 611+ messages in thread

* [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths
@ 2026-06-01 22:41 Andrey Chernyy <andrey.cherny@tantorlabs.com>
  0 siblings, 0 replies; 611+ messages in thread

From: Andrey Chernyy @ 2026-06-01 22:41 UTC (permalink / raw)

pgxml_xpath() builds an xpath_workspace before returning it to
callers.  If an ERROR is thrown before the function returns, callers
have not received the workspace pointer yet and cannot run
cleanup_workspace().

Add local error cleanup for the partially built workspace and the
compiled XPath expression.  Also check xmlXPathNewContext() before
dereferencing the returned context.
---
 contrib/xml2/xpath.c | 51 +++++++++++++++++++++++++++-----------------
 1 file changed, 32 insertions(+), 19 deletions(-)

diff --git a/contrib/xml2/xpath.c b/contrib/xml2/xpath.c
index 9fe75cb5ff4..283bb51178d 100644
--- a/contrib/xml2/xpath.c
+++ b/contrib/xml2/xpath.c
@@ -497,36 +497,49 @@ static xpath_workspace *
 pgxml_xpath(text *document, xmlChar *xpath, PgXmlErrorContext *xmlerrcxt)
 {
 	int32		docsize = VARSIZE_ANY_EXHDR(document);
-	xmlXPathCompExprPtr comppath;
+	xmlXPathCompExprPtr volatile comppath = NULL;
 	xpath_workspace *workspace = palloc0_object(xpath_workspace);
 
 	workspace->doctree = NULL;
 	workspace->ctxt = NULL;
 	workspace->res = NULL;
 
-	workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
-									   docsize, NULL, NULL,
-									   XML_PARSE_NOENT);
-	if (workspace->doctree != NULL)
+	PG_TRY();
 	{
-		workspace->ctxt = xmlXPathNewContext(workspace->doctree);
-		workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
-
-		/* compile the path */
-		comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
-		if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+		workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
+										   docsize, NULL, NULL,
+										   XML_PARSE_NOENT);
+		if (workspace->doctree != NULL)
 		{
-			if (comppath != NULL)
-				xmlXPathFreeCompExpr(comppath);
-			xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
-						"XPath Syntax Error");
-		}
+			workspace->ctxt = xmlXPathNewContext(workspace->doctree);
+			if (workspace->ctxt == NULL)
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_OUT_OF_MEMORY,
+							"could not allocate XPath context");
 
-		/* Now evaluate the path expression. */
-		workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+			workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
+
+			/* compile the path */
+			comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
+			if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
+							"XPath Syntax Error");
+
+			/* Now evaluate the path expression. */
+			workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+
+			xmlXPathFreeCompExpr(comppath);
+			comppath = NULL;
+		}
+	}
+	PG_CATCH();
+	{
+		if (comppath != NULL)
+			xmlXPathFreeCompExpr(comppath);
+		cleanup_workspace(workspace);
 
-		xmlXPathFreeCompExpr(comppath);
+		PG_RE_THROW();
 	}
+	PG_END_TRY();
 
 	return workspace;
 }
-- 
2.54.0


--MP_/LMSk9=uMhuQ1QiIJDarDO8G--





^ permalink  raw  reply  [nested|flat] 611+ messages in thread

* [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths
@ 2026-06-01 22:41 Andrey Chernyy <andrey.cherny@tantorlabs.com>
  0 siblings, 0 replies; 611+ messages in thread

From: Andrey Chernyy @ 2026-06-01 22:41 UTC (permalink / raw)

pgxml_xpath() builds an xpath_workspace before returning it to
callers.  If an ERROR is thrown before the function returns, callers
have not received the workspace pointer yet and cannot run
cleanup_workspace().

Add local error cleanup for the partially built workspace and the
compiled XPath expression.  Also check xmlXPathNewContext() before
dereferencing the returned context.
---
 contrib/xml2/xpath.c | 51 +++++++++++++++++++++++++++-----------------
 1 file changed, 32 insertions(+), 19 deletions(-)

diff --git a/contrib/xml2/xpath.c b/contrib/xml2/xpath.c
index 9fe75cb5ff4..283bb51178d 100644
--- a/contrib/xml2/xpath.c
+++ b/contrib/xml2/xpath.c
@@ -497,36 +497,49 @@ static xpath_workspace *
 pgxml_xpath(text *document, xmlChar *xpath, PgXmlErrorContext *xmlerrcxt)
 {
 	int32		docsize = VARSIZE_ANY_EXHDR(document);
-	xmlXPathCompExprPtr comppath;
+	xmlXPathCompExprPtr volatile comppath = NULL;
 	xpath_workspace *workspace = palloc0_object(xpath_workspace);
 
 	workspace->doctree = NULL;
 	workspace->ctxt = NULL;
 	workspace->res = NULL;
 
-	workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
-									   docsize, NULL, NULL,
-									   XML_PARSE_NOENT);
-	if (workspace->doctree != NULL)
+	PG_TRY();
 	{
-		workspace->ctxt = xmlXPathNewContext(workspace->doctree);
-		workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
-
-		/* compile the path */
-		comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
-		if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+		workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
+										   docsize, NULL, NULL,
+										   XML_PARSE_NOENT);
+		if (workspace->doctree != NULL)
 		{
-			if (comppath != NULL)
-				xmlXPathFreeCompExpr(comppath);
-			xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
-						"XPath Syntax Error");
-		}
+			workspace->ctxt = xmlXPathNewContext(workspace->doctree);
+			if (workspace->ctxt == NULL)
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_OUT_OF_MEMORY,
+							"could not allocate XPath context");
 
-		/* Now evaluate the path expression. */
-		workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+			workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
+
+			/* compile the path */
+			comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
+			if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
+							"XPath Syntax Error");
+
+			/* Now evaluate the path expression. */
+			workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+
+			xmlXPathFreeCompExpr(comppath);
+			comppath = NULL;
+		}
+	}
+	PG_CATCH();
+	{
+		if (comppath != NULL)
+			xmlXPathFreeCompExpr(comppath);
+		cleanup_workspace(workspace);
 
-		xmlXPathFreeCompExpr(comppath);
+		PG_RE_THROW();
 	}
+	PG_END_TRY();
 
 	return workspace;
 }
-- 
2.54.0


--MP_/LMSk9=uMhuQ1QiIJDarDO8G--






^ permalink  raw  reply  [nested|flat] 611+ messages in thread

* [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths
@ 2026-06-01 22:41 Andrey Chernyy <andrey.cherny@tantorlabs.com>
  0 siblings, 0 replies; 611+ messages in thread

From: Andrey Chernyy @ 2026-06-01 22:41 UTC (permalink / raw)

pgxml_xpath() builds an xpath_workspace before returning it to
callers.  If an ERROR is thrown before the function returns, callers
have not received the workspace pointer yet and cannot run
cleanup_workspace().

Add local error cleanup for the partially built workspace and the
compiled XPath expression.  Also check xmlXPathNewContext() before
dereferencing the returned context.
---
 contrib/xml2/xpath.c | 51 +++++++++++++++++++++++++++-----------------
 1 file changed, 32 insertions(+), 19 deletions(-)

diff --git a/contrib/xml2/xpath.c b/contrib/xml2/xpath.c
index 9fe75cb5ff4..283bb51178d 100644
--- a/contrib/xml2/xpath.c
+++ b/contrib/xml2/xpath.c
@@ -497,36 +497,49 @@ static xpath_workspace *
 pgxml_xpath(text *document, xmlChar *xpath, PgXmlErrorContext *xmlerrcxt)
 {
 	int32		docsize = VARSIZE_ANY_EXHDR(document);
-	xmlXPathCompExprPtr comppath;
+	xmlXPathCompExprPtr volatile comppath = NULL;
 	xpath_workspace *workspace = palloc0_object(xpath_workspace);
 
 	workspace->doctree = NULL;
 	workspace->ctxt = NULL;
 	workspace->res = NULL;
 
-	workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
-									   docsize, NULL, NULL,
-									   XML_PARSE_NOENT);
-	if (workspace->doctree != NULL)
+	PG_TRY();
 	{
-		workspace->ctxt = xmlXPathNewContext(workspace->doctree);
-		workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
-
-		/* compile the path */
-		comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
-		if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+		workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
+										   docsize, NULL, NULL,
+										   XML_PARSE_NOENT);
+		if (workspace->doctree != NULL)
 		{
-			if (comppath != NULL)
-				xmlXPathFreeCompExpr(comppath);
-			xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
-						"XPath Syntax Error");
-		}
+			workspace->ctxt = xmlXPathNewContext(workspace->doctree);
+			if (workspace->ctxt == NULL)
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_OUT_OF_MEMORY,
+							"could not allocate XPath context");
 
-		/* Now evaluate the path expression. */
-		workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+			workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
+
+			/* compile the path */
+			comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
+			if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
+							"XPath Syntax Error");
+
+			/* Now evaluate the path expression. */
+			workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+
+			xmlXPathFreeCompExpr(comppath);
+			comppath = NULL;
+		}
+	}
+	PG_CATCH();
+	{
+		if (comppath != NULL)
+			xmlXPathFreeCompExpr(comppath);
+		cleanup_workspace(workspace);
 
-		xmlXPathFreeCompExpr(comppath);
+		PG_RE_THROW();
 	}
+	PG_END_TRY();
 
 	return workspace;
 }
-- 
2.54.0


--MP_/LMSk9=uMhuQ1QiIJDarDO8G--





^ permalink  raw  reply  [nested|flat] 611+ messages in thread

* [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths
@ 2026-06-01 22:41 Andrey Chernyy <andrey.cherny@tantorlabs.com>
  0 siblings, 0 replies; 611+ messages in thread

From: Andrey Chernyy @ 2026-06-01 22:41 UTC (permalink / raw)

pgxml_xpath() builds an xpath_workspace before returning it to
callers.  If an ERROR is thrown before the function returns, callers
have not received the workspace pointer yet and cannot run
cleanup_workspace().

Add local error cleanup for the partially built workspace and the
compiled XPath expression.  Also check xmlXPathNewContext() before
dereferencing the returned context.
---
 contrib/xml2/xpath.c | 51 +++++++++++++++++++++++++++-----------------
 1 file changed, 32 insertions(+), 19 deletions(-)

diff --git a/contrib/xml2/xpath.c b/contrib/xml2/xpath.c
index 9fe75cb5ff4..283bb51178d 100644
--- a/contrib/xml2/xpath.c
+++ b/contrib/xml2/xpath.c
@@ -497,36 +497,49 @@ static xpath_workspace *
 pgxml_xpath(text *document, xmlChar *xpath, PgXmlErrorContext *xmlerrcxt)
 {
 	int32		docsize = VARSIZE_ANY_EXHDR(document);
-	xmlXPathCompExprPtr comppath;
+	xmlXPathCompExprPtr volatile comppath = NULL;
 	xpath_workspace *workspace = palloc0_object(xpath_workspace);
 
 	workspace->doctree = NULL;
 	workspace->ctxt = NULL;
 	workspace->res = NULL;
 
-	workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
-									   docsize, NULL, NULL,
-									   XML_PARSE_NOENT);
-	if (workspace->doctree != NULL)
+	PG_TRY();
 	{
-		workspace->ctxt = xmlXPathNewContext(workspace->doctree);
-		workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
-
-		/* compile the path */
-		comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
-		if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+		workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
+										   docsize, NULL, NULL,
+										   XML_PARSE_NOENT);
+		if (workspace->doctree != NULL)
 		{
-			if (comppath != NULL)
-				xmlXPathFreeCompExpr(comppath);
-			xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
-						"XPath Syntax Error");
-		}
+			workspace->ctxt = xmlXPathNewContext(workspace->doctree);
+			if (workspace->ctxt == NULL)
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_OUT_OF_MEMORY,
+							"could not allocate XPath context");
 
-		/* Now evaluate the path expression. */
-		workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+			workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
+
+			/* compile the path */
+			comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
+			if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
+							"XPath Syntax Error");
+
+			/* Now evaluate the path expression. */
+			workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+
+			xmlXPathFreeCompExpr(comppath);
+			comppath = NULL;
+		}
+	}
+	PG_CATCH();
+	{
+		if (comppath != NULL)
+			xmlXPathFreeCompExpr(comppath);
+		cleanup_workspace(workspace);
 
-		xmlXPathFreeCompExpr(comppath);
+		PG_RE_THROW();
 	}
+	PG_END_TRY();
 
 	return workspace;
 }
-- 
2.54.0


--MP_/LMSk9=uMhuQ1QiIJDarDO8G--





^ permalink  raw  reply  [nested|flat] 611+ messages in thread

* [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths
@ 2026-06-01 22:41 Andrey Chernyy <andrey.cherny@tantorlabs.com>
  0 siblings, 0 replies; 611+ messages in thread

From: Andrey Chernyy @ 2026-06-01 22:41 UTC (permalink / raw)

pgxml_xpath() builds an xpath_workspace before returning it to
callers.  If an ERROR is thrown before the function returns, callers
have not received the workspace pointer yet and cannot run
cleanup_workspace().

Add local error cleanup for the partially built workspace and the
compiled XPath expression.  Also check xmlXPathNewContext() before
dereferencing the returned context.
---
 contrib/xml2/xpath.c | 51 +++++++++++++++++++++++++++-----------------
 1 file changed, 32 insertions(+), 19 deletions(-)

diff --git a/contrib/xml2/xpath.c b/contrib/xml2/xpath.c
index 9fe75cb5ff4..283bb51178d 100644
--- a/contrib/xml2/xpath.c
+++ b/contrib/xml2/xpath.c
@@ -497,36 +497,49 @@ static xpath_workspace *
 pgxml_xpath(text *document, xmlChar *xpath, PgXmlErrorContext *xmlerrcxt)
 {
 	int32		docsize = VARSIZE_ANY_EXHDR(document);
-	xmlXPathCompExprPtr comppath;
+	xmlXPathCompExprPtr volatile comppath = NULL;
 	xpath_workspace *workspace = palloc0_object(xpath_workspace);
 
 	workspace->doctree = NULL;
 	workspace->ctxt = NULL;
 	workspace->res = NULL;
 
-	workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
-									   docsize, NULL, NULL,
-									   XML_PARSE_NOENT);
-	if (workspace->doctree != NULL)
+	PG_TRY();
 	{
-		workspace->ctxt = xmlXPathNewContext(workspace->doctree);
-		workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
-
-		/* compile the path */
-		comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
-		if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+		workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
+										   docsize, NULL, NULL,
+										   XML_PARSE_NOENT);
+		if (workspace->doctree != NULL)
 		{
-			if (comppath != NULL)
-				xmlXPathFreeCompExpr(comppath);
-			xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
-						"XPath Syntax Error");
-		}
+			workspace->ctxt = xmlXPathNewContext(workspace->doctree);
+			if (workspace->ctxt == NULL)
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_OUT_OF_MEMORY,
+							"could not allocate XPath context");
 
-		/* Now evaluate the path expression. */
-		workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+			workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
+
+			/* compile the path */
+			comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
+			if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
+							"XPath Syntax Error");
+
+			/* Now evaluate the path expression. */
+			workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+
+			xmlXPathFreeCompExpr(comppath);
+			comppath = NULL;
+		}
+	}
+	PG_CATCH();
+	{
+		if (comppath != NULL)
+			xmlXPathFreeCompExpr(comppath);
+		cleanup_workspace(workspace);
 
-		xmlXPathFreeCompExpr(comppath);
+		PG_RE_THROW();
 	}
+	PG_END_TRY();
 
 	return workspace;
 }
-- 
2.54.0


--MP_/LMSk9=uMhuQ1QiIJDarDO8G--






^ permalink  raw  reply  [nested|flat] 611+ messages in thread

* [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths
@ 2026-06-01 22:41 Andrey Chernyy <andrey.cherny@tantorlabs.com>
  0 siblings, 0 replies; 611+ messages in thread

From: Andrey Chernyy @ 2026-06-01 22:41 UTC (permalink / raw)

pgxml_xpath() builds an xpath_workspace before returning it to
callers.  If an ERROR is thrown before the function returns, callers
have not received the workspace pointer yet and cannot run
cleanup_workspace().

Add local error cleanup for the partially built workspace and the
compiled XPath expression.  Also check xmlXPathNewContext() before
dereferencing the returned context.
---
 contrib/xml2/xpath.c | 51 +++++++++++++++++++++++++++-----------------
 1 file changed, 32 insertions(+), 19 deletions(-)

diff --git a/contrib/xml2/xpath.c b/contrib/xml2/xpath.c
index 9fe75cb5ff4..283bb51178d 100644
--- a/contrib/xml2/xpath.c
+++ b/contrib/xml2/xpath.c
@@ -497,36 +497,49 @@ static xpath_workspace *
 pgxml_xpath(text *document, xmlChar *xpath, PgXmlErrorContext *xmlerrcxt)
 {
 	int32		docsize = VARSIZE_ANY_EXHDR(document);
-	xmlXPathCompExprPtr comppath;
+	xmlXPathCompExprPtr volatile comppath = NULL;
 	xpath_workspace *workspace = palloc0_object(xpath_workspace);
 
 	workspace->doctree = NULL;
 	workspace->ctxt = NULL;
 	workspace->res = NULL;
 
-	workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
-									   docsize, NULL, NULL,
-									   XML_PARSE_NOENT);
-	if (workspace->doctree != NULL)
+	PG_TRY();
 	{
-		workspace->ctxt = xmlXPathNewContext(workspace->doctree);
-		workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
-
-		/* compile the path */
-		comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
-		if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+		workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
+										   docsize, NULL, NULL,
+										   XML_PARSE_NOENT);
+		if (workspace->doctree != NULL)
 		{
-			if (comppath != NULL)
-				xmlXPathFreeCompExpr(comppath);
-			xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
-						"XPath Syntax Error");
-		}
+			workspace->ctxt = xmlXPathNewContext(workspace->doctree);
+			if (workspace->ctxt == NULL)
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_OUT_OF_MEMORY,
+							"could not allocate XPath context");
 
-		/* Now evaluate the path expression. */
-		workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+			workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
+
+			/* compile the path */
+			comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
+			if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
+							"XPath Syntax Error");
+
+			/* Now evaluate the path expression. */
+			workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+
+			xmlXPathFreeCompExpr(comppath);
+			comppath = NULL;
+		}
+	}
+	PG_CATCH();
+	{
+		if (comppath != NULL)
+			xmlXPathFreeCompExpr(comppath);
+		cleanup_workspace(workspace);
 
-		xmlXPathFreeCompExpr(comppath);
+		PG_RE_THROW();
 	}
+	PG_END_TRY();
 
 	return workspace;
 }
-- 
2.54.0


--MP_/LMSk9=uMhuQ1QiIJDarDO8G--





^ permalink  raw  reply  [nested|flat] 611+ messages in thread

* [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths
@ 2026-06-01 22:41 Andrey Chernyy <andrey.cherny@tantorlabs.com>
  0 siblings, 0 replies; 611+ messages in thread

From: Andrey Chernyy @ 2026-06-01 22:41 UTC (permalink / raw)

pgxml_xpath() builds an xpath_workspace before returning it to
callers.  If an ERROR is thrown before the function returns, callers
have not received the workspace pointer yet and cannot run
cleanup_workspace().

Add local error cleanup for the partially built workspace and the
compiled XPath expression.  Also check xmlXPathNewContext() before
dereferencing the returned context.
---
 contrib/xml2/xpath.c | 51 +++++++++++++++++++++++++++-----------------
 1 file changed, 32 insertions(+), 19 deletions(-)

diff --git a/contrib/xml2/xpath.c b/contrib/xml2/xpath.c
index 9fe75cb5ff4..283bb51178d 100644
--- a/contrib/xml2/xpath.c
+++ b/contrib/xml2/xpath.c
@@ -497,36 +497,49 @@ static xpath_workspace *
 pgxml_xpath(text *document, xmlChar *xpath, PgXmlErrorContext *xmlerrcxt)
 {
 	int32		docsize = VARSIZE_ANY_EXHDR(document);
-	xmlXPathCompExprPtr comppath;
+	xmlXPathCompExprPtr volatile comppath = NULL;
 	xpath_workspace *workspace = palloc0_object(xpath_workspace);
 
 	workspace->doctree = NULL;
 	workspace->ctxt = NULL;
 	workspace->res = NULL;
 
-	workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
-									   docsize, NULL, NULL,
-									   XML_PARSE_NOENT);
-	if (workspace->doctree != NULL)
+	PG_TRY();
 	{
-		workspace->ctxt = xmlXPathNewContext(workspace->doctree);
-		workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
-
-		/* compile the path */
-		comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
-		if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+		workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
+										   docsize, NULL, NULL,
+										   XML_PARSE_NOENT);
+		if (workspace->doctree != NULL)
 		{
-			if (comppath != NULL)
-				xmlXPathFreeCompExpr(comppath);
-			xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
-						"XPath Syntax Error");
-		}
+			workspace->ctxt = xmlXPathNewContext(workspace->doctree);
+			if (workspace->ctxt == NULL)
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_OUT_OF_MEMORY,
+							"could not allocate XPath context");
 
-		/* Now evaluate the path expression. */
-		workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+			workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
+
+			/* compile the path */
+			comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
+			if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
+							"XPath Syntax Error");
+
+			/* Now evaluate the path expression. */
+			workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+
+			xmlXPathFreeCompExpr(comppath);
+			comppath = NULL;
+		}
+	}
+	PG_CATCH();
+	{
+		if (comppath != NULL)
+			xmlXPathFreeCompExpr(comppath);
+		cleanup_workspace(workspace);
 
-		xmlXPathFreeCompExpr(comppath);
+		PG_RE_THROW();
 	}
+	PG_END_TRY();
 
 	return workspace;
 }
-- 
2.54.0


--MP_/LMSk9=uMhuQ1QiIJDarDO8G--





^ permalink  raw  reply  [nested|flat] 611+ messages in thread

* [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths
@ 2026-06-01 22:41 Andrey Chernyy <andrey.cherny@tantorlabs.com>
  0 siblings, 0 replies; 611+ messages in thread

From: Andrey Chernyy @ 2026-06-01 22:41 UTC (permalink / raw)

pgxml_xpath() builds an xpath_workspace before returning it to
callers.  If an ERROR is thrown before the function returns, callers
have not received the workspace pointer yet and cannot run
cleanup_workspace().

Add local error cleanup for the partially built workspace and the
compiled XPath expression.  Also check xmlXPathNewContext() before
dereferencing the returned context.
---
 contrib/xml2/xpath.c | 51 +++++++++++++++++++++++++++-----------------
 1 file changed, 32 insertions(+), 19 deletions(-)

diff --git a/contrib/xml2/xpath.c b/contrib/xml2/xpath.c
index 9fe75cb5ff4..283bb51178d 100644
--- a/contrib/xml2/xpath.c
+++ b/contrib/xml2/xpath.c
@@ -497,36 +497,49 @@ static xpath_workspace *
 pgxml_xpath(text *document, xmlChar *xpath, PgXmlErrorContext *xmlerrcxt)
 {
 	int32		docsize = VARSIZE_ANY_EXHDR(document);
-	xmlXPathCompExprPtr comppath;
+	xmlXPathCompExprPtr volatile comppath = NULL;
 	xpath_workspace *workspace = palloc0_object(xpath_workspace);
 
 	workspace->doctree = NULL;
 	workspace->ctxt = NULL;
 	workspace->res = NULL;
 
-	workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
-									   docsize, NULL, NULL,
-									   XML_PARSE_NOENT);
-	if (workspace->doctree != NULL)
+	PG_TRY();
 	{
-		workspace->ctxt = xmlXPathNewContext(workspace->doctree);
-		workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
-
-		/* compile the path */
-		comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
-		if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+		workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
+										   docsize, NULL, NULL,
+										   XML_PARSE_NOENT);
+		if (workspace->doctree != NULL)
 		{
-			if (comppath != NULL)
-				xmlXPathFreeCompExpr(comppath);
-			xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
-						"XPath Syntax Error");
-		}
+			workspace->ctxt = xmlXPathNewContext(workspace->doctree);
+			if (workspace->ctxt == NULL)
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_OUT_OF_MEMORY,
+							"could not allocate XPath context");
 
-		/* Now evaluate the path expression. */
-		workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+			workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
+
+			/* compile the path */
+			comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
+			if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
+							"XPath Syntax Error");
+
+			/* Now evaluate the path expression. */
+			workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+
+			xmlXPathFreeCompExpr(comppath);
+			comppath = NULL;
+		}
+	}
+	PG_CATCH();
+	{
+		if (comppath != NULL)
+			xmlXPathFreeCompExpr(comppath);
+		cleanup_workspace(workspace);
 
-		xmlXPathFreeCompExpr(comppath);
+		PG_RE_THROW();
 	}
+	PG_END_TRY();
 
 	return workspace;
 }
-- 
2.54.0


--MP_/LMSk9=uMhuQ1QiIJDarDO8G--






^ permalink  raw  reply  [nested|flat] 611+ messages in thread

* [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths
@ 2026-06-01 22:41 Andrey Chernyy <andrey.cherny@tantorlabs.com>
  0 siblings, 0 replies; 611+ messages in thread

From: Andrey Chernyy @ 2026-06-01 22:41 UTC (permalink / raw)

pgxml_xpath() builds an xpath_workspace before returning it to
callers.  If an ERROR is thrown before the function returns, callers
have not received the workspace pointer yet and cannot run
cleanup_workspace().

Add local error cleanup for the partially built workspace and the
compiled XPath expression.  Also check xmlXPathNewContext() before
dereferencing the returned context.
---
 contrib/xml2/xpath.c | 51 +++++++++++++++++++++++++++-----------------
 1 file changed, 32 insertions(+), 19 deletions(-)

diff --git a/contrib/xml2/xpath.c b/contrib/xml2/xpath.c
index 9fe75cb5ff4..283bb51178d 100644
--- a/contrib/xml2/xpath.c
+++ b/contrib/xml2/xpath.c
@@ -497,36 +497,49 @@ static xpath_workspace *
 pgxml_xpath(text *document, xmlChar *xpath, PgXmlErrorContext *xmlerrcxt)
 {
 	int32		docsize = VARSIZE_ANY_EXHDR(document);
-	xmlXPathCompExprPtr comppath;
+	xmlXPathCompExprPtr volatile comppath = NULL;
 	xpath_workspace *workspace = palloc0_object(xpath_workspace);
 
 	workspace->doctree = NULL;
 	workspace->ctxt = NULL;
 	workspace->res = NULL;
 
-	workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
-									   docsize, NULL, NULL,
-									   XML_PARSE_NOENT);
-	if (workspace->doctree != NULL)
+	PG_TRY();
 	{
-		workspace->ctxt = xmlXPathNewContext(workspace->doctree);
-		workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
-
-		/* compile the path */
-		comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
-		if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+		workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
+										   docsize, NULL, NULL,
+										   XML_PARSE_NOENT);
+		if (workspace->doctree != NULL)
 		{
-			if (comppath != NULL)
-				xmlXPathFreeCompExpr(comppath);
-			xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
-						"XPath Syntax Error");
-		}
+			workspace->ctxt = xmlXPathNewContext(workspace->doctree);
+			if (workspace->ctxt == NULL)
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_OUT_OF_MEMORY,
+							"could not allocate XPath context");
 
-		/* Now evaluate the path expression. */
-		workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+			workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
+
+			/* compile the path */
+			comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
+			if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
+							"XPath Syntax Error");
+
+			/* Now evaluate the path expression. */
+			workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+
+			xmlXPathFreeCompExpr(comppath);
+			comppath = NULL;
+		}
+	}
+	PG_CATCH();
+	{
+		if (comppath != NULL)
+			xmlXPathFreeCompExpr(comppath);
+		cleanup_workspace(workspace);
 
-		xmlXPathFreeCompExpr(comppath);
+		PG_RE_THROW();
 	}
+	PG_END_TRY();
 
 	return workspace;
 }
-- 
2.54.0


--MP_/LMSk9=uMhuQ1QiIJDarDO8G--





^ permalink  raw  reply  [nested|flat] 611+ messages in thread

* [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths
@ 2026-06-01 22:41 Andrey Chernyy <andrey.cherny@tantorlabs.com>
  0 siblings, 0 replies; 611+ messages in thread

From: Andrey Chernyy @ 2026-06-01 22:41 UTC (permalink / raw)

pgxml_xpath() builds an xpath_workspace before returning it to
callers.  If an ERROR is thrown before the function returns, callers
have not received the workspace pointer yet and cannot run
cleanup_workspace().

Add local error cleanup for the partially built workspace and the
compiled XPath expression.  Also check xmlXPathNewContext() before
dereferencing the returned context.
---
 contrib/xml2/xpath.c | 51 +++++++++++++++++++++++++++-----------------
 1 file changed, 32 insertions(+), 19 deletions(-)

diff --git a/contrib/xml2/xpath.c b/contrib/xml2/xpath.c
index 9fe75cb5ff4..283bb51178d 100644
--- a/contrib/xml2/xpath.c
+++ b/contrib/xml2/xpath.c
@@ -497,36 +497,49 @@ static xpath_workspace *
 pgxml_xpath(text *document, xmlChar *xpath, PgXmlErrorContext *xmlerrcxt)
 {
 	int32		docsize = VARSIZE_ANY_EXHDR(document);
-	xmlXPathCompExprPtr comppath;
+	xmlXPathCompExprPtr volatile comppath = NULL;
 	xpath_workspace *workspace = palloc0_object(xpath_workspace);
 
 	workspace->doctree = NULL;
 	workspace->ctxt = NULL;
 	workspace->res = NULL;
 
-	workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
-									   docsize, NULL, NULL,
-									   XML_PARSE_NOENT);
-	if (workspace->doctree != NULL)
+	PG_TRY();
 	{
-		workspace->ctxt = xmlXPathNewContext(workspace->doctree);
-		workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
-
-		/* compile the path */
-		comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
-		if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+		workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
+										   docsize, NULL, NULL,
+										   XML_PARSE_NOENT);
+		if (workspace->doctree != NULL)
 		{
-			if (comppath != NULL)
-				xmlXPathFreeCompExpr(comppath);
-			xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
-						"XPath Syntax Error");
-		}
+			workspace->ctxt = xmlXPathNewContext(workspace->doctree);
+			if (workspace->ctxt == NULL)
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_OUT_OF_MEMORY,
+							"could not allocate XPath context");
 
-		/* Now evaluate the path expression. */
-		workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+			workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
+
+			/* compile the path */
+			comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
+			if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
+							"XPath Syntax Error");
+
+			/* Now evaluate the path expression. */
+			workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+
+			xmlXPathFreeCompExpr(comppath);
+			comppath = NULL;
+		}
+	}
+	PG_CATCH();
+	{
+		if (comppath != NULL)
+			xmlXPathFreeCompExpr(comppath);
+		cleanup_workspace(workspace);
 
-		xmlXPathFreeCompExpr(comppath);
+		PG_RE_THROW();
 	}
+	PG_END_TRY();
 
 	return workspace;
 }
-- 
2.54.0


--MP_/LMSk9=uMhuQ1QiIJDarDO8G--






^ permalink  raw  reply  [nested|flat] 611+ messages in thread

* [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths
@ 2026-06-01 22:41 Andrey Chernyy <andrey.cherny@tantorlabs.com>
  0 siblings, 0 replies; 611+ messages in thread

From: Andrey Chernyy @ 2026-06-01 22:41 UTC (permalink / raw)

pgxml_xpath() builds an xpath_workspace before returning it to
callers.  If an ERROR is thrown before the function returns, callers
have not received the workspace pointer yet and cannot run
cleanup_workspace().

Add local error cleanup for the partially built workspace and the
compiled XPath expression.  Also check xmlXPathNewContext() before
dereferencing the returned context.
---
 contrib/xml2/xpath.c | 51 +++++++++++++++++++++++++++-----------------
 1 file changed, 32 insertions(+), 19 deletions(-)

diff --git a/contrib/xml2/xpath.c b/contrib/xml2/xpath.c
index 9fe75cb5ff4..283bb51178d 100644
--- a/contrib/xml2/xpath.c
+++ b/contrib/xml2/xpath.c
@@ -497,36 +497,49 @@ static xpath_workspace *
 pgxml_xpath(text *document, xmlChar *xpath, PgXmlErrorContext *xmlerrcxt)
 {
 	int32		docsize = VARSIZE_ANY_EXHDR(document);
-	xmlXPathCompExprPtr comppath;
+	xmlXPathCompExprPtr volatile comppath = NULL;
 	xpath_workspace *workspace = palloc0_object(xpath_workspace);
 
 	workspace->doctree = NULL;
 	workspace->ctxt = NULL;
 	workspace->res = NULL;
 
-	workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
-									   docsize, NULL, NULL,
-									   XML_PARSE_NOENT);
-	if (workspace->doctree != NULL)
+	PG_TRY();
 	{
-		workspace->ctxt = xmlXPathNewContext(workspace->doctree);
-		workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
-
-		/* compile the path */
-		comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
-		if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+		workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
+										   docsize, NULL, NULL,
+										   XML_PARSE_NOENT);
+		if (workspace->doctree != NULL)
 		{
-			if (comppath != NULL)
-				xmlXPathFreeCompExpr(comppath);
-			xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
-						"XPath Syntax Error");
-		}
+			workspace->ctxt = xmlXPathNewContext(workspace->doctree);
+			if (workspace->ctxt == NULL)
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_OUT_OF_MEMORY,
+							"could not allocate XPath context");
 
-		/* Now evaluate the path expression. */
-		workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+			workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
+
+			/* compile the path */
+			comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
+			if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
+							"XPath Syntax Error");
+
+			/* Now evaluate the path expression. */
+			workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+
+			xmlXPathFreeCompExpr(comppath);
+			comppath = NULL;
+		}
+	}
+	PG_CATCH();
+	{
+		if (comppath != NULL)
+			xmlXPathFreeCompExpr(comppath);
+		cleanup_workspace(workspace);
 
-		xmlXPathFreeCompExpr(comppath);
+		PG_RE_THROW();
 	}
+	PG_END_TRY();
 
 	return workspace;
 }
-- 
2.54.0


--MP_/LMSk9=uMhuQ1QiIJDarDO8G--






^ permalink  raw  reply  [nested|flat] 611+ messages in thread

* [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths
@ 2026-06-01 22:41 Andrey Chernyy <andrey.cherny@tantorlabs.com>
  0 siblings, 0 replies; 611+ messages in thread

From: Andrey Chernyy @ 2026-06-01 22:41 UTC (permalink / raw)

pgxml_xpath() builds an xpath_workspace before returning it to
callers.  If an ERROR is thrown before the function returns, callers
have not received the workspace pointer yet and cannot run
cleanup_workspace().

Add local error cleanup for the partially built workspace and the
compiled XPath expression.  Also check xmlXPathNewContext() before
dereferencing the returned context.
---
 contrib/xml2/xpath.c | 51 +++++++++++++++++++++++++++-----------------
 1 file changed, 32 insertions(+), 19 deletions(-)

diff --git a/contrib/xml2/xpath.c b/contrib/xml2/xpath.c
index 9fe75cb5ff4..283bb51178d 100644
--- a/contrib/xml2/xpath.c
+++ b/contrib/xml2/xpath.c
@@ -497,36 +497,49 @@ static xpath_workspace *
 pgxml_xpath(text *document, xmlChar *xpath, PgXmlErrorContext *xmlerrcxt)
 {
 	int32		docsize = VARSIZE_ANY_EXHDR(document);
-	xmlXPathCompExprPtr comppath;
+	xmlXPathCompExprPtr volatile comppath = NULL;
 	xpath_workspace *workspace = palloc0_object(xpath_workspace);
 
 	workspace->doctree = NULL;
 	workspace->ctxt = NULL;
 	workspace->res = NULL;
 
-	workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
-									   docsize, NULL, NULL,
-									   XML_PARSE_NOENT);
-	if (workspace->doctree != NULL)
+	PG_TRY();
 	{
-		workspace->ctxt = xmlXPathNewContext(workspace->doctree);
-		workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
-
-		/* compile the path */
-		comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
-		if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+		workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
+										   docsize, NULL, NULL,
+										   XML_PARSE_NOENT);
+		if (workspace->doctree != NULL)
 		{
-			if (comppath != NULL)
-				xmlXPathFreeCompExpr(comppath);
-			xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
-						"XPath Syntax Error");
-		}
+			workspace->ctxt = xmlXPathNewContext(workspace->doctree);
+			if (workspace->ctxt == NULL)
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_OUT_OF_MEMORY,
+							"could not allocate XPath context");
 
-		/* Now evaluate the path expression. */
-		workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+			workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
+
+			/* compile the path */
+			comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
+			if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
+							"XPath Syntax Error");
+
+			/* Now evaluate the path expression. */
+			workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+
+			xmlXPathFreeCompExpr(comppath);
+			comppath = NULL;
+		}
+	}
+	PG_CATCH();
+	{
+		if (comppath != NULL)
+			xmlXPathFreeCompExpr(comppath);
+		cleanup_workspace(workspace);
 
-		xmlXPathFreeCompExpr(comppath);
+		PG_RE_THROW();
 	}
+	PG_END_TRY();
 
 	return workspace;
 }
-- 
2.54.0


--MP_/LMSk9=uMhuQ1QiIJDarDO8G--






^ permalink  raw  reply  [nested|flat] 611+ messages in thread

* [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths
@ 2026-06-01 22:41 Andrey Chernyy <andrey.cherny@tantorlabs.com>
  0 siblings, 0 replies; 611+ messages in thread

From: Andrey Chernyy @ 2026-06-01 22:41 UTC (permalink / raw)

pgxml_xpath() builds an xpath_workspace before returning it to
callers.  If an ERROR is thrown before the function returns, callers
have not received the workspace pointer yet and cannot run
cleanup_workspace().

Add local error cleanup for the partially built workspace and the
compiled XPath expression.  Also check xmlXPathNewContext() before
dereferencing the returned context.
---
 contrib/xml2/xpath.c | 51 +++++++++++++++++++++++++++-----------------
 1 file changed, 32 insertions(+), 19 deletions(-)

diff --git a/contrib/xml2/xpath.c b/contrib/xml2/xpath.c
index 9fe75cb5ff4..283bb51178d 100644
--- a/contrib/xml2/xpath.c
+++ b/contrib/xml2/xpath.c
@@ -497,36 +497,49 @@ static xpath_workspace *
 pgxml_xpath(text *document, xmlChar *xpath, PgXmlErrorContext *xmlerrcxt)
 {
 	int32		docsize = VARSIZE_ANY_EXHDR(document);
-	xmlXPathCompExprPtr comppath;
+	xmlXPathCompExprPtr volatile comppath = NULL;
 	xpath_workspace *workspace = palloc0_object(xpath_workspace);
 
 	workspace->doctree = NULL;
 	workspace->ctxt = NULL;
 	workspace->res = NULL;
 
-	workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
-									   docsize, NULL, NULL,
-									   XML_PARSE_NOENT);
-	if (workspace->doctree != NULL)
+	PG_TRY();
 	{
-		workspace->ctxt = xmlXPathNewContext(workspace->doctree);
-		workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
-
-		/* compile the path */
-		comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
-		if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+		workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
+										   docsize, NULL, NULL,
+										   XML_PARSE_NOENT);
+		if (workspace->doctree != NULL)
 		{
-			if (comppath != NULL)
-				xmlXPathFreeCompExpr(comppath);
-			xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
-						"XPath Syntax Error");
-		}
+			workspace->ctxt = xmlXPathNewContext(workspace->doctree);
+			if (workspace->ctxt == NULL)
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_OUT_OF_MEMORY,
+							"could not allocate XPath context");
 
-		/* Now evaluate the path expression. */
-		workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+			workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
+
+			/* compile the path */
+			comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
+			if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
+							"XPath Syntax Error");
+
+			/* Now evaluate the path expression. */
+			workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+
+			xmlXPathFreeCompExpr(comppath);
+			comppath = NULL;
+		}
+	}
+	PG_CATCH();
+	{
+		if (comppath != NULL)
+			xmlXPathFreeCompExpr(comppath);
+		cleanup_workspace(workspace);
 
-		xmlXPathFreeCompExpr(comppath);
+		PG_RE_THROW();
 	}
+	PG_END_TRY();
 
 	return workspace;
 }
-- 
2.54.0


--MP_/LMSk9=uMhuQ1QiIJDarDO8G--





^ permalink  raw  reply  [nested|flat] 611+ messages in thread

* [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths
@ 2026-06-01 22:41 Andrey Chernyy <andrey.cherny@tantorlabs.com>
  0 siblings, 0 replies; 611+ messages in thread

From: Andrey Chernyy @ 2026-06-01 22:41 UTC (permalink / raw)

pgxml_xpath() builds an xpath_workspace before returning it to
callers.  If an ERROR is thrown before the function returns, callers
have not received the workspace pointer yet and cannot run
cleanup_workspace().

Add local error cleanup for the partially built workspace and the
compiled XPath expression.  Also check xmlXPathNewContext() before
dereferencing the returned context.
---
 contrib/xml2/xpath.c | 51 +++++++++++++++++++++++++++-----------------
 1 file changed, 32 insertions(+), 19 deletions(-)

diff --git a/contrib/xml2/xpath.c b/contrib/xml2/xpath.c
index 9fe75cb5ff4..283bb51178d 100644
--- a/contrib/xml2/xpath.c
+++ b/contrib/xml2/xpath.c
@@ -497,36 +497,49 @@ static xpath_workspace *
 pgxml_xpath(text *document, xmlChar *xpath, PgXmlErrorContext *xmlerrcxt)
 {
 	int32		docsize = VARSIZE_ANY_EXHDR(document);
-	xmlXPathCompExprPtr comppath;
+	xmlXPathCompExprPtr volatile comppath = NULL;
 	xpath_workspace *workspace = palloc0_object(xpath_workspace);
 
 	workspace->doctree = NULL;
 	workspace->ctxt = NULL;
 	workspace->res = NULL;
 
-	workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
-									   docsize, NULL, NULL,
-									   XML_PARSE_NOENT);
-	if (workspace->doctree != NULL)
+	PG_TRY();
 	{
-		workspace->ctxt = xmlXPathNewContext(workspace->doctree);
-		workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
-
-		/* compile the path */
-		comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
-		if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+		workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
+										   docsize, NULL, NULL,
+										   XML_PARSE_NOENT);
+		if (workspace->doctree != NULL)
 		{
-			if (comppath != NULL)
-				xmlXPathFreeCompExpr(comppath);
-			xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
-						"XPath Syntax Error");
-		}
+			workspace->ctxt = xmlXPathNewContext(workspace->doctree);
+			if (workspace->ctxt == NULL)
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_OUT_OF_MEMORY,
+							"could not allocate XPath context");
 
-		/* Now evaluate the path expression. */
-		workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+			workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
+
+			/* compile the path */
+			comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
+			if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
+							"XPath Syntax Error");
+
+			/* Now evaluate the path expression. */
+			workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+
+			xmlXPathFreeCompExpr(comppath);
+			comppath = NULL;
+		}
+	}
+	PG_CATCH();
+	{
+		if (comppath != NULL)
+			xmlXPathFreeCompExpr(comppath);
+		cleanup_workspace(workspace);
 
-		xmlXPathFreeCompExpr(comppath);
+		PG_RE_THROW();
 	}
+	PG_END_TRY();
 
 	return workspace;
 }
-- 
2.54.0


--MP_/LMSk9=uMhuQ1QiIJDarDO8G--





^ permalink  raw  reply  [nested|flat] 611+ messages in thread

* [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths
@ 2026-06-01 22:41 Andrey Chernyy <andrey.cherny@tantorlabs.com>
  0 siblings, 0 replies; 611+ messages in thread

From: Andrey Chernyy @ 2026-06-01 22:41 UTC (permalink / raw)

pgxml_xpath() builds an xpath_workspace before returning it to
callers.  If an ERROR is thrown before the function returns, callers
have not received the workspace pointer yet and cannot run
cleanup_workspace().

Add local error cleanup for the partially built workspace and the
compiled XPath expression.  Also check xmlXPathNewContext() before
dereferencing the returned context.
---
 contrib/xml2/xpath.c | 51 +++++++++++++++++++++++++++-----------------
 1 file changed, 32 insertions(+), 19 deletions(-)

diff --git a/contrib/xml2/xpath.c b/contrib/xml2/xpath.c
index 9fe75cb5ff4..283bb51178d 100644
--- a/contrib/xml2/xpath.c
+++ b/contrib/xml2/xpath.c
@@ -497,36 +497,49 @@ static xpath_workspace *
 pgxml_xpath(text *document, xmlChar *xpath, PgXmlErrorContext *xmlerrcxt)
 {
 	int32		docsize = VARSIZE_ANY_EXHDR(document);
-	xmlXPathCompExprPtr comppath;
+	xmlXPathCompExprPtr volatile comppath = NULL;
 	xpath_workspace *workspace = palloc0_object(xpath_workspace);
 
 	workspace->doctree = NULL;
 	workspace->ctxt = NULL;
 	workspace->res = NULL;
 
-	workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
-									   docsize, NULL, NULL,
-									   XML_PARSE_NOENT);
-	if (workspace->doctree != NULL)
+	PG_TRY();
 	{
-		workspace->ctxt = xmlXPathNewContext(workspace->doctree);
-		workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
-
-		/* compile the path */
-		comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
-		if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+		workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
+										   docsize, NULL, NULL,
+										   XML_PARSE_NOENT);
+		if (workspace->doctree != NULL)
 		{
-			if (comppath != NULL)
-				xmlXPathFreeCompExpr(comppath);
-			xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
-						"XPath Syntax Error");
-		}
+			workspace->ctxt = xmlXPathNewContext(workspace->doctree);
+			if (workspace->ctxt == NULL)
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_OUT_OF_MEMORY,
+							"could not allocate XPath context");
 
-		/* Now evaluate the path expression. */
-		workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+			workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
+
+			/* compile the path */
+			comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
+			if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
+							"XPath Syntax Error");
+
+			/* Now evaluate the path expression. */
+			workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+
+			xmlXPathFreeCompExpr(comppath);
+			comppath = NULL;
+		}
+	}
+	PG_CATCH();
+	{
+		if (comppath != NULL)
+			xmlXPathFreeCompExpr(comppath);
+		cleanup_workspace(workspace);
 
-		xmlXPathFreeCompExpr(comppath);
+		PG_RE_THROW();
 	}
+	PG_END_TRY();
 
 	return workspace;
 }
-- 
2.54.0


--MP_/LMSk9=uMhuQ1QiIJDarDO8G--






^ permalink  raw  reply  [nested|flat] 611+ messages in thread

* [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths
@ 2026-06-01 22:41 Andrey Chernyy <andrey.cherny@tantorlabs.com>
  0 siblings, 0 replies; 611+ messages in thread

From: Andrey Chernyy @ 2026-06-01 22:41 UTC (permalink / raw)

pgxml_xpath() builds an xpath_workspace before returning it to
callers.  If an ERROR is thrown before the function returns, callers
have not received the workspace pointer yet and cannot run
cleanup_workspace().

Add local error cleanup for the partially built workspace and the
compiled XPath expression.  Also check xmlXPathNewContext() before
dereferencing the returned context.
---
 contrib/xml2/xpath.c | 51 +++++++++++++++++++++++++++-----------------
 1 file changed, 32 insertions(+), 19 deletions(-)

diff --git a/contrib/xml2/xpath.c b/contrib/xml2/xpath.c
index 9fe75cb5ff4..283bb51178d 100644
--- a/contrib/xml2/xpath.c
+++ b/contrib/xml2/xpath.c
@@ -497,36 +497,49 @@ static xpath_workspace *
 pgxml_xpath(text *document, xmlChar *xpath, PgXmlErrorContext *xmlerrcxt)
 {
 	int32		docsize = VARSIZE_ANY_EXHDR(document);
-	xmlXPathCompExprPtr comppath;
+	xmlXPathCompExprPtr volatile comppath = NULL;
 	xpath_workspace *workspace = palloc0_object(xpath_workspace);
 
 	workspace->doctree = NULL;
 	workspace->ctxt = NULL;
 	workspace->res = NULL;
 
-	workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
-									   docsize, NULL, NULL,
-									   XML_PARSE_NOENT);
-	if (workspace->doctree != NULL)
+	PG_TRY();
 	{
-		workspace->ctxt = xmlXPathNewContext(workspace->doctree);
-		workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
-
-		/* compile the path */
-		comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
-		if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+		workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
+										   docsize, NULL, NULL,
+										   XML_PARSE_NOENT);
+		if (workspace->doctree != NULL)
 		{
-			if (comppath != NULL)
-				xmlXPathFreeCompExpr(comppath);
-			xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
-						"XPath Syntax Error");
-		}
+			workspace->ctxt = xmlXPathNewContext(workspace->doctree);
+			if (workspace->ctxt == NULL)
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_OUT_OF_MEMORY,
+							"could not allocate XPath context");
 
-		/* Now evaluate the path expression. */
-		workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+			workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
+
+			/* compile the path */
+			comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
+			if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
+							"XPath Syntax Error");
+
+			/* Now evaluate the path expression. */
+			workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+
+			xmlXPathFreeCompExpr(comppath);
+			comppath = NULL;
+		}
+	}
+	PG_CATCH();
+	{
+		if (comppath != NULL)
+			xmlXPathFreeCompExpr(comppath);
+		cleanup_workspace(workspace);
 
-		xmlXPathFreeCompExpr(comppath);
+		PG_RE_THROW();
 	}
+	PG_END_TRY();
 
 	return workspace;
 }
-- 
2.54.0


--MP_/LMSk9=uMhuQ1QiIJDarDO8G--






^ permalink  raw  reply  [nested|flat] 611+ messages in thread

* [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths
@ 2026-06-01 22:41 Andrey Chernyy <andrey.cherny@tantorlabs.com>
  0 siblings, 0 replies; 611+ messages in thread

From: Andrey Chernyy @ 2026-06-01 22:41 UTC (permalink / raw)

pgxml_xpath() builds an xpath_workspace before returning it to
callers.  If an ERROR is thrown before the function returns, callers
have not received the workspace pointer yet and cannot run
cleanup_workspace().

Add local error cleanup for the partially built workspace and the
compiled XPath expression.  Also check xmlXPathNewContext() before
dereferencing the returned context.
---
 contrib/xml2/xpath.c | 51 +++++++++++++++++++++++++++-----------------
 1 file changed, 32 insertions(+), 19 deletions(-)

diff --git a/contrib/xml2/xpath.c b/contrib/xml2/xpath.c
index 9fe75cb5ff4..283bb51178d 100644
--- a/contrib/xml2/xpath.c
+++ b/contrib/xml2/xpath.c
@@ -497,36 +497,49 @@ static xpath_workspace *
 pgxml_xpath(text *document, xmlChar *xpath, PgXmlErrorContext *xmlerrcxt)
 {
 	int32		docsize = VARSIZE_ANY_EXHDR(document);
-	xmlXPathCompExprPtr comppath;
+	xmlXPathCompExprPtr volatile comppath = NULL;
 	xpath_workspace *workspace = palloc0_object(xpath_workspace);
 
 	workspace->doctree = NULL;
 	workspace->ctxt = NULL;
 	workspace->res = NULL;
 
-	workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
-									   docsize, NULL, NULL,
-									   XML_PARSE_NOENT);
-	if (workspace->doctree != NULL)
+	PG_TRY();
 	{
-		workspace->ctxt = xmlXPathNewContext(workspace->doctree);
-		workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
-
-		/* compile the path */
-		comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
-		if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+		workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
+										   docsize, NULL, NULL,
+										   XML_PARSE_NOENT);
+		if (workspace->doctree != NULL)
 		{
-			if (comppath != NULL)
-				xmlXPathFreeCompExpr(comppath);
-			xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
-						"XPath Syntax Error");
-		}
+			workspace->ctxt = xmlXPathNewContext(workspace->doctree);
+			if (workspace->ctxt == NULL)
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_OUT_OF_MEMORY,
+							"could not allocate XPath context");
 
-		/* Now evaluate the path expression. */
-		workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+			workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
+
+			/* compile the path */
+			comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
+			if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
+							"XPath Syntax Error");
+
+			/* Now evaluate the path expression. */
+			workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+
+			xmlXPathFreeCompExpr(comppath);
+			comppath = NULL;
+		}
+	}
+	PG_CATCH();
+	{
+		if (comppath != NULL)
+			xmlXPathFreeCompExpr(comppath);
+		cleanup_workspace(workspace);
 
-		xmlXPathFreeCompExpr(comppath);
+		PG_RE_THROW();
 	}
+	PG_END_TRY();
 
 	return workspace;
 }
-- 
2.54.0


--MP_/LMSk9=uMhuQ1QiIJDarDO8G--





^ permalink  raw  reply  [nested|flat] 611+ messages in thread

* [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths
@ 2026-06-01 22:41 Andrey Chernyy <andrey.cherny@tantorlabs.com>
  0 siblings, 0 replies; 611+ messages in thread

From: Andrey Chernyy @ 2026-06-01 22:41 UTC (permalink / raw)

pgxml_xpath() builds an xpath_workspace before returning it to
callers.  If an ERROR is thrown before the function returns, callers
have not received the workspace pointer yet and cannot run
cleanup_workspace().

Add local error cleanup for the partially built workspace and the
compiled XPath expression.  Also check xmlXPathNewContext() before
dereferencing the returned context.
---
 contrib/xml2/xpath.c | 51 +++++++++++++++++++++++++++-----------------
 1 file changed, 32 insertions(+), 19 deletions(-)

diff --git a/contrib/xml2/xpath.c b/contrib/xml2/xpath.c
index 9fe75cb5ff4..283bb51178d 100644
--- a/contrib/xml2/xpath.c
+++ b/contrib/xml2/xpath.c
@@ -497,36 +497,49 @@ static xpath_workspace *
 pgxml_xpath(text *document, xmlChar *xpath, PgXmlErrorContext *xmlerrcxt)
 {
 	int32		docsize = VARSIZE_ANY_EXHDR(document);
-	xmlXPathCompExprPtr comppath;
+	xmlXPathCompExprPtr volatile comppath = NULL;
 	xpath_workspace *workspace = palloc0_object(xpath_workspace);
 
 	workspace->doctree = NULL;
 	workspace->ctxt = NULL;
 	workspace->res = NULL;
 
-	workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
-									   docsize, NULL, NULL,
-									   XML_PARSE_NOENT);
-	if (workspace->doctree != NULL)
+	PG_TRY();
 	{
-		workspace->ctxt = xmlXPathNewContext(workspace->doctree);
-		workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
-
-		/* compile the path */
-		comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
-		if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+		workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
+										   docsize, NULL, NULL,
+										   XML_PARSE_NOENT);
+		if (workspace->doctree != NULL)
 		{
-			if (comppath != NULL)
-				xmlXPathFreeCompExpr(comppath);
-			xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
-						"XPath Syntax Error");
-		}
+			workspace->ctxt = xmlXPathNewContext(workspace->doctree);
+			if (workspace->ctxt == NULL)
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_OUT_OF_MEMORY,
+							"could not allocate XPath context");
 
-		/* Now evaluate the path expression. */
-		workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+			workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
+
+			/* compile the path */
+			comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
+			if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
+							"XPath Syntax Error");
+
+			/* Now evaluate the path expression. */
+			workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+
+			xmlXPathFreeCompExpr(comppath);
+			comppath = NULL;
+		}
+	}
+	PG_CATCH();
+	{
+		if (comppath != NULL)
+			xmlXPathFreeCompExpr(comppath);
+		cleanup_workspace(workspace);
 
-		xmlXPathFreeCompExpr(comppath);
+		PG_RE_THROW();
 	}
+	PG_END_TRY();
 
 	return workspace;
 }
-- 
2.54.0


--MP_/LMSk9=uMhuQ1QiIJDarDO8G--






^ permalink  raw  reply  [nested|flat] 611+ messages in thread

* [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths
@ 2026-06-01 22:41 Andrey Chernyy <andrey.cherny@tantorlabs.com>
  0 siblings, 0 replies; 611+ messages in thread

From: Andrey Chernyy @ 2026-06-01 22:41 UTC (permalink / raw)

pgxml_xpath() builds an xpath_workspace before returning it to
callers.  If an ERROR is thrown before the function returns, callers
have not received the workspace pointer yet and cannot run
cleanup_workspace().

Add local error cleanup for the partially built workspace and the
compiled XPath expression.  Also check xmlXPathNewContext() before
dereferencing the returned context.
---
 contrib/xml2/xpath.c | 51 +++++++++++++++++++++++++++-----------------
 1 file changed, 32 insertions(+), 19 deletions(-)

diff --git a/contrib/xml2/xpath.c b/contrib/xml2/xpath.c
index 9fe75cb5ff4..283bb51178d 100644
--- a/contrib/xml2/xpath.c
+++ b/contrib/xml2/xpath.c
@@ -497,36 +497,49 @@ static xpath_workspace *
 pgxml_xpath(text *document, xmlChar *xpath, PgXmlErrorContext *xmlerrcxt)
 {
 	int32		docsize = VARSIZE_ANY_EXHDR(document);
-	xmlXPathCompExprPtr comppath;
+	xmlXPathCompExprPtr volatile comppath = NULL;
 	xpath_workspace *workspace = palloc0_object(xpath_workspace);
 
 	workspace->doctree = NULL;
 	workspace->ctxt = NULL;
 	workspace->res = NULL;
 
-	workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
-									   docsize, NULL, NULL,
-									   XML_PARSE_NOENT);
-	if (workspace->doctree != NULL)
+	PG_TRY();
 	{
-		workspace->ctxt = xmlXPathNewContext(workspace->doctree);
-		workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
-
-		/* compile the path */
-		comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
-		if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+		workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
+										   docsize, NULL, NULL,
+										   XML_PARSE_NOENT);
+		if (workspace->doctree != NULL)
 		{
-			if (comppath != NULL)
-				xmlXPathFreeCompExpr(comppath);
-			xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
-						"XPath Syntax Error");
-		}
+			workspace->ctxt = xmlXPathNewContext(workspace->doctree);
+			if (workspace->ctxt == NULL)
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_OUT_OF_MEMORY,
+							"could not allocate XPath context");
 
-		/* Now evaluate the path expression. */
-		workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+			workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
+
+			/* compile the path */
+			comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
+			if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
+							"XPath Syntax Error");
+
+			/* Now evaluate the path expression. */
+			workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+
+			xmlXPathFreeCompExpr(comppath);
+			comppath = NULL;
+		}
+	}
+	PG_CATCH();
+	{
+		if (comppath != NULL)
+			xmlXPathFreeCompExpr(comppath);
+		cleanup_workspace(workspace);
 
-		xmlXPathFreeCompExpr(comppath);
+		PG_RE_THROW();
 	}
+	PG_END_TRY();
 
 	return workspace;
 }
-- 
2.54.0


--MP_/LMSk9=uMhuQ1QiIJDarDO8G--






^ permalink  raw  reply  [nested|flat] 611+ messages in thread

* [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths
@ 2026-06-01 22:41 Andrey Chernyy <andrey.cherny@tantorlabs.com>
  0 siblings, 0 replies; 611+ messages in thread

From: Andrey Chernyy @ 2026-06-01 22:41 UTC (permalink / raw)

pgxml_xpath() builds an xpath_workspace before returning it to
callers.  If an ERROR is thrown before the function returns, callers
have not received the workspace pointer yet and cannot run
cleanup_workspace().

Add local error cleanup for the partially built workspace and the
compiled XPath expression.  Also check xmlXPathNewContext() before
dereferencing the returned context.
---
 contrib/xml2/xpath.c | 51 +++++++++++++++++++++++++++-----------------
 1 file changed, 32 insertions(+), 19 deletions(-)

diff --git a/contrib/xml2/xpath.c b/contrib/xml2/xpath.c
index 9fe75cb5ff4..283bb51178d 100644
--- a/contrib/xml2/xpath.c
+++ b/contrib/xml2/xpath.c
@@ -497,36 +497,49 @@ static xpath_workspace *
 pgxml_xpath(text *document, xmlChar *xpath, PgXmlErrorContext *xmlerrcxt)
 {
 	int32		docsize = VARSIZE_ANY_EXHDR(document);
-	xmlXPathCompExprPtr comppath;
+	xmlXPathCompExprPtr volatile comppath = NULL;
 	xpath_workspace *workspace = palloc0_object(xpath_workspace);
 
 	workspace->doctree = NULL;
 	workspace->ctxt = NULL;
 	workspace->res = NULL;
 
-	workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
-									   docsize, NULL, NULL,
-									   XML_PARSE_NOENT);
-	if (workspace->doctree != NULL)
+	PG_TRY();
 	{
-		workspace->ctxt = xmlXPathNewContext(workspace->doctree);
-		workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
-
-		/* compile the path */
-		comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
-		if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+		workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
+										   docsize, NULL, NULL,
+										   XML_PARSE_NOENT);
+		if (workspace->doctree != NULL)
 		{
-			if (comppath != NULL)
-				xmlXPathFreeCompExpr(comppath);
-			xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
-						"XPath Syntax Error");
-		}
+			workspace->ctxt = xmlXPathNewContext(workspace->doctree);
+			if (workspace->ctxt == NULL)
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_OUT_OF_MEMORY,
+							"could not allocate XPath context");
 
-		/* Now evaluate the path expression. */
-		workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+			workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
+
+			/* compile the path */
+			comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
+			if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
+							"XPath Syntax Error");
+
+			/* Now evaluate the path expression. */
+			workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+
+			xmlXPathFreeCompExpr(comppath);
+			comppath = NULL;
+		}
+	}
+	PG_CATCH();
+	{
+		if (comppath != NULL)
+			xmlXPathFreeCompExpr(comppath);
+		cleanup_workspace(workspace);
 
-		xmlXPathFreeCompExpr(comppath);
+		PG_RE_THROW();
 	}
+	PG_END_TRY();
 
 	return workspace;
 }
-- 
2.54.0


--MP_/LMSk9=uMhuQ1QiIJDarDO8G--






^ permalink  raw  reply  [nested|flat] 611+ messages in thread

* [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths
@ 2026-06-01 22:41 Andrey Chernyy <andrey.cherny@tantorlabs.com>
  0 siblings, 0 replies; 611+ messages in thread

From: Andrey Chernyy @ 2026-06-01 22:41 UTC (permalink / raw)

pgxml_xpath() builds an xpath_workspace before returning it to
callers.  If an ERROR is thrown before the function returns, callers
have not received the workspace pointer yet and cannot run
cleanup_workspace().

Add local error cleanup for the partially built workspace and the
compiled XPath expression.  Also check xmlXPathNewContext() before
dereferencing the returned context.
---
 contrib/xml2/xpath.c | 51 +++++++++++++++++++++++++++-----------------
 1 file changed, 32 insertions(+), 19 deletions(-)

diff --git a/contrib/xml2/xpath.c b/contrib/xml2/xpath.c
index 9fe75cb5ff4..283bb51178d 100644
--- a/contrib/xml2/xpath.c
+++ b/contrib/xml2/xpath.c
@@ -497,36 +497,49 @@ static xpath_workspace *
 pgxml_xpath(text *document, xmlChar *xpath, PgXmlErrorContext *xmlerrcxt)
 {
 	int32		docsize = VARSIZE_ANY_EXHDR(document);
-	xmlXPathCompExprPtr comppath;
+	xmlXPathCompExprPtr volatile comppath = NULL;
 	xpath_workspace *workspace = palloc0_object(xpath_workspace);
 
 	workspace->doctree = NULL;
 	workspace->ctxt = NULL;
 	workspace->res = NULL;
 
-	workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
-									   docsize, NULL, NULL,
-									   XML_PARSE_NOENT);
-	if (workspace->doctree != NULL)
+	PG_TRY();
 	{
-		workspace->ctxt = xmlXPathNewContext(workspace->doctree);
-		workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
-
-		/* compile the path */
-		comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
-		if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+		workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
+										   docsize, NULL, NULL,
+										   XML_PARSE_NOENT);
+		if (workspace->doctree != NULL)
 		{
-			if (comppath != NULL)
-				xmlXPathFreeCompExpr(comppath);
-			xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
-						"XPath Syntax Error");
-		}
+			workspace->ctxt = xmlXPathNewContext(workspace->doctree);
+			if (workspace->ctxt == NULL)
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_OUT_OF_MEMORY,
+							"could not allocate XPath context");
 
-		/* Now evaluate the path expression. */
-		workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+			workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
+
+			/* compile the path */
+			comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
+			if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
+							"XPath Syntax Error");
+
+			/* Now evaluate the path expression. */
+			workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+
+			xmlXPathFreeCompExpr(comppath);
+			comppath = NULL;
+		}
+	}
+	PG_CATCH();
+	{
+		if (comppath != NULL)
+			xmlXPathFreeCompExpr(comppath);
+		cleanup_workspace(workspace);
 
-		xmlXPathFreeCompExpr(comppath);
+		PG_RE_THROW();
 	}
+	PG_END_TRY();
 
 	return workspace;
 }
-- 
2.54.0


--MP_/LMSk9=uMhuQ1QiIJDarDO8G--






^ permalink  raw  reply  [nested|flat] 611+ messages in thread

* [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths
@ 2026-06-01 22:41 Andrey Chernyy <andrey.cherny@tantorlabs.com>
  0 siblings, 0 replies; 611+ messages in thread

From: Andrey Chernyy @ 2026-06-01 22:41 UTC (permalink / raw)

pgxml_xpath() builds an xpath_workspace before returning it to
callers.  If an ERROR is thrown before the function returns, callers
have not received the workspace pointer yet and cannot run
cleanup_workspace().

Add local error cleanup for the partially built workspace and the
compiled XPath expression.  Also check xmlXPathNewContext() before
dereferencing the returned context.
---
 contrib/xml2/xpath.c | 51 +++++++++++++++++++++++++++-----------------
 1 file changed, 32 insertions(+), 19 deletions(-)

diff --git a/contrib/xml2/xpath.c b/contrib/xml2/xpath.c
index 9fe75cb5ff4..283bb51178d 100644
--- a/contrib/xml2/xpath.c
+++ b/contrib/xml2/xpath.c
@@ -497,36 +497,49 @@ static xpath_workspace *
 pgxml_xpath(text *document, xmlChar *xpath, PgXmlErrorContext *xmlerrcxt)
 {
 	int32		docsize = VARSIZE_ANY_EXHDR(document);
-	xmlXPathCompExprPtr comppath;
+	xmlXPathCompExprPtr volatile comppath = NULL;
 	xpath_workspace *workspace = palloc0_object(xpath_workspace);
 
 	workspace->doctree = NULL;
 	workspace->ctxt = NULL;
 	workspace->res = NULL;
 
-	workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
-									   docsize, NULL, NULL,
-									   XML_PARSE_NOENT);
-	if (workspace->doctree != NULL)
+	PG_TRY();
 	{
-		workspace->ctxt = xmlXPathNewContext(workspace->doctree);
-		workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
-
-		/* compile the path */
-		comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
-		if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+		workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
+										   docsize, NULL, NULL,
+										   XML_PARSE_NOENT);
+		if (workspace->doctree != NULL)
 		{
-			if (comppath != NULL)
-				xmlXPathFreeCompExpr(comppath);
-			xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
-						"XPath Syntax Error");
-		}
+			workspace->ctxt = xmlXPathNewContext(workspace->doctree);
+			if (workspace->ctxt == NULL)
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_OUT_OF_MEMORY,
+							"could not allocate XPath context");
 
-		/* Now evaluate the path expression. */
-		workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+			workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
+
+			/* compile the path */
+			comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
+			if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
+							"XPath Syntax Error");
+
+			/* Now evaluate the path expression. */
+			workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+
+			xmlXPathFreeCompExpr(comppath);
+			comppath = NULL;
+		}
+	}
+	PG_CATCH();
+	{
+		if (comppath != NULL)
+			xmlXPathFreeCompExpr(comppath);
+		cleanup_workspace(workspace);
 
-		xmlXPathFreeCompExpr(comppath);
+		PG_RE_THROW();
 	}
+	PG_END_TRY();
 
 	return workspace;
 }
-- 
2.54.0


--MP_/LMSk9=uMhuQ1QiIJDarDO8G--






^ permalink  raw  reply  [nested|flat] 611+ messages in thread

* [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths
@ 2026-06-01 22:41 Andrey Chernyy <andrey.cherny@tantorlabs.com>
  0 siblings, 0 replies; 611+ messages in thread

From: Andrey Chernyy @ 2026-06-01 22:41 UTC (permalink / raw)

pgxml_xpath() builds an xpath_workspace before returning it to
callers.  If an ERROR is thrown before the function returns, callers
have not received the workspace pointer yet and cannot run
cleanup_workspace().

Add local error cleanup for the partially built workspace and the
compiled XPath expression.  Also check xmlXPathNewContext() before
dereferencing the returned context.
---
 contrib/xml2/xpath.c | 51 +++++++++++++++++++++++++++-----------------
 1 file changed, 32 insertions(+), 19 deletions(-)

diff --git a/contrib/xml2/xpath.c b/contrib/xml2/xpath.c
index 9fe75cb5ff4..283bb51178d 100644
--- a/contrib/xml2/xpath.c
+++ b/contrib/xml2/xpath.c
@@ -497,36 +497,49 @@ static xpath_workspace *
 pgxml_xpath(text *document, xmlChar *xpath, PgXmlErrorContext *xmlerrcxt)
 {
 	int32		docsize = VARSIZE_ANY_EXHDR(document);
-	xmlXPathCompExprPtr comppath;
+	xmlXPathCompExprPtr volatile comppath = NULL;
 	xpath_workspace *workspace = palloc0_object(xpath_workspace);
 
 	workspace->doctree = NULL;
 	workspace->ctxt = NULL;
 	workspace->res = NULL;
 
-	workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
-									   docsize, NULL, NULL,
-									   XML_PARSE_NOENT);
-	if (workspace->doctree != NULL)
+	PG_TRY();
 	{
-		workspace->ctxt = xmlXPathNewContext(workspace->doctree);
-		workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
-
-		/* compile the path */
-		comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
-		if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+		workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
+										   docsize, NULL, NULL,
+										   XML_PARSE_NOENT);
+		if (workspace->doctree != NULL)
 		{
-			if (comppath != NULL)
-				xmlXPathFreeCompExpr(comppath);
-			xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
-						"XPath Syntax Error");
-		}
+			workspace->ctxt = xmlXPathNewContext(workspace->doctree);
+			if (workspace->ctxt == NULL)
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_OUT_OF_MEMORY,
+							"could not allocate XPath context");
 
-		/* Now evaluate the path expression. */
-		workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+			workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
+
+			/* compile the path */
+			comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
+			if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
+							"XPath Syntax Error");
+
+			/* Now evaluate the path expression. */
+			workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+
+			xmlXPathFreeCompExpr(comppath);
+			comppath = NULL;
+		}
+	}
+	PG_CATCH();
+	{
+		if (comppath != NULL)
+			xmlXPathFreeCompExpr(comppath);
+		cleanup_workspace(workspace);
 
-		xmlXPathFreeCompExpr(comppath);
+		PG_RE_THROW();
 	}
+	PG_END_TRY();
 
 	return workspace;
 }
-- 
2.54.0


--MP_/LMSk9=uMhuQ1QiIJDarDO8G--





^ permalink  raw  reply  [nested|flat] 611+ messages in thread

* [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths
@ 2026-06-01 22:41 Andrey Chernyy <andrey.cherny@tantorlabs.com>
  0 siblings, 0 replies; 611+ messages in thread

From: Andrey Chernyy @ 2026-06-01 22:41 UTC (permalink / raw)

pgxml_xpath() builds an xpath_workspace before returning it to
callers.  If an ERROR is thrown before the function returns, callers
have not received the workspace pointer yet and cannot run
cleanup_workspace().

Add local error cleanup for the partially built workspace and the
compiled XPath expression.  Also check xmlXPathNewContext() before
dereferencing the returned context.
---
 contrib/xml2/xpath.c | 51 +++++++++++++++++++++++++++-----------------
 1 file changed, 32 insertions(+), 19 deletions(-)

diff --git a/contrib/xml2/xpath.c b/contrib/xml2/xpath.c
index 9fe75cb5ff4..283bb51178d 100644
--- a/contrib/xml2/xpath.c
+++ b/contrib/xml2/xpath.c
@@ -497,36 +497,49 @@ static xpath_workspace *
 pgxml_xpath(text *document, xmlChar *xpath, PgXmlErrorContext *xmlerrcxt)
 {
 	int32		docsize = VARSIZE_ANY_EXHDR(document);
-	xmlXPathCompExprPtr comppath;
+	xmlXPathCompExprPtr volatile comppath = NULL;
 	xpath_workspace *workspace = palloc0_object(xpath_workspace);
 
 	workspace->doctree = NULL;
 	workspace->ctxt = NULL;
 	workspace->res = NULL;
 
-	workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
-									   docsize, NULL, NULL,
-									   XML_PARSE_NOENT);
-	if (workspace->doctree != NULL)
+	PG_TRY();
 	{
-		workspace->ctxt = xmlXPathNewContext(workspace->doctree);
-		workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
-
-		/* compile the path */
-		comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
-		if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+		workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
+										   docsize, NULL, NULL,
+										   XML_PARSE_NOENT);
+		if (workspace->doctree != NULL)
 		{
-			if (comppath != NULL)
-				xmlXPathFreeCompExpr(comppath);
-			xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
-						"XPath Syntax Error");
-		}
+			workspace->ctxt = xmlXPathNewContext(workspace->doctree);
+			if (workspace->ctxt == NULL)
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_OUT_OF_MEMORY,
+							"could not allocate XPath context");
 
-		/* Now evaluate the path expression. */
-		workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+			workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
+
+			/* compile the path */
+			comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
+			if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
+							"XPath Syntax Error");
+
+			/* Now evaluate the path expression. */
+			workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+
+			xmlXPathFreeCompExpr(comppath);
+			comppath = NULL;
+		}
+	}
+	PG_CATCH();
+	{
+		if (comppath != NULL)
+			xmlXPathFreeCompExpr(comppath);
+		cleanup_workspace(workspace);
 
-		xmlXPathFreeCompExpr(comppath);
+		PG_RE_THROW();
 	}
+	PG_END_TRY();
 
 	return workspace;
 }
-- 
2.54.0


--MP_/LMSk9=uMhuQ1QiIJDarDO8G--






^ permalink  raw  reply  [nested|flat] 611+ messages in thread

* [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths
@ 2026-06-01 22:41 Andrey Chernyy <andrey.cherny@tantorlabs.com>
  0 siblings, 0 replies; 611+ messages in thread

From: Andrey Chernyy @ 2026-06-01 22:41 UTC (permalink / raw)

pgxml_xpath() builds an xpath_workspace before returning it to
callers.  If an ERROR is thrown before the function returns, callers
have not received the workspace pointer yet and cannot run
cleanup_workspace().

Add local error cleanup for the partially built workspace and the
compiled XPath expression.  Also check xmlXPathNewContext() before
dereferencing the returned context.
---
 contrib/xml2/xpath.c | 51 +++++++++++++++++++++++++++-----------------
 1 file changed, 32 insertions(+), 19 deletions(-)

diff --git a/contrib/xml2/xpath.c b/contrib/xml2/xpath.c
index 9fe75cb5ff4..283bb51178d 100644
--- a/contrib/xml2/xpath.c
+++ b/contrib/xml2/xpath.c
@@ -497,36 +497,49 @@ static xpath_workspace *
 pgxml_xpath(text *document, xmlChar *xpath, PgXmlErrorContext *xmlerrcxt)
 {
 	int32		docsize = VARSIZE_ANY_EXHDR(document);
-	xmlXPathCompExprPtr comppath;
+	xmlXPathCompExprPtr volatile comppath = NULL;
 	xpath_workspace *workspace = palloc0_object(xpath_workspace);
 
 	workspace->doctree = NULL;
 	workspace->ctxt = NULL;
 	workspace->res = NULL;
 
-	workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
-									   docsize, NULL, NULL,
-									   XML_PARSE_NOENT);
-	if (workspace->doctree != NULL)
+	PG_TRY();
 	{
-		workspace->ctxt = xmlXPathNewContext(workspace->doctree);
-		workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
-
-		/* compile the path */
-		comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
-		if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+		workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
+										   docsize, NULL, NULL,
+										   XML_PARSE_NOENT);
+		if (workspace->doctree != NULL)
 		{
-			if (comppath != NULL)
-				xmlXPathFreeCompExpr(comppath);
-			xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
-						"XPath Syntax Error");
-		}
+			workspace->ctxt = xmlXPathNewContext(workspace->doctree);
+			if (workspace->ctxt == NULL)
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_OUT_OF_MEMORY,
+							"could not allocate XPath context");
 
-		/* Now evaluate the path expression. */
-		workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+			workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
+
+			/* compile the path */
+			comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
+			if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
+							"XPath Syntax Error");
+
+			/* Now evaluate the path expression. */
+			workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+
+			xmlXPathFreeCompExpr(comppath);
+			comppath = NULL;
+		}
+	}
+	PG_CATCH();
+	{
+		if (comppath != NULL)
+			xmlXPathFreeCompExpr(comppath);
+		cleanup_workspace(workspace);
 
-		xmlXPathFreeCompExpr(comppath);
+		PG_RE_THROW();
 	}
+	PG_END_TRY();
 
 	return workspace;
 }
-- 
2.54.0


--MP_/LMSk9=uMhuQ1QiIJDarDO8G--





^ permalink  raw  reply  [nested|flat] 611+ messages in thread

* [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths
@ 2026-06-01 22:41 Andrey Chernyy <andrey.cherny@tantorlabs.com>
  0 siblings, 0 replies; 611+ messages in thread

From: Andrey Chernyy @ 2026-06-01 22:41 UTC (permalink / raw)

pgxml_xpath() builds an xpath_workspace before returning it to
callers.  If an ERROR is thrown before the function returns, callers
have not received the workspace pointer yet and cannot run
cleanup_workspace().

Add local error cleanup for the partially built workspace and the
compiled XPath expression.  Also check xmlXPathNewContext() before
dereferencing the returned context.
---
 contrib/xml2/xpath.c | 51 +++++++++++++++++++++++++++-----------------
 1 file changed, 32 insertions(+), 19 deletions(-)

diff --git a/contrib/xml2/xpath.c b/contrib/xml2/xpath.c
index 9fe75cb5ff4..283bb51178d 100644
--- a/contrib/xml2/xpath.c
+++ b/contrib/xml2/xpath.c
@@ -497,36 +497,49 @@ static xpath_workspace *
 pgxml_xpath(text *document, xmlChar *xpath, PgXmlErrorContext *xmlerrcxt)
 {
 	int32		docsize = VARSIZE_ANY_EXHDR(document);
-	xmlXPathCompExprPtr comppath;
+	xmlXPathCompExprPtr volatile comppath = NULL;
 	xpath_workspace *workspace = palloc0_object(xpath_workspace);
 
 	workspace->doctree = NULL;
 	workspace->ctxt = NULL;
 	workspace->res = NULL;
 
-	workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
-									   docsize, NULL, NULL,
-									   XML_PARSE_NOENT);
-	if (workspace->doctree != NULL)
+	PG_TRY();
 	{
-		workspace->ctxt = xmlXPathNewContext(workspace->doctree);
-		workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
-
-		/* compile the path */
-		comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
-		if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+		workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
+										   docsize, NULL, NULL,
+										   XML_PARSE_NOENT);
+		if (workspace->doctree != NULL)
 		{
-			if (comppath != NULL)
-				xmlXPathFreeCompExpr(comppath);
-			xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
-						"XPath Syntax Error");
-		}
+			workspace->ctxt = xmlXPathNewContext(workspace->doctree);
+			if (workspace->ctxt == NULL)
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_OUT_OF_MEMORY,
+							"could not allocate XPath context");
 
-		/* Now evaluate the path expression. */
-		workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+			workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
+
+			/* compile the path */
+			comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
+			if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
+							"XPath Syntax Error");
+
+			/* Now evaluate the path expression. */
+			workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+
+			xmlXPathFreeCompExpr(comppath);
+			comppath = NULL;
+		}
+	}
+	PG_CATCH();
+	{
+		if (comppath != NULL)
+			xmlXPathFreeCompExpr(comppath);
+		cleanup_workspace(workspace);
 
-		xmlXPathFreeCompExpr(comppath);
+		PG_RE_THROW();
 	}
+	PG_END_TRY();
 
 	return workspace;
 }
-- 
2.54.0


--MP_/LMSk9=uMhuQ1QiIJDarDO8G--





^ permalink  raw  reply  [nested|flat] 611+ messages in thread

* [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths
@ 2026-06-01 22:41 Andrey Chernyy <andrey.cherny@tantorlabs.com>
  0 siblings, 0 replies; 611+ messages in thread

From: Andrey Chernyy @ 2026-06-01 22:41 UTC (permalink / raw)

pgxml_xpath() builds an xpath_workspace before returning it to
callers.  If an ERROR is thrown before the function returns, callers
have not received the workspace pointer yet and cannot run
cleanup_workspace().

Add local error cleanup for the partially built workspace and the
compiled XPath expression.  Also check xmlXPathNewContext() before
dereferencing the returned context.
---
 contrib/xml2/xpath.c | 51 +++++++++++++++++++++++++++-----------------
 1 file changed, 32 insertions(+), 19 deletions(-)

diff --git a/contrib/xml2/xpath.c b/contrib/xml2/xpath.c
index 9fe75cb5ff4..283bb51178d 100644
--- a/contrib/xml2/xpath.c
+++ b/contrib/xml2/xpath.c
@@ -497,36 +497,49 @@ static xpath_workspace *
 pgxml_xpath(text *document, xmlChar *xpath, PgXmlErrorContext *xmlerrcxt)
 {
 	int32		docsize = VARSIZE_ANY_EXHDR(document);
-	xmlXPathCompExprPtr comppath;
+	xmlXPathCompExprPtr volatile comppath = NULL;
 	xpath_workspace *workspace = palloc0_object(xpath_workspace);
 
 	workspace->doctree = NULL;
 	workspace->ctxt = NULL;
 	workspace->res = NULL;
 
-	workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
-									   docsize, NULL, NULL,
-									   XML_PARSE_NOENT);
-	if (workspace->doctree != NULL)
+	PG_TRY();
 	{
-		workspace->ctxt = xmlXPathNewContext(workspace->doctree);
-		workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
-
-		/* compile the path */
-		comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
-		if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+		workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
+										   docsize, NULL, NULL,
+										   XML_PARSE_NOENT);
+		if (workspace->doctree != NULL)
 		{
-			if (comppath != NULL)
-				xmlXPathFreeCompExpr(comppath);
-			xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
-						"XPath Syntax Error");
-		}
+			workspace->ctxt = xmlXPathNewContext(workspace->doctree);
+			if (workspace->ctxt == NULL)
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_OUT_OF_MEMORY,
+							"could not allocate XPath context");
 
-		/* Now evaluate the path expression. */
-		workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+			workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
+
+			/* compile the path */
+			comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
+			if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
+							"XPath Syntax Error");
+
+			/* Now evaluate the path expression. */
+			workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+
+			xmlXPathFreeCompExpr(comppath);
+			comppath = NULL;
+		}
+	}
+	PG_CATCH();
+	{
+		if (comppath != NULL)
+			xmlXPathFreeCompExpr(comppath);
+		cleanup_workspace(workspace);
 
-		xmlXPathFreeCompExpr(comppath);
+		PG_RE_THROW();
 	}
+	PG_END_TRY();
 
 	return workspace;
 }
-- 
2.54.0


--MP_/LMSk9=uMhuQ1QiIJDarDO8G--





^ permalink  raw  reply  [nested|flat] 611+ messages in thread

* [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths
@ 2026-06-01 22:41 Andrey Chernyy <andrey.cherny@tantorlabs.com>
  0 siblings, 0 replies; 611+ messages in thread

From: Andrey Chernyy @ 2026-06-01 22:41 UTC (permalink / raw)

pgxml_xpath() builds an xpath_workspace before returning it to
callers.  If an ERROR is thrown before the function returns, callers
have not received the workspace pointer yet and cannot run
cleanup_workspace().

Add local error cleanup for the partially built workspace and the
compiled XPath expression.  Also check xmlXPathNewContext() before
dereferencing the returned context.
---
 contrib/xml2/xpath.c | 51 +++++++++++++++++++++++++++-----------------
 1 file changed, 32 insertions(+), 19 deletions(-)

diff --git a/contrib/xml2/xpath.c b/contrib/xml2/xpath.c
index 9fe75cb5ff4..283bb51178d 100644
--- a/contrib/xml2/xpath.c
+++ b/contrib/xml2/xpath.c
@@ -497,36 +497,49 @@ static xpath_workspace *
 pgxml_xpath(text *document, xmlChar *xpath, PgXmlErrorContext *xmlerrcxt)
 {
 	int32		docsize = VARSIZE_ANY_EXHDR(document);
-	xmlXPathCompExprPtr comppath;
+	xmlXPathCompExprPtr volatile comppath = NULL;
 	xpath_workspace *workspace = palloc0_object(xpath_workspace);
 
 	workspace->doctree = NULL;
 	workspace->ctxt = NULL;
 	workspace->res = NULL;
 
-	workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
-									   docsize, NULL, NULL,
-									   XML_PARSE_NOENT);
-	if (workspace->doctree != NULL)
+	PG_TRY();
 	{
-		workspace->ctxt = xmlXPathNewContext(workspace->doctree);
-		workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
-
-		/* compile the path */
-		comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
-		if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+		workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
+										   docsize, NULL, NULL,
+										   XML_PARSE_NOENT);
+		if (workspace->doctree != NULL)
 		{
-			if (comppath != NULL)
-				xmlXPathFreeCompExpr(comppath);
-			xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
-						"XPath Syntax Error");
-		}
+			workspace->ctxt = xmlXPathNewContext(workspace->doctree);
+			if (workspace->ctxt == NULL)
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_OUT_OF_MEMORY,
+							"could not allocate XPath context");
 
-		/* Now evaluate the path expression. */
-		workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+			workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
+
+			/* compile the path */
+			comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
+			if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
+							"XPath Syntax Error");
+
+			/* Now evaluate the path expression. */
+			workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+
+			xmlXPathFreeCompExpr(comppath);
+			comppath = NULL;
+		}
+	}
+	PG_CATCH();
+	{
+		if (comppath != NULL)
+			xmlXPathFreeCompExpr(comppath);
+		cleanup_workspace(workspace);
 
-		xmlXPathFreeCompExpr(comppath);
+		PG_RE_THROW();
 	}
+	PG_END_TRY();
 
 	return workspace;
 }
-- 
2.54.0


--MP_/LMSk9=uMhuQ1QiIJDarDO8G--





^ permalink  raw  reply  [nested|flat] 611+ messages in thread

* [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths
@ 2026-06-01 22:41 Andrey Chernyy <andrey.cherny@tantorlabs.com>
  0 siblings, 0 replies; 611+ messages in thread

From: Andrey Chernyy @ 2026-06-01 22:41 UTC (permalink / raw)

pgxml_xpath() builds an xpath_workspace before returning it to
callers.  If an ERROR is thrown before the function returns, callers
have not received the workspace pointer yet and cannot run
cleanup_workspace().

Add local error cleanup for the partially built workspace and the
compiled XPath expression.  Also check xmlXPathNewContext() before
dereferencing the returned context.
---
 contrib/xml2/xpath.c | 51 +++++++++++++++++++++++++++-----------------
 1 file changed, 32 insertions(+), 19 deletions(-)

diff --git a/contrib/xml2/xpath.c b/contrib/xml2/xpath.c
index 9fe75cb5ff4..283bb51178d 100644
--- a/contrib/xml2/xpath.c
+++ b/contrib/xml2/xpath.c
@@ -497,36 +497,49 @@ static xpath_workspace *
 pgxml_xpath(text *document, xmlChar *xpath, PgXmlErrorContext *xmlerrcxt)
 {
 	int32		docsize = VARSIZE_ANY_EXHDR(document);
-	xmlXPathCompExprPtr comppath;
+	xmlXPathCompExprPtr volatile comppath = NULL;
 	xpath_workspace *workspace = palloc0_object(xpath_workspace);
 
 	workspace->doctree = NULL;
 	workspace->ctxt = NULL;
 	workspace->res = NULL;
 
-	workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
-									   docsize, NULL, NULL,
-									   XML_PARSE_NOENT);
-	if (workspace->doctree != NULL)
+	PG_TRY();
 	{
-		workspace->ctxt = xmlXPathNewContext(workspace->doctree);
-		workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
-
-		/* compile the path */
-		comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
-		if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+		workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
+										   docsize, NULL, NULL,
+										   XML_PARSE_NOENT);
+		if (workspace->doctree != NULL)
 		{
-			if (comppath != NULL)
-				xmlXPathFreeCompExpr(comppath);
-			xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
-						"XPath Syntax Error");
-		}
+			workspace->ctxt = xmlXPathNewContext(workspace->doctree);
+			if (workspace->ctxt == NULL)
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_OUT_OF_MEMORY,
+							"could not allocate XPath context");
 
-		/* Now evaluate the path expression. */
-		workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+			workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
+
+			/* compile the path */
+			comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
+			if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
+							"XPath Syntax Error");
+
+			/* Now evaluate the path expression. */
+			workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+
+			xmlXPathFreeCompExpr(comppath);
+			comppath = NULL;
+		}
+	}
+	PG_CATCH();
+	{
+		if (comppath != NULL)
+			xmlXPathFreeCompExpr(comppath);
+		cleanup_workspace(workspace);
 
-		xmlXPathFreeCompExpr(comppath);
+		PG_RE_THROW();
 	}
+	PG_END_TRY();
 
 	return workspace;
 }
-- 
2.54.0


--MP_/LMSk9=uMhuQ1QiIJDarDO8G--






^ permalink  raw  reply  [nested|flat] 611+ messages in thread

* [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths
@ 2026-06-01 22:41 Andrey Chernyy <andrey.cherny@tantorlabs.com>
  0 siblings, 0 replies; 611+ messages in thread

From: Andrey Chernyy @ 2026-06-01 22:41 UTC (permalink / raw)

pgxml_xpath() builds an xpath_workspace before returning it to
callers.  If an ERROR is thrown before the function returns, callers
have not received the workspace pointer yet and cannot run
cleanup_workspace().

Add local error cleanup for the partially built workspace and the
compiled XPath expression.  Also check xmlXPathNewContext() before
dereferencing the returned context.
---
 contrib/xml2/xpath.c | 51 +++++++++++++++++++++++++++-----------------
 1 file changed, 32 insertions(+), 19 deletions(-)

diff --git a/contrib/xml2/xpath.c b/contrib/xml2/xpath.c
index 9fe75cb5ff4..283bb51178d 100644
--- a/contrib/xml2/xpath.c
+++ b/contrib/xml2/xpath.c
@@ -497,36 +497,49 @@ static xpath_workspace *
 pgxml_xpath(text *document, xmlChar *xpath, PgXmlErrorContext *xmlerrcxt)
 {
 	int32		docsize = VARSIZE_ANY_EXHDR(document);
-	xmlXPathCompExprPtr comppath;
+	xmlXPathCompExprPtr volatile comppath = NULL;
 	xpath_workspace *workspace = palloc0_object(xpath_workspace);
 
 	workspace->doctree = NULL;
 	workspace->ctxt = NULL;
 	workspace->res = NULL;
 
-	workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
-									   docsize, NULL, NULL,
-									   XML_PARSE_NOENT);
-	if (workspace->doctree != NULL)
+	PG_TRY();
 	{
-		workspace->ctxt = xmlXPathNewContext(workspace->doctree);
-		workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
-
-		/* compile the path */
-		comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
-		if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+		workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
+										   docsize, NULL, NULL,
+										   XML_PARSE_NOENT);
+		if (workspace->doctree != NULL)
 		{
-			if (comppath != NULL)
-				xmlXPathFreeCompExpr(comppath);
-			xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
-						"XPath Syntax Error");
-		}
+			workspace->ctxt = xmlXPathNewContext(workspace->doctree);
+			if (workspace->ctxt == NULL)
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_OUT_OF_MEMORY,
+							"could not allocate XPath context");
 
-		/* Now evaluate the path expression. */
-		workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+			workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
+
+			/* compile the path */
+			comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
+			if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
+							"XPath Syntax Error");
+
+			/* Now evaluate the path expression. */
+			workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+
+			xmlXPathFreeCompExpr(comppath);
+			comppath = NULL;
+		}
+	}
+	PG_CATCH();
+	{
+		if (comppath != NULL)
+			xmlXPathFreeCompExpr(comppath);
+		cleanup_workspace(workspace);
 
-		xmlXPathFreeCompExpr(comppath);
+		PG_RE_THROW();
 	}
+	PG_END_TRY();
 
 	return workspace;
 }
-- 
2.54.0


--MP_/LMSk9=uMhuQ1QiIJDarDO8G--





^ permalink  raw  reply  [nested|flat] 611+ messages in thread

* [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths
@ 2026-06-01 22:41 Andrey Chernyy <andrey.cherny@tantorlabs.com>
  0 siblings, 0 replies; 611+ messages in thread

From: Andrey Chernyy @ 2026-06-01 22:41 UTC (permalink / raw)

pgxml_xpath() builds an xpath_workspace before returning it to
callers.  If an ERROR is thrown before the function returns, callers
have not received the workspace pointer yet and cannot run
cleanup_workspace().

Add local error cleanup for the partially built workspace and the
compiled XPath expression.  Also check xmlXPathNewContext() before
dereferencing the returned context.
---
 contrib/xml2/xpath.c | 51 +++++++++++++++++++++++++++-----------------
 1 file changed, 32 insertions(+), 19 deletions(-)

diff --git a/contrib/xml2/xpath.c b/contrib/xml2/xpath.c
index 9fe75cb5ff4..283bb51178d 100644
--- a/contrib/xml2/xpath.c
+++ b/contrib/xml2/xpath.c
@@ -497,36 +497,49 @@ static xpath_workspace *
 pgxml_xpath(text *document, xmlChar *xpath, PgXmlErrorContext *xmlerrcxt)
 {
 	int32		docsize = VARSIZE_ANY_EXHDR(document);
-	xmlXPathCompExprPtr comppath;
+	xmlXPathCompExprPtr volatile comppath = NULL;
 	xpath_workspace *workspace = palloc0_object(xpath_workspace);
 
 	workspace->doctree = NULL;
 	workspace->ctxt = NULL;
 	workspace->res = NULL;
 
-	workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
-									   docsize, NULL, NULL,
-									   XML_PARSE_NOENT);
-	if (workspace->doctree != NULL)
+	PG_TRY();
 	{
-		workspace->ctxt = xmlXPathNewContext(workspace->doctree);
-		workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
-
-		/* compile the path */
-		comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
-		if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+		workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
+										   docsize, NULL, NULL,
+										   XML_PARSE_NOENT);
+		if (workspace->doctree != NULL)
 		{
-			if (comppath != NULL)
-				xmlXPathFreeCompExpr(comppath);
-			xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
-						"XPath Syntax Error");
-		}
+			workspace->ctxt = xmlXPathNewContext(workspace->doctree);
+			if (workspace->ctxt == NULL)
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_OUT_OF_MEMORY,
+							"could not allocate XPath context");
 
-		/* Now evaluate the path expression. */
-		workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+			workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
+
+			/* compile the path */
+			comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
+			if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
+							"XPath Syntax Error");
+
+			/* Now evaluate the path expression. */
+			workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+
+			xmlXPathFreeCompExpr(comppath);
+			comppath = NULL;
+		}
+	}
+	PG_CATCH();
+	{
+		if (comppath != NULL)
+			xmlXPathFreeCompExpr(comppath);
+		cleanup_workspace(workspace);
 
-		xmlXPathFreeCompExpr(comppath);
+		PG_RE_THROW();
 	}
+	PG_END_TRY();
 
 	return workspace;
 }
-- 
2.54.0


--MP_/LMSk9=uMhuQ1QiIJDarDO8G--





^ permalink  raw  reply  [nested|flat] 611+ messages in thread

* [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths
@ 2026-06-01 22:41 Andrey Chernyy <andrey.cherny@tantorlabs.com>
  0 siblings, 0 replies; 611+ messages in thread

From: Andrey Chernyy @ 2026-06-01 22:41 UTC (permalink / raw)

pgxml_xpath() builds an xpath_workspace before returning it to
callers.  If an ERROR is thrown before the function returns, callers
have not received the workspace pointer yet and cannot run
cleanup_workspace().

Add local error cleanup for the partially built workspace and the
compiled XPath expression.  Also check xmlXPathNewContext() before
dereferencing the returned context.
---
 contrib/xml2/xpath.c | 51 +++++++++++++++++++++++++++-----------------
 1 file changed, 32 insertions(+), 19 deletions(-)

diff --git a/contrib/xml2/xpath.c b/contrib/xml2/xpath.c
index 9fe75cb5ff4..283bb51178d 100644
--- a/contrib/xml2/xpath.c
+++ b/contrib/xml2/xpath.c
@@ -497,36 +497,49 @@ static xpath_workspace *
 pgxml_xpath(text *document, xmlChar *xpath, PgXmlErrorContext *xmlerrcxt)
 {
 	int32		docsize = VARSIZE_ANY_EXHDR(document);
-	xmlXPathCompExprPtr comppath;
+	xmlXPathCompExprPtr volatile comppath = NULL;
 	xpath_workspace *workspace = palloc0_object(xpath_workspace);
 
 	workspace->doctree = NULL;
 	workspace->ctxt = NULL;
 	workspace->res = NULL;
 
-	workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
-									   docsize, NULL, NULL,
-									   XML_PARSE_NOENT);
-	if (workspace->doctree != NULL)
+	PG_TRY();
 	{
-		workspace->ctxt = xmlXPathNewContext(workspace->doctree);
-		workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
-
-		/* compile the path */
-		comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
-		if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+		workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
+										   docsize, NULL, NULL,
+										   XML_PARSE_NOENT);
+		if (workspace->doctree != NULL)
 		{
-			if (comppath != NULL)
-				xmlXPathFreeCompExpr(comppath);
-			xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
-						"XPath Syntax Error");
-		}
+			workspace->ctxt = xmlXPathNewContext(workspace->doctree);
+			if (workspace->ctxt == NULL)
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_OUT_OF_MEMORY,
+							"could not allocate XPath context");
 
-		/* Now evaluate the path expression. */
-		workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+			workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
+
+			/* compile the path */
+			comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
+			if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
+							"XPath Syntax Error");
+
+			/* Now evaluate the path expression. */
+			workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+
+			xmlXPathFreeCompExpr(comppath);
+			comppath = NULL;
+		}
+	}
+	PG_CATCH();
+	{
+		if (comppath != NULL)
+			xmlXPathFreeCompExpr(comppath);
+		cleanup_workspace(workspace);
 
-		xmlXPathFreeCompExpr(comppath);
+		PG_RE_THROW();
 	}
+	PG_END_TRY();
 
 	return workspace;
 }
-- 
2.54.0


--MP_/LMSk9=uMhuQ1QiIJDarDO8G--





^ permalink  raw  reply  [nested|flat] 611+ messages in thread

* [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths
@ 2026-06-01 22:41 Andrey Chernyy <andrey.cherny@tantorlabs.com>
  0 siblings, 0 replies; 611+ messages in thread

From: Andrey Chernyy @ 2026-06-01 22:41 UTC (permalink / raw)

pgxml_xpath() builds an xpath_workspace before returning it to
callers.  If an ERROR is thrown before the function returns, callers
have not received the workspace pointer yet and cannot run
cleanup_workspace().

Add local error cleanup for the partially built workspace and the
compiled XPath expression.  Also check xmlXPathNewContext() before
dereferencing the returned context.
---
 contrib/xml2/xpath.c | 51 +++++++++++++++++++++++++++-----------------
 1 file changed, 32 insertions(+), 19 deletions(-)

diff --git a/contrib/xml2/xpath.c b/contrib/xml2/xpath.c
index 9fe75cb5ff4..283bb51178d 100644
--- a/contrib/xml2/xpath.c
+++ b/contrib/xml2/xpath.c
@@ -497,36 +497,49 @@ static xpath_workspace *
 pgxml_xpath(text *document, xmlChar *xpath, PgXmlErrorContext *xmlerrcxt)
 {
 	int32		docsize = VARSIZE_ANY_EXHDR(document);
-	xmlXPathCompExprPtr comppath;
+	xmlXPathCompExprPtr volatile comppath = NULL;
 	xpath_workspace *workspace = palloc0_object(xpath_workspace);
 
 	workspace->doctree = NULL;
 	workspace->ctxt = NULL;
 	workspace->res = NULL;
 
-	workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
-									   docsize, NULL, NULL,
-									   XML_PARSE_NOENT);
-	if (workspace->doctree != NULL)
+	PG_TRY();
 	{
-		workspace->ctxt = xmlXPathNewContext(workspace->doctree);
-		workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
-
-		/* compile the path */
-		comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
-		if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+		workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
+										   docsize, NULL, NULL,
+										   XML_PARSE_NOENT);
+		if (workspace->doctree != NULL)
 		{
-			if (comppath != NULL)
-				xmlXPathFreeCompExpr(comppath);
-			xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
-						"XPath Syntax Error");
-		}
+			workspace->ctxt = xmlXPathNewContext(workspace->doctree);
+			if (workspace->ctxt == NULL)
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_OUT_OF_MEMORY,
+							"could not allocate XPath context");
 
-		/* Now evaluate the path expression. */
-		workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+			workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
+
+			/* compile the path */
+			comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
+			if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
+							"XPath Syntax Error");
+
+			/* Now evaluate the path expression. */
+			workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+
+			xmlXPathFreeCompExpr(comppath);
+			comppath = NULL;
+		}
+	}
+	PG_CATCH();
+	{
+		if (comppath != NULL)
+			xmlXPathFreeCompExpr(comppath);
+		cleanup_workspace(workspace);
 
-		xmlXPathFreeCompExpr(comppath);
+		PG_RE_THROW();
 	}
+	PG_END_TRY();
 
 	return workspace;
 }
-- 
2.54.0


--MP_/LMSk9=uMhuQ1QiIJDarDO8G--






^ permalink  raw  reply  [nested|flat] 611+ messages in thread

* [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths
@ 2026-06-01 22:41 Andrey Chernyy <andrey.cherny@tantorlabs.com>
  0 siblings, 0 replies; 611+ messages in thread

From: Andrey Chernyy @ 2026-06-01 22:41 UTC (permalink / raw)

pgxml_xpath() builds an xpath_workspace before returning it to
callers.  If an ERROR is thrown before the function returns, callers
have not received the workspace pointer yet and cannot run
cleanup_workspace().

Add local error cleanup for the partially built workspace and the
compiled XPath expression.  Also check xmlXPathNewContext() before
dereferencing the returned context.
---
 contrib/xml2/xpath.c | 51 +++++++++++++++++++++++++++-----------------
 1 file changed, 32 insertions(+), 19 deletions(-)

diff --git a/contrib/xml2/xpath.c b/contrib/xml2/xpath.c
index 9fe75cb5ff4..283bb51178d 100644
--- a/contrib/xml2/xpath.c
+++ b/contrib/xml2/xpath.c
@@ -497,36 +497,49 @@ static xpath_workspace *
 pgxml_xpath(text *document, xmlChar *xpath, PgXmlErrorContext *xmlerrcxt)
 {
 	int32		docsize = VARSIZE_ANY_EXHDR(document);
-	xmlXPathCompExprPtr comppath;
+	xmlXPathCompExprPtr volatile comppath = NULL;
 	xpath_workspace *workspace = palloc0_object(xpath_workspace);
 
 	workspace->doctree = NULL;
 	workspace->ctxt = NULL;
 	workspace->res = NULL;
 
-	workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
-									   docsize, NULL, NULL,
-									   XML_PARSE_NOENT);
-	if (workspace->doctree != NULL)
+	PG_TRY();
 	{
-		workspace->ctxt = xmlXPathNewContext(workspace->doctree);
-		workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
-
-		/* compile the path */
-		comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
-		if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+		workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
+										   docsize, NULL, NULL,
+										   XML_PARSE_NOENT);
+		if (workspace->doctree != NULL)
 		{
-			if (comppath != NULL)
-				xmlXPathFreeCompExpr(comppath);
-			xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
-						"XPath Syntax Error");
-		}
+			workspace->ctxt = xmlXPathNewContext(workspace->doctree);
+			if (workspace->ctxt == NULL)
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_OUT_OF_MEMORY,
+							"could not allocate XPath context");
 
-		/* Now evaluate the path expression. */
-		workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+			workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
+
+			/* compile the path */
+			comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
+			if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
+							"XPath Syntax Error");
+
+			/* Now evaluate the path expression. */
+			workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+
+			xmlXPathFreeCompExpr(comppath);
+			comppath = NULL;
+		}
+	}
+	PG_CATCH();
+	{
+		if (comppath != NULL)
+			xmlXPathFreeCompExpr(comppath);
+		cleanup_workspace(workspace);
 
-		xmlXPathFreeCompExpr(comppath);
+		PG_RE_THROW();
 	}
+	PG_END_TRY();
 
 	return workspace;
 }
-- 
2.54.0


--MP_/LMSk9=uMhuQ1QiIJDarDO8G--






^ permalink  raw  reply  [nested|flat] 611+ messages in thread

* [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths
@ 2026-06-01 22:41 Andrey Chernyy <andrey.cherny@tantorlabs.com>
  0 siblings, 0 replies; 611+ messages in thread

From: Andrey Chernyy @ 2026-06-01 22:41 UTC (permalink / raw)

pgxml_xpath() builds an xpath_workspace before returning it to
callers.  If an ERROR is thrown before the function returns, callers
have not received the workspace pointer yet and cannot run
cleanup_workspace().

Add local error cleanup for the partially built workspace and the
compiled XPath expression.  Also check xmlXPathNewContext() before
dereferencing the returned context.
---
 contrib/xml2/xpath.c | 51 +++++++++++++++++++++++++++-----------------
 1 file changed, 32 insertions(+), 19 deletions(-)

diff --git a/contrib/xml2/xpath.c b/contrib/xml2/xpath.c
index 9fe75cb5ff4..283bb51178d 100644
--- a/contrib/xml2/xpath.c
+++ b/contrib/xml2/xpath.c
@@ -497,36 +497,49 @@ static xpath_workspace *
 pgxml_xpath(text *document, xmlChar *xpath, PgXmlErrorContext *xmlerrcxt)
 {
 	int32		docsize = VARSIZE_ANY_EXHDR(document);
-	xmlXPathCompExprPtr comppath;
+	xmlXPathCompExprPtr volatile comppath = NULL;
 	xpath_workspace *workspace = palloc0_object(xpath_workspace);
 
 	workspace->doctree = NULL;
 	workspace->ctxt = NULL;
 	workspace->res = NULL;
 
-	workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
-									   docsize, NULL, NULL,
-									   XML_PARSE_NOENT);
-	if (workspace->doctree != NULL)
+	PG_TRY();
 	{
-		workspace->ctxt = xmlXPathNewContext(workspace->doctree);
-		workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
-
-		/* compile the path */
-		comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
-		if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+		workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
+										   docsize, NULL, NULL,
+										   XML_PARSE_NOENT);
+		if (workspace->doctree != NULL)
 		{
-			if (comppath != NULL)
-				xmlXPathFreeCompExpr(comppath);
-			xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
-						"XPath Syntax Error");
-		}
+			workspace->ctxt = xmlXPathNewContext(workspace->doctree);
+			if (workspace->ctxt == NULL)
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_OUT_OF_MEMORY,
+							"could not allocate XPath context");
 
-		/* Now evaluate the path expression. */
-		workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+			workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
+
+			/* compile the path */
+			comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
+			if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
+							"XPath Syntax Error");
+
+			/* Now evaluate the path expression. */
+			workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+
+			xmlXPathFreeCompExpr(comppath);
+			comppath = NULL;
+		}
+	}
+	PG_CATCH();
+	{
+		if (comppath != NULL)
+			xmlXPathFreeCompExpr(comppath);
+		cleanup_workspace(workspace);
 
-		xmlXPathFreeCompExpr(comppath);
+		PG_RE_THROW();
 	}
+	PG_END_TRY();
 
 	return workspace;
 }
-- 
2.54.0


--MP_/LMSk9=uMhuQ1QiIJDarDO8G--






^ permalink  raw  reply  [nested|flat] 611+ messages in thread

* [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths
@ 2026-06-01 22:41 Andrey Chernyy <andrey.cherny@tantorlabs.com>
  0 siblings, 0 replies; 611+ messages in thread

From: Andrey Chernyy @ 2026-06-01 22:41 UTC (permalink / raw)

pgxml_xpath() builds an xpath_workspace before returning it to
callers.  If an ERROR is thrown before the function returns, callers
have not received the workspace pointer yet and cannot run
cleanup_workspace().

Add local error cleanup for the partially built workspace and the
compiled XPath expression.  Also check xmlXPathNewContext() before
dereferencing the returned context.
---
 contrib/xml2/xpath.c | 51 +++++++++++++++++++++++++++-----------------
 1 file changed, 32 insertions(+), 19 deletions(-)

diff --git a/contrib/xml2/xpath.c b/contrib/xml2/xpath.c
index 9fe75cb5ff4..283bb51178d 100644
--- a/contrib/xml2/xpath.c
+++ b/contrib/xml2/xpath.c
@@ -497,36 +497,49 @@ static xpath_workspace *
 pgxml_xpath(text *document, xmlChar *xpath, PgXmlErrorContext *xmlerrcxt)
 {
 	int32		docsize = VARSIZE_ANY_EXHDR(document);
-	xmlXPathCompExprPtr comppath;
+	xmlXPathCompExprPtr volatile comppath = NULL;
 	xpath_workspace *workspace = palloc0_object(xpath_workspace);
 
 	workspace->doctree = NULL;
 	workspace->ctxt = NULL;
 	workspace->res = NULL;
 
-	workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
-									   docsize, NULL, NULL,
-									   XML_PARSE_NOENT);
-	if (workspace->doctree != NULL)
+	PG_TRY();
 	{
-		workspace->ctxt = xmlXPathNewContext(workspace->doctree);
-		workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
-
-		/* compile the path */
-		comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
-		if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+		workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
+										   docsize, NULL, NULL,
+										   XML_PARSE_NOENT);
+		if (workspace->doctree != NULL)
 		{
-			if (comppath != NULL)
-				xmlXPathFreeCompExpr(comppath);
-			xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
-						"XPath Syntax Error");
-		}
+			workspace->ctxt = xmlXPathNewContext(workspace->doctree);
+			if (workspace->ctxt == NULL)
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_OUT_OF_MEMORY,
+							"could not allocate XPath context");
 
-		/* Now evaluate the path expression. */
-		workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+			workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
+
+			/* compile the path */
+			comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
+			if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
+							"XPath Syntax Error");
+
+			/* Now evaluate the path expression. */
+			workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+
+			xmlXPathFreeCompExpr(comppath);
+			comppath = NULL;
+		}
+	}
+	PG_CATCH();
+	{
+		if (comppath != NULL)
+			xmlXPathFreeCompExpr(comppath);
+		cleanup_workspace(workspace);
 
-		xmlXPathFreeCompExpr(comppath);
+		PG_RE_THROW();
 	}
+	PG_END_TRY();
 
 	return workspace;
 }
-- 
2.54.0


--MP_/LMSk9=uMhuQ1QiIJDarDO8G--






^ permalink  raw  reply  [nested|flat] 611+ messages in thread

* [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths
@ 2026-06-01 22:41 Andrey Chernyy <andrey.cherny@tantorlabs.com>
  0 siblings, 0 replies; 611+ messages in thread

From: Andrey Chernyy @ 2026-06-01 22:41 UTC (permalink / raw)

pgxml_xpath() builds an xpath_workspace before returning it to
callers.  If an ERROR is thrown before the function returns, callers
have not received the workspace pointer yet and cannot run
cleanup_workspace().

Add local error cleanup for the partially built workspace and the
compiled XPath expression.  Also check xmlXPathNewContext() before
dereferencing the returned context.
---
 contrib/xml2/xpath.c | 51 +++++++++++++++++++++++++++-----------------
 1 file changed, 32 insertions(+), 19 deletions(-)

diff --git a/contrib/xml2/xpath.c b/contrib/xml2/xpath.c
index 9fe75cb5ff4..283bb51178d 100644
--- a/contrib/xml2/xpath.c
+++ b/contrib/xml2/xpath.c
@@ -497,36 +497,49 @@ static xpath_workspace *
 pgxml_xpath(text *document, xmlChar *xpath, PgXmlErrorContext *xmlerrcxt)
 {
 	int32		docsize = VARSIZE_ANY_EXHDR(document);
-	xmlXPathCompExprPtr comppath;
+	xmlXPathCompExprPtr volatile comppath = NULL;
 	xpath_workspace *workspace = palloc0_object(xpath_workspace);
 
 	workspace->doctree = NULL;
 	workspace->ctxt = NULL;
 	workspace->res = NULL;
 
-	workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
-									   docsize, NULL, NULL,
-									   XML_PARSE_NOENT);
-	if (workspace->doctree != NULL)
+	PG_TRY();
 	{
-		workspace->ctxt = xmlXPathNewContext(workspace->doctree);
-		workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
-
-		/* compile the path */
-		comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
-		if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+		workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
+										   docsize, NULL, NULL,
+										   XML_PARSE_NOENT);
+		if (workspace->doctree != NULL)
 		{
-			if (comppath != NULL)
-				xmlXPathFreeCompExpr(comppath);
-			xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
-						"XPath Syntax Error");
-		}
+			workspace->ctxt = xmlXPathNewContext(workspace->doctree);
+			if (workspace->ctxt == NULL)
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_OUT_OF_MEMORY,
+							"could not allocate XPath context");
 
-		/* Now evaluate the path expression. */
-		workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+			workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
+
+			/* compile the path */
+			comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
+			if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
+							"XPath Syntax Error");
+
+			/* Now evaluate the path expression. */
+			workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+
+			xmlXPathFreeCompExpr(comppath);
+			comppath = NULL;
+		}
+	}
+	PG_CATCH();
+	{
+		if (comppath != NULL)
+			xmlXPathFreeCompExpr(comppath);
+		cleanup_workspace(workspace);
 
-		xmlXPathFreeCompExpr(comppath);
+		PG_RE_THROW();
 	}
+	PG_END_TRY();
 
 	return workspace;
 }
-- 
2.54.0


--MP_/LMSk9=uMhuQ1QiIJDarDO8G--





^ permalink  raw  reply  [nested|flat] 611+ messages in thread

* [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths
@ 2026-06-01 22:41 Andrey Chernyy <andrey.cherny@tantorlabs.com>
  0 siblings, 0 replies; 611+ messages in thread

From: Andrey Chernyy @ 2026-06-01 22:41 UTC (permalink / raw)

pgxml_xpath() builds an xpath_workspace before returning it to
callers.  If an ERROR is thrown before the function returns, callers
have not received the workspace pointer yet and cannot run
cleanup_workspace().

Add local error cleanup for the partially built workspace and the
compiled XPath expression.  Also check xmlXPathNewContext() before
dereferencing the returned context.
---
 contrib/xml2/xpath.c | 51 +++++++++++++++++++++++++++-----------------
 1 file changed, 32 insertions(+), 19 deletions(-)

diff --git a/contrib/xml2/xpath.c b/contrib/xml2/xpath.c
index 9fe75cb5ff4..283bb51178d 100644
--- a/contrib/xml2/xpath.c
+++ b/contrib/xml2/xpath.c
@@ -497,36 +497,49 @@ static xpath_workspace *
 pgxml_xpath(text *document, xmlChar *xpath, PgXmlErrorContext *xmlerrcxt)
 {
 	int32		docsize = VARSIZE_ANY_EXHDR(document);
-	xmlXPathCompExprPtr comppath;
+	xmlXPathCompExprPtr volatile comppath = NULL;
 	xpath_workspace *workspace = palloc0_object(xpath_workspace);
 
 	workspace->doctree = NULL;
 	workspace->ctxt = NULL;
 	workspace->res = NULL;
 
-	workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
-									   docsize, NULL, NULL,
-									   XML_PARSE_NOENT);
-	if (workspace->doctree != NULL)
+	PG_TRY();
 	{
-		workspace->ctxt = xmlXPathNewContext(workspace->doctree);
-		workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
-
-		/* compile the path */
-		comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
-		if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+		workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
+										   docsize, NULL, NULL,
+										   XML_PARSE_NOENT);
+		if (workspace->doctree != NULL)
 		{
-			if (comppath != NULL)
-				xmlXPathFreeCompExpr(comppath);
-			xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
-						"XPath Syntax Error");
-		}
+			workspace->ctxt = xmlXPathNewContext(workspace->doctree);
+			if (workspace->ctxt == NULL)
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_OUT_OF_MEMORY,
+							"could not allocate XPath context");
 
-		/* Now evaluate the path expression. */
-		workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+			workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
+
+			/* compile the path */
+			comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
+			if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
+							"XPath Syntax Error");
+
+			/* Now evaluate the path expression. */
+			workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+
+			xmlXPathFreeCompExpr(comppath);
+			comppath = NULL;
+		}
+	}
+	PG_CATCH();
+	{
+		if (comppath != NULL)
+			xmlXPathFreeCompExpr(comppath);
+		cleanup_workspace(workspace);
 
-		xmlXPathFreeCompExpr(comppath);
+		PG_RE_THROW();
 	}
+	PG_END_TRY();
 
 	return workspace;
 }
-- 
2.54.0


--MP_/LMSk9=uMhuQ1QiIJDarDO8G--






^ permalink  raw  reply  [nested|flat] 611+ messages in thread

* [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths
@ 2026-06-01 22:41 Andrey Chernyy <andrey.cherny@tantorlabs.com>
  0 siblings, 0 replies; 611+ messages in thread

From: Andrey Chernyy @ 2026-06-01 22:41 UTC (permalink / raw)

pgxml_xpath() builds an xpath_workspace before returning it to
callers.  If an ERROR is thrown before the function returns, callers
have not received the workspace pointer yet and cannot run
cleanup_workspace().

Add local error cleanup for the partially built workspace and the
compiled XPath expression.  Also check xmlXPathNewContext() before
dereferencing the returned context.
---
 contrib/xml2/xpath.c | 51 +++++++++++++++++++++++++++-----------------
 1 file changed, 32 insertions(+), 19 deletions(-)

diff --git a/contrib/xml2/xpath.c b/contrib/xml2/xpath.c
index 9fe75cb5ff4..283bb51178d 100644
--- a/contrib/xml2/xpath.c
+++ b/contrib/xml2/xpath.c
@@ -497,36 +497,49 @@ static xpath_workspace *
 pgxml_xpath(text *document, xmlChar *xpath, PgXmlErrorContext *xmlerrcxt)
 {
 	int32		docsize = VARSIZE_ANY_EXHDR(document);
-	xmlXPathCompExprPtr comppath;
+	xmlXPathCompExprPtr volatile comppath = NULL;
 	xpath_workspace *workspace = palloc0_object(xpath_workspace);
 
 	workspace->doctree = NULL;
 	workspace->ctxt = NULL;
 	workspace->res = NULL;
 
-	workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
-									   docsize, NULL, NULL,
-									   XML_PARSE_NOENT);
-	if (workspace->doctree != NULL)
+	PG_TRY();
 	{
-		workspace->ctxt = xmlXPathNewContext(workspace->doctree);
-		workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
-
-		/* compile the path */
-		comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
-		if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+		workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
+										   docsize, NULL, NULL,
+										   XML_PARSE_NOENT);
+		if (workspace->doctree != NULL)
 		{
-			if (comppath != NULL)
-				xmlXPathFreeCompExpr(comppath);
-			xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
-						"XPath Syntax Error");
-		}
+			workspace->ctxt = xmlXPathNewContext(workspace->doctree);
+			if (workspace->ctxt == NULL)
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_OUT_OF_MEMORY,
+							"could not allocate XPath context");
 
-		/* Now evaluate the path expression. */
-		workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+			workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
+
+			/* compile the path */
+			comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
+			if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
+							"XPath Syntax Error");
+
+			/* Now evaluate the path expression. */
+			workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+
+			xmlXPathFreeCompExpr(comppath);
+			comppath = NULL;
+		}
+	}
+	PG_CATCH();
+	{
+		if (comppath != NULL)
+			xmlXPathFreeCompExpr(comppath);
+		cleanup_workspace(workspace);
 
-		xmlXPathFreeCompExpr(comppath);
+		PG_RE_THROW();
 	}
+	PG_END_TRY();
 
 	return workspace;
 }
-- 
2.54.0


--MP_/LMSk9=uMhuQ1QiIJDarDO8G--





^ permalink  raw  reply  [nested|flat] 611+ messages in thread

* [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths
@ 2026-06-01 22:41 Andrey Chernyy <andrey.cherny@tantorlabs.com>
  0 siblings, 0 replies; 611+ messages in thread

From: Andrey Chernyy @ 2026-06-01 22:41 UTC (permalink / raw)

pgxml_xpath() builds an xpath_workspace before returning it to
callers.  If an ERROR is thrown before the function returns, callers
have not received the workspace pointer yet and cannot run
cleanup_workspace().

Add local error cleanup for the partially built workspace and the
compiled XPath expression.  Also check xmlXPathNewContext() before
dereferencing the returned context.
---
 contrib/xml2/xpath.c | 51 +++++++++++++++++++++++++++-----------------
 1 file changed, 32 insertions(+), 19 deletions(-)

diff --git a/contrib/xml2/xpath.c b/contrib/xml2/xpath.c
index 9fe75cb5ff4..283bb51178d 100644
--- a/contrib/xml2/xpath.c
+++ b/contrib/xml2/xpath.c
@@ -497,36 +497,49 @@ static xpath_workspace *
 pgxml_xpath(text *document, xmlChar *xpath, PgXmlErrorContext *xmlerrcxt)
 {
 	int32		docsize = VARSIZE_ANY_EXHDR(document);
-	xmlXPathCompExprPtr comppath;
+	xmlXPathCompExprPtr volatile comppath = NULL;
 	xpath_workspace *workspace = palloc0_object(xpath_workspace);
 
 	workspace->doctree = NULL;
 	workspace->ctxt = NULL;
 	workspace->res = NULL;
 
-	workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
-									   docsize, NULL, NULL,
-									   XML_PARSE_NOENT);
-	if (workspace->doctree != NULL)
+	PG_TRY();
 	{
-		workspace->ctxt = xmlXPathNewContext(workspace->doctree);
-		workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
-
-		/* compile the path */
-		comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
-		if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+		workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
+										   docsize, NULL, NULL,
+										   XML_PARSE_NOENT);
+		if (workspace->doctree != NULL)
 		{
-			if (comppath != NULL)
-				xmlXPathFreeCompExpr(comppath);
-			xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
-						"XPath Syntax Error");
-		}
+			workspace->ctxt = xmlXPathNewContext(workspace->doctree);
+			if (workspace->ctxt == NULL)
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_OUT_OF_MEMORY,
+							"could not allocate XPath context");
 
-		/* Now evaluate the path expression. */
-		workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+			workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
+
+			/* compile the path */
+			comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
+			if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
+							"XPath Syntax Error");
+
+			/* Now evaluate the path expression. */
+			workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+
+			xmlXPathFreeCompExpr(comppath);
+			comppath = NULL;
+		}
+	}
+	PG_CATCH();
+	{
+		if (comppath != NULL)
+			xmlXPathFreeCompExpr(comppath);
+		cleanup_workspace(workspace);
 
-		xmlXPathFreeCompExpr(comppath);
+		PG_RE_THROW();
 	}
+	PG_END_TRY();
 
 	return workspace;
 }
-- 
2.54.0


--MP_/LMSk9=uMhuQ1QiIJDarDO8G--





^ permalink  raw  reply  [nested|flat] 611+ messages in thread

* [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths
@ 2026-06-01 22:41 Andrey Chernyy <andrey.cherny@tantorlabs.com>
  0 siblings, 0 replies; 611+ messages in thread

From: Andrey Chernyy @ 2026-06-01 22:41 UTC (permalink / raw)

pgxml_xpath() builds an xpath_workspace before returning it to
callers.  If an ERROR is thrown before the function returns, callers
have not received the workspace pointer yet and cannot run
cleanup_workspace().

Add local error cleanup for the partially built workspace and the
compiled XPath expression.  Also check xmlXPathNewContext() before
dereferencing the returned context.
---
 contrib/xml2/xpath.c | 51 +++++++++++++++++++++++++++-----------------
 1 file changed, 32 insertions(+), 19 deletions(-)

diff --git a/contrib/xml2/xpath.c b/contrib/xml2/xpath.c
index 9fe75cb5ff4..283bb51178d 100644
--- a/contrib/xml2/xpath.c
+++ b/contrib/xml2/xpath.c
@@ -497,36 +497,49 @@ static xpath_workspace *
 pgxml_xpath(text *document, xmlChar *xpath, PgXmlErrorContext *xmlerrcxt)
 {
 	int32		docsize = VARSIZE_ANY_EXHDR(document);
-	xmlXPathCompExprPtr comppath;
+	xmlXPathCompExprPtr volatile comppath = NULL;
 	xpath_workspace *workspace = palloc0_object(xpath_workspace);
 
 	workspace->doctree = NULL;
 	workspace->ctxt = NULL;
 	workspace->res = NULL;
 
-	workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
-									   docsize, NULL, NULL,
-									   XML_PARSE_NOENT);
-	if (workspace->doctree != NULL)
+	PG_TRY();
 	{
-		workspace->ctxt = xmlXPathNewContext(workspace->doctree);
-		workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
-
-		/* compile the path */
-		comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
-		if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+		workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
+										   docsize, NULL, NULL,
+										   XML_PARSE_NOENT);
+		if (workspace->doctree != NULL)
 		{
-			if (comppath != NULL)
-				xmlXPathFreeCompExpr(comppath);
-			xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
-						"XPath Syntax Error");
-		}
+			workspace->ctxt = xmlXPathNewContext(workspace->doctree);
+			if (workspace->ctxt == NULL)
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_OUT_OF_MEMORY,
+							"could not allocate XPath context");
 
-		/* Now evaluate the path expression. */
-		workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+			workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
+
+			/* compile the path */
+			comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
+			if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
+							"XPath Syntax Error");
+
+			/* Now evaluate the path expression. */
+			workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+
+			xmlXPathFreeCompExpr(comppath);
+			comppath = NULL;
+		}
+	}
+	PG_CATCH();
+	{
+		if (comppath != NULL)
+			xmlXPathFreeCompExpr(comppath);
+		cleanup_workspace(workspace);
 
-		xmlXPathFreeCompExpr(comppath);
+		PG_RE_THROW();
 	}
+	PG_END_TRY();
 
 	return workspace;
 }
-- 
2.54.0


--MP_/LMSk9=uMhuQ1QiIJDarDO8G--






^ permalink  raw  reply  [nested|flat] 611+ messages in thread

* [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths
@ 2026-06-01 22:41 Andrey Chernyy <andrey.cherny@tantorlabs.com>
  0 siblings, 0 replies; 611+ messages in thread

From: Andrey Chernyy @ 2026-06-01 22:41 UTC (permalink / raw)

pgxml_xpath() builds an xpath_workspace before returning it to
callers.  If an ERROR is thrown before the function returns, callers
have not received the workspace pointer yet and cannot run
cleanup_workspace().

Add local error cleanup for the partially built workspace and the
compiled XPath expression.  Also check xmlXPathNewContext() before
dereferencing the returned context.
---
 contrib/xml2/xpath.c | 51 +++++++++++++++++++++++++++-----------------
 1 file changed, 32 insertions(+), 19 deletions(-)

diff --git a/contrib/xml2/xpath.c b/contrib/xml2/xpath.c
index 9fe75cb5ff4..283bb51178d 100644
--- a/contrib/xml2/xpath.c
+++ b/contrib/xml2/xpath.c
@@ -497,36 +497,49 @@ static xpath_workspace *
 pgxml_xpath(text *document, xmlChar *xpath, PgXmlErrorContext *xmlerrcxt)
 {
 	int32		docsize = VARSIZE_ANY_EXHDR(document);
-	xmlXPathCompExprPtr comppath;
+	xmlXPathCompExprPtr volatile comppath = NULL;
 	xpath_workspace *workspace = palloc0_object(xpath_workspace);
 
 	workspace->doctree = NULL;
 	workspace->ctxt = NULL;
 	workspace->res = NULL;
 
-	workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
-									   docsize, NULL, NULL,
-									   XML_PARSE_NOENT);
-	if (workspace->doctree != NULL)
+	PG_TRY();
 	{
-		workspace->ctxt = xmlXPathNewContext(workspace->doctree);
-		workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
-
-		/* compile the path */
-		comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
-		if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+		workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
+										   docsize, NULL, NULL,
+										   XML_PARSE_NOENT);
+		if (workspace->doctree != NULL)
 		{
-			if (comppath != NULL)
-				xmlXPathFreeCompExpr(comppath);
-			xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
-						"XPath Syntax Error");
-		}
+			workspace->ctxt = xmlXPathNewContext(workspace->doctree);
+			if (workspace->ctxt == NULL)
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_OUT_OF_MEMORY,
+							"could not allocate XPath context");
 
-		/* Now evaluate the path expression. */
-		workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+			workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
+
+			/* compile the path */
+			comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
+			if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
+							"XPath Syntax Error");
+
+			/* Now evaluate the path expression. */
+			workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+
+			xmlXPathFreeCompExpr(comppath);
+			comppath = NULL;
+		}
+	}
+	PG_CATCH();
+	{
+		if (comppath != NULL)
+			xmlXPathFreeCompExpr(comppath);
+		cleanup_workspace(workspace);
 
-		xmlXPathFreeCompExpr(comppath);
+		PG_RE_THROW();
 	}
+	PG_END_TRY();
 
 	return workspace;
 }
-- 
2.54.0


--MP_/LMSk9=uMhuQ1QiIJDarDO8G--





^ permalink  raw  reply  [nested|flat] 611+ messages in thread

* [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths
@ 2026-06-01 22:41 Andrey Chernyy <andrey.cherny@tantorlabs.com>
  0 siblings, 0 replies; 611+ messages in thread

From: Andrey Chernyy @ 2026-06-01 22:41 UTC (permalink / raw)

pgxml_xpath() builds an xpath_workspace before returning it to
callers.  If an ERROR is thrown before the function returns, callers
have not received the workspace pointer yet and cannot run
cleanup_workspace().

Add local error cleanup for the partially built workspace and the
compiled XPath expression.  Also check xmlXPathNewContext() before
dereferencing the returned context.
---
 contrib/xml2/xpath.c | 51 +++++++++++++++++++++++++++-----------------
 1 file changed, 32 insertions(+), 19 deletions(-)

diff --git a/contrib/xml2/xpath.c b/contrib/xml2/xpath.c
index 9fe75cb5ff4..283bb51178d 100644
--- a/contrib/xml2/xpath.c
+++ b/contrib/xml2/xpath.c
@@ -497,36 +497,49 @@ static xpath_workspace *
 pgxml_xpath(text *document, xmlChar *xpath, PgXmlErrorContext *xmlerrcxt)
 {
 	int32		docsize = VARSIZE_ANY_EXHDR(document);
-	xmlXPathCompExprPtr comppath;
+	xmlXPathCompExprPtr volatile comppath = NULL;
 	xpath_workspace *workspace = palloc0_object(xpath_workspace);
 
 	workspace->doctree = NULL;
 	workspace->ctxt = NULL;
 	workspace->res = NULL;
 
-	workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
-									   docsize, NULL, NULL,
-									   XML_PARSE_NOENT);
-	if (workspace->doctree != NULL)
+	PG_TRY();
 	{
-		workspace->ctxt = xmlXPathNewContext(workspace->doctree);
-		workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
-
-		/* compile the path */
-		comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
-		if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+		workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
+										   docsize, NULL, NULL,
+										   XML_PARSE_NOENT);
+		if (workspace->doctree != NULL)
 		{
-			if (comppath != NULL)
-				xmlXPathFreeCompExpr(comppath);
-			xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
-						"XPath Syntax Error");
-		}
+			workspace->ctxt = xmlXPathNewContext(workspace->doctree);
+			if (workspace->ctxt == NULL)
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_OUT_OF_MEMORY,
+							"could not allocate XPath context");
 
-		/* Now evaluate the path expression. */
-		workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+			workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
+
+			/* compile the path */
+			comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
+			if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
+							"XPath Syntax Error");
+
+			/* Now evaluate the path expression. */
+			workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+
+			xmlXPathFreeCompExpr(comppath);
+			comppath = NULL;
+		}
+	}
+	PG_CATCH();
+	{
+		if (comppath != NULL)
+			xmlXPathFreeCompExpr(comppath);
+		cleanup_workspace(workspace);
 
-		xmlXPathFreeCompExpr(comppath);
+		PG_RE_THROW();
 	}
+	PG_END_TRY();
 
 	return workspace;
 }
-- 
2.54.0


--MP_/LMSk9=uMhuQ1QiIJDarDO8G--





^ permalink  raw  reply  [nested|flat] 611+ messages in thread

* [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths
@ 2026-06-01 22:41 Andrey Chernyy <andrey.cherny@tantorlabs.com>
  0 siblings, 0 replies; 611+ messages in thread

From: Andrey Chernyy @ 2026-06-01 22:41 UTC (permalink / raw)

pgxml_xpath() builds an xpath_workspace before returning it to
callers.  If an ERROR is thrown before the function returns, callers
have not received the workspace pointer yet and cannot run
cleanup_workspace().

Add local error cleanup for the partially built workspace and the
compiled XPath expression.  Also check xmlXPathNewContext() before
dereferencing the returned context.
---
 contrib/xml2/xpath.c | 51 +++++++++++++++++++++++++++-----------------
 1 file changed, 32 insertions(+), 19 deletions(-)

diff --git a/contrib/xml2/xpath.c b/contrib/xml2/xpath.c
index 9fe75cb5ff4..283bb51178d 100644
--- a/contrib/xml2/xpath.c
+++ b/contrib/xml2/xpath.c
@@ -497,36 +497,49 @@ static xpath_workspace *
 pgxml_xpath(text *document, xmlChar *xpath, PgXmlErrorContext *xmlerrcxt)
 {
 	int32		docsize = VARSIZE_ANY_EXHDR(document);
-	xmlXPathCompExprPtr comppath;
+	xmlXPathCompExprPtr volatile comppath = NULL;
 	xpath_workspace *workspace = palloc0_object(xpath_workspace);
 
 	workspace->doctree = NULL;
 	workspace->ctxt = NULL;
 	workspace->res = NULL;
 
-	workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
-									   docsize, NULL, NULL,
-									   XML_PARSE_NOENT);
-	if (workspace->doctree != NULL)
+	PG_TRY();
 	{
-		workspace->ctxt = xmlXPathNewContext(workspace->doctree);
-		workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
-
-		/* compile the path */
-		comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
-		if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+		workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
+										   docsize, NULL, NULL,
+										   XML_PARSE_NOENT);
+		if (workspace->doctree != NULL)
 		{
-			if (comppath != NULL)
-				xmlXPathFreeCompExpr(comppath);
-			xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
-						"XPath Syntax Error");
-		}
+			workspace->ctxt = xmlXPathNewContext(workspace->doctree);
+			if (workspace->ctxt == NULL)
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_OUT_OF_MEMORY,
+							"could not allocate XPath context");
 
-		/* Now evaluate the path expression. */
-		workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+			workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
+
+			/* compile the path */
+			comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
+			if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
+							"XPath Syntax Error");
+
+			/* Now evaluate the path expression. */
+			workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+
+			xmlXPathFreeCompExpr(comppath);
+			comppath = NULL;
+		}
+	}
+	PG_CATCH();
+	{
+		if (comppath != NULL)
+			xmlXPathFreeCompExpr(comppath);
+		cleanup_workspace(workspace);
 
-		xmlXPathFreeCompExpr(comppath);
+		PG_RE_THROW();
 	}
+	PG_END_TRY();
 
 	return workspace;
 }
-- 
2.54.0


--MP_/LMSk9=uMhuQ1QiIJDarDO8G--






^ permalink  raw  reply  [nested|flat] 611+ messages in thread

* [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths
@ 2026-06-01 22:41 Andrey Chernyy <andrey.cherny@tantorlabs.com>
  0 siblings, 0 replies; 611+ messages in thread

From: Andrey Chernyy @ 2026-06-01 22:41 UTC (permalink / raw)

pgxml_xpath() builds an xpath_workspace before returning it to
callers.  If an ERROR is thrown before the function returns, callers
have not received the workspace pointer yet and cannot run
cleanup_workspace().

Add local error cleanup for the partially built workspace and the
compiled XPath expression.  Also check xmlXPathNewContext() before
dereferencing the returned context.
---
 contrib/xml2/xpath.c | 51 +++++++++++++++++++++++++++-----------------
 1 file changed, 32 insertions(+), 19 deletions(-)

diff --git a/contrib/xml2/xpath.c b/contrib/xml2/xpath.c
index 9fe75cb5ff4..283bb51178d 100644
--- a/contrib/xml2/xpath.c
+++ b/contrib/xml2/xpath.c
@@ -497,36 +497,49 @@ static xpath_workspace *
 pgxml_xpath(text *document, xmlChar *xpath, PgXmlErrorContext *xmlerrcxt)
 {
 	int32		docsize = VARSIZE_ANY_EXHDR(document);
-	xmlXPathCompExprPtr comppath;
+	xmlXPathCompExprPtr volatile comppath = NULL;
 	xpath_workspace *workspace = palloc0_object(xpath_workspace);
 
 	workspace->doctree = NULL;
 	workspace->ctxt = NULL;
 	workspace->res = NULL;
 
-	workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
-									   docsize, NULL, NULL,
-									   XML_PARSE_NOENT);
-	if (workspace->doctree != NULL)
+	PG_TRY();
 	{
-		workspace->ctxt = xmlXPathNewContext(workspace->doctree);
-		workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
-
-		/* compile the path */
-		comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
-		if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+		workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
+										   docsize, NULL, NULL,
+										   XML_PARSE_NOENT);
+		if (workspace->doctree != NULL)
 		{
-			if (comppath != NULL)
-				xmlXPathFreeCompExpr(comppath);
-			xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
-						"XPath Syntax Error");
-		}
+			workspace->ctxt = xmlXPathNewContext(workspace->doctree);
+			if (workspace->ctxt == NULL)
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_OUT_OF_MEMORY,
+							"could not allocate XPath context");
 
-		/* Now evaluate the path expression. */
-		workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+			workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
+
+			/* compile the path */
+			comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
+			if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
+							"XPath Syntax Error");
+
+			/* Now evaluate the path expression. */
+			workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+
+			xmlXPathFreeCompExpr(comppath);
+			comppath = NULL;
+		}
+	}
+	PG_CATCH();
+	{
+		if (comppath != NULL)
+			xmlXPathFreeCompExpr(comppath);
+		cleanup_workspace(workspace);
 
-		xmlXPathFreeCompExpr(comppath);
+		PG_RE_THROW();
 	}
+	PG_END_TRY();
 
 	return workspace;
 }
-- 
2.54.0


--MP_/LMSk9=uMhuQ1QiIJDarDO8G--





^ permalink  raw  reply  [nested|flat] 611+ messages in thread

* [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths
@ 2026-06-01 22:41 Andrey Chernyy <andrey.cherny@tantorlabs.com>
  0 siblings, 0 replies; 611+ messages in thread

From: Andrey Chernyy @ 2026-06-01 22:41 UTC (permalink / raw)

pgxml_xpath() builds an xpath_workspace before returning it to
callers.  If an ERROR is thrown before the function returns, callers
have not received the workspace pointer yet and cannot run
cleanup_workspace().

Add local error cleanup for the partially built workspace and the
compiled XPath expression.  Also check xmlXPathNewContext() before
dereferencing the returned context.
---
 contrib/xml2/xpath.c | 51 +++++++++++++++++++++++++++-----------------
 1 file changed, 32 insertions(+), 19 deletions(-)

diff --git a/contrib/xml2/xpath.c b/contrib/xml2/xpath.c
index 9fe75cb5ff4..283bb51178d 100644
--- a/contrib/xml2/xpath.c
+++ b/contrib/xml2/xpath.c
@@ -497,36 +497,49 @@ static xpath_workspace *
 pgxml_xpath(text *document, xmlChar *xpath, PgXmlErrorContext *xmlerrcxt)
 {
 	int32		docsize = VARSIZE_ANY_EXHDR(document);
-	xmlXPathCompExprPtr comppath;
+	xmlXPathCompExprPtr volatile comppath = NULL;
 	xpath_workspace *workspace = palloc0_object(xpath_workspace);
 
 	workspace->doctree = NULL;
 	workspace->ctxt = NULL;
 	workspace->res = NULL;
 
-	workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
-									   docsize, NULL, NULL,
-									   XML_PARSE_NOENT);
-	if (workspace->doctree != NULL)
+	PG_TRY();
 	{
-		workspace->ctxt = xmlXPathNewContext(workspace->doctree);
-		workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
-
-		/* compile the path */
-		comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
-		if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+		workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
+										   docsize, NULL, NULL,
+										   XML_PARSE_NOENT);
+		if (workspace->doctree != NULL)
 		{
-			if (comppath != NULL)
-				xmlXPathFreeCompExpr(comppath);
-			xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
-						"XPath Syntax Error");
-		}
+			workspace->ctxt = xmlXPathNewContext(workspace->doctree);
+			if (workspace->ctxt == NULL)
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_OUT_OF_MEMORY,
+							"could not allocate XPath context");
 
-		/* Now evaluate the path expression. */
-		workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+			workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
+
+			/* compile the path */
+			comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
+			if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
+							"XPath Syntax Error");
+
+			/* Now evaluate the path expression. */
+			workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+
+			xmlXPathFreeCompExpr(comppath);
+			comppath = NULL;
+		}
+	}
+	PG_CATCH();
+	{
+		if (comppath != NULL)
+			xmlXPathFreeCompExpr(comppath);
+		cleanup_workspace(workspace);
 
-		xmlXPathFreeCompExpr(comppath);
+		PG_RE_THROW();
 	}
+	PG_END_TRY();
 
 	return workspace;
 }
-- 
2.54.0


--MP_/LMSk9=uMhuQ1QiIJDarDO8G--





^ permalink  raw  reply  [nested|flat] 611+ messages in thread

* [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths
@ 2026-06-01 22:41 Andrey Chernyy <andrey.cherny@tantorlabs.com>
  0 siblings, 0 replies; 611+ messages in thread

From: Andrey Chernyy @ 2026-06-01 22:41 UTC (permalink / raw)

pgxml_xpath() builds an xpath_workspace before returning it to
callers.  If an ERROR is thrown before the function returns, callers
have not received the workspace pointer yet and cannot run
cleanup_workspace().

Add local error cleanup for the partially built workspace and the
compiled XPath expression.  Also check xmlXPathNewContext() before
dereferencing the returned context.
---
 contrib/xml2/xpath.c | 51 +++++++++++++++++++++++++++-----------------
 1 file changed, 32 insertions(+), 19 deletions(-)

diff --git a/contrib/xml2/xpath.c b/contrib/xml2/xpath.c
index 9fe75cb5ff4..283bb51178d 100644
--- a/contrib/xml2/xpath.c
+++ b/contrib/xml2/xpath.c
@@ -497,36 +497,49 @@ static xpath_workspace *
 pgxml_xpath(text *document, xmlChar *xpath, PgXmlErrorContext *xmlerrcxt)
 {
 	int32		docsize = VARSIZE_ANY_EXHDR(document);
-	xmlXPathCompExprPtr comppath;
+	xmlXPathCompExprPtr volatile comppath = NULL;
 	xpath_workspace *workspace = palloc0_object(xpath_workspace);
 
 	workspace->doctree = NULL;
 	workspace->ctxt = NULL;
 	workspace->res = NULL;
 
-	workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
-									   docsize, NULL, NULL,
-									   XML_PARSE_NOENT);
-	if (workspace->doctree != NULL)
+	PG_TRY();
 	{
-		workspace->ctxt = xmlXPathNewContext(workspace->doctree);
-		workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
-
-		/* compile the path */
-		comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
-		if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+		workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
+										   docsize, NULL, NULL,
+										   XML_PARSE_NOENT);
+		if (workspace->doctree != NULL)
 		{
-			if (comppath != NULL)
-				xmlXPathFreeCompExpr(comppath);
-			xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
-						"XPath Syntax Error");
-		}
+			workspace->ctxt = xmlXPathNewContext(workspace->doctree);
+			if (workspace->ctxt == NULL)
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_OUT_OF_MEMORY,
+							"could not allocate XPath context");
 
-		/* Now evaluate the path expression. */
-		workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+			workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
+
+			/* compile the path */
+			comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
+			if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
+							"XPath Syntax Error");
+
+			/* Now evaluate the path expression. */
+			workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+
+			xmlXPathFreeCompExpr(comppath);
+			comppath = NULL;
+		}
+	}
+	PG_CATCH();
+	{
+		if (comppath != NULL)
+			xmlXPathFreeCompExpr(comppath);
+		cleanup_workspace(workspace);
 
-		xmlXPathFreeCompExpr(comppath);
+		PG_RE_THROW();
 	}
+	PG_END_TRY();
 
 	return workspace;
 }
-- 
2.54.0


--MP_/LMSk9=uMhuQ1QiIJDarDO8G--





^ permalink  raw  reply  [nested|flat] 611+ messages in thread

* [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths
@ 2026-06-01 22:41 Andrey Chernyy <andrey.cherny@tantorlabs.com>
  0 siblings, 0 replies; 611+ messages in thread

From: Andrey Chernyy @ 2026-06-01 22:41 UTC (permalink / raw)

pgxml_xpath() builds an xpath_workspace before returning it to
callers.  If an ERROR is thrown before the function returns, callers
have not received the workspace pointer yet and cannot run
cleanup_workspace().

Add local error cleanup for the partially built workspace and the
compiled XPath expression.  Also check xmlXPathNewContext() before
dereferencing the returned context.
---
 contrib/xml2/xpath.c | 51 +++++++++++++++++++++++++++-----------------
 1 file changed, 32 insertions(+), 19 deletions(-)

diff --git a/contrib/xml2/xpath.c b/contrib/xml2/xpath.c
index 9fe75cb5ff4..283bb51178d 100644
--- a/contrib/xml2/xpath.c
+++ b/contrib/xml2/xpath.c
@@ -497,36 +497,49 @@ static xpath_workspace *
 pgxml_xpath(text *document, xmlChar *xpath, PgXmlErrorContext *xmlerrcxt)
 {
 	int32		docsize = VARSIZE_ANY_EXHDR(document);
-	xmlXPathCompExprPtr comppath;
+	xmlXPathCompExprPtr volatile comppath = NULL;
 	xpath_workspace *workspace = palloc0_object(xpath_workspace);
 
 	workspace->doctree = NULL;
 	workspace->ctxt = NULL;
 	workspace->res = NULL;
 
-	workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
-									   docsize, NULL, NULL,
-									   XML_PARSE_NOENT);
-	if (workspace->doctree != NULL)
+	PG_TRY();
 	{
-		workspace->ctxt = xmlXPathNewContext(workspace->doctree);
-		workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
-
-		/* compile the path */
-		comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
-		if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+		workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
+										   docsize, NULL, NULL,
+										   XML_PARSE_NOENT);
+		if (workspace->doctree != NULL)
 		{
-			if (comppath != NULL)
-				xmlXPathFreeCompExpr(comppath);
-			xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
-						"XPath Syntax Error");
-		}
+			workspace->ctxt = xmlXPathNewContext(workspace->doctree);
+			if (workspace->ctxt == NULL)
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_OUT_OF_MEMORY,
+							"could not allocate XPath context");
 
-		/* Now evaluate the path expression. */
-		workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+			workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
+
+			/* compile the path */
+			comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
+			if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
+							"XPath Syntax Error");
+
+			/* Now evaluate the path expression. */
+			workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+
+			xmlXPathFreeCompExpr(comppath);
+			comppath = NULL;
+		}
+	}
+	PG_CATCH();
+	{
+		if (comppath != NULL)
+			xmlXPathFreeCompExpr(comppath);
+		cleanup_workspace(workspace);
 
-		xmlXPathFreeCompExpr(comppath);
+		PG_RE_THROW();
 	}
+	PG_END_TRY();
 
 	return workspace;
 }
-- 
2.54.0


--MP_/LMSk9=uMhuQ1QiIJDarDO8G--





^ permalink  raw  reply  [nested|flat] 611+ messages in thread

* [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths
@ 2026-06-01 22:41 Andrey Chernyy <andrey.cherny@tantorlabs.com>
  0 siblings, 0 replies; 611+ messages in thread

From: Andrey Chernyy @ 2026-06-01 22:41 UTC (permalink / raw)

pgxml_xpath() builds an xpath_workspace before returning it to
callers.  If an ERROR is thrown before the function returns, callers
have not received the workspace pointer yet and cannot run
cleanup_workspace().

Add local error cleanup for the partially built workspace and the
compiled XPath expression.  Also check xmlXPathNewContext() before
dereferencing the returned context.
---
 contrib/xml2/xpath.c | 51 +++++++++++++++++++++++++++-----------------
 1 file changed, 32 insertions(+), 19 deletions(-)

diff --git a/contrib/xml2/xpath.c b/contrib/xml2/xpath.c
index 9fe75cb5ff4..283bb51178d 100644
--- a/contrib/xml2/xpath.c
+++ b/contrib/xml2/xpath.c
@@ -497,36 +497,49 @@ static xpath_workspace *
 pgxml_xpath(text *document, xmlChar *xpath, PgXmlErrorContext *xmlerrcxt)
 {
 	int32		docsize = VARSIZE_ANY_EXHDR(document);
-	xmlXPathCompExprPtr comppath;
+	xmlXPathCompExprPtr volatile comppath = NULL;
 	xpath_workspace *workspace = palloc0_object(xpath_workspace);
 
 	workspace->doctree = NULL;
 	workspace->ctxt = NULL;
 	workspace->res = NULL;
 
-	workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
-									   docsize, NULL, NULL,
-									   XML_PARSE_NOENT);
-	if (workspace->doctree != NULL)
+	PG_TRY();
 	{
-		workspace->ctxt = xmlXPathNewContext(workspace->doctree);
-		workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
-
-		/* compile the path */
-		comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
-		if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+		workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
+										   docsize, NULL, NULL,
+										   XML_PARSE_NOENT);
+		if (workspace->doctree != NULL)
 		{
-			if (comppath != NULL)
-				xmlXPathFreeCompExpr(comppath);
-			xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
-						"XPath Syntax Error");
-		}
+			workspace->ctxt = xmlXPathNewContext(workspace->doctree);
+			if (workspace->ctxt == NULL)
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_OUT_OF_MEMORY,
+							"could not allocate XPath context");
 
-		/* Now evaluate the path expression. */
-		workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+			workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
+
+			/* compile the path */
+			comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
+			if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
+							"XPath Syntax Error");
+
+			/* Now evaluate the path expression. */
+			workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+
+			xmlXPathFreeCompExpr(comppath);
+			comppath = NULL;
+		}
+	}
+	PG_CATCH();
+	{
+		if (comppath != NULL)
+			xmlXPathFreeCompExpr(comppath);
+		cleanup_workspace(workspace);
 
-		xmlXPathFreeCompExpr(comppath);
+		PG_RE_THROW();
 	}
+	PG_END_TRY();
 
 	return workspace;
 }
-- 
2.54.0


--MP_/LMSk9=uMhuQ1QiIJDarDO8G--





^ permalink  raw  reply  [nested|flat] 611+ messages in thread

* [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths
@ 2026-06-01 22:41 Andrey Chernyy <andrey.cherny@tantorlabs.com>
  0 siblings, 0 replies; 611+ messages in thread

From: Andrey Chernyy @ 2026-06-01 22:41 UTC (permalink / raw)

pgxml_xpath() builds an xpath_workspace before returning it to
callers.  If an ERROR is thrown before the function returns, callers
have not received the workspace pointer yet and cannot run
cleanup_workspace().

Add local error cleanup for the partially built workspace and the
compiled XPath expression.  Also check xmlXPathNewContext() before
dereferencing the returned context.
---
 contrib/xml2/xpath.c | 51 +++++++++++++++++++++++++++-----------------
 1 file changed, 32 insertions(+), 19 deletions(-)

diff --git a/contrib/xml2/xpath.c b/contrib/xml2/xpath.c
index 9fe75cb5ff4..283bb51178d 100644
--- a/contrib/xml2/xpath.c
+++ b/contrib/xml2/xpath.c
@@ -497,36 +497,49 @@ static xpath_workspace *
 pgxml_xpath(text *document, xmlChar *xpath, PgXmlErrorContext *xmlerrcxt)
 {
 	int32		docsize = VARSIZE_ANY_EXHDR(document);
-	xmlXPathCompExprPtr comppath;
+	xmlXPathCompExprPtr volatile comppath = NULL;
 	xpath_workspace *workspace = palloc0_object(xpath_workspace);
 
 	workspace->doctree = NULL;
 	workspace->ctxt = NULL;
 	workspace->res = NULL;
 
-	workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
-									   docsize, NULL, NULL,
-									   XML_PARSE_NOENT);
-	if (workspace->doctree != NULL)
+	PG_TRY();
 	{
-		workspace->ctxt = xmlXPathNewContext(workspace->doctree);
-		workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
-
-		/* compile the path */
-		comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
-		if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+		workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
+										   docsize, NULL, NULL,
+										   XML_PARSE_NOENT);
+		if (workspace->doctree != NULL)
 		{
-			if (comppath != NULL)
-				xmlXPathFreeCompExpr(comppath);
-			xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
-						"XPath Syntax Error");
-		}
+			workspace->ctxt = xmlXPathNewContext(workspace->doctree);
+			if (workspace->ctxt == NULL)
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_OUT_OF_MEMORY,
+							"could not allocate XPath context");
 
-		/* Now evaluate the path expression. */
-		workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+			workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
+
+			/* compile the path */
+			comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
+			if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
+							"XPath Syntax Error");
+
+			/* Now evaluate the path expression. */
+			workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+
+			xmlXPathFreeCompExpr(comppath);
+			comppath = NULL;
+		}
+	}
+	PG_CATCH();
+	{
+		if (comppath != NULL)
+			xmlXPathFreeCompExpr(comppath);
+		cleanup_workspace(workspace);
 
-		xmlXPathFreeCompExpr(comppath);
+		PG_RE_THROW();
 	}
+	PG_END_TRY();
 
 	return workspace;
 }
-- 
2.54.0


--MP_/LMSk9=uMhuQ1QiIJDarDO8G--





^ permalink  raw  reply  [nested|flat] 611+ messages in thread

* [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths
@ 2026-06-01 22:41 Andrey Chernyy <andrey.cherny@tantorlabs.com>
  0 siblings, 0 replies; 611+ messages in thread

From: Andrey Chernyy @ 2026-06-01 22:41 UTC (permalink / raw)

pgxml_xpath() builds an xpath_workspace before returning it to
callers.  If an ERROR is thrown before the function returns, callers
have not received the workspace pointer yet and cannot run
cleanup_workspace().

Add local error cleanup for the partially built workspace and the
compiled XPath expression.  Also check xmlXPathNewContext() before
dereferencing the returned context.
---
 contrib/xml2/xpath.c | 51 +++++++++++++++++++++++++++-----------------
 1 file changed, 32 insertions(+), 19 deletions(-)

diff --git a/contrib/xml2/xpath.c b/contrib/xml2/xpath.c
index 9fe75cb5ff4..283bb51178d 100644
--- a/contrib/xml2/xpath.c
+++ b/contrib/xml2/xpath.c
@@ -497,36 +497,49 @@ static xpath_workspace *
 pgxml_xpath(text *document, xmlChar *xpath, PgXmlErrorContext *xmlerrcxt)
 {
 	int32		docsize = VARSIZE_ANY_EXHDR(document);
-	xmlXPathCompExprPtr comppath;
+	xmlXPathCompExprPtr volatile comppath = NULL;
 	xpath_workspace *workspace = palloc0_object(xpath_workspace);
 
 	workspace->doctree = NULL;
 	workspace->ctxt = NULL;
 	workspace->res = NULL;
 
-	workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
-									   docsize, NULL, NULL,
-									   XML_PARSE_NOENT);
-	if (workspace->doctree != NULL)
+	PG_TRY();
 	{
-		workspace->ctxt = xmlXPathNewContext(workspace->doctree);
-		workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
-
-		/* compile the path */
-		comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
-		if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+		workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
+										   docsize, NULL, NULL,
+										   XML_PARSE_NOENT);
+		if (workspace->doctree != NULL)
 		{
-			if (comppath != NULL)
-				xmlXPathFreeCompExpr(comppath);
-			xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
-						"XPath Syntax Error");
-		}
+			workspace->ctxt = xmlXPathNewContext(workspace->doctree);
+			if (workspace->ctxt == NULL)
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_OUT_OF_MEMORY,
+							"could not allocate XPath context");
 
-		/* Now evaluate the path expression. */
-		workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+			workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
+
+			/* compile the path */
+			comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
+			if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
+							"XPath Syntax Error");
+
+			/* Now evaluate the path expression. */
+			workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+
+			xmlXPathFreeCompExpr(comppath);
+			comppath = NULL;
+		}
+	}
+	PG_CATCH();
+	{
+		if (comppath != NULL)
+			xmlXPathFreeCompExpr(comppath);
+		cleanup_workspace(workspace);
 
-		xmlXPathFreeCompExpr(comppath);
+		PG_RE_THROW();
 	}
+	PG_END_TRY();
 
 	return workspace;
 }
-- 
2.54.0


--MP_/LMSk9=uMhuQ1QiIJDarDO8G--






^ permalink  raw  reply  [nested|flat] 611+ messages in thread

* [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths
@ 2026-06-01 22:41 Andrey Chernyy <andrey.cherny@tantorlabs.com>
  0 siblings, 0 replies; 611+ messages in thread

From: Andrey Chernyy @ 2026-06-01 22:41 UTC (permalink / raw)

pgxml_xpath() builds an xpath_workspace before returning it to
callers.  If an ERROR is thrown before the function returns, callers
have not received the workspace pointer yet and cannot run
cleanup_workspace().

Add local error cleanup for the partially built workspace and the
compiled XPath expression.  Also check xmlXPathNewContext() before
dereferencing the returned context.
---
 contrib/xml2/xpath.c | 51 +++++++++++++++++++++++++++-----------------
 1 file changed, 32 insertions(+), 19 deletions(-)

diff --git a/contrib/xml2/xpath.c b/contrib/xml2/xpath.c
index 9fe75cb5ff4..283bb51178d 100644
--- a/contrib/xml2/xpath.c
+++ b/contrib/xml2/xpath.c
@@ -497,36 +497,49 @@ static xpath_workspace *
 pgxml_xpath(text *document, xmlChar *xpath, PgXmlErrorContext *xmlerrcxt)
 {
 	int32		docsize = VARSIZE_ANY_EXHDR(document);
-	xmlXPathCompExprPtr comppath;
+	xmlXPathCompExprPtr volatile comppath = NULL;
 	xpath_workspace *workspace = palloc0_object(xpath_workspace);
 
 	workspace->doctree = NULL;
 	workspace->ctxt = NULL;
 	workspace->res = NULL;
 
-	workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
-									   docsize, NULL, NULL,
-									   XML_PARSE_NOENT);
-	if (workspace->doctree != NULL)
+	PG_TRY();
 	{
-		workspace->ctxt = xmlXPathNewContext(workspace->doctree);
-		workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
-
-		/* compile the path */
-		comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
-		if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+		workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
+										   docsize, NULL, NULL,
+										   XML_PARSE_NOENT);
+		if (workspace->doctree != NULL)
 		{
-			if (comppath != NULL)
-				xmlXPathFreeCompExpr(comppath);
-			xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
-						"XPath Syntax Error");
-		}
+			workspace->ctxt = xmlXPathNewContext(workspace->doctree);
+			if (workspace->ctxt == NULL)
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_OUT_OF_MEMORY,
+							"could not allocate XPath context");
 
-		/* Now evaluate the path expression. */
-		workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+			workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
+
+			/* compile the path */
+			comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
+			if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
+							"XPath Syntax Error");
+
+			/* Now evaluate the path expression. */
+			workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+
+			xmlXPathFreeCompExpr(comppath);
+			comppath = NULL;
+		}
+	}
+	PG_CATCH();
+	{
+		if (comppath != NULL)
+			xmlXPathFreeCompExpr(comppath);
+		cleanup_workspace(workspace);
 
-		xmlXPathFreeCompExpr(comppath);
+		PG_RE_THROW();
 	}
+	PG_END_TRY();
 
 	return workspace;
 }
-- 
2.54.0


--MP_/LMSk9=uMhuQ1QiIJDarDO8G--






^ permalink  raw  reply  [nested|flat] 611+ messages in thread

* [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths
@ 2026-06-01 22:41 Andrey Chernyy <andrey.cherny@tantorlabs.com>
  0 siblings, 0 replies; 611+ messages in thread

From: Andrey Chernyy @ 2026-06-01 22:41 UTC (permalink / raw)

pgxml_xpath() builds an xpath_workspace before returning it to
callers.  If an ERROR is thrown before the function returns, callers
have not received the workspace pointer yet and cannot run
cleanup_workspace().

Add local error cleanup for the partially built workspace and the
compiled XPath expression.  Also check xmlXPathNewContext() before
dereferencing the returned context.
---
 contrib/xml2/xpath.c | 51 +++++++++++++++++++++++++++-----------------
 1 file changed, 32 insertions(+), 19 deletions(-)

diff --git a/contrib/xml2/xpath.c b/contrib/xml2/xpath.c
index 9fe75cb5ff4..283bb51178d 100644
--- a/contrib/xml2/xpath.c
+++ b/contrib/xml2/xpath.c
@@ -497,36 +497,49 @@ static xpath_workspace *
 pgxml_xpath(text *document, xmlChar *xpath, PgXmlErrorContext *xmlerrcxt)
 {
 	int32		docsize = VARSIZE_ANY_EXHDR(document);
-	xmlXPathCompExprPtr comppath;
+	xmlXPathCompExprPtr volatile comppath = NULL;
 	xpath_workspace *workspace = palloc0_object(xpath_workspace);
 
 	workspace->doctree = NULL;
 	workspace->ctxt = NULL;
 	workspace->res = NULL;
 
-	workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
-									   docsize, NULL, NULL,
-									   XML_PARSE_NOENT);
-	if (workspace->doctree != NULL)
+	PG_TRY();
 	{
-		workspace->ctxt = xmlXPathNewContext(workspace->doctree);
-		workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
-
-		/* compile the path */
-		comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
-		if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+		workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
+										   docsize, NULL, NULL,
+										   XML_PARSE_NOENT);
+		if (workspace->doctree != NULL)
 		{
-			if (comppath != NULL)
-				xmlXPathFreeCompExpr(comppath);
-			xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
-						"XPath Syntax Error");
-		}
+			workspace->ctxt = xmlXPathNewContext(workspace->doctree);
+			if (workspace->ctxt == NULL)
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_OUT_OF_MEMORY,
+							"could not allocate XPath context");
 
-		/* Now evaluate the path expression. */
-		workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+			workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
+
+			/* compile the path */
+			comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
+			if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
+							"XPath Syntax Error");
+
+			/* Now evaluate the path expression. */
+			workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+
+			xmlXPathFreeCompExpr(comppath);
+			comppath = NULL;
+		}
+	}
+	PG_CATCH();
+	{
+		if (comppath != NULL)
+			xmlXPathFreeCompExpr(comppath);
+		cleanup_workspace(workspace);
 
-		xmlXPathFreeCompExpr(comppath);
+		PG_RE_THROW();
 	}
+	PG_END_TRY();
 
 	return workspace;
 }
-- 
2.54.0


--MP_/LMSk9=uMhuQ1QiIJDarDO8G--






^ permalink  raw  reply  [nested|flat] 611+ messages in thread

* [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths
@ 2026-06-01 22:41 Andrey Chernyy <andrey.cherny@tantorlabs.com>
  0 siblings, 0 replies; 611+ messages in thread

From: Andrey Chernyy @ 2026-06-01 22:41 UTC (permalink / raw)

pgxml_xpath() builds an xpath_workspace before returning it to
callers.  If an ERROR is thrown before the function returns, callers
have not received the workspace pointer yet and cannot run
cleanup_workspace().

Add local error cleanup for the partially built workspace and the
compiled XPath expression.  Also check xmlXPathNewContext() before
dereferencing the returned context.
---
 contrib/xml2/xpath.c | 51 +++++++++++++++++++++++++++-----------------
 1 file changed, 32 insertions(+), 19 deletions(-)

diff --git a/contrib/xml2/xpath.c b/contrib/xml2/xpath.c
index 9fe75cb5ff4..283bb51178d 100644
--- a/contrib/xml2/xpath.c
+++ b/contrib/xml2/xpath.c
@@ -497,36 +497,49 @@ static xpath_workspace *
 pgxml_xpath(text *document, xmlChar *xpath, PgXmlErrorContext *xmlerrcxt)
 {
 	int32		docsize = VARSIZE_ANY_EXHDR(document);
-	xmlXPathCompExprPtr comppath;
+	xmlXPathCompExprPtr volatile comppath = NULL;
 	xpath_workspace *workspace = palloc0_object(xpath_workspace);
 
 	workspace->doctree = NULL;
 	workspace->ctxt = NULL;
 	workspace->res = NULL;
 
-	workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
-									   docsize, NULL, NULL,
-									   XML_PARSE_NOENT);
-	if (workspace->doctree != NULL)
+	PG_TRY();
 	{
-		workspace->ctxt = xmlXPathNewContext(workspace->doctree);
-		workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
-
-		/* compile the path */
-		comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
-		if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+		workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
+										   docsize, NULL, NULL,
+										   XML_PARSE_NOENT);
+		if (workspace->doctree != NULL)
 		{
-			if (comppath != NULL)
-				xmlXPathFreeCompExpr(comppath);
-			xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
-						"XPath Syntax Error");
-		}
+			workspace->ctxt = xmlXPathNewContext(workspace->doctree);
+			if (workspace->ctxt == NULL)
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_OUT_OF_MEMORY,
+							"could not allocate XPath context");
 
-		/* Now evaluate the path expression. */
-		workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+			workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
+
+			/* compile the path */
+			comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
+			if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
+							"XPath Syntax Error");
+
+			/* Now evaluate the path expression. */
+			workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+
+			xmlXPathFreeCompExpr(comppath);
+			comppath = NULL;
+		}
+	}
+	PG_CATCH();
+	{
+		if (comppath != NULL)
+			xmlXPathFreeCompExpr(comppath);
+		cleanup_workspace(workspace);
 
-		xmlXPathFreeCompExpr(comppath);
+		PG_RE_THROW();
 	}
+	PG_END_TRY();
 
 	return workspace;
 }
-- 
2.54.0


--MP_/LMSk9=uMhuQ1QiIJDarDO8G--





^ permalink  raw  reply  [nested|flat] 611+ messages in thread

* [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths
@ 2026-06-01 22:41 Andrey Chernyy <andrey.cherny@tantorlabs.com>
  0 siblings, 0 replies; 611+ messages in thread

From: Andrey Chernyy @ 2026-06-01 22:41 UTC (permalink / raw)

pgxml_xpath() builds an xpath_workspace before returning it to
callers.  If an ERROR is thrown before the function returns, callers
have not received the workspace pointer yet and cannot run
cleanup_workspace().

Add local error cleanup for the partially built workspace and the
compiled XPath expression.  Also check xmlXPathNewContext() before
dereferencing the returned context.
---
 contrib/xml2/xpath.c | 51 +++++++++++++++++++++++++++-----------------
 1 file changed, 32 insertions(+), 19 deletions(-)

diff --git a/contrib/xml2/xpath.c b/contrib/xml2/xpath.c
index 9fe75cb5ff4..283bb51178d 100644
--- a/contrib/xml2/xpath.c
+++ b/contrib/xml2/xpath.c
@@ -497,36 +497,49 @@ static xpath_workspace *
 pgxml_xpath(text *document, xmlChar *xpath, PgXmlErrorContext *xmlerrcxt)
 {
 	int32		docsize = VARSIZE_ANY_EXHDR(document);
-	xmlXPathCompExprPtr comppath;
+	xmlXPathCompExprPtr volatile comppath = NULL;
 	xpath_workspace *workspace = palloc0_object(xpath_workspace);
 
 	workspace->doctree = NULL;
 	workspace->ctxt = NULL;
 	workspace->res = NULL;
 
-	workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
-									   docsize, NULL, NULL,
-									   XML_PARSE_NOENT);
-	if (workspace->doctree != NULL)
+	PG_TRY();
 	{
-		workspace->ctxt = xmlXPathNewContext(workspace->doctree);
-		workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
-
-		/* compile the path */
-		comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
-		if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+		workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
+										   docsize, NULL, NULL,
+										   XML_PARSE_NOENT);
+		if (workspace->doctree != NULL)
 		{
-			if (comppath != NULL)
-				xmlXPathFreeCompExpr(comppath);
-			xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
-						"XPath Syntax Error");
-		}
+			workspace->ctxt = xmlXPathNewContext(workspace->doctree);
+			if (workspace->ctxt == NULL)
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_OUT_OF_MEMORY,
+							"could not allocate XPath context");
 
-		/* Now evaluate the path expression. */
-		workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+			workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
+
+			/* compile the path */
+			comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
+			if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
+							"XPath Syntax Error");
+
+			/* Now evaluate the path expression. */
+			workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+
+			xmlXPathFreeCompExpr(comppath);
+			comppath = NULL;
+		}
+	}
+	PG_CATCH();
+	{
+		if (comppath != NULL)
+			xmlXPathFreeCompExpr(comppath);
+		cleanup_workspace(workspace);
 
-		xmlXPathFreeCompExpr(comppath);
+		PG_RE_THROW();
 	}
+	PG_END_TRY();
 
 	return workspace;
 }
-- 
2.54.0


--MP_/LMSk9=uMhuQ1QiIJDarDO8G--





^ permalink  raw  reply  [nested|flat] 611+ messages in thread

* [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths
@ 2026-06-01 22:41 Andrey Chernyy <andrey.cherny@tantorlabs.com>
  0 siblings, 0 replies; 611+ messages in thread

From: Andrey Chernyy @ 2026-06-01 22:41 UTC (permalink / raw)

pgxml_xpath() builds an xpath_workspace before returning it to
callers.  If an ERROR is thrown before the function returns, callers
have not received the workspace pointer yet and cannot run
cleanup_workspace().

Add local error cleanup for the partially built workspace and the
compiled XPath expression.  Also check xmlXPathNewContext() before
dereferencing the returned context.
---
 contrib/xml2/xpath.c | 51 +++++++++++++++++++++++++++-----------------
 1 file changed, 32 insertions(+), 19 deletions(-)

diff --git a/contrib/xml2/xpath.c b/contrib/xml2/xpath.c
index 9fe75cb5ff4..283bb51178d 100644
--- a/contrib/xml2/xpath.c
+++ b/contrib/xml2/xpath.c
@@ -497,36 +497,49 @@ static xpath_workspace *
 pgxml_xpath(text *document, xmlChar *xpath, PgXmlErrorContext *xmlerrcxt)
 {
 	int32		docsize = VARSIZE_ANY_EXHDR(document);
-	xmlXPathCompExprPtr comppath;
+	xmlXPathCompExprPtr volatile comppath = NULL;
 	xpath_workspace *workspace = palloc0_object(xpath_workspace);
 
 	workspace->doctree = NULL;
 	workspace->ctxt = NULL;
 	workspace->res = NULL;
 
-	workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
-									   docsize, NULL, NULL,
-									   XML_PARSE_NOENT);
-	if (workspace->doctree != NULL)
+	PG_TRY();
 	{
-		workspace->ctxt = xmlXPathNewContext(workspace->doctree);
-		workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
-
-		/* compile the path */
-		comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
-		if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+		workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
+										   docsize, NULL, NULL,
+										   XML_PARSE_NOENT);
+		if (workspace->doctree != NULL)
 		{
-			if (comppath != NULL)
-				xmlXPathFreeCompExpr(comppath);
-			xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
-						"XPath Syntax Error");
-		}
+			workspace->ctxt = xmlXPathNewContext(workspace->doctree);
+			if (workspace->ctxt == NULL)
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_OUT_OF_MEMORY,
+							"could not allocate XPath context");
 
-		/* Now evaluate the path expression. */
-		workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+			workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
+
+			/* compile the path */
+			comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
+			if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
+							"XPath Syntax Error");
+
+			/* Now evaluate the path expression. */
+			workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+
+			xmlXPathFreeCompExpr(comppath);
+			comppath = NULL;
+		}
+	}
+	PG_CATCH();
+	{
+		if (comppath != NULL)
+			xmlXPathFreeCompExpr(comppath);
+		cleanup_workspace(workspace);
 
-		xmlXPathFreeCompExpr(comppath);
+		PG_RE_THROW();
 	}
+	PG_END_TRY();
 
 	return workspace;
 }
-- 
2.54.0


--MP_/LMSk9=uMhuQ1QiIJDarDO8G--






^ permalink  raw  reply  [nested|flat] 611+ messages in thread

* [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths
@ 2026-06-01 22:41 Andrey Chernyy <andrey.cherny@tantorlabs.com>
  0 siblings, 0 replies; 611+ messages in thread

From: Andrey Chernyy @ 2026-06-01 22:41 UTC (permalink / raw)

pgxml_xpath() builds an xpath_workspace before returning it to
callers.  If an ERROR is thrown before the function returns, callers
have not received the workspace pointer yet and cannot run
cleanup_workspace().

Add local error cleanup for the partially built workspace and the
compiled XPath expression.  Also check xmlXPathNewContext() before
dereferencing the returned context.
---
 contrib/xml2/xpath.c | 51 +++++++++++++++++++++++++++-----------------
 1 file changed, 32 insertions(+), 19 deletions(-)

diff --git a/contrib/xml2/xpath.c b/contrib/xml2/xpath.c
index 9fe75cb5ff4..283bb51178d 100644
--- a/contrib/xml2/xpath.c
+++ b/contrib/xml2/xpath.c
@@ -497,36 +497,49 @@ static xpath_workspace *
 pgxml_xpath(text *document, xmlChar *xpath, PgXmlErrorContext *xmlerrcxt)
 {
 	int32		docsize = VARSIZE_ANY_EXHDR(document);
-	xmlXPathCompExprPtr comppath;
+	xmlXPathCompExprPtr volatile comppath = NULL;
 	xpath_workspace *workspace = palloc0_object(xpath_workspace);
 
 	workspace->doctree = NULL;
 	workspace->ctxt = NULL;
 	workspace->res = NULL;
 
-	workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
-									   docsize, NULL, NULL,
-									   XML_PARSE_NOENT);
-	if (workspace->doctree != NULL)
+	PG_TRY();
 	{
-		workspace->ctxt = xmlXPathNewContext(workspace->doctree);
-		workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
-
-		/* compile the path */
-		comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
-		if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+		workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
+										   docsize, NULL, NULL,
+										   XML_PARSE_NOENT);
+		if (workspace->doctree != NULL)
 		{
-			if (comppath != NULL)
-				xmlXPathFreeCompExpr(comppath);
-			xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
-						"XPath Syntax Error");
-		}
+			workspace->ctxt = xmlXPathNewContext(workspace->doctree);
+			if (workspace->ctxt == NULL)
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_OUT_OF_MEMORY,
+							"could not allocate XPath context");
 
-		/* Now evaluate the path expression. */
-		workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+			workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
+
+			/* compile the path */
+			comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
+			if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
+							"XPath Syntax Error");
+
+			/* Now evaluate the path expression. */
+			workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+
+			xmlXPathFreeCompExpr(comppath);
+			comppath = NULL;
+		}
+	}
+	PG_CATCH();
+	{
+		if (comppath != NULL)
+			xmlXPathFreeCompExpr(comppath);
+		cleanup_workspace(workspace);
 
-		xmlXPathFreeCompExpr(comppath);
+		PG_RE_THROW();
 	}
+	PG_END_TRY();
 
 	return workspace;
 }
-- 
2.54.0


--MP_/LMSk9=uMhuQ1QiIJDarDO8G--





^ permalink  raw  reply  [nested|flat] 611+ messages in thread

* [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths
@ 2026-06-01 22:41 Andrey Chernyy <andrey.cherny@tantorlabs.com>
  0 siblings, 0 replies; 611+ messages in thread

From: Andrey Chernyy @ 2026-06-01 22:41 UTC (permalink / raw)

pgxml_xpath() builds an xpath_workspace before returning it to
callers.  If an ERROR is thrown before the function returns, callers
have not received the workspace pointer yet and cannot run
cleanup_workspace().

Add local error cleanup for the partially built workspace and the
compiled XPath expression.  Also check xmlXPathNewContext() before
dereferencing the returned context.
---
 contrib/xml2/xpath.c | 51 +++++++++++++++++++++++++++-----------------
 1 file changed, 32 insertions(+), 19 deletions(-)

diff --git a/contrib/xml2/xpath.c b/contrib/xml2/xpath.c
index 9fe75cb5ff4..283bb51178d 100644
--- a/contrib/xml2/xpath.c
+++ b/contrib/xml2/xpath.c
@@ -497,36 +497,49 @@ static xpath_workspace *
 pgxml_xpath(text *document, xmlChar *xpath, PgXmlErrorContext *xmlerrcxt)
 {
 	int32		docsize = VARSIZE_ANY_EXHDR(document);
-	xmlXPathCompExprPtr comppath;
+	xmlXPathCompExprPtr volatile comppath = NULL;
 	xpath_workspace *workspace = palloc0_object(xpath_workspace);
 
 	workspace->doctree = NULL;
 	workspace->ctxt = NULL;
 	workspace->res = NULL;
 
-	workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
-									   docsize, NULL, NULL,
-									   XML_PARSE_NOENT);
-	if (workspace->doctree != NULL)
+	PG_TRY();
 	{
-		workspace->ctxt = xmlXPathNewContext(workspace->doctree);
-		workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
-
-		/* compile the path */
-		comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
-		if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+		workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
+										   docsize, NULL, NULL,
+										   XML_PARSE_NOENT);
+		if (workspace->doctree != NULL)
 		{
-			if (comppath != NULL)
-				xmlXPathFreeCompExpr(comppath);
-			xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
-						"XPath Syntax Error");
-		}
+			workspace->ctxt = xmlXPathNewContext(workspace->doctree);
+			if (workspace->ctxt == NULL)
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_OUT_OF_MEMORY,
+							"could not allocate XPath context");
 
-		/* Now evaluate the path expression. */
-		workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+			workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
+
+			/* compile the path */
+			comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
+			if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
+							"XPath Syntax Error");
+
+			/* Now evaluate the path expression. */
+			workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+
+			xmlXPathFreeCompExpr(comppath);
+			comppath = NULL;
+		}
+	}
+	PG_CATCH();
+	{
+		if (comppath != NULL)
+			xmlXPathFreeCompExpr(comppath);
+		cleanup_workspace(workspace);
 
-		xmlXPathFreeCompExpr(comppath);
+		PG_RE_THROW();
 	}
+	PG_END_TRY();
 
 	return workspace;
 }
-- 
2.54.0


--MP_/LMSk9=uMhuQ1QiIJDarDO8G--





^ permalink  raw  reply  [nested|flat] 611+ messages in thread

* [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths
@ 2026-06-01 22:41 Andrey Chernyy <andrey.cherny@tantorlabs.com>
  0 siblings, 0 replies; 611+ messages in thread

From: Andrey Chernyy @ 2026-06-01 22:41 UTC (permalink / raw)

pgxml_xpath() builds an xpath_workspace before returning it to
callers.  If an ERROR is thrown before the function returns, callers
have not received the workspace pointer yet and cannot run
cleanup_workspace().

Add local error cleanup for the partially built workspace and the
compiled XPath expression.  Also check xmlXPathNewContext() before
dereferencing the returned context.
---
 contrib/xml2/xpath.c | 51 +++++++++++++++++++++++++++-----------------
 1 file changed, 32 insertions(+), 19 deletions(-)

diff --git a/contrib/xml2/xpath.c b/contrib/xml2/xpath.c
index 9fe75cb5ff4..283bb51178d 100644
--- a/contrib/xml2/xpath.c
+++ b/contrib/xml2/xpath.c
@@ -497,36 +497,49 @@ static xpath_workspace *
 pgxml_xpath(text *document, xmlChar *xpath, PgXmlErrorContext *xmlerrcxt)
 {
 	int32		docsize = VARSIZE_ANY_EXHDR(document);
-	xmlXPathCompExprPtr comppath;
+	xmlXPathCompExprPtr volatile comppath = NULL;
 	xpath_workspace *workspace = palloc0_object(xpath_workspace);
 
 	workspace->doctree = NULL;
 	workspace->ctxt = NULL;
 	workspace->res = NULL;
 
-	workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
-									   docsize, NULL, NULL,
-									   XML_PARSE_NOENT);
-	if (workspace->doctree != NULL)
+	PG_TRY();
 	{
-		workspace->ctxt = xmlXPathNewContext(workspace->doctree);
-		workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
-
-		/* compile the path */
-		comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
-		if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+		workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
+										   docsize, NULL, NULL,
+										   XML_PARSE_NOENT);
+		if (workspace->doctree != NULL)
 		{
-			if (comppath != NULL)
-				xmlXPathFreeCompExpr(comppath);
-			xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
-						"XPath Syntax Error");
-		}
+			workspace->ctxt = xmlXPathNewContext(workspace->doctree);
+			if (workspace->ctxt == NULL)
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_OUT_OF_MEMORY,
+							"could not allocate XPath context");
 
-		/* Now evaluate the path expression. */
-		workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+			workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
+
+			/* compile the path */
+			comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
+			if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
+							"XPath Syntax Error");
+
+			/* Now evaluate the path expression. */
+			workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+
+			xmlXPathFreeCompExpr(comppath);
+			comppath = NULL;
+		}
+	}
+	PG_CATCH();
+	{
+		if (comppath != NULL)
+			xmlXPathFreeCompExpr(comppath);
+		cleanup_workspace(workspace);
 
-		xmlXPathFreeCompExpr(comppath);
+		PG_RE_THROW();
 	}
+	PG_END_TRY();
 
 	return workspace;
 }
-- 
2.54.0


--MP_/LMSk9=uMhuQ1QiIJDarDO8G--





^ permalink  raw  reply  [nested|flat] 611+ messages in thread

* [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths
@ 2026-06-01 22:41 Andrey Chernyy <andrey.cherny@tantorlabs.com>
  0 siblings, 0 replies; 611+ messages in thread

From: Andrey Chernyy @ 2026-06-01 22:41 UTC (permalink / raw)

pgxml_xpath() builds an xpath_workspace before returning it to
callers.  If an ERROR is thrown before the function returns, callers
have not received the workspace pointer yet and cannot run
cleanup_workspace().

Add local error cleanup for the partially built workspace and the
compiled XPath expression.  Also check xmlXPathNewContext() before
dereferencing the returned context.
---
 contrib/xml2/xpath.c | 51 +++++++++++++++++++++++++++-----------------
 1 file changed, 32 insertions(+), 19 deletions(-)

diff --git a/contrib/xml2/xpath.c b/contrib/xml2/xpath.c
index 9fe75cb5ff4..283bb51178d 100644
--- a/contrib/xml2/xpath.c
+++ b/contrib/xml2/xpath.c
@@ -497,36 +497,49 @@ static xpath_workspace *
 pgxml_xpath(text *document, xmlChar *xpath, PgXmlErrorContext *xmlerrcxt)
 {
 	int32		docsize = VARSIZE_ANY_EXHDR(document);
-	xmlXPathCompExprPtr comppath;
+	xmlXPathCompExprPtr volatile comppath = NULL;
 	xpath_workspace *workspace = palloc0_object(xpath_workspace);
 
 	workspace->doctree = NULL;
 	workspace->ctxt = NULL;
 	workspace->res = NULL;
 
-	workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
-									   docsize, NULL, NULL,
-									   XML_PARSE_NOENT);
-	if (workspace->doctree != NULL)
+	PG_TRY();
 	{
-		workspace->ctxt = xmlXPathNewContext(workspace->doctree);
-		workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
-
-		/* compile the path */
-		comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
-		if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+		workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
+										   docsize, NULL, NULL,
+										   XML_PARSE_NOENT);
+		if (workspace->doctree != NULL)
 		{
-			if (comppath != NULL)
-				xmlXPathFreeCompExpr(comppath);
-			xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
-						"XPath Syntax Error");
-		}
+			workspace->ctxt = xmlXPathNewContext(workspace->doctree);
+			if (workspace->ctxt == NULL)
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_OUT_OF_MEMORY,
+							"could not allocate XPath context");
 
-		/* Now evaluate the path expression. */
-		workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+			workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
+
+			/* compile the path */
+			comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
+			if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
+							"XPath Syntax Error");
+
+			/* Now evaluate the path expression. */
+			workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+
+			xmlXPathFreeCompExpr(comppath);
+			comppath = NULL;
+		}
+	}
+	PG_CATCH();
+	{
+		if (comppath != NULL)
+			xmlXPathFreeCompExpr(comppath);
+		cleanup_workspace(workspace);
 
-		xmlXPathFreeCompExpr(comppath);
+		PG_RE_THROW();
 	}
+	PG_END_TRY();
 
 	return workspace;
 }
-- 
2.54.0


--MP_/LMSk9=uMhuQ1QiIJDarDO8G--






^ permalink  raw  reply  [nested|flat] 611+ messages in thread

* [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths
@ 2026-06-01 22:41 Andrey Chernyy <andrey.cherny@tantorlabs.com>
  0 siblings, 0 replies; 611+ messages in thread

From: Andrey Chernyy @ 2026-06-01 22:41 UTC (permalink / raw)

pgxml_xpath() builds an xpath_workspace before returning it to
callers.  If an ERROR is thrown before the function returns, callers
have not received the workspace pointer yet and cannot run
cleanup_workspace().

Add local error cleanup for the partially built workspace and the
compiled XPath expression.  Also check xmlXPathNewContext() before
dereferencing the returned context.
---
 contrib/xml2/xpath.c | 51 +++++++++++++++++++++++++++-----------------
 1 file changed, 32 insertions(+), 19 deletions(-)

diff --git a/contrib/xml2/xpath.c b/contrib/xml2/xpath.c
index 9fe75cb5ff4..283bb51178d 100644
--- a/contrib/xml2/xpath.c
+++ b/contrib/xml2/xpath.c
@@ -497,36 +497,49 @@ static xpath_workspace *
 pgxml_xpath(text *document, xmlChar *xpath, PgXmlErrorContext *xmlerrcxt)
 {
 	int32		docsize = VARSIZE_ANY_EXHDR(document);
-	xmlXPathCompExprPtr comppath;
+	xmlXPathCompExprPtr volatile comppath = NULL;
 	xpath_workspace *workspace = palloc0_object(xpath_workspace);
 
 	workspace->doctree = NULL;
 	workspace->ctxt = NULL;
 	workspace->res = NULL;
 
-	workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
-									   docsize, NULL, NULL,
-									   XML_PARSE_NOENT);
-	if (workspace->doctree != NULL)
+	PG_TRY();
 	{
-		workspace->ctxt = xmlXPathNewContext(workspace->doctree);
-		workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
-
-		/* compile the path */
-		comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
-		if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+		workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
+										   docsize, NULL, NULL,
+										   XML_PARSE_NOENT);
+		if (workspace->doctree != NULL)
 		{
-			if (comppath != NULL)
-				xmlXPathFreeCompExpr(comppath);
-			xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
-						"XPath Syntax Error");
-		}
+			workspace->ctxt = xmlXPathNewContext(workspace->doctree);
+			if (workspace->ctxt == NULL)
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_OUT_OF_MEMORY,
+							"could not allocate XPath context");
 
-		/* Now evaluate the path expression. */
-		workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+			workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
+
+			/* compile the path */
+			comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
+			if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
+							"XPath Syntax Error");
+
+			/* Now evaluate the path expression. */
+			workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+
+			xmlXPathFreeCompExpr(comppath);
+			comppath = NULL;
+		}
+	}
+	PG_CATCH();
+	{
+		if (comppath != NULL)
+			xmlXPathFreeCompExpr(comppath);
+		cleanup_workspace(workspace);
 
-		xmlXPathFreeCompExpr(comppath);
+		PG_RE_THROW();
 	}
+	PG_END_TRY();
 
 	return workspace;
 }
-- 
2.54.0


--MP_/LMSk9=uMhuQ1QiIJDarDO8G--






^ permalink  raw  reply  [nested|flat] 611+ messages in thread

* [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths
@ 2026-06-01 22:41 Andrey Chernyy <andrey.cherny@tantorlabs.com>
  0 siblings, 0 replies; 611+ messages in thread

From: Andrey Chernyy @ 2026-06-01 22:41 UTC (permalink / raw)

pgxml_xpath() builds an xpath_workspace before returning it to
callers.  If an ERROR is thrown before the function returns, callers
have not received the workspace pointer yet and cannot run
cleanup_workspace().

Add local error cleanup for the partially built workspace and the
compiled XPath expression.  Also check xmlXPathNewContext() before
dereferencing the returned context.
---
 contrib/xml2/xpath.c | 51 +++++++++++++++++++++++++++-----------------
 1 file changed, 32 insertions(+), 19 deletions(-)

diff --git a/contrib/xml2/xpath.c b/contrib/xml2/xpath.c
index 9fe75cb5ff4..283bb51178d 100644
--- a/contrib/xml2/xpath.c
+++ b/contrib/xml2/xpath.c
@@ -497,36 +497,49 @@ static xpath_workspace *
 pgxml_xpath(text *document, xmlChar *xpath, PgXmlErrorContext *xmlerrcxt)
 {
 	int32		docsize = VARSIZE_ANY_EXHDR(document);
-	xmlXPathCompExprPtr comppath;
+	xmlXPathCompExprPtr volatile comppath = NULL;
 	xpath_workspace *workspace = palloc0_object(xpath_workspace);
 
 	workspace->doctree = NULL;
 	workspace->ctxt = NULL;
 	workspace->res = NULL;
 
-	workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
-									   docsize, NULL, NULL,
-									   XML_PARSE_NOENT);
-	if (workspace->doctree != NULL)
+	PG_TRY();
 	{
-		workspace->ctxt = xmlXPathNewContext(workspace->doctree);
-		workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
-
-		/* compile the path */
-		comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
-		if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+		workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
+										   docsize, NULL, NULL,
+										   XML_PARSE_NOENT);
+		if (workspace->doctree != NULL)
 		{
-			if (comppath != NULL)
-				xmlXPathFreeCompExpr(comppath);
-			xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
-						"XPath Syntax Error");
-		}
+			workspace->ctxt = xmlXPathNewContext(workspace->doctree);
+			if (workspace->ctxt == NULL)
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_OUT_OF_MEMORY,
+							"could not allocate XPath context");
 
-		/* Now evaluate the path expression. */
-		workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+			workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
+
+			/* compile the path */
+			comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
+			if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
+							"XPath Syntax Error");
+
+			/* Now evaluate the path expression. */
+			workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+
+			xmlXPathFreeCompExpr(comppath);
+			comppath = NULL;
+		}
+	}
+	PG_CATCH();
+	{
+		if (comppath != NULL)
+			xmlXPathFreeCompExpr(comppath);
+		cleanup_workspace(workspace);
 
-		xmlXPathFreeCompExpr(comppath);
+		PG_RE_THROW();
 	}
+	PG_END_TRY();
 
 	return workspace;
 }
-- 
2.54.0


--MP_/LMSk9=uMhuQ1QiIJDarDO8G--






^ permalink  raw  reply  [nested|flat] 611+ messages in thread

* [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths
@ 2026-06-01 22:41 Andrey Chernyy <andrey.cherny@tantorlabs.com>
  0 siblings, 0 replies; 611+ messages in thread

From: Andrey Chernyy @ 2026-06-01 22:41 UTC (permalink / raw)

pgxml_xpath() builds an xpath_workspace before returning it to
callers.  If an ERROR is thrown before the function returns, callers
have not received the workspace pointer yet and cannot run
cleanup_workspace().

Add local error cleanup for the partially built workspace and the
compiled XPath expression.  Also check xmlXPathNewContext() before
dereferencing the returned context.
---
 contrib/xml2/xpath.c | 51 +++++++++++++++++++++++++++-----------------
 1 file changed, 32 insertions(+), 19 deletions(-)

diff --git a/contrib/xml2/xpath.c b/contrib/xml2/xpath.c
index 9fe75cb5ff4..283bb51178d 100644
--- a/contrib/xml2/xpath.c
+++ b/contrib/xml2/xpath.c
@@ -497,36 +497,49 @@ static xpath_workspace *
 pgxml_xpath(text *document, xmlChar *xpath, PgXmlErrorContext *xmlerrcxt)
 {
 	int32		docsize = VARSIZE_ANY_EXHDR(document);
-	xmlXPathCompExprPtr comppath;
+	xmlXPathCompExprPtr volatile comppath = NULL;
 	xpath_workspace *workspace = palloc0_object(xpath_workspace);
 
 	workspace->doctree = NULL;
 	workspace->ctxt = NULL;
 	workspace->res = NULL;
 
-	workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
-									   docsize, NULL, NULL,
-									   XML_PARSE_NOENT);
-	if (workspace->doctree != NULL)
+	PG_TRY();
 	{
-		workspace->ctxt = xmlXPathNewContext(workspace->doctree);
-		workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
-
-		/* compile the path */
-		comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
-		if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+		workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
+										   docsize, NULL, NULL,
+										   XML_PARSE_NOENT);
+		if (workspace->doctree != NULL)
 		{
-			if (comppath != NULL)
-				xmlXPathFreeCompExpr(comppath);
-			xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
-						"XPath Syntax Error");
-		}
+			workspace->ctxt = xmlXPathNewContext(workspace->doctree);
+			if (workspace->ctxt == NULL)
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_OUT_OF_MEMORY,
+							"could not allocate XPath context");
 
-		/* Now evaluate the path expression. */
-		workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+			workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
+
+			/* compile the path */
+			comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
+			if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
+							"XPath Syntax Error");
+
+			/* Now evaluate the path expression. */
+			workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+
+			xmlXPathFreeCompExpr(comppath);
+			comppath = NULL;
+		}
+	}
+	PG_CATCH();
+	{
+		if (comppath != NULL)
+			xmlXPathFreeCompExpr(comppath);
+		cleanup_workspace(workspace);
 
-		xmlXPathFreeCompExpr(comppath);
+		PG_RE_THROW();
 	}
+	PG_END_TRY();
 
 	return workspace;
 }
-- 
2.54.0


--MP_/LMSk9=uMhuQ1QiIJDarDO8G--






^ permalink  raw  reply  [nested|flat] 611+ messages in thread

* [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths
@ 2026-06-01 22:41 Andrey Chernyy <andrey.cherny@tantorlabs.com>
  0 siblings, 0 replies; 611+ messages in thread

From: Andrey Chernyy @ 2026-06-01 22:41 UTC (permalink / raw)

pgxml_xpath() builds an xpath_workspace before returning it to
callers.  If an ERROR is thrown before the function returns, callers
have not received the workspace pointer yet and cannot run
cleanup_workspace().

Add local error cleanup for the partially built workspace and the
compiled XPath expression.  Also check xmlXPathNewContext() before
dereferencing the returned context.
---
 contrib/xml2/xpath.c | 51 +++++++++++++++++++++++++++-----------------
 1 file changed, 32 insertions(+), 19 deletions(-)

diff --git a/contrib/xml2/xpath.c b/contrib/xml2/xpath.c
index 9fe75cb5ff4..283bb51178d 100644
--- a/contrib/xml2/xpath.c
+++ b/contrib/xml2/xpath.c
@@ -497,36 +497,49 @@ static xpath_workspace *
 pgxml_xpath(text *document, xmlChar *xpath, PgXmlErrorContext *xmlerrcxt)
 {
 	int32		docsize = VARSIZE_ANY_EXHDR(document);
-	xmlXPathCompExprPtr comppath;
+	xmlXPathCompExprPtr volatile comppath = NULL;
 	xpath_workspace *workspace = palloc0_object(xpath_workspace);
 
 	workspace->doctree = NULL;
 	workspace->ctxt = NULL;
 	workspace->res = NULL;
 
-	workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
-									   docsize, NULL, NULL,
-									   XML_PARSE_NOENT);
-	if (workspace->doctree != NULL)
+	PG_TRY();
 	{
-		workspace->ctxt = xmlXPathNewContext(workspace->doctree);
-		workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
-
-		/* compile the path */
-		comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
-		if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+		workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
+										   docsize, NULL, NULL,
+										   XML_PARSE_NOENT);
+		if (workspace->doctree != NULL)
 		{
-			if (comppath != NULL)
-				xmlXPathFreeCompExpr(comppath);
-			xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
-						"XPath Syntax Error");
-		}
+			workspace->ctxt = xmlXPathNewContext(workspace->doctree);
+			if (workspace->ctxt == NULL)
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_OUT_OF_MEMORY,
+							"could not allocate XPath context");
 
-		/* Now evaluate the path expression. */
-		workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+			workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
+
+			/* compile the path */
+			comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
+			if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
+							"XPath Syntax Error");
+
+			/* Now evaluate the path expression. */
+			workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+
+			xmlXPathFreeCompExpr(comppath);
+			comppath = NULL;
+		}
+	}
+	PG_CATCH();
+	{
+		if (comppath != NULL)
+			xmlXPathFreeCompExpr(comppath);
+		cleanup_workspace(workspace);
 
-		xmlXPathFreeCompExpr(comppath);
+		PG_RE_THROW();
 	}
+	PG_END_TRY();
 
 	return workspace;
 }
-- 
2.54.0


--MP_/LMSk9=uMhuQ1QiIJDarDO8G--






^ permalink  raw  reply  [nested|flat] 611+ messages in thread

* [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths
@ 2026-06-01 22:41 Andrey Chernyy <andrey.cherny@tantorlabs.com>
  0 siblings, 0 replies; 611+ messages in thread

From: Andrey Chernyy @ 2026-06-01 22:41 UTC (permalink / raw)

pgxml_xpath() builds an xpath_workspace before returning it to
callers.  If an ERROR is thrown before the function returns, callers
have not received the workspace pointer yet and cannot run
cleanup_workspace().

Add local error cleanup for the partially built workspace and the
compiled XPath expression.  Also check xmlXPathNewContext() before
dereferencing the returned context.
---
 contrib/xml2/xpath.c | 51 +++++++++++++++++++++++++++-----------------
 1 file changed, 32 insertions(+), 19 deletions(-)

diff --git a/contrib/xml2/xpath.c b/contrib/xml2/xpath.c
index 9fe75cb5ff4..283bb51178d 100644
--- a/contrib/xml2/xpath.c
+++ b/contrib/xml2/xpath.c
@@ -497,36 +497,49 @@ static xpath_workspace *
 pgxml_xpath(text *document, xmlChar *xpath, PgXmlErrorContext *xmlerrcxt)
 {
 	int32		docsize = VARSIZE_ANY_EXHDR(document);
-	xmlXPathCompExprPtr comppath;
+	xmlXPathCompExprPtr volatile comppath = NULL;
 	xpath_workspace *workspace = palloc0_object(xpath_workspace);
 
 	workspace->doctree = NULL;
 	workspace->ctxt = NULL;
 	workspace->res = NULL;
 
-	workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
-									   docsize, NULL, NULL,
-									   XML_PARSE_NOENT);
-	if (workspace->doctree != NULL)
+	PG_TRY();
 	{
-		workspace->ctxt = xmlXPathNewContext(workspace->doctree);
-		workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
-
-		/* compile the path */
-		comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
-		if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+		workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
+										   docsize, NULL, NULL,
+										   XML_PARSE_NOENT);
+		if (workspace->doctree != NULL)
 		{
-			if (comppath != NULL)
-				xmlXPathFreeCompExpr(comppath);
-			xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
-						"XPath Syntax Error");
-		}
+			workspace->ctxt = xmlXPathNewContext(workspace->doctree);
+			if (workspace->ctxt == NULL)
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_OUT_OF_MEMORY,
+							"could not allocate XPath context");
 
-		/* Now evaluate the path expression. */
-		workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+			workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
+
+			/* compile the path */
+			comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
+			if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
+							"XPath Syntax Error");
+
+			/* Now evaluate the path expression. */
+			workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+
+			xmlXPathFreeCompExpr(comppath);
+			comppath = NULL;
+		}
+	}
+	PG_CATCH();
+	{
+		if (comppath != NULL)
+			xmlXPathFreeCompExpr(comppath);
+		cleanup_workspace(workspace);
 
-		xmlXPathFreeCompExpr(comppath);
+		PG_RE_THROW();
 	}
+	PG_END_TRY();
 
 	return workspace;
 }
-- 
2.54.0


--MP_/LMSk9=uMhuQ1QiIJDarDO8G--





^ permalink  raw  reply  [nested|flat] 611+ messages in thread

* [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths
@ 2026-06-01 22:41 Andrey Chernyy <andrey.cherny@tantorlabs.com>
  0 siblings, 0 replies; 611+ messages in thread

From: Andrey Chernyy @ 2026-06-01 22:41 UTC (permalink / raw)

pgxml_xpath() builds an xpath_workspace before returning it to
callers.  If an ERROR is thrown before the function returns, callers
have not received the workspace pointer yet and cannot run
cleanup_workspace().

Add local error cleanup for the partially built workspace and the
compiled XPath expression.  Also check xmlXPathNewContext() before
dereferencing the returned context.
---
 contrib/xml2/xpath.c | 51 +++++++++++++++++++++++++++-----------------
 1 file changed, 32 insertions(+), 19 deletions(-)

diff --git a/contrib/xml2/xpath.c b/contrib/xml2/xpath.c
index 9fe75cb5ff4..283bb51178d 100644
--- a/contrib/xml2/xpath.c
+++ b/contrib/xml2/xpath.c
@@ -497,36 +497,49 @@ static xpath_workspace *
 pgxml_xpath(text *document, xmlChar *xpath, PgXmlErrorContext *xmlerrcxt)
 {
 	int32		docsize = VARSIZE_ANY_EXHDR(document);
-	xmlXPathCompExprPtr comppath;
+	xmlXPathCompExprPtr volatile comppath = NULL;
 	xpath_workspace *workspace = palloc0_object(xpath_workspace);
 
 	workspace->doctree = NULL;
 	workspace->ctxt = NULL;
 	workspace->res = NULL;
 
-	workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
-									   docsize, NULL, NULL,
-									   XML_PARSE_NOENT);
-	if (workspace->doctree != NULL)
+	PG_TRY();
 	{
-		workspace->ctxt = xmlXPathNewContext(workspace->doctree);
-		workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
-
-		/* compile the path */
-		comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
-		if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+		workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
+										   docsize, NULL, NULL,
+										   XML_PARSE_NOENT);
+		if (workspace->doctree != NULL)
 		{
-			if (comppath != NULL)
-				xmlXPathFreeCompExpr(comppath);
-			xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
-						"XPath Syntax Error");
-		}
+			workspace->ctxt = xmlXPathNewContext(workspace->doctree);
+			if (workspace->ctxt == NULL)
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_OUT_OF_MEMORY,
+							"could not allocate XPath context");
 
-		/* Now evaluate the path expression. */
-		workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+			workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
+
+			/* compile the path */
+			comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
+			if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
+							"XPath Syntax Error");
+
+			/* Now evaluate the path expression. */
+			workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+
+			xmlXPathFreeCompExpr(comppath);
+			comppath = NULL;
+		}
+	}
+	PG_CATCH();
+	{
+		if (comppath != NULL)
+			xmlXPathFreeCompExpr(comppath);
+		cleanup_workspace(workspace);
 
-		xmlXPathFreeCompExpr(comppath);
+		PG_RE_THROW();
 	}
+	PG_END_TRY();
 
 	return workspace;
 }
-- 
2.54.0


--MP_/LMSk9=uMhuQ1QiIJDarDO8G--






^ permalink  raw  reply  [nested|flat] 611+ messages in thread

* [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths
@ 2026-06-01 22:41 Andrey Chernyy <andrey.cherny@tantorlabs.com>
  0 siblings, 0 replies; 611+ messages in thread

From: Andrey Chernyy @ 2026-06-01 22:41 UTC (permalink / raw)

pgxml_xpath() builds an xpath_workspace before returning it to
callers.  If an ERROR is thrown before the function returns, callers
have not received the workspace pointer yet and cannot run
cleanup_workspace().

Add local error cleanup for the partially built workspace and the
compiled XPath expression.  Also check xmlXPathNewContext() before
dereferencing the returned context.
---
 contrib/xml2/xpath.c | 51 +++++++++++++++++++++++++++-----------------
 1 file changed, 32 insertions(+), 19 deletions(-)

diff --git a/contrib/xml2/xpath.c b/contrib/xml2/xpath.c
index 9fe75cb5ff4..283bb51178d 100644
--- a/contrib/xml2/xpath.c
+++ b/contrib/xml2/xpath.c
@@ -497,36 +497,49 @@ static xpath_workspace *
 pgxml_xpath(text *document, xmlChar *xpath, PgXmlErrorContext *xmlerrcxt)
 {
 	int32		docsize = VARSIZE_ANY_EXHDR(document);
-	xmlXPathCompExprPtr comppath;
+	xmlXPathCompExprPtr volatile comppath = NULL;
 	xpath_workspace *workspace = palloc0_object(xpath_workspace);
 
 	workspace->doctree = NULL;
 	workspace->ctxt = NULL;
 	workspace->res = NULL;
 
-	workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
-									   docsize, NULL, NULL,
-									   XML_PARSE_NOENT);
-	if (workspace->doctree != NULL)
+	PG_TRY();
 	{
-		workspace->ctxt = xmlXPathNewContext(workspace->doctree);
-		workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
-
-		/* compile the path */
-		comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
-		if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+		workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
+										   docsize, NULL, NULL,
+										   XML_PARSE_NOENT);
+		if (workspace->doctree != NULL)
 		{
-			if (comppath != NULL)
-				xmlXPathFreeCompExpr(comppath);
-			xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
-						"XPath Syntax Error");
-		}
+			workspace->ctxt = xmlXPathNewContext(workspace->doctree);
+			if (workspace->ctxt == NULL)
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_OUT_OF_MEMORY,
+							"could not allocate XPath context");
 
-		/* Now evaluate the path expression. */
-		workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+			workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
+
+			/* compile the path */
+			comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
+			if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
+							"XPath Syntax Error");
+
+			/* Now evaluate the path expression. */
+			workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+
+			xmlXPathFreeCompExpr(comppath);
+			comppath = NULL;
+		}
+	}
+	PG_CATCH();
+	{
+		if (comppath != NULL)
+			xmlXPathFreeCompExpr(comppath);
+		cleanup_workspace(workspace);
 
-		xmlXPathFreeCompExpr(comppath);
+		PG_RE_THROW();
 	}
+	PG_END_TRY();
 
 	return workspace;
 }
-- 
2.54.0


--MP_/LMSk9=uMhuQ1QiIJDarDO8G--






^ permalink  raw  reply  [nested|flat] 611+ messages in thread

* [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths
@ 2026-06-01 22:41 Andrey Chernyy <andrey.cherny@tantorlabs.com>
  0 siblings, 0 replies; 611+ messages in thread

From: Andrey Chernyy @ 2026-06-01 22:41 UTC (permalink / raw)

pgxml_xpath() builds an xpath_workspace before returning it to
callers.  If an ERROR is thrown before the function returns, callers
have not received the workspace pointer yet and cannot run
cleanup_workspace().

Add local error cleanup for the partially built workspace and the
compiled XPath expression.  Also check xmlXPathNewContext() before
dereferencing the returned context.
---
 contrib/xml2/xpath.c | 51 +++++++++++++++++++++++++++-----------------
 1 file changed, 32 insertions(+), 19 deletions(-)

diff --git a/contrib/xml2/xpath.c b/contrib/xml2/xpath.c
index 9fe75cb5ff4..283bb51178d 100644
--- a/contrib/xml2/xpath.c
+++ b/contrib/xml2/xpath.c
@@ -497,36 +497,49 @@ static xpath_workspace *
 pgxml_xpath(text *document, xmlChar *xpath, PgXmlErrorContext *xmlerrcxt)
 {
 	int32		docsize = VARSIZE_ANY_EXHDR(document);
-	xmlXPathCompExprPtr comppath;
+	xmlXPathCompExprPtr volatile comppath = NULL;
 	xpath_workspace *workspace = palloc0_object(xpath_workspace);
 
 	workspace->doctree = NULL;
 	workspace->ctxt = NULL;
 	workspace->res = NULL;
 
-	workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
-									   docsize, NULL, NULL,
-									   XML_PARSE_NOENT);
-	if (workspace->doctree != NULL)
+	PG_TRY();
 	{
-		workspace->ctxt = xmlXPathNewContext(workspace->doctree);
-		workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
-
-		/* compile the path */
-		comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
-		if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+		workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
+										   docsize, NULL, NULL,
+										   XML_PARSE_NOENT);
+		if (workspace->doctree != NULL)
 		{
-			if (comppath != NULL)
-				xmlXPathFreeCompExpr(comppath);
-			xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
-						"XPath Syntax Error");
-		}
+			workspace->ctxt = xmlXPathNewContext(workspace->doctree);
+			if (workspace->ctxt == NULL)
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_OUT_OF_MEMORY,
+							"could not allocate XPath context");
 
-		/* Now evaluate the path expression. */
-		workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+			workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
+
+			/* compile the path */
+			comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
+			if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
+							"XPath Syntax Error");
+
+			/* Now evaluate the path expression. */
+			workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+
+			xmlXPathFreeCompExpr(comppath);
+			comppath = NULL;
+		}
+	}
+	PG_CATCH();
+	{
+		if (comppath != NULL)
+			xmlXPathFreeCompExpr(comppath);
+		cleanup_workspace(workspace);
 
-		xmlXPathFreeCompExpr(comppath);
+		PG_RE_THROW();
 	}
+	PG_END_TRY();
 
 	return workspace;
 }
-- 
2.54.0


--MP_/LMSk9=uMhuQ1QiIJDarDO8G--






^ permalink  raw  reply  [nested|flat] 611+ messages in thread

* [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths
@ 2026-06-01 22:41 Andrey Chernyy <andrey.cherny@tantorlabs.com>
  0 siblings, 0 replies; 611+ messages in thread

From: Andrey Chernyy @ 2026-06-01 22:41 UTC (permalink / raw)

pgxml_xpath() builds an xpath_workspace before returning it to
callers.  If an ERROR is thrown before the function returns, callers
have not received the workspace pointer yet and cannot run
cleanup_workspace().

Add local error cleanup for the partially built workspace and the
compiled XPath expression.  Also check xmlXPathNewContext() before
dereferencing the returned context.
---
 contrib/xml2/xpath.c | 51 +++++++++++++++++++++++++++-----------------
 1 file changed, 32 insertions(+), 19 deletions(-)

diff --git a/contrib/xml2/xpath.c b/contrib/xml2/xpath.c
index 9fe75cb5ff4..283bb51178d 100644
--- a/contrib/xml2/xpath.c
+++ b/contrib/xml2/xpath.c
@@ -497,36 +497,49 @@ static xpath_workspace *
 pgxml_xpath(text *document, xmlChar *xpath, PgXmlErrorContext *xmlerrcxt)
 {
 	int32		docsize = VARSIZE_ANY_EXHDR(document);
-	xmlXPathCompExprPtr comppath;
+	xmlXPathCompExprPtr volatile comppath = NULL;
 	xpath_workspace *workspace = palloc0_object(xpath_workspace);
 
 	workspace->doctree = NULL;
 	workspace->ctxt = NULL;
 	workspace->res = NULL;
 
-	workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
-									   docsize, NULL, NULL,
-									   XML_PARSE_NOENT);
-	if (workspace->doctree != NULL)
+	PG_TRY();
 	{
-		workspace->ctxt = xmlXPathNewContext(workspace->doctree);
-		workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
-
-		/* compile the path */
-		comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
-		if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+		workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
+										   docsize, NULL, NULL,
+										   XML_PARSE_NOENT);
+		if (workspace->doctree != NULL)
 		{
-			if (comppath != NULL)
-				xmlXPathFreeCompExpr(comppath);
-			xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
-						"XPath Syntax Error");
-		}
+			workspace->ctxt = xmlXPathNewContext(workspace->doctree);
+			if (workspace->ctxt == NULL)
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_OUT_OF_MEMORY,
+							"could not allocate XPath context");
 
-		/* Now evaluate the path expression. */
-		workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+			workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
+
+			/* compile the path */
+			comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
+			if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
+							"XPath Syntax Error");
+
+			/* Now evaluate the path expression. */
+			workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+
+			xmlXPathFreeCompExpr(comppath);
+			comppath = NULL;
+		}
+	}
+	PG_CATCH();
+	{
+		if (comppath != NULL)
+			xmlXPathFreeCompExpr(comppath);
+		cleanup_workspace(workspace);
 
-		xmlXPathFreeCompExpr(comppath);
+		PG_RE_THROW();
 	}
+	PG_END_TRY();
 
 	return workspace;
 }
-- 
2.54.0


--MP_/LMSk9=uMhuQ1QiIJDarDO8G--





^ permalink  raw  reply  [nested|flat] 611+ messages in thread

* [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths
@ 2026-06-01 22:41 Andrey Chernyy <andrey.cherny@tantorlabs.com>
  0 siblings, 0 replies; 611+ messages in thread

From: Andrey Chernyy @ 2026-06-01 22:41 UTC (permalink / raw)

pgxml_xpath() builds an xpath_workspace before returning it to
callers.  If an ERROR is thrown before the function returns, callers
have not received the workspace pointer yet and cannot run
cleanup_workspace().

Add local error cleanup for the partially built workspace and the
compiled XPath expression.  Also check xmlXPathNewContext() before
dereferencing the returned context.
---
 contrib/xml2/xpath.c | 51 +++++++++++++++++++++++++++-----------------
 1 file changed, 32 insertions(+), 19 deletions(-)

diff --git a/contrib/xml2/xpath.c b/contrib/xml2/xpath.c
index 9fe75cb5ff4..283bb51178d 100644
--- a/contrib/xml2/xpath.c
+++ b/contrib/xml2/xpath.c
@@ -497,36 +497,49 @@ static xpath_workspace *
 pgxml_xpath(text *document, xmlChar *xpath, PgXmlErrorContext *xmlerrcxt)
 {
 	int32		docsize = VARSIZE_ANY_EXHDR(document);
-	xmlXPathCompExprPtr comppath;
+	xmlXPathCompExprPtr volatile comppath = NULL;
 	xpath_workspace *workspace = palloc0_object(xpath_workspace);
 
 	workspace->doctree = NULL;
 	workspace->ctxt = NULL;
 	workspace->res = NULL;
 
-	workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
-									   docsize, NULL, NULL,
-									   XML_PARSE_NOENT);
-	if (workspace->doctree != NULL)
+	PG_TRY();
 	{
-		workspace->ctxt = xmlXPathNewContext(workspace->doctree);
-		workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
-
-		/* compile the path */
-		comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
-		if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+		workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
+										   docsize, NULL, NULL,
+										   XML_PARSE_NOENT);
+		if (workspace->doctree != NULL)
 		{
-			if (comppath != NULL)
-				xmlXPathFreeCompExpr(comppath);
-			xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
-						"XPath Syntax Error");
-		}
+			workspace->ctxt = xmlXPathNewContext(workspace->doctree);
+			if (workspace->ctxt == NULL)
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_OUT_OF_MEMORY,
+							"could not allocate XPath context");
 
-		/* Now evaluate the path expression. */
-		workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+			workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
+
+			/* compile the path */
+			comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
+			if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
+							"XPath Syntax Error");
+
+			/* Now evaluate the path expression. */
+			workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+
+			xmlXPathFreeCompExpr(comppath);
+			comppath = NULL;
+		}
+	}
+	PG_CATCH();
+	{
+		if (comppath != NULL)
+			xmlXPathFreeCompExpr(comppath);
+		cleanup_workspace(workspace);
 
-		xmlXPathFreeCompExpr(comppath);
+		PG_RE_THROW();
 	}
+	PG_END_TRY();
 
 	return workspace;
 }
-- 
2.54.0


--MP_/LMSk9=uMhuQ1QiIJDarDO8G--





^ permalink  raw  reply  [nested|flat] 611+ messages in thread

* [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths
@ 2026-06-01 22:41 Andrey Chernyy <andrey.cherny@tantorlabs.com>
  0 siblings, 0 replies; 611+ messages in thread

From: Andrey Chernyy @ 2026-06-01 22:41 UTC (permalink / raw)

pgxml_xpath() builds an xpath_workspace before returning it to
callers.  If an ERROR is thrown before the function returns, callers
have not received the workspace pointer yet and cannot run
cleanup_workspace().

Add local error cleanup for the partially built workspace and the
compiled XPath expression.  Also check xmlXPathNewContext() before
dereferencing the returned context.
---
 contrib/xml2/xpath.c | 51 +++++++++++++++++++++++++++-----------------
 1 file changed, 32 insertions(+), 19 deletions(-)

diff --git a/contrib/xml2/xpath.c b/contrib/xml2/xpath.c
index 9fe75cb5ff4..283bb51178d 100644
--- a/contrib/xml2/xpath.c
+++ b/contrib/xml2/xpath.c
@@ -497,36 +497,49 @@ static xpath_workspace *
 pgxml_xpath(text *document, xmlChar *xpath, PgXmlErrorContext *xmlerrcxt)
 {
 	int32		docsize = VARSIZE_ANY_EXHDR(document);
-	xmlXPathCompExprPtr comppath;
+	xmlXPathCompExprPtr volatile comppath = NULL;
 	xpath_workspace *workspace = palloc0_object(xpath_workspace);
 
 	workspace->doctree = NULL;
 	workspace->ctxt = NULL;
 	workspace->res = NULL;
 
-	workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
-									   docsize, NULL, NULL,
-									   XML_PARSE_NOENT);
-	if (workspace->doctree != NULL)
+	PG_TRY();
 	{
-		workspace->ctxt = xmlXPathNewContext(workspace->doctree);
-		workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
-
-		/* compile the path */
-		comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
-		if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+		workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
+										   docsize, NULL, NULL,
+										   XML_PARSE_NOENT);
+		if (workspace->doctree != NULL)
 		{
-			if (comppath != NULL)
-				xmlXPathFreeCompExpr(comppath);
-			xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
-						"XPath Syntax Error");
-		}
+			workspace->ctxt = xmlXPathNewContext(workspace->doctree);
+			if (workspace->ctxt == NULL)
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_OUT_OF_MEMORY,
+							"could not allocate XPath context");
 
-		/* Now evaluate the path expression. */
-		workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+			workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
+
+			/* compile the path */
+			comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
+			if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
+							"XPath Syntax Error");
+
+			/* Now evaluate the path expression. */
+			workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+
+			xmlXPathFreeCompExpr(comppath);
+			comppath = NULL;
+		}
+	}
+	PG_CATCH();
+	{
+		if (comppath != NULL)
+			xmlXPathFreeCompExpr(comppath);
+		cleanup_workspace(workspace);
 
-		xmlXPathFreeCompExpr(comppath);
+		PG_RE_THROW();
 	}
+	PG_END_TRY();
 
 	return workspace;
 }
-- 
2.54.0


--MP_/LMSk9=uMhuQ1QiIJDarDO8G--





^ permalink  raw  reply  [nested|flat] 611+ messages in thread

* [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths
@ 2026-06-01 22:41 Andrey Chernyy <andrey.cherny@tantorlabs.com>
  0 siblings, 0 replies; 611+ messages in thread

From: Andrey Chernyy @ 2026-06-01 22:41 UTC (permalink / raw)

pgxml_xpath() builds an xpath_workspace before returning it to
callers.  If an ERROR is thrown before the function returns, callers
have not received the workspace pointer yet and cannot run
cleanup_workspace().

Add local error cleanup for the partially built workspace and the
compiled XPath expression.  Also check xmlXPathNewContext() before
dereferencing the returned context.
---
 contrib/xml2/xpath.c | 51 +++++++++++++++++++++++++++-----------------
 1 file changed, 32 insertions(+), 19 deletions(-)

diff --git a/contrib/xml2/xpath.c b/contrib/xml2/xpath.c
index 9fe75cb5ff4..283bb51178d 100644
--- a/contrib/xml2/xpath.c
+++ b/contrib/xml2/xpath.c
@@ -497,36 +497,49 @@ static xpath_workspace *
 pgxml_xpath(text *document, xmlChar *xpath, PgXmlErrorContext *xmlerrcxt)
 {
 	int32		docsize = VARSIZE_ANY_EXHDR(document);
-	xmlXPathCompExprPtr comppath;
+	xmlXPathCompExprPtr volatile comppath = NULL;
 	xpath_workspace *workspace = palloc0_object(xpath_workspace);
 
 	workspace->doctree = NULL;
 	workspace->ctxt = NULL;
 	workspace->res = NULL;
 
-	workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
-									   docsize, NULL, NULL,
-									   XML_PARSE_NOENT);
-	if (workspace->doctree != NULL)
+	PG_TRY();
 	{
-		workspace->ctxt = xmlXPathNewContext(workspace->doctree);
-		workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
-
-		/* compile the path */
-		comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
-		if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+		workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
+										   docsize, NULL, NULL,
+										   XML_PARSE_NOENT);
+		if (workspace->doctree != NULL)
 		{
-			if (comppath != NULL)
-				xmlXPathFreeCompExpr(comppath);
-			xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
-						"XPath Syntax Error");
-		}
+			workspace->ctxt = xmlXPathNewContext(workspace->doctree);
+			if (workspace->ctxt == NULL)
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_OUT_OF_MEMORY,
+							"could not allocate XPath context");
 
-		/* Now evaluate the path expression. */
-		workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+			workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
+
+			/* compile the path */
+			comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
+			if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
+							"XPath Syntax Error");
+
+			/* Now evaluate the path expression. */
+			workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+
+			xmlXPathFreeCompExpr(comppath);
+			comppath = NULL;
+		}
+	}
+	PG_CATCH();
+	{
+		if (comppath != NULL)
+			xmlXPathFreeCompExpr(comppath);
+		cleanup_workspace(workspace);
 
-		xmlXPathFreeCompExpr(comppath);
+		PG_RE_THROW();
 	}
+	PG_END_TRY();
 
 	return workspace;
 }
-- 
2.54.0


--MP_/LMSk9=uMhuQ1QiIJDarDO8G--






^ permalink  raw  reply  [nested|flat] 611+ messages in thread

* [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths
@ 2026-06-01 22:41 Andrey Chernyy <andrey.cherny@tantorlabs.com>
  0 siblings, 0 replies; 611+ messages in thread

From: Andrey Chernyy @ 2026-06-01 22:41 UTC (permalink / raw)

pgxml_xpath() builds an xpath_workspace before returning it to
callers.  If an ERROR is thrown before the function returns, callers
have not received the workspace pointer yet and cannot run
cleanup_workspace().

Add local error cleanup for the partially built workspace and the
compiled XPath expression.  Also check xmlXPathNewContext() before
dereferencing the returned context.
---
 contrib/xml2/xpath.c | 51 +++++++++++++++++++++++++++-----------------
 1 file changed, 32 insertions(+), 19 deletions(-)

diff --git a/contrib/xml2/xpath.c b/contrib/xml2/xpath.c
index 9fe75cb5ff4..283bb51178d 100644
--- a/contrib/xml2/xpath.c
+++ b/contrib/xml2/xpath.c
@@ -497,36 +497,49 @@ static xpath_workspace *
 pgxml_xpath(text *document, xmlChar *xpath, PgXmlErrorContext *xmlerrcxt)
 {
 	int32		docsize = VARSIZE_ANY_EXHDR(document);
-	xmlXPathCompExprPtr comppath;
+	xmlXPathCompExprPtr volatile comppath = NULL;
 	xpath_workspace *workspace = palloc0_object(xpath_workspace);
 
 	workspace->doctree = NULL;
 	workspace->ctxt = NULL;
 	workspace->res = NULL;
 
-	workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
-									   docsize, NULL, NULL,
-									   XML_PARSE_NOENT);
-	if (workspace->doctree != NULL)
+	PG_TRY();
 	{
-		workspace->ctxt = xmlXPathNewContext(workspace->doctree);
-		workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
-
-		/* compile the path */
-		comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
-		if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+		workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
+										   docsize, NULL, NULL,
+										   XML_PARSE_NOENT);
+		if (workspace->doctree != NULL)
 		{
-			if (comppath != NULL)
-				xmlXPathFreeCompExpr(comppath);
-			xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
-						"XPath Syntax Error");
-		}
+			workspace->ctxt = xmlXPathNewContext(workspace->doctree);
+			if (workspace->ctxt == NULL)
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_OUT_OF_MEMORY,
+							"could not allocate XPath context");
 
-		/* Now evaluate the path expression. */
-		workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+			workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
+
+			/* compile the path */
+			comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
+			if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
+							"XPath Syntax Error");
+
+			/* Now evaluate the path expression. */
+			workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+
+			xmlXPathFreeCompExpr(comppath);
+			comppath = NULL;
+		}
+	}
+	PG_CATCH();
+	{
+		if (comppath != NULL)
+			xmlXPathFreeCompExpr(comppath);
+		cleanup_workspace(workspace);
 
-		xmlXPathFreeCompExpr(comppath);
+		PG_RE_THROW();
 	}
+	PG_END_TRY();
 
 	return workspace;
 }
-- 
2.54.0


--MP_/LMSk9=uMhuQ1QiIJDarDO8G--





^ permalink  raw  reply  [nested|flat] 611+ messages in thread

* [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths
@ 2026-06-01 22:41 Andrey Chernyy <andrey.cherny@tantorlabs.com>
  0 siblings, 0 replies; 611+ messages in thread

From: Andrey Chernyy @ 2026-06-01 22:41 UTC (permalink / raw)

pgxml_xpath() builds an xpath_workspace before returning it to
callers.  If an ERROR is thrown before the function returns, callers
have not received the workspace pointer yet and cannot run
cleanup_workspace().

Add local error cleanup for the partially built workspace and the
compiled XPath expression.  Also check xmlXPathNewContext() before
dereferencing the returned context.
---
 contrib/xml2/xpath.c | 51 +++++++++++++++++++++++++++-----------------
 1 file changed, 32 insertions(+), 19 deletions(-)

diff --git a/contrib/xml2/xpath.c b/contrib/xml2/xpath.c
index 9fe75cb5ff4..283bb51178d 100644
--- a/contrib/xml2/xpath.c
+++ b/contrib/xml2/xpath.c
@@ -497,36 +497,49 @@ static xpath_workspace *
 pgxml_xpath(text *document, xmlChar *xpath, PgXmlErrorContext *xmlerrcxt)
 {
 	int32		docsize = VARSIZE_ANY_EXHDR(document);
-	xmlXPathCompExprPtr comppath;
+	xmlXPathCompExprPtr volatile comppath = NULL;
 	xpath_workspace *workspace = palloc0_object(xpath_workspace);
 
 	workspace->doctree = NULL;
 	workspace->ctxt = NULL;
 	workspace->res = NULL;
 
-	workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
-									   docsize, NULL, NULL,
-									   XML_PARSE_NOENT);
-	if (workspace->doctree != NULL)
+	PG_TRY();
 	{
-		workspace->ctxt = xmlXPathNewContext(workspace->doctree);
-		workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
-
-		/* compile the path */
-		comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
-		if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+		workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
+										   docsize, NULL, NULL,
+										   XML_PARSE_NOENT);
+		if (workspace->doctree != NULL)
 		{
-			if (comppath != NULL)
-				xmlXPathFreeCompExpr(comppath);
-			xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
-						"XPath Syntax Error");
-		}
+			workspace->ctxt = xmlXPathNewContext(workspace->doctree);
+			if (workspace->ctxt == NULL)
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_OUT_OF_MEMORY,
+							"could not allocate XPath context");
 
-		/* Now evaluate the path expression. */
-		workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+			workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
+
+			/* compile the path */
+			comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
+			if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
+							"XPath Syntax Error");
+
+			/* Now evaluate the path expression. */
+			workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+
+			xmlXPathFreeCompExpr(comppath);
+			comppath = NULL;
+		}
+	}
+	PG_CATCH();
+	{
+		if (comppath != NULL)
+			xmlXPathFreeCompExpr(comppath);
+		cleanup_workspace(workspace);
 
-		xmlXPathFreeCompExpr(comppath);
+		PG_RE_THROW();
 	}
+	PG_END_TRY();
 
 	return workspace;
 }
-- 
2.54.0


--MP_/LMSk9=uMhuQ1QiIJDarDO8G--





^ permalink  raw  reply  [nested|flat] 611+ messages in thread

* [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths
@ 2026-06-01 22:41 Andrey Chernyy <andrey.cherny@tantorlabs.com>
  0 siblings, 0 replies; 611+ messages in thread

From: Andrey Chernyy @ 2026-06-01 22:41 UTC (permalink / raw)

pgxml_xpath() builds an xpath_workspace before returning it to
callers.  If an ERROR is thrown before the function returns, callers
have not received the workspace pointer yet and cannot run
cleanup_workspace().

Add local error cleanup for the partially built workspace and the
compiled XPath expression.  Also check xmlXPathNewContext() before
dereferencing the returned context.
---
 contrib/xml2/xpath.c | 51 +++++++++++++++++++++++++++-----------------
 1 file changed, 32 insertions(+), 19 deletions(-)

diff --git a/contrib/xml2/xpath.c b/contrib/xml2/xpath.c
index 9fe75cb5ff4..283bb51178d 100644
--- a/contrib/xml2/xpath.c
+++ b/contrib/xml2/xpath.c
@@ -497,36 +497,49 @@ static xpath_workspace *
 pgxml_xpath(text *document, xmlChar *xpath, PgXmlErrorContext *xmlerrcxt)
 {
 	int32		docsize = VARSIZE_ANY_EXHDR(document);
-	xmlXPathCompExprPtr comppath;
+	xmlXPathCompExprPtr volatile comppath = NULL;
 	xpath_workspace *workspace = palloc0_object(xpath_workspace);
 
 	workspace->doctree = NULL;
 	workspace->ctxt = NULL;
 	workspace->res = NULL;
 
-	workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
-									   docsize, NULL, NULL,
-									   XML_PARSE_NOENT);
-	if (workspace->doctree != NULL)
+	PG_TRY();
 	{
-		workspace->ctxt = xmlXPathNewContext(workspace->doctree);
-		workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
-
-		/* compile the path */
-		comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
-		if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+		workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
+										   docsize, NULL, NULL,
+										   XML_PARSE_NOENT);
+		if (workspace->doctree != NULL)
 		{
-			if (comppath != NULL)
-				xmlXPathFreeCompExpr(comppath);
-			xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
-						"XPath Syntax Error");
-		}
+			workspace->ctxt = xmlXPathNewContext(workspace->doctree);
+			if (workspace->ctxt == NULL)
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_OUT_OF_MEMORY,
+							"could not allocate XPath context");
 
-		/* Now evaluate the path expression. */
-		workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+			workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
+
+			/* compile the path */
+			comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
+			if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
+							"XPath Syntax Error");
+
+			/* Now evaluate the path expression. */
+			workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+
+			xmlXPathFreeCompExpr(comppath);
+			comppath = NULL;
+		}
+	}
+	PG_CATCH();
+	{
+		if (comppath != NULL)
+			xmlXPathFreeCompExpr(comppath);
+		cleanup_workspace(workspace);
 
-		xmlXPathFreeCompExpr(comppath);
+		PG_RE_THROW();
 	}
+	PG_END_TRY();
 
 	return workspace;
 }
-- 
2.54.0


--MP_/LMSk9=uMhuQ1QiIJDarDO8G--





^ permalink  raw  reply  [nested|flat] 611+ messages in thread

* [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths
@ 2026-06-01 22:41 Andrey Chernyy <andrey.cherny@tantorlabs.com>
  0 siblings, 0 replies; 611+ messages in thread

From: Andrey Chernyy @ 2026-06-01 22:41 UTC (permalink / raw)

pgxml_xpath() builds an xpath_workspace before returning it to
callers.  If an ERROR is thrown before the function returns, callers
have not received the workspace pointer yet and cannot run
cleanup_workspace().

Add local error cleanup for the partially built workspace and the
compiled XPath expression.  Also check xmlXPathNewContext() before
dereferencing the returned context.
---
 contrib/xml2/xpath.c | 51 +++++++++++++++++++++++++++-----------------
 1 file changed, 32 insertions(+), 19 deletions(-)

diff --git a/contrib/xml2/xpath.c b/contrib/xml2/xpath.c
index 9fe75cb5ff4..283bb51178d 100644
--- a/contrib/xml2/xpath.c
+++ b/contrib/xml2/xpath.c
@@ -497,36 +497,49 @@ static xpath_workspace *
 pgxml_xpath(text *document, xmlChar *xpath, PgXmlErrorContext *xmlerrcxt)
 {
 	int32		docsize = VARSIZE_ANY_EXHDR(document);
-	xmlXPathCompExprPtr comppath;
+	xmlXPathCompExprPtr volatile comppath = NULL;
 	xpath_workspace *workspace = palloc0_object(xpath_workspace);
 
 	workspace->doctree = NULL;
 	workspace->ctxt = NULL;
 	workspace->res = NULL;
 
-	workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
-									   docsize, NULL, NULL,
-									   XML_PARSE_NOENT);
-	if (workspace->doctree != NULL)
+	PG_TRY();
 	{
-		workspace->ctxt = xmlXPathNewContext(workspace->doctree);
-		workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
-
-		/* compile the path */
-		comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
-		if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+		workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
+										   docsize, NULL, NULL,
+										   XML_PARSE_NOENT);
+		if (workspace->doctree != NULL)
 		{
-			if (comppath != NULL)
-				xmlXPathFreeCompExpr(comppath);
-			xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
-						"XPath Syntax Error");
-		}
+			workspace->ctxt = xmlXPathNewContext(workspace->doctree);
+			if (workspace->ctxt == NULL)
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_OUT_OF_MEMORY,
+							"could not allocate XPath context");
 
-		/* Now evaluate the path expression. */
-		workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+			workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
+
+			/* compile the path */
+			comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
+			if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
+							"XPath Syntax Error");
+
+			/* Now evaluate the path expression. */
+			workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+
+			xmlXPathFreeCompExpr(comppath);
+			comppath = NULL;
+		}
+	}
+	PG_CATCH();
+	{
+		if (comppath != NULL)
+			xmlXPathFreeCompExpr(comppath);
+		cleanup_workspace(workspace);
 
-		xmlXPathFreeCompExpr(comppath);
+		PG_RE_THROW();
 	}
+	PG_END_TRY();
 
 	return workspace;
 }
-- 
2.54.0


--MP_/LMSk9=uMhuQ1QiIJDarDO8G--





^ permalink  raw  reply  [nested|flat] 611+ messages in thread

* [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths
@ 2026-06-01 22:41 Andrey Chernyy <andrey.cherny@tantorlabs.com>
  0 siblings, 0 replies; 611+ messages in thread

From: Andrey Chernyy @ 2026-06-01 22:41 UTC (permalink / raw)

pgxml_xpath() builds an xpath_workspace before returning it to
callers.  If an ERROR is thrown before the function returns, callers
have not received the workspace pointer yet and cannot run
cleanup_workspace().

Add local error cleanup for the partially built workspace and the
compiled XPath expression.  Also check xmlXPathNewContext() before
dereferencing the returned context.
---
 contrib/xml2/xpath.c | 51 +++++++++++++++++++++++++++-----------------
 1 file changed, 32 insertions(+), 19 deletions(-)

diff --git a/contrib/xml2/xpath.c b/contrib/xml2/xpath.c
index 9fe75cb5ff4..283bb51178d 100644
--- a/contrib/xml2/xpath.c
+++ b/contrib/xml2/xpath.c
@@ -497,36 +497,49 @@ static xpath_workspace *
 pgxml_xpath(text *document, xmlChar *xpath, PgXmlErrorContext *xmlerrcxt)
 {
 	int32		docsize = VARSIZE_ANY_EXHDR(document);
-	xmlXPathCompExprPtr comppath;
+	xmlXPathCompExprPtr volatile comppath = NULL;
 	xpath_workspace *workspace = palloc0_object(xpath_workspace);
 
 	workspace->doctree = NULL;
 	workspace->ctxt = NULL;
 	workspace->res = NULL;
 
-	workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
-									   docsize, NULL, NULL,
-									   XML_PARSE_NOENT);
-	if (workspace->doctree != NULL)
+	PG_TRY();
 	{
-		workspace->ctxt = xmlXPathNewContext(workspace->doctree);
-		workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
-
-		/* compile the path */
-		comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
-		if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+		workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
+										   docsize, NULL, NULL,
+										   XML_PARSE_NOENT);
+		if (workspace->doctree != NULL)
 		{
-			if (comppath != NULL)
-				xmlXPathFreeCompExpr(comppath);
-			xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
-						"XPath Syntax Error");
-		}
+			workspace->ctxt = xmlXPathNewContext(workspace->doctree);
+			if (workspace->ctxt == NULL)
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_OUT_OF_MEMORY,
+							"could not allocate XPath context");
 
-		/* Now evaluate the path expression. */
-		workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+			workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
+
+			/* compile the path */
+			comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
+			if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
+							"XPath Syntax Error");
+
+			/* Now evaluate the path expression. */
+			workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+
+			xmlXPathFreeCompExpr(comppath);
+			comppath = NULL;
+		}
+	}
+	PG_CATCH();
+	{
+		if (comppath != NULL)
+			xmlXPathFreeCompExpr(comppath);
+		cleanup_workspace(workspace);
 
-		xmlXPathFreeCompExpr(comppath);
+		PG_RE_THROW();
 	}
+	PG_END_TRY();
 
 	return workspace;
 }
-- 
2.54.0


--MP_/LMSk9=uMhuQ1QiIJDarDO8G--





^ permalink  raw  reply  [nested|flat] 611+ messages in thread

* [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths
@ 2026-06-01 22:41 Andrey Chernyy <andrey.cherny@tantorlabs.com>
  0 siblings, 0 replies; 611+ messages in thread

From: Andrey Chernyy @ 2026-06-01 22:41 UTC (permalink / raw)

pgxml_xpath() builds an xpath_workspace before returning it to
callers.  If an ERROR is thrown before the function returns, callers
have not received the workspace pointer yet and cannot run
cleanup_workspace().

Add local error cleanup for the partially built workspace and the
compiled XPath expression.  Also check xmlXPathNewContext() before
dereferencing the returned context.
---
 contrib/xml2/xpath.c | 51 +++++++++++++++++++++++++++-----------------
 1 file changed, 32 insertions(+), 19 deletions(-)

diff --git a/contrib/xml2/xpath.c b/contrib/xml2/xpath.c
index 9fe75cb5ff4..283bb51178d 100644
--- a/contrib/xml2/xpath.c
+++ b/contrib/xml2/xpath.c
@@ -497,36 +497,49 @@ static xpath_workspace *
 pgxml_xpath(text *document, xmlChar *xpath, PgXmlErrorContext *xmlerrcxt)
 {
 	int32		docsize = VARSIZE_ANY_EXHDR(document);
-	xmlXPathCompExprPtr comppath;
+	xmlXPathCompExprPtr volatile comppath = NULL;
 	xpath_workspace *workspace = palloc0_object(xpath_workspace);
 
 	workspace->doctree = NULL;
 	workspace->ctxt = NULL;
 	workspace->res = NULL;
 
-	workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
-									   docsize, NULL, NULL,
-									   XML_PARSE_NOENT);
-	if (workspace->doctree != NULL)
+	PG_TRY();
 	{
-		workspace->ctxt = xmlXPathNewContext(workspace->doctree);
-		workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
-
-		/* compile the path */
-		comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
-		if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+		workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
+										   docsize, NULL, NULL,
+										   XML_PARSE_NOENT);
+		if (workspace->doctree != NULL)
 		{
-			if (comppath != NULL)
-				xmlXPathFreeCompExpr(comppath);
-			xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
-						"XPath Syntax Error");
-		}
+			workspace->ctxt = xmlXPathNewContext(workspace->doctree);
+			if (workspace->ctxt == NULL)
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_OUT_OF_MEMORY,
+							"could not allocate XPath context");
 
-		/* Now evaluate the path expression. */
-		workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+			workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
+
+			/* compile the path */
+			comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
+			if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
+							"XPath Syntax Error");
+
+			/* Now evaluate the path expression. */
+			workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+
+			xmlXPathFreeCompExpr(comppath);
+			comppath = NULL;
+		}
+	}
+	PG_CATCH();
+	{
+		if (comppath != NULL)
+			xmlXPathFreeCompExpr(comppath);
+		cleanup_workspace(workspace);
 
-		xmlXPathFreeCompExpr(comppath);
+		PG_RE_THROW();
 	}
+	PG_END_TRY();
 
 	return workspace;
 }
-- 
2.54.0


--MP_/LMSk9=uMhuQ1QiIJDarDO8G--






^ permalink  raw  reply  [nested|flat] 611+ messages in thread

* [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths
@ 2026-06-01 22:41 Andrey Chernyy <andrey.cherny@tantorlabs.com>
  0 siblings, 0 replies; 611+ messages in thread

From: Andrey Chernyy @ 2026-06-01 22:41 UTC (permalink / raw)

pgxml_xpath() builds an xpath_workspace before returning it to
callers.  If an ERROR is thrown before the function returns, callers
have not received the workspace pointer yet and cannot run
cleanup_workspace().

Add local error cleanup for the partially built workspace and the
compiled XPath expression.  Also check xmlXPathNewContext() before
dereferencing the returned context.
---
 contrib/xml2/xpath.c | 51 +++++++++++++++++++++++++++-----------------
 1 file changed, 32 insertions(+), 19 deletions(-)

diff --git a/contrib/xml2/xpath.c b/contrib/xml2/xpath.c
index 9fe75cb5ff4..283bb51178d 100644
--- a/contrib/xml2/xpath.c
+++ b/contrib/xml2/xpath.c
@@ -497,36 +497,49 @@ static xpath_workspace *
 pgxml_xpath(text *document, xmlChar *xpath, PgXmlErrorContext *xmlerrcxt)
 {
 	int32		docsize = VARSIZE_ANY_EXHDR(document);
-	xmlXPathCompExprPtr comppath;
+	xmlXPathCompExprPtr volatile comppath = NULL;
 	xpath_workspace *workspace = palloc0_object(xpath_workspace);
 
 	workspace->doctree = NULL;
 	workspace->ctxt = NULL;
 	workspace->res = NULL;
 
-	workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
-									   docsize, NULL, NULL,
-									   XML_PARSE_NOENT);
-	if (workspace->doctree != NULL)
+	PG_TRY();
 	{
-		workspace->ctxt = xmlXPathNewContext(workspace->doctree);
-		workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
-
-		/* compile the path */
-		comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
-		if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+		workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
+										   docsize, NULL, NULL,
+										   XML_PARSE_NOENT);
+		if (workspace->doctree != NULL)
 		{
-			if (comppath != NULL)
-				xmlXPathFreeCompExpr(comppath);
-			xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
-						"XPath Syntax Error");
-		}
+			workspace->ctxt = xmlXPathNewContext(workspace->doctree);
+			if (workspace->ctxt == NULL)
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_OUT_OF_MEMORY,
+							"could not allocate XPath context");
 
-		/* Now evaluate the path expression. */
-		workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+			workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
+
+			/* compile the path */
+			comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
+			if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
+							"XPath Syntax Error");
+
+			/* Now evaluate the path expression. */
+			workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+
+			xmlXPathFreeCompExpr(comppath);
+			comppath = NULL;
+		}
+	}
+	PG_CATCH();
+	{
+		if (comppath != NULL)
+			xmlXPathFreeCompExpr(comppath);
+		cleanup_workspace(workspace);
 
-		xmlXPathFreeCompExpr(comppath);
+		PG_RE_THROW();
 	}
+	PG_END_TRY();
 
 	return workspace;
 }
-- 
2.54.0


--MP_/LMSk9=uMhuQ1QiIJDarDO8G--





^ permalink  raw  reply  [nested|flat] 611+ messages in thread

* [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths
@ 2026-06-01 22:41 Andrey Chernyy <andrey.cherny@tantorlabs.com>
  0 siblings, 0 replies; 611+ messages in thread

From: Andrey Chernyy @ 2026-06-01 22:41 UTC (permalink / raw)

pgxml_xpath() builds an xpath_workspace before returning it to
callers.  If an ERROR is thrown before the function returns, callers
have not received the workspace pointer yet and cannot run
cleanup_workspace().

Add local error cleanup for the partially built workspace and the
compiled XPath expression.  Also check xmlXPathNewContext() before
dereferencing the returned context.
---
 contrib/xml2/xpath.c | 51 +++++++++++++++++++++++++++-----------------
 1 file changed, 32 insertions(+), 19 deletions(-)

diff --git a/contrib/xml2/xpath.c b/contrib/xml2/xpath.c
index 9fe75cb5ff4..283bb51178d 100644
--- a/contrib/xml2/xpath.c
+++ b/contrib/xml2/xpath.c
@@ -497,36 +497,49 @@ static xpath_workspace *
 pgxml_xpath(text *document, xmlChar *xpath, PgXmlErrorContext *xmlerrcxt)
 {
 	int32		docsize = VARSIZE_ANY_EXHDR(document);
-	xmlXPathCompExprPtr comppath;
+	xmlXPathCompExprPtr volatile comppath = NULL;
 	xpath_workspace *workspace = palloc0_object(xpath_workspace);
 
 	workspace->doctree = NULL;
 	workspace->ctxt = NULL;
 	workspace->res = NULL;
 
-	workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
-									   docsize, NULL, NULL,
-									   XML_PARSE_NOENT);
-	if (workspace->doctree != NULL)
+	PG_TRY();
 	{
-		workspace->ctxt = xmlXPathNewContext(workspace->doctree);
-		workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
-
-		/* compile the path */
-		comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
-		if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+		workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
+										   docsize, NULL, NULL,
+										   XML_PARSE_NOENT);
+		if (workspace->doctree != NULL)
 		{
-			if (comppath != NULL)
-				xmlXPathFreeCompExpr(comppath);
-			xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
-						"XPath Syntax Error");
-		}
+			workspace->ctxt = xmlXPathNewContext(workspace->doctree);
+			if (workspace->ctxt == NULL)
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_OUT_OF_MEMORY,
+							"could not allocate XPath context");
 
-		/* Now evaluate the path expression. */
-		workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+			workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
+
+			/* compile the path */
+			comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
+			if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
+							"XPath Syntax Error");
+
+			/* Now evaluate the path expression. */
+			workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+
+			xmlXPathFreeCompExpr(comppath);
+			comppath = NULL;
+		}
+	}
+	PG_CATCH();
+	{
+		if (comppath != NULL)
+			xmlXPathFreeCompExpr(comppath);
+		cleanup_workspace(workspace);
 
-		xmlXPathFreeCompExpr(comppath);
+		PG_RE_THROW();
 	}
+	PG_END_TRY();
 
 	return workspace;
 }
-- 
2.54.0


--MP_/LMSk9=uMhuQ1QiIJDarDO8G--





^ permalink  raw  reply  [nested|flat] 611+ messages in thread

* [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths
@ 2026-06-01 22:41 Andrey Chernyy <andrey.cherny@tantorlabs.com>
  0 siblings, 0 replies; 611+ messages in thread

From: Andrey Chernyy @ 2026-06-01 22:41 UTC (permalink / raw)

pgxml_xpath() builds an xpath_workspace before returning it to
callers.  If an ERROR is thrown before the function returns, callers
have not received the workspace pointer yet and cannot run
cleanup_workspace().

Add local error cleanup for the partially built workspace and the
compiled XPath expression.  Also check xmlXPathNewContext() before
dereferencing the returned context.
---
 contrib/xml2/xpath.c | 51 +++++++++++++++++++++++++++-----------------
 1 file changed, 32 insertions(+), 19 deletions(-)

diff --git a/contrib/xml2/xpath.c b/contrib/xml2/xpath.c
index 9fe75cb5ff4..283bb51178d 100644
--- a/contrib/xml2/xpath.c
+++ b/contrib/xml2/xpath.c
@@ -497,36 +497,49 @@ static xpath_workspace *
 pgxml_xpath(text *document, xmlChar *xpath, PgXmlErrorContext *xmlerrcxt)
 {
 	int32		docsize = VARSIZE_ANY_EXHDR(document);
-	xmlXPathCompExprPtr comppath;
+	xmlXPathCompExprPtr volatile comppath = NULL;
 	xpath_workspace *workspace = palloc0_object(xpath_workspace);
 
 	workspace->doctree = NULL;
 	workspace->ctxt = NULL;
 	workspace->res = NULL;
 
-	workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
-									   docsize, NULL, NULL,
-									   XML_PARSE_NOENT);
-	if (workspace->doctree != NULL)
+	PG_TRY();
 	{
-		workspace->ctxt = xmlXPathNewContext(workspace->doctree);
-		workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
-
-		/* compile the path */
-		comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
-		if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+		workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
+										   docsize, NULL, NULL,
+										   XML_PARSE_NOENT);
+		if (workspace->doctree != NULL)
 		{
-			if (comppath != NULL)
-				xmlXPathFreeCompExpr(comppath);
-			xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
-						"XPath Syntax Error");
-		}
+			workspace->ctxt = xmlXPathNewContext(workspace->doctree);
+			if (workspace->ctxt == NULL)
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_OUT_OF_MEMORY,
+							"could not allocate XPath context");
 
-		/* Now evaluate the path expression. */
-		workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+			workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
+
+			/* compile the path */
+			comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
+			if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
+							"XPath Syntax Error");
+
+			/* Now evaluate the path expression. */
+			workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+
+			xmlXPathFreeCompExpr(comppath);
+			comppath = NULL;
+		}
+	}
+	PG_CATCH();
+	{
+		if (comppath != NULL)
+			xmlXPathFreeCompExpr(comppath);
+		cleanup_workspace(workspace);
 
-		xmlXPathFreeCompExpr(comppath);
+		PG_RE_THROW();
 	}
+	PG_END_TRY();
 
 	return workspace;
 }
-- 
2.54.0


--MP_/LMSk9=uMhuQ1QiIJDarDO8G--






^ permalink  raw  reply  [nested|flat] 611+ messages in thread

* [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths
@ 2026-06-01 22:41 Andrey Chernyy <andrey.cherny@tantorlabs.com>
  0 siblings, 0 replies; 611+ messages in thread

From: Andrey Chernyy @ 2026-06-01 22:41 UTC (permalink / raw)

pgxml_xpath() builds an xpath_workspace before returning it to
callers.  If an ERROR is thrown before the function returns, callers
have not received the workspace pointer yet and cannot run
cleanup_workspace().

Add local error cleanup for the partially built workspace and the
compiled XPath expression.  Also check xmlXPathNewContext() before
dereferencing the returned context.
---
 contrib/xml2/xpath.c | 51 +++++++++++++++++++++++++++-----------------
 1 file changed, 32 insertions(+), 19 deletions(-)

diff --git a/contrib/xml2/xpath.c b/contrib/xml2/xpath.c
index 9fe75cb5ff4..283bb51178d 100644
--- a/contrib/xml2/xpath.c
+++ b/contrib/xml2/xpath.c
@@ -497,36 +497,49 @@ static xpath_workspace *
 pgxml_xpath(text *document, xmlChar *xpath, PgXmlErrorContext *xmlerrcxt)
 {
 	int32		docsize = VARSIZE_ANY_EXHDR(document);
-	xmlXPathCompExprPtr comppath;
+	xmlXPathCompExprPtr volatile comppath = NULL;
 	xpath_workspace *workspace = palloc0_object(xpath_workspace);
 
 	workspace->doctree = NULL;
 	workspace->ctxt = NULL;
 	workspace->res = NULL;
 
-	workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
-									   docsize, NULL, NULL,
-									   XML_PARSE_NOENT);
-	if (workspace->doctree != NULL)
+	PG_TRY();
 	{
-		workspace->ctxt = xmlXPathNewContext(workspace->doctree);
-		workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
-
-		/* compile the path */
-		comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
-		if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+		workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
+										   docsize, NULL, NULL,
+										   XML_PARSE_NOENT);
+		if (workspace->doctree != NULL)
 		{
-			if (comppath != NULL)
-				xmlXPathFreeCompExpr(comppath);
-			xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
-						"XPath Syntax Error");
-		}
+			workspace->ctxt = xmlXPathNewContext(workspace->doctree);
+			if (workspace->ctxt == NULL)
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_OUT_OF_MEMORY,
+							"could not allocate XPath context");
 
-		/* Now evaluate the path expression. */
-		workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+			workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
+
+			/* compile the path */
+			comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
+			if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
+							"XPath Syntax Error");
+
+			/* Now evaluate the path expression. */
+			workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+
+			xmlXPathFreeCompExpr(comppath);
+			comppath = NULL;
+		}
+	}
+	PG_CATCH();
+	{
+		if (comppath != NULL)
+			xmlXPathFreeCompExpr(comppath);
+		cleanup_workspace(workspace);
 
-		xmlXPathFreeCompExpr(comppath);
+		PG_RE_THROW();
 	}
+	PG_END_TRY();
 
 	return workspace;
 }
-- 
2.54.0


--MP_/LMSk9=uMhuQ1QiIJDarDO8G--






^ permalink  raw  reply  [nested|flat] 611+ messages in thread

* [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths
@ 2026-06-01 22:41 Andrey Chernyy <andrey.cherny@tantorlabs.com>
  0 siblings, 0 replies; 611+ messages in thread

From: Andrey Chernyy @ 2026-06-01 22:41 UTC (permalink / raw)

pgxml_xpath() builds an xpath_workspace before returning it to
callers.  If an ERROR is thrown before the function returns, callers
have not received the workspace pointer yet and cannot run
cleanup_workspace().

Add local error cleanup for the partially built workspace and the
compiled XPath expression.  Also check xmlXPathNewContext() before
dereferencing the returned context.
---
 contrib/xml2/xpath.c | 51 +++++++++++++++++++++++++++-----------------
 1 file changed, 32 insertions(+), 19 deletions(-)

diff --git a/contrib/xml2/xpath.c b/contrib/xml2/xpath.c
index 9fe75cb5ff4..283bb51178d 100644
--- a/contrib/xml2/xpath.c
+++ b/contrib/xml2/xpath.c
@@ -497,36 +497,49 @@ static xpath_workspace *
 pgxml_xpath(text *document, xmlChar *xpath, PgXmlErrorContext *xmlerrcxt)
 {
 	int32		docsize = VARSIZE_ANY_EXHDR(document);
-	xmlXPathCompExprPtr comppath;
+	xmlXPathCompExprPtr volatile comppath = NULL;
 	xpath_workspace *workspace = palloc0_object(xpath_workspace);
 
 	workspace->doctree = NULL;
 	workspace->ctxt = NULL;
 	workspace->res = NULL;
 
-	workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
-									   docsize, NULL, NULL,
-									   XML_PARSE_NOENT);
-	if (workspace->doctree != NULL)
+	PG_TRY();
 	{
-		workspace->ctxt = xmlXPathNewContext(workspace->doctree);
-		workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
-
-		/* compile the path */
-		comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
-		if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+		workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
+										   docsize, NULL, NULL,
+										   XML_PARSE_NOENT);
+		if (workspace->doctree != NULL)
 		{
-			if (comppath != NULL)
-				xmlXPathFreeCompExpr(comppath);
-			xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
-						"XPath Syntax Error");
-		}
+			workspace->ctxt = xmlXPathNewContext(workspace->doctree);
+			if (workspace->ctxt == NULL)
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_OUT_OF_MEMORY,
+							"could not allocate XPath context");
 
-		/* Now evaluate the path expression. */
-		workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+			workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
+
+			/* compile the path */
+			comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
+			if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
+							"XPath Syntax Error");
+
+			/* Now evaluate the path expression. */
+			workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+
+			xmlXPathFreeCompExpr(comppath);
+			comppath = NULL;
+		}
+	}
+	PG_CATCH();
+	{
+		if (comppath != NULL)
+			xmlXPathFreeCompExpr(comppath);
+		cleanup_workspace(workspace);
 
-		xmlXPathFreeCompExpr(comppath);
+		PG_RE_THROW();
 	}
+	PG_END_TRY();
 
 	return workspace;
 }
-- 
2.54.0


--MP_/LMSk9=uMhuQ1QiIJDarDO8G--






^ permalink  raw  reply  [nested|flat] 611+ messages in thread

* [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths
@ 2026-06-01 22:41 Andrey Chernyy <andrey.cherny@tantorlabs.com>
  0 siblings, 0 replies; 611+ messages in thread

From: Andrey Chernyy @ 2026-06-01 22:41 UTC (permalink / raw)

pgxml_xpath() builds an xpath_workspace before returning it to
callers.  If an ERROR is thrown before the function returns, callers
have not received the workspace pointer yet and cannot run
cleanup_workspace().

Add local error cleanup for the partially built workspace and the
compiled XPath expression.  Also check xmlXPathNewContext() before
dereferencing the returned context.
---
 contrib/xml2/xpath.c | 51 +++++++++++++++++++++++++++-----------------
 1 file changed, 32 insertions(+), 19 deletions(-)

diff --git a/contrib/xml2/xpath.c b/contrib/xml2/xpath.c
index 9fe75cb5ff4..283bb51178d 100644
--- a/contrib/xml2/xpath.c
+++ b/contrib/xml2/xpath.c
@@ -497,36 +497,49 @@ static xpath_workspace *
 pgxml_xpath(text *document, xmlChar *xpath, PgXmlErrorContext *xmlerrcxt)
 {
 	int32		docsize = VARSIZE_ANY_EXHDR(document);
-	xmlXPathCompExprPtr comppath;
+	xmlXPathCompExprPtr volatile comppath = NULL;
 	xpath_workspace *workspace = palloc0_object(xpath_workspace);
 
 	workspace->doctree = NULL;
 	workspace->ctxt = NULL;
 	workspace->res = NULL;
 
-	workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
-									   docsize, NULL, NULL,
-									   XML_PARSE_NOENT);
-	if (workspace->doctree != NULL)
+	PG_TRY();
 	{
-		workspace->ctxt = xmlXPathNewContext(workspace->doctree);
-		workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
-
-		/* compile the path */
-		comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
-		if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+		workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
+										   docsize, NULL, NULL,
+										   XML_PARSE_NOENT);
+		if (workspace->doctree != NULL)
 		{
-			if (comppath != NULL)
-				xmlXPathFreeCompExpr(comppath);
-			xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
-						"XPath Syntax Error");
-		}
+			workspace->ctxt = xmlXPathNewContext(workspace->doctree);
+			if (workspace->ctxt == NULL)
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_OUT_OF_MEMORY,
+							"could not allocate XPath context");
 
-		/* Now evaluate the path expression. */
-		workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+			workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
+
+			/* compile the path */
+			comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
+			if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
+							"XPath Syntax Error");
+
+			/* Now evaluate the path expression. */
+			workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+
+			xmlXPathFreeCompExpr(comppath);
+			comppath = NULL;
+		}
+	}
+	PG_CATCH();
+	{
+		if (comppath != NULL)
+			xmlXPathFreeCompExpr(comppath);
+		cleanup_workspace(workspace);
 
-		xmlXPathFreeCompExpr(comppath);
+		PG_RE_THROW();
 	}
+	PG_END_TRY();
 
 	return workspace;
 }
-- 
2.54.0


--MP_/LMSk9=uMhuQ1QiIJDarDO8G--






^ permalink  raw  reply  [nested|flat] 611+ messages in thread

* [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths
@ 2026-06-01 22:41 Andrey Chernyy <andrey.cherny@tantorlabs.com>
  0 siblings, 0 replies; 611+ messages in thread

From: Andrey Chernyy @ 2026-06-01 22:41 UTC (permalink / raw)

pgxml_xpath() builds an xpath_workspace before returning it to
callers.  If an ERROR is thrown before the function returns, callers
have not received the workspace pointer yet and cannot run
cleanup_workspace().

Add local error cleanup for the partially built workspace and the
compiled XPath expression.  Also check xmlXPathNewContext() before
dereferencing the returned context.
---
 contrib/xml2/xpath.c | 51 +++++++++++++++++++++++++++-----------------
 1 file changed, 32 insertions(+), 19 deletions(-)

diff --git a/contrib/xml2/xpath.c b/contrib/xml2/xpath.c
index 9fe75cb5ff4..283bb51178d 100644
--- a/contrib/xml2/xpath.c
+++ b/contrib/xml2/xpath.c
@@ -497,36 +497,49 @@ static xpath_workspace *
 pgxml_xpath(text *document, xmlChar *xpath, PgXmlErrorContext *xmlerrcxt)
 {
 	int32		docsize = VARSIZE_ANY_EXHDR(document);
-	xmlXPathCompExprPtr comppath;
+	xmlXPathCompExprPtr volatile comppath = NULL;
 	xpath_workspace *workspace = palloc0_object(xpath_workspace);
 
 	workspace->doctree = NULL;
 	workspace->ctxt = NULL;
 	workspace->res = NULL;
 
-	workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
-									   docsize, NULL, NULL,
-									   XML_PARSE_NOENT);
-	if (workspace->doctree != NULL)
+	PG_TRY();
 	{
-		workspace->ctxt = xmlXPathNewContext(workspace->doctree);
-		workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
-
-		/* compile the path */
-		comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
-		if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+		workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
+										   docsize, NULL, NULL,
+										   XML_PARSE_NOENT);
+		if (workspace->doctree != NULL)
 		{
-			if (comppath != NULL)
-				xmlXPathFreeCompExpr(comppath);
-			xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
-						"XPath Syntax Error");
-		}
+			workspace->ctxt = xmlXPathNewContext(workspace->doctree);
+			if (workspace->ctxt == NULL)
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_OUT_OF_MEMORY,
+							"could not allocate XPath context");
 
-		/* Now evaluate the path expression. */
-		workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+			workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
+
+			/* compile the path */
+			comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
+			if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
+							"XPath Syntax Error");
+
+			/* Now evaluate the path expression. */
+			workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+
+			xmlXPathFreeCompExpr(comppath);
+			comppath = NULL;
+		}
+	}
+	PG_CATCH();
+	{
+		if (comppath != NULL)
+			xmlXPathFreeCompExpr(comppath);
+		cleanup_workspace(workspace);
 
-		xmlXPathFreeCompExpr(comppath);
+		PG_RE_THROW();
 	}
+	PG_END_TRY();
 
 	return workspace;
 }
-- 
2.54.0


--MP_/LMSk9=uMhuQ1QiIJDarDO8G--





^ permalink  raw  reply  [nested|flat] 611+ messages in thread

* [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths
@ 2026-06-01 22:41 Andrey Chernyy <andrey.cherny@tantorlabs.com>
  0 siblings, 0 replies; 611+ messages in thread

From: Andrey Chernyy @ 2026-06-01 22:41 UTC (permalink / raw)

pgxml_xpath() builds an xpath_workspace before returning it to
callers.  If an ERROR is thrown before the function returns, callers
have not received the workspace pointer yet and cannot run
cleanup_workspace().

Add local error cleanup for the partially built workspace and the
compiled XPath expression.  Also check xmlXPathNewContext() before
dereferencing the returned context.
---
 contrib/xml2/xpath.c | 51 +++++++++++++++++++++++++++-----------------
 1 file changed, 32 insertions(+), 19 deletions(-)

diff --git a/contrib/xml2/xpath.c b/contrib/xml2/xpath.c
index 9fe75cb5ff4..283bb51178d 100644
--- a/contrib/xml2/xpath.c
+++ b/contrib/xml2/xpath.c
@@ -497,36 +497,49 @@ static xpath_workspace *
 pgxml_xpath(text *document, xmlChar *xpath, PgXmlErrorContext *xmlerrcxt)
 {
 	int32		docsize = VARSIZE_ANY_EXHDR(document);
-	xmlXPathCompExprPtr comppath;
+	xmlXPathCompExprPtr volatile comppath = NULL;
 	xpath_workspace *workspace = palloc0_object(xpath_workspace);
 
 	workspace->doctree = NULL;
 	workspace->ctxt = NULL;
 	workspace->res = NULL;
 
-	workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
-									   docsize, NULL, NULL,
-									   XML_PARSE_NOENT);
-	if (workspace->doctree != NULL)
+	PG_TRY();
 	{
-		workspace->ctxt = xmlXPathNewContext(workspace->doctree);
-		workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
-
-		/* compile the path */
-		comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
-		if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+		workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
+										   docsize, NULL, NULL,
+										   XML_PARSE_NOENT);
+		if (workspace->doctree != NULL)
 		{
-			if (comppath != NULL)
-				xmlXPathFreeCompExpr(comppath);
-			xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
-						"XPath Syntax Error");
-		}
+			workspace->ctxt = xmlXPathNewContext(workspace->doctree);
+			if (workspace->ctxt == NULL)
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_OUT_OF_MEMORY,
+							"could not allocate XPath context");
 
-		/* Now evaluate the path expression. */
-		workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+			workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
+
+			/* compile the path */
+			comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
+			if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
+							"XPath Syntax Error");
+
+			/* Now evaluate the path expression. */
+			workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+
+			xmlXPathFreeCompExpr(comppath);
+			comppath = NULL;
+		}
+	}
+	PG_CATCH();
+	{
+		if (comppath != NULL)
+			xmlXPathFreeCompExpr(comppath);
+		cleanup_workspace(workspace);
 
-		xmlXPathFreeCompExpr(comppath);
+		PG_RE_THROW();
 	}
+	PG_END_TRY();
 
 	return workspace;
 }
-- 
2.54.0


--MP_/LMSk9=uMhuQ1QiIJDarDO8G--






^ permalink  raw  reply  [nested|flat] 611+ messages in thread

* [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths
@ 2026-06-01 22:41 Andrey Chernyy <andrey.cherny@tantorlabs.com>
  0 siblings, 0 replies; 611+ messages in thread

From: Andrey Chernyy @ 2026-06-01 22:41 UTC (permalink / raw)

pgxml_xpath() builds an xpath_workspace before returning it to
callers.  If an ERROR is thrown before the function returns, callers
have not received the workspace pointer yet and cannot run
cleanup_workspace().

Add local error cleanup for the partially built workspace and the
compiled XPath expression.  Also check xmlXPathNewContext() before
dereferencing the returned context.
---
 contrib/xml2/xpath.c | 51 +++++++++++++++++++++++++++-----------------
 1 file changed, 32 insertions(+), 19 deletions(-)

diff --git a/contrib/xml2/xpath.c b/contrib/xml2/xpath.c
index 9fe75cb5ff4..283bb51178d 100644
--- a/contrib/xml2/xpath.c
+++ b/contrib/xml2/xpath.c
@@ -497,36 +497,49 @@ static xpath_workspace *
 pgxml_xpath(text *document, xmlChar *xpath, PgXmlErrorContext *xmlerrcxt)
 {
 	int32		docsize = VARSIZE_ANY_EXHDR(document);
-	xmlXPathCompExprPtr comppath;
+	xmlXPathCompExprPtr volatile comppath = NULL;
 	xpath_workspace *workspace = palloc0_object(xpath_workspace);
 
 	workspace->doctree = NULL;
 	workspace->ctxt = NULL;
 	workspace->res = NULL;
 
-	workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
-									   docsize, NULL, NULL,
-									   XML_PARSE_NOENT);
-	if (workspace->doctree != NULL)
+	PG_TRY();
 	{
-		workspace->ctxt = xmlXPathNewContext(workspace->doctree);
-		workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
-
-		/* compile the path */
-		comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
-		if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+		workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
+										   docsize, NULL, NULL,
+										   XML_PARSE_NOENT);
+		if (workspace->doctree != NULL)
 		{
-			if (comppath != NULL)
-				xmlXPathFreeCompExpr(comppath);
-			xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
-						"XPath Syntax Error");
-		}
+			workspace->ctxt = xmlXPathNewContext(workspace->doctree);
+			if (workspace->ctxt == NULL)
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_OUT_OF_MEMORY,
+							"could not allocate XPath context");
 
-		/* Now evaluate the path expression. */
-		workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+			workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
+
+			/* compile the path */
+			comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
+			if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
+							"XPath Syntax Error");
+
+			/* Now evaluate the path expression. */
+			workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+
+			xmlXPathFreeCompExpr(comppath);
+			comppath = NULL;
+		}
+	}
+	PG_CATCH();
+	{
+		if (comppath != NULL)
+			xmlXPathFreeCompExpr(comppath);
+		cleanup_workspace(workspace);
 
-		xmlXPathFreeCompExpr(comppath);
+		PG_RE_THROW();
 	}
+	PG_END_TRY();
 
 	return workspace;
 }
-- 
2.54.0


--MP_/LMSk9=uMhuQ1QiIJDarDO8G--





^ permalink  raw  reply  [nested|flat] 611+ messages in thread

* [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths
@ 2026-06-01 22:41 Andrey Chernyy <andrey.cherny@tantorlabs.com>
  0 siblings, 0 replies; 611+ messages in thread

From: Andrey Chernyy @ 2026-06-01 22:41 UTC (permalink / raw)

pgxml_xpath() builds an xpath_workspace before returning it to
callers.  If an ERROR is thrown before the function returns, callers
have not received the workspace pointer yet and cannot run
cleanup_workspace().

Add local error cleanup for the partially built workspace and the
compiled XPath expression.  Also check xmlXPathNewContext() before
dereferencing the returned context.
---
 contrib/xml2/xpath.c | 51 +++++++++++++++++++++++++++-----------------
 1 file changed, 32 insertions(+), 19 deletions(-)

diff --git a/contrib/xml2/xpath.c b/contrib/xml2/xpath.c
index 9fe75cb5ff4..283bb51178d 100644
--- a/contrib/xml2/xpath.c
+++ b/contrib/xml2/xpath.c
@@ -497,36 +497,49 @@ static xpath_workspace *
 pgxml_xpath(text *document, xmlChar *xpath, PgXmlErrorContext *xmlerrcxt)
 {
 	int32		docsize = VARSIZE_ANY_EXHDR(document);
-	xmlXPathCompExprPtr comppath;
+	xmlXPathCompExprPtr volatile comppath = NULL;
 	xpath_workspace *workspace = palloc0_object(xpath_workspace);
 
 	workspace->doctree = NULL;
 	workspace->ctxt = NULL;
 	workspace->res = NULL;
 
-	workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
-									   docsize, NULL, NULL,
-									   XML_PARSE_NOENT);
-	if (workspace->doctree != NULL)
+	PG_TRY();
 	{
-		workspace->ctxt = xmlXPathNewContext(workspace->doctree);
-		workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
-
-		/* compile the path */
-		comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
-		if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+		workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
+										   docsize, NULL, NULL,
+										   XML_PARSE_NOENT);
+		if (workspace->doctree != NULL)
 		{
-			if (comppath != NULL)
-				xmlXPathFreeCompExpr(comppath);
-			xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
-						"XPath Syntax Error");
-		}
+			workspace->ctxt = xmlXPathNewContext(workspace->doctree);
+			if (workspace->ctxt == NULL)
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_OUT_OF_MEMORY,
+							"could not allocate XPath context");
 
-		/* Now evaluate the path expression. */
-		workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+			workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
+
+			/* compile the path */
+			comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
+			if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
+							"XPath Syntax Error");
+
+			/* Now evaluate the path expression. */
+			workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+
+			xmlXPathFreeCompExpr(comppath);
+			comppath = NULL;
+		}
+	}
+	PG_CATCH();
+	{
+		if (comppath != NULL)
+			xmlXPathFreeCompExpr(comppath);
+		cleanup_workspace(workspace);
 
-		xmlXPathFreeCompExpr(comppath);
+		PG_RE_THROW();
 	}
+	PG_END_TRY();
 
 	return workspace;
 }
-- 
2.54.0


--MP_/LMSk9=uMhuQ1QiIJDarDO8G--






^ permalink  raw  reply  [nested|flat] 611+ messages in thread

* [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths
@ 2026-06-01 22:41 Andrey Chernyy <andrey.cherny@tantorlabs.com>
  0 siblings, 0 replies; 611+ messages in thread

From: Andrey Chernyy @ 2026-06-01 22:41 UTC (permalink / raw)

pgxml_xpath() builds an xpath_workspace before returning it to
callers.  If an ERROR is thrown before the function returns, callers
have not received the workspace pointer yet and cannot run
cleanup_workspace().

Add local error cleanup for the partially built workspace and the
compiled XPath expression.  Also check xmlXPathNewContext() before
dereferencing the returned context.
---
 contrib/xml2/xpath.c | 51 +++++++++++++++++++++++++++-----------------
 1 file changed, 32 insertions(+), 19 deletions(-)

diff --git a/contrib/xml2/xpath.c b/contrib/xml2/xpath.c
index 9fe75cb5ff4..283bb51178d 100644
--- a/contrib/xml2/xpath.c
+++ b/contrib/xml2/xpath.c
@@ -497,36 +497,49 @@ static xpath_workspace *
 pgxml_xpath(text *document, xmlChar *xpath, PgXmlErrorContext *xmlerrcxt)
 {
 	int32		docsize = VARSIZE_ANY_EXHDR(document);
-	xmlXPathCompExprPtr comppath;
+	xmlXPathCompExprPtr volatile comppath = NULL;
 	xpath_workspace *workspace = palloc0_object(xpath_workspace);
 
 	workspace->doctree = NULL;
 	workspace->ctxt = NULL;
 	workspace->res = NULL;
 
-	workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
-									   docsize, NULL, NULL,
-									   XML_PARSE_NOENT);
-	if (workspace->doctree != NULL)
+	PG_TRY();
 	{
-		workspace->ctxt = xmlXPathNewContext(workspace->doctree);
-		workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
-
-		/* compile the path */
-		comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
-		if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+		workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
+										   docsize, NULL, NULL,
+										   XML_PARSE_NOENT);
+		if (workspace->doctree != NULL)
 		{
-			if (comppath != NULL)
-				xmlXPathFreeCompExpr(comppath);
-			xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
-						"XPath Syntax Error");
-		}
+			workspace->ctxt = xmlXPathNewContext(workspace->doctree);
+			if (workspace->ctxt == NULL)
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_OUT_OF_MEMORY,
+							"could not allocate XPath context");
 
-		/* Now evaluate the path expression. */
-		workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+			workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
+
+			/* compile the path */
+			comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
+			if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
+							"XPath Syntax Error");
+
+			/* Now evaluate the path expression. */
+			workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+
+			xmlXPathFreeCompExpr(comppath);
+			comppath = NULL;
+		}
+	}
+	PG_CATCH();
+	{
+		if (comppath != NULL)
+			xmlXPathFreeCompExpr(comppath);
+		cleanup_workspace(workspace);
 
-		xmlXPathFreeCompExpr(comppath);
+		PG_RE_THROW();
 	}
+	PG_END_TRY();
 
 	return workspace;
 }
-- 
2.54.0


--MP_/LMSk9=uMhuQ1QiIJDarDO8G--





^ permalink  raw  reply  [nested|flat] 611+ messages in thread

* [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths
@ 2026-06-01 22:41 Andrey Chernyy <andrey.cherny@tantorlabs.com>
  0 siblings, 0 replies; 611+ messages in thread

From: Andrey Chernyy @ 2026-06-01 22:41 UTC (permalink / raw)

pgxml_xpath() builds an xpath_workspace before returning it to
callers.  If an ERROR is thrown before the function returns, callers
have not received the workspace pointer yet and cannot run
cleanup_workspace().

Add local error cleanup for the partially built workspace and the
compiled XPath expression.  Also check xmlXPathNewContext() before
dereferencing the returned context.
---
 contrib/xml2/xpath.c | 51 +++++++++++++++++++++++++++-----------------
 1 file changed, 32 insertions(+), 19 deletions(-)

diff --git a/contrib/xml2/xpath.c b/contrib/xml2/xpath.c
index 9fe75cb5ff4..283bb51178d 100644
--- a/contrib/xml2/xpath.c
+++ b/contrib/xml2/xpath.c
@@ -497,36 +497,49 @@ static xpath_workspace *
 pgxml_xpath(text *document, xmlChar *xpath, PgXmlErrorContext *xmlerrcxt)
 {
 	int32		docsize = VARSIZE_ANY_EXHDR(document);
-	xmlXPathCompExprPtr comppath;
+	xmlXPathCompExprPtr volatile comppath = NULL;
 	xpath_workspace *workspace = palloc0_object(xpath_workspace);
 
 	workspace->doctree = NULL;
 	workspace->ctxt = NULL;
 	workspace->res = NULL;
 
-	workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
-									   docsize, NULL, NULL,
-									   XML_PARSE_NOENT);
-	if (workspace->doctree != NULL)
+	PG_TRY();
 	{
-		workspace->ctxt = xmlXPathNewContext(workspace->doctree);
-		workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
-
-		/* compile the path */
-		comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
-		if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+		workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
+										   docsize, NULL, NULL,
+										   XML_PARSE_NOENT);
+		if (workspace->doctree != NULL)
 		{
-			if (comppath != NULL)
-				xmlXPathFreeCompExpr(comppath);
-			xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
-						"XPath Syntax Error");
-		}
+			workspace->ctxt = xmlXPathNewContext(workspace->doctree);
+			if (workspace->ctxt == NULL)
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_OUT_OF_MEMORY,
+							"could not allocate XPath context");
 
-		/* Now evaluate the path expression. */
-		workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+			workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
+
+			/* compile the path */
+			comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
+			if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
+							"XPath Syntax Error");
+
+			/* Now evaluate the path expression. */
+			workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+
+			xmlXPathFreeCompExpr(comppath);
+			comppath = NULL;
+		}
+	}
+	PG_CATCH();
+	{
+		if (comppath != NULL)
+			xmlXPathFreeCompExpr(comppath);
+		cleanup_workspace(workspace);
 
-		xmlXPathFreeCompExpr(comppath);
+		PG_RE_THROW();
 	}
+	PG_END_TRY();
 
 	return workspace;
 }
-- 
2.54.0


--MP_/LMSk9=uMhuQ1QiIJDarDO8G--





^ permalink  raw  reply  [nested|flat] 611+ messages in thread

* [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths
@ 2026-06-01 22:41 Andrey Chernyy <andrey.cherny@tantorlabs.com>
  0 siblings, 0 replies; 611+ messages in thread

From: Andrey Chernyy @ 2026-06-01 22:41 UTC (permalink / raw)

pgxml_xpath() builds an xpath_workspace before returning it to
callers.  If an ERROR is thrown before the function returns, callers
have not received the workspace pointer yet and cannot run
cleanup_workspace().

Add local error cleanup for the partially built workspace and the
compiled XPath expression.  Also check xmlXPathNewContext() before
dereferencing the returned context.
---
 contrib/xml2/xpath.c | 51 +++++++++++++++++++++++++++-----------------
 1 file changed, 32 insertions(+), 19 deletions(-)

diff --git a/contrib/xml2/xpath.c b/contrib/xml2/xpath.c
index 9fe75cb5ff4..283bb51178d 100644
--- a/contrib/xml2/xpath.c
+++ b/contrib/xml2/xpath.c
@@ -497,36 +497,49 @@ static xpath_workspace *
 pgxml_xpath(text *document, xmlChar *xpath, PgXmlErrorContext *xmlerrcxt)
 {
 	int32		docsize = VARSIZE_ANY_EXHDR(document);
-	xmlXPathCompExprPtr comppath;
+	xmlXPathCompExprPtr volatile comppath = NULL;
 	xpath_workspace *workspace = palloc0_object(xpath_workspace);
 
 	workspace->doctree = NULL;
 	workspace->ctxt = NULL;
 	workspace->res = NULL;
 
-	workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
-									   docsize, NULL, NULL,
-									   XML_PARSE_NOENT);
-	if (workspace->doctree != NULL)
+	PG_TRY();
 	{
-		workspace->ctxt = xmlXPathNewContext(workspace->doctree);
-		workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
-
-		/* compile the path */
-		comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
-		if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+		workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
+										   docsize, NULL, NULL,
+										   XML_PARSE_NOENT);
+		if (workspace->doctree != NULL)
 		{
-			if (comppath != NULL)
-				xmlXPathFreeCompExpr(comppath);
-			xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
-						"XPath Syntax Error");
-		}
+			workspace->ctxt = xmlXPathNewContext(workspace->doctree);
+			if (workspace->ctxt == NULL)
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_OUT_OF_MEMORY,
+							"could not allocate XPath context");
 
-		/* Now evaluate the path expression. */
-		workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+			workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
+
+			/* compile the path */
+			comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
+			if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
+							"XPath Syntax Error");
+
+			/* Now evaluate the path expression. */
+			workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+
+			xmlXPathFreeCompExpr(comppath);
+			comppath = NULL;
+		}
+	}
+	PG_CATCH();
+	{
+		if (comppath != NULL)
+			xmlXPathFreeCompExpr(comppath);
+		cleanup_workspace(workspace);
 
-		xmlXPathFreeCompExpr(comppath);
+		PG_RE_THROW();
 	}
+	PG_END_TRY();
 
 	return workspace;
 }
-- 
2.54.0


--MP_/LMSk9=uMhuQ1QiIJDarDO8G--






^ permalink  raw  reply  [nested|flat] 611+ messages in thread

* [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths
@ 2026-06-01 22:41 Andrey Chernyy <andrey.cherny@tantorlabs.com>
  0 siblings, 0 replies; 611+ messages in thread

From: Andrey Chernyy @ 2026-06-01 22:41 UTC (permalink / raw)

pgxml_xpath() builds an xpath_workspace before returning it to
callers.  If an ERROR is thrown before the function returns, callers
have not received the workspace pointer yet and cannot run
cleanup_workspace().

Add local error cleanup for the partially built workspace and the
compiled XPath expression.  Also check xmlXPathNewContext() before
dereferencing the returned context.
---
 contrib/xml2/xpath.c | 51 +++++++++++++++++++++++++++-----------------
 1 file changed, 32 insertions(+), 19 deletions(-)

diff --git a/contrib/xml2/xpath.c b/contrib/xml2/xpath.c
index 9fe75cb5ff4..283bb51178d 100644
--- a/contrib/xml2/xpath.c
+++ b/contrib/xml2/xpath.c
@@ -497,36 +497,49 @@ static xpath_workspace *
 pgxml_xpath(text *document, xmlChar *xpath, PgXmlErrorContext *xmlerrcxt)
 {
 	int32		docsize = VARSIZE_ANY_EXHDR(document);
-	xmlXPathCompExprPtr comppath;
+	xmlXPathCompExprPtr volatile comppath = NULL;
 	xpath_workspace *workspace = palloc0_object(xpath_workspace);
 
 	workspace->doctree = NULL;
 	workspace->ctxt = NULL;
 	workspace->res = NULL;
 
-	workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
-									   docsize, NULL, NULL,
-									   XML_PARSE_NOENT);
-	if (workspace->doctree != NULL)
+	PG_TRY();
 	{
-		workspace->ctxt = xmlXPathNewContext(workspace->doctree);
-		workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
-
-		/* compile the path */
-		comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
-		if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+		workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
+										   docsize, NULL, NULL,
+										   XML_PARSE_NOENT);
+		if (workspace->doctree != NULL)
 		{
-			if (comppath != NULL)
-				xmlXPathFreeCompExpr(comppath);
-			xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
-						"XPath Syntax Error");
-		}
+			workspace->ctxt = xmlXPathNewContext(workspace->doctree);
+			if (workspace->ctxt == NULL)
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_OUT_OF_MEMORY,
+							"could not allocate XPath context");
 
-		/* Now evaluate the path expression. */
-		workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+			workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
+
+			/* compile the path */
+			comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
+			if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
+							"XPath Syntax Error");
+
+			/* Now evaluate the path expression. */
+			workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+
+			xmlXPathFreeCompExpr(comppath);
+			comppath = NULL;
+		}
+	}
+	PG_CATCH();
+	{
+		if (comppath != NULL)
+			xmlXPathFreeCompExpr(comppath);
+		cleanup_workspace(workspace);
 
-		xmlXPathFreeCompExpr(comppath);
+		PG_RE_THROW();
 	}
+	PG_END_TRY();
 
 	return workspace;
 }
-- 
2.54.0


--MP_/LMSk9=uMhuQ1QiIJDarDO8G--






^ permalink  raw  reply  [nested|flat] 611+ messages in thread

* [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths
@ 2026-06-01 22:41 Andrey Chernyy <andrey.cherny@tantorlabs.com>
  0 siblings, 0 replies; 611+ messages in thread

From: Andrey Chernyy @ 2026-06-01 22:41 UTC (permalink / raw)

pgxml_xpath() builds an xpath_workspace before returning it to
callers.  If an ERROR is thrown before the function returns, callers
have not received the workspace pointer yet and cannot run
cleanup_workspace().

Add local error cleanup for the partially built workspace and the
compiled XPath expression.  Also check xmlXPathNewContext() before
dereferencing the returned context.
---
 contrib/xml2/xpath.c | 51 +++++++++++++++++++++++++++-----------------
 1 file changed, 32 insertions(+), 19 deletions(-)

diff --git a/contrib/xml2/xpath.c b/contrib/xml2/xpath.c
index 9fe75cb5ff4..283bb51178d 100644
--- a/contrib/xml2/xpath.c
+++ b/contrib/xml2/xpath.c
@@ -497,36 +497,49 @@ static xpath_workspace *
 pgxml_xpath(text *document, xmlChar *xpath, PgXmlErrorContext *xmlerrcxt)
 {
 	int32		docsize = VARSIZE_ANY_EXHDR(document);
-	xmlXPathCompExprPtr comppath;
+	xmlXPathCompExprPtr volatile comppath = NULL;
 	xpath_workspace *workspace = palloc0_object(xpath_workspace);
 
 	workspace->doctree = NULL;
 	workspace->ctxt = NULL;
 	workspace->res = NULL;
 
-	workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
-									   docsize, NULL, NULL,
-									   XML_PARSE_NOENT);
-	if (workspace->doctree != NULL)
+	PG_TRY();
 	{
-		workspace->ctxt = xmlXPathNewContext(workspace->doctree);
-		workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
-
-		/* compile the path */
-		comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
-		if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+		workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
+										   docsize, NULL, NULL,
+										   XML_PARSE_NOENT);
+		if (workspace->doctree != NULL)
 		{
-			if (comppath != NULL)
-				xmlXPathFreeCompExpr(comppath);
-			xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
-						"XPath Syntax Error");
-		}
+			workspace->ctxt = xmlXPathNewContext(workspace->doctree);
+			if (workspace->ctxt == NULL)
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_OUT_OF_MEMORY,
+							"could not allocate XPath context");
 
-		/* Now evaluate the path expression. */
-		workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+			workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
+
+			/* compile the path */
+			comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
+			if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
+							"XPath Syntax Error");
+
+			/* Now evaluate the path expression. */
+			workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+
+			xmlXPathFreeCompExpr(comppath);
+			comppath = NULL;
+		}
+	}
+	PG_CATCH();
+	{
+		if (comppath != NULL)
+			xmlXPathFreeCompExpr(comppath);
+		cleanup_workspace(workspace);
 
-		xmlXPathFreeCompExpr(comppath);
+		PG_RE_THROW();
 	}
+	PG_END_TRY();
 
 	return workspace;
 }
-- 
2.54.0


--MP_/LMSk9=uMhuQ1QiIJDarDO8G--





^ permalink  raw  reply  [nested|flat] 611+ messages in thread

* [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths
@ 2026-06-01 22:41 Andrey Chernyy <andrey.cherny@tantorlabs.com>
  0 siblings, 0 replies; 611+ messages in thread

From: Andrey Chernyy @ 2026-06-01 22:41 UTC (permalink / raw)

pgxml_xpath() builds an xpath_workspace before returning it to
callers.  If an ERROR is thrown before the function returns, callers
have not received the workspace pointer yet and cannot run
cleanup_workspace().

Add local error cleanup for the partially built workspace and the
compiled XPath expression.  Also check xmlXPathNewContext() before
dereferencing the returned context.
---
 contrib/xml2/xpath.c | 51 +++++++++++++++++++++++++++-----------------
 1 file changed, 32 insertions(+), 19 deletions(-)

diff --git a/contrib/xml2/xpath.c b/contrib/xml2/xpath.c
index 9fe75cb5ff4..283bb51178d 100644
--- a/contrib/xml2/xpath.c
+++ b/contrib/xml2/xpath.c
@@ -497,36 +497,49 @@ static xpath_workspace *
 pgxml_xpath(text *document, xmlChar *xpath, PgXmlErrorContext *xmlerrcxt)
 {
 	int32		docsize = VARSIZE_ANY_EXHDR(document);
-	xmlXPathCompExprPtr comppath;
+	xmlXPathCompExprPtr volatile comppath = NULL;
 	xpath_workspace *workspace = palloc0_object(xpath_workspace);
 
 	workspace->doctree = NULL;
 	workspace->ctxt = NULL;
 	workspace->res = NULL;
 
-	workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
-									   docsize, NULL, NULL,
-									   XML_PARSE_NOENT);
-	if (workspace->doctree != NULL)
+	PG_TRY();
 	{
-		workspace->ctxt = xmlXPathNewContext(workspace->doctree);
-		workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
-
-		/* compile the path */
-		comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
-		if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+		workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
+										   docsize, NULL, NULL,
+										   XML_PARSE_NOENT);
+		if (workspace->doctree != NULL)
 		{
-			if (comppath != NULL)
-				xmlXPathFreeCompExpr(comppath);
-			xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
-						"XPath Syntax Error");
-		}
+			workspace->ctxt = xmlXPathNewContext(workspace->doctree);
+			if (workspace->ctxt == NULL)
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_OUT_OF_MEMORY,
+							"could not allocate XPath context");
 
-		/* Now evaluate the path expression. */
-		workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+			workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
+
+			/* compile the path */
+			comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
+			if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
+							"XPath Syntax Error");
+
+			/* Now evaluate the path expression. */
+			workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+
+			xmlXPathFreeCompExpr(comppath);
+			comppath = NULL;
+		}
+	}
+	PG_CATCH();
+	{
+		if (comppath != NULL)
+			xmlXPathFreeCompExpr(comppath);
+		cleanup_workspace(workspace);
 
-		xmlXPathFreeCompExpr(comppath);
+		PG_RE_THROW();
 	}
+	PG_END_TRY();
 
 	return workspace;
 }
-- 
2.54.0


--MP_/LMSk9=uMhuQ1QiIJDarDO8G--





^ permalink  raw  reply  [nested|flat] 611+ messages in thread

* [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths
@ 2026-06-01 22:41 Andrey Chernyy <andrey.cherny@tantorlabs.com>
  0 siblings, 0 replies; 611+ messages in thread

From: Andrey Chernyy @ 2026-06-01 22:41 UTC (permalink / raw)

pgxml_xpath() builds an xpath_workspace before returning it to
callers.  If an ERROR is thrown before the function returns, callers
have not received the workspace pointer yet and cannot run
cleanup_workspace().

Add local error cleanup for the partially built workspace and the
compiled XPath expression.  Also check xmlXPathNewContext() before
dereferencing the returned context.
---
 contrib/xml2/xpath.c | 51 +++++++++++++++++++++++++++-----------------
 1 file changed, 32 insertions(+), 19 deletions(-)

diff --git a/contrib/xml2/xpath.c b/contrib/xml2/xpath.c
index 9fe75cb5ff4..283bb51178d 100644
--- a/contrib/xml2/xpath.c
+++ b/contrib/xml2/xpath.c
@@ -497,36 +497,49 @@ static xpath_workspace *
 pgxml_xpath(text *document, xmlChar *xpath, PgXmlErrorContext *xmlerrcxt)
 {
 	int32		docsize = VARSIZE_ANY_EXHDR(document);
-	xmlXPathCompExprPtr comppath;
+	xmlXPathCompExprPtr volatile comppath = NULL;
 	xpath_workspace *workspace = palloc0_object(xpath_workspace);
 
 	workspace->doctree = NULL;
 	workspace->ctxt = NULL;
 	workspace->res = NULL;
 
-	workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
-									   docsize, NULL, NULL,
-									   XML_PARSE_NOENT);
-	if (workspace->doctree != NULL)
+	PG_TRY();
 	{
-		workspace->ctxt = xmlXPathNewContext(workspace->doctree);
-		workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
-
-		/* compile the path */
-		comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
-		if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+		workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
+										   docsize, NULL, NULL,
+										   XML_PARSE_NOENT);
+		if (workspace->doctree != NULL)
 		{
-			if (comppath != NULL)
-				xmlXPathFreeCompExpr(comppath);
-			xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
-						"XPath Syntax Error");
-		}
+			workspace->ctxt = xmlXPathNewContext(workspace->doctree);
+			if (workspace->ctxt == NULL)
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_OUT_OF_MEMORY,
+							"could not allocate XPath context");
 
-		/* Now evaluate the path expression. */
-		workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+			workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
+
+			/* compile the path */
+			comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
+			if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
+							"XPath Syntax Error");
+
+			/* Now evaluate the path expression. */
+			workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+
+			xmlXPathFreeCompExpr(comppath);
+			comppath = NULL;
+		}
+	}
+	PG_CATCH();
+	{
+		if (comppath != NULL)
+			xmlXPathFreeCompExpr(comppath);
+		cleanup_workspace(workspace);
 
-		xmlXPathFreeCompExpr(comppath);
+		PG_RE_THROW();
 	}
+	PG_END_TRY();
 
 	return workspace;
 }
-- 
2.54.0


--MP_/LMSk9=uMhuQ1QiIJDarDO8G--






^ permalink  raw  reply  [nested|flat] 611+ messages in thread

* [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths
@ 2026-06-01 22:41 Andrey Chernyy <andrey.cherny@tantorlabs.com>
  0 siblings, 0 replies; 611+ messages in thread

From: Andrey Chernyy @ 2026-06-01 22:41 UTC (permalink / raw)

pgxml_xpath() builds an xpath_workspace before returning it to
callers.  If an ERROR is thrown before the function returns, callers
have not received the workspace pointer yet and cannot run
cleanup_workspace().

Add local error cleanup for the partially built workspace and the
compiled XPath expression.  Also check xmlXPathNewContext() before
dereferencing the returned context.
---
 contrib/xml2/xpath.c | 51 +++++++++++++++++++++++++++-----------------
 1 file changed, 32 insertions(+), 19 deletions(-)

diff --git a/contrib/xml2/xpath.c b/contrib/xml2/xpath.c
index 9fe75cb5ff4..283bb51178d 100644
--- a/contrib/xml2/xpath.c
+++ b/contrib/xml2/xpath.c
@@ -497,36 +497,49 @@ static xpath_workspace *
 pgxml_xpath(text *document, xmlChar *xpath, PgXmlErrorContext *xmlerrcxt)
 {
 	int32		docsize = VARSIZE_ANY_EXHDR(document);
-	xmlXPathCompExprPtr comppath;
+	xmlXPathCompExprPtr volatile comppath = NULL;
 	xpath_workspace *workspace = palloc0_object(xpath_workspace);
 
 	workspace->doctree = NULL;
 	workspace->ctxt = NULL;
 	workspace->res = NULL;
 
-	workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
-									   docsize, NULL, NULL,
-									   XML_PARSE_NOENT);
-	if (workspace->doctree != NULL)
+	PG_TRY();
 	{
-		workspace->ctxt = xmlXPathNewContext(workspace->doctree);
-		workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
-
-		/* compile the path */
-		comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
-		if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+		workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
+										   docsize, NULL, NULL,
+										   XML_PARSE_NOENT);
+		if (workspace->doctree != NULL)
 		{
-			if (comppath != NULL)
-				xmlXPathFreeCompExpr(comppath);
-			xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
-						"XPath Syntax Error");
-		}
+			workspace->ctxt = xmlXPathNewContext(workspace->doctree);
+			if (workspace->ctxt == NULL)
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_OUT_OF_MEMORY,
+							"could not allocate XPath context");
 
-		/* Now evaluate the path expression. */
-		workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+			workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
+
+			/* compile the path */
+			comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
+			if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
+							"XPath Syntax Error");
+
+			/* Now evaluate the path expression. */
+			workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+
+			xmlXPathFreeCompExpr(comppath);
+			comppath = NULL;
+		}
+	}
+	PG_CATCH();
+	{
+		if (comppath != NULL)
+			xmlXPathFreeCompExpr(comppath);
+		cleanup_workspace(workspace);
 
-		xmlXPathFreeCompExpr(comppath);
+		PG_RE_THROW();
 	}
+	PG_END_TRY();
 
 	return workspace;
 }
-- 
2.54.0


--MP_/LMSk9=uMhuQ1QiIJDarDO8G--






^ permalink  raw  reply  [nested|flat] 611+ messages in thread

* [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths
@ 2026-06-01 22:41 Andrey Chernyy <andrey.cherny@tantorlabs.com>
  0 siblings, 0 replies; 611+ messages in thread

From: Andrey Chernyy @ 2026-06-01 22:41 UTC (permalink / raw)

pgxml_xpath() builds an xpath_workspace before returning it to
callers.  If an ERROR is thrown before the function returns, callers
have not received the workspace pointer yet and cannot run
cleanup_workspace().

Add local error cleanup for the partially built workspace and the
compiled XPath expression.  Also check xmlXPathNewContext() before
dereferencing the returned context.
---
 contrib/xml2/xpath.c | 51 +++++++++++++++++++++++++++-----------------
 1 file changed, 32 insertions(+), 19 deletions(-)

diff --git a/contrib/xml2/xpath.c b/contrib/xml2/xpath.c
index 9fe75cb5ff4..283bb51178d 100644
--- a/contrib/xml2/xpath.c
+++ b/contrib/xml2/xpath.c
@@ -497,36 +497,49 @@ static xpath_workspace *
 pgxml_xpath(text *document, xmlChar *xpath, PgXmlErrorContext *xmlerrcxt)
 {
 	int32		docsize = VARSIZE_ANY_EXHDR(document);
-	xmlXPathCompExprPtr comppath;
+	xmlXPathCompExprPtr volatile comppath = NULL;
 	xpath_workspace *workspace = palloc0_object(xpath_workspace);
 
 	workspace->doctree = NULL;
 	workspace->ctxt = NULL;
 	workspace->res = NULL;
 
-	workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
-									   docsize, NULL, NULL,
-									   XML_PARSE_NOENT);
-	if (workspace->doctree != NULL)
+	PG_TRY();
 	{
-		workspace->ctxt = xmlXPathNewContext(workspace->doctree);
-		workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
-
-		/* compile the path */
-		comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
-		if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+		workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
+										   docsize, NULL, NULL,
+										   XML_PARSE_NOENT);
+		if (workspace->doctree != NULL)
 		{
-			if (comppath != NULL)
-				xmlXPathFreeCompExpr(comppath);
-			xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
-						"XPath Syntax Error");
-		}
+			workspace->ctxt = xmlXPathNewContext(workspace->doctree);
+			if (workspace->ctxt == NULL)
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_OUT_OF_MEMORY,
+							"could not allocate XPath context");
 
-		/* Now evaluate the path expression. */
-		workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+			workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
+
+			/* compile the path */
+			comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
+			if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
+							"XPath Syntax Error");
+
+			/* Now evaluate the path expression. */
+			workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+
+			xmlXPathFreeCompExpr(comppath);
+			comppath = NULL;
+		}
+	}
+	PG_CATCH();
+	{
+		if (comppath != NULL)
+			xmlXPathFreeCompExpr(comppath);
+		cleanup_workspace(workspace);
 
-		xmlXPathFreeCompExpr(comppath);
+		PG_RE_THROW();
 	}
+	PG_END_TRY();
 
 	return workspace;
 }
-- 
2.54.0


--MP_/LMSk9=uMhuQ1QiIJDarDO8G--





^ permalink  raw  reply  [nested|flat] 611+ messages in thread

* [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths
@ 2026-06-01 22:41 Andrey Chernyy <andrey.cherny@tantorlabs.com>
  0 siblings, 0 replies; 611+ messages in thread

From: Andrey Chernyy @ 2026-06-01 22:41 UTC (permalink / raw)

pgxml_xpath() builds an xpath_workspace before returning it to
callers.  If an ERROR is thrown before the function returns, callers
have not received the workspace pointer yet and cannot run
cleanup_workspace().

Add local error cleanup for the partially built workspace and the
compiled XPath expression.  Also check xmlXPathNewContext() before
dereferencing the returned context.
---
 contrib/xml2/xpath.c | 51 +++++++++++++++++++++++++++-----------------
 1 file changed, 32 insertions(+), 19 deletions(-)

diff --git a/contrib/xml2/xpath.c b/contrib/xml2/xpath.c
index 9fe75cb5ff4..283bb51178d 100644
--- a/contrib/xml2/xpath.c
+++ b/contrib/xml2/xpath.c
@@ -497,36 +497,49 @@ static xpath_workspace *
 pgxml_xpath(text *document, xmlChar *xpath, PgXmlErrorContext *xmlerrcxt)
 {
 	int32		docsize = VARSIZE_ANY_EXHDR(document);
-	xmlXPathCompExprPtr comppath;
+	xmlXPathCompExprPtr volatile comppath = NULL;
 	xpath_workspace *workspace = palloc0_object(xpath_workspace);
 
 	workspace->doctree = NULL;
 	workspace->ctxt = NULL;
 	workspace->res = NULL;
 
-	workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
-									   docsize, NULL, NULL,
-									   XML_PARSE_NOENT);
-	if (workspace->doctree != NULL)
+	PG_TRY();
 	{
-		workspace->ctxt = xmlXPathNewContext(workspace->doctree);
-		workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
-
-		/* compile the path */
-		comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
-		if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+		workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
+										   docsize, NULL, NULL,
+										   XML_PARSE_NOENT);
+		if (workspace->doctree != NULL)
 		{
-			if (comppath != NULL)
-				xmlXPathFreeCompExpr(comppath);
-			xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
-						"XPath Syntax Error");
-		}
+			workspace->ctxt = xmlXPathNewContext(workspace->doctree);
+			if (workspace->ctxt == NULL)
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_OUT_OF_MEMORY,
+							"could not allocate XPath context");
 
-		/* Now evaluate the path expression. */
-		workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+			workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
+
+			/* compile the path */
+			comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
+			if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
+							"XPath Syntax Error");
+
+			/* Now evaluate the path expression. */
+			workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+
+			xmlXPathFreeCompExpr(comppath);
+			comppath = NULL;
+		}
+	}
+	PG_CATCH();
+	{
+		if (comppath != NULL)
+			xmlXPathFreeCompExpr(comppath);
+		cleanup_workspace(workspace);
 
-		xmlXPathFreeCompExpr(comppath);
+		PG_RE_THROW();
 	}
+	PG_END_TRY();
 
 	return workspace;
 }
-- 
2.54.0


--MP_/LMSk9=uMhuQ1QiIJDarDO8G--





^ permalink  raw  reply  [nested|flat] 611+ messages in thread

* [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths
@ 2026-06-01 22:41 Andrey Chernyy <andrey.cherny@tantorlabs.com>
  0 siblings, 0 replies; 611+ messages in thread

From: Andrey Chernyy @ 2026-06-01 22:41 UTC (permalink / raw)

pgxml_xpath() builds an xpath_workspace before returning it to
callers.  If an ERROR is thrown before the function returns, callers
have not received the workspace pointer yet and cannot run
cleanup_workspace().

Add local error cleanup for the partially built workspace and the
compiled XPath expression.  Also check xmlXPathNewContext() before
dereferencing the returned context.
---
 contrib/xml2/xpath.c | 51 +++++++++++++++++++++++++++-----------------
 1 file changed, 32 insertions(+), 19 deletions(-)

diff --git a/contrib/xml2/xpath.c b/contrib/xml2/xpath.c
index 9fe75cb5ff4..283bb51178d 100644
--- a/contrib/xml2/xpath.c
+++ b/contrib/xml2/xpath.c
@@ -497,36 +497,49 @@ static xpath_workspace *
 pgxml_xpath(text *document, xmlChar *xpath, PgXmlErrorContext *xmlerrcxt)
 {
 	int32		docsize = VARSIZE_ANY_EXHDR(document);
-	xmlXPathCompExprPtr comppath;
+	xmlXPathCompExprPtr volatile comppath = NULL;
 	xpath_workspace *workspace = palloc0_object(xpath_workspace);
 
 	workspace->doctree = NULL;
 	workspace->ctxt = NULL;
 	workspace->res = NULL;
 
-	workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
-									   docsize, NULL, NULL,
-									   XML_PARSE_NOENT);
-	if (workspace->doctree != NULL)
+	PG_TRY();
 	{
-		workspace->ctxt = xmlXPathNewContext(workspace->doctree);
-		workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
-
-		/* compile the path */
-		comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
-		if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+		workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
+										   docsize, NULL, NULL,
+										   XML_PARSE_NOENT);
+		if (workspace->doctree != NULL)
 		{
-			if (comppath != NULL)
-				xmlXPathFreeCompExpr(comppath);
-			xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
-						"XPath Syntax Error");
-		}
+			workspace->ctxt = xmlXPathNewContext(workspace->doctree);
+			if (workspace->ctxt == NULL)
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_OUT_OF_MEMORY,
+							"could not allocate XPath context");
 
-		/* Now evaluate the path expression. */
-		workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+			workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
+
+			/* compile the path */
+			comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
+			if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
+							"XPath Syntax Error");
+
+			/* Now evaluate the path expression. */
+			workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+
+			xmlXPathFreeCompExpr(comppath);
+			comppath = NULL;
+		}
+	}
+	PG_CATCH();
+	{
+		if (comppath != NULL)
+			xmlXPathFreeCompExpr(comppath);
+		cleanup_workspace(workspace);
 
-		xmlXPathFreeCompExpr(comppath);
+		PG_RE_THROW();
 	}
+	PG_END_TRY();
 
 	return workspace;
 }
-- 
2.54.0


--MP_/LMSk9=uMhuQ1QiIJDarDO8G--






^ permalink  raw  reply  [nested|flat] 611+ messages in thread

* [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths
@ 2026-06-01 22:41 Andrey Chernyy <andrey.cherny@tantorlabs.com>
  0 siblings, 0 replies; 611+ messages in thread

From: Andrey Chernyy @ 2026-06-01 22:41 UTC (permalink / raw)

pgxml_xpath() builds an xpath_workspace before returning it to
callers.  If an ERROR is thrown before the function returns, callers
have not received the workspace pointer yet and cannot run
cleanup_workspace().

Add local error cleanup for the partially built workspace and the
compiled XPath expression.  Also check xmlXPathNewContext() before
dereferencing the returned context.
---
 contrib/xml2/xpath.c | 51 +++++++++++++++++++++++++++-----------------
 1 file changed, 32 insertions(+), 19 deletions(-)

diff --git a/contrib/xml2/xpath.c b/contrib/xml2/xpath.c
index 9fe75cb5ff4..283bb51178d 100644
--- a/contrib/xml2/xpath.c
+++ b/contrib/xml2/xpath.c
@@ -497,36 +497,49 @@ static xpath_workspace *
 pgxml_xpath(text *document, xmlChar *xpath, PgXmlErrorContext *xmlerrcxt)
 {
 	int32		docsize = VARSIZE_ANY_EXHDR(document);
-	xmlXPathCompExprPtr comppath;
+	xmlXPathCompExprPtr volatile comppath = NULL;
 	xpath_workspace *workspace = palloc0_object(xpath_workspace);
 
 	workspace->doctree = NULL;
 	workspace->ctxt = NULL;
 	workspace->res = NULL;
 
-	workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
-									   docsize, NULL, NULL,
-									   XML_PARSE_NOENT);
-	if (workspace->doctree != NULL)
+	PG_TRY();
 	{
-		workspace->ctxt = xmlXPathNewContext(workspace->doctree);
-		workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
-
-		/* compile the path */
-		comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
-		if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+		workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
+										   docsize, NULL, NULL,
+										   XML_PARSE_NOENT);
+		if (workspace->doctree != NULL)
 		{
-			if (comppath != NULL)
-				xmlXPathFreeCompExpr(comppath);
-			xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
-						"XPath Syntax Error");
-		}
+			workspace->ctxt = xmlXPathNewContext(workspace->doctree);
+			if (workspace->ctxt == NULL)
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_OUT_OF_MEMORY,
+							"could not allocate XPath context");
 
-		/* Now evaluate the path expression. */
-		workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+			workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
+
+			/* compile the path */
+			comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
+			if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
+							"XPath Syntax Error");
+
+			/* Now evaluate the path expression. */
+			workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+
+			xmlXPathFreeCompExpr(comppath);
+			comppath = NULL;
+		}
+	}
+	PG_CATCH();
+	{
+		if (comppath != NULL)
+			xmlXPathFreeCompExpr(comppath);
+		cleanup_workspace(workspace);
 
-		xmlXPathFreeCompExpr(comppath);
+		PG_RE_THROW();
 	}
+	PG_END_TRY();
 
 	return workspace;
 }
-- 
2.54.0


--MP_/LMSk9=uMhuQ1QiIJDarDO8G--






^ permalink  raw  reply  [nested|flat] 611+ messages in thread

* [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths
@ 2026-06-01 22:41 Andrey Chernyy <andrey.cherny@tantorlabs.com>
  0 siblings, 0 replies; 611+ messages in thread

From: Andrey Chernyy @ 2026-06-01 22:41 UTC (permalink / raw)

pgxml_xpath() builds an xpath_workspace before returning it to
callers.  If an ERROR is thrown before the function returns, callers
have not received the workspace pointer yet and cannot run
cleanup_workspace().

Add local error cleanup for the partially built workspace and the
compiled XPath expression.  Also check xmlXPathNewContext() before
dereferencing the returned context.
---
 contrib/xml2/xpath.c | 51 +++++++++++++++++++++++++++-----------------
 1 file changed, 32 insertions(+), 19 deletions(-)

diff --git a/contrib/xml2/xpath.c b/contrib/xml2/xpath.c
index 9fe75cb5ff4..283bb51178d 100644
--- a/contrib/xml2/xpath.c
+++ b/contrib/xml2/xpath.c
@@ -497,36 +497,49 @@ static xpath_workspace *
 pgxml_xpath(text *document, xmlChar *xpath, PgXmlErrorContext *xmlerrcxt)
 {
 	int32		docsize = VARSIZE_ANY_EXHDR(document);
-	xmlXPathCompExprPtr comppath;
+	xmlXPathCompExprPtr volatile comppath = NULL;
 	xpath_workspace *workspace = palloc0_object(xpath_workspace);
 
 	workspace->doctree = NULL;
 	workspace->ctxt = NULL;
 	workspace->res = NULL;
 
-	workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
-									   docsize, NULL, NULL,
-									   XML_PARSE_NOENT);
-	if (workspace->doctree != NULL)
+	PG_TRY();
 	{
-		workspace->ctxt = xmlXPathNewContext(workspace->doctree);
-		workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
-
-		/* compile the path */
-		comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
-		if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+		workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
+										   docsize, NULL, NULL,
+										   XML_PARSE_NOENT);
+		if (workspace->doctree != NULL)
 		{
-			if (comppath != NULL)
-				xmlXPathFreeCompExpr(comppath);
-			xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
-						"XPath Syntax Error");
-		}
+			workspace->ctxt = xmlXPathNewContext(workspace->doctree);
+			if (workspace->ctxt == NULL)
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_OUT_OF_MEMORY,
+							"could not allocate XPath context");
 
-		/* Now evaluate the path expression. */
-		workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+			workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
+
+			/* compile the path */
+			comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
+			if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
+							"XPath Syntax Error");
+
+			/* Now evaluate the path expression. */
+			workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+
+			xmlXPathFreeCompExpr(comppath);
+			comppath = NULL;
+		}
+	}
+	PG_CATCH();
+	{
+		if (comppath != NULL)
+			xmlXPathFreeCompExpr(comppath);
+		cleanup_workspace(workspace);
 
-		xmlXPathFreeCompExpr(comppath);
+		PG_RE_THROW();
 	}
+	PG_END_TRY();
 
 	return workspace;
 }
-- 
2.54.0


--MP_/LMSk9=uMhuQ1QiIJDarDO8G--





^ permalink  raw  reply  [nested|flat] 611+ messages in thread

* [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths
@ 2026-06-01 22:41 Andrey Chernyy <andrey.cherny@tantorlabs.com>
  0 siblings, 0 replies; 611+ messages in thread

From: Andrey Chernyy @ 2026-06-01 22:41 UTC (permalink / raw)

pgxml_xpath() builds an xpath_workspace before returning it to
callers.  If an ERROR is thrown before the function returns, callers
have not received the workspace pointer yet and cannot run
cleanup_workspace().

Add local error cleanup for the partially built workspace and the
compiled XPath expression.  Also check xmlXPathNewContext() before
dereferencing the returned context.
---
 contrib/xml2/xpath.c | 51 +++++++++++++++++++++++++++-----------------
 1 file changed, 32 insertions(+), 19 deletions(-)

diff --git a/contrib/xml2/xpath.c b/contrib/xml2/xpath.c
index 9fe75cb5ff4..283bb51178d 100644
--- a/contrib/xml2/xpath.c
+++ b/contrib/xml2/xpath.c
@@ -497,36 +497,49 @@ static xpath_workspace *
 pgxml_xpath(text *document, xmlChar *xpath, PgXmlErrorContext *xmlerrcxt)
 {
 	int32		docsize = VARSIZE_ANY_EXHDR(document);
-	xmlXPathCompExprPtr comppath;
+	xmlXPathCompExprPtr volatile comppath = NULL;
 	xpath_workspace *workspace = palloc0_object(xpath_workspace);
 
 	workspace->doctree = NULL;
 	workspace->ctxt = NULL;
 	workspace->res = NULL;
 
-	workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
-									   docsize, NULL, NULL,
-									   XML_PARSE_NOENT);
-	if (workspace->doctree != NULL)
+	PG_TRY();
 	{
-		workspace->ctxt = xmlXPathNewContext(workspace->doctree);
-		workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
-
-		/* compile the path */
-		comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
-		if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+		workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
+										   docsize, NULL, NULL,
+										   XML_PARSE_NOENT);
+		if (workspace->doctree != NULL)
 		{
-			if (comppath != NULL)
-				xmlXPathFreeCompExpr(comppath);
-			xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
-						"XPath Syntax Error");
-		}
+			workspace->ctxt = xmlXPathNewContext(workspace->doctree);
+			if (workspace->ctxt == NULL)
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_OUT_OF_MEMORY,
+							"could not allocate XPath context");
 
-		/* Now evaluate the path expression. */
-		workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+			workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
+
+			/* compile the path */
+			comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
+			if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
+							"XPath Syntax Error");
+
+			/* Now evaluate the path expression. */
+			workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+
+			xmlXPathFreeCompExpr(comppath);
+			comppath = NULL;
+		}
+	}
+	PG_CATCH();
+	{
+		if (comppath != NULL)
+			xmlXPathFreeCompExpr(comppath);
+		cleanup_workspace(workspace);
 
-		xmlXPathFreeCompExpr(comppath);
+		PG_RE_THROW();
 	}
+	PG_END_TRY();
 
 	return workspace;
 }
-- 
2.54.0


--MP_/LMSk9=uMhuQ1QiIJDarDO8G--





^ permalink  raw  reply  [nested|flat] 611+ messages in thread

* [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths
@ 2026-06-01 22:41 Andrey Chernyy <andrey.cherny@tantorlabs.com>
  0 siblings, 0 replies; 611+ messages in thread

From: Andrey Chernyy @ 2026-06-01 22:41 UTC (permalink / raw)

pgxml_xpath() builds an xpath_workspace before returning it to
callers.  If an ERROR is thrown before the function returns, callers
have not received the workspace pointer yet and cannot run
cleanup_workspace().

Add local error cleanup for the partially built workspace and the
compiled XPath expression.  Also check xmlXPathNewContext() before
dereferencing the returned context.
---
 contrib/xml2/xpath.c | 51 +++++++++++++++++++++++++++-----------------
 1 file changed, 32 insertions(+), 19 deletions(-)

diff --git a/contrib/xml2/xpath.c b/contrib/xml2/xpath.c
index 9fe75cb5ff4..283bb51178d 100644
--- a/contrib/xml2/xpath.c
+++ b/contrib/xml2/xpath.c
@@ -497,36 +497,49 @@ static xpath_workspace *
 pgxml_xpath(text *document, xmlChar *xpath, PgXmlErrorContext *xmlerrcxt)
 {
 	int32		docsize = VARSIZE_ANY_EXHDR(document);
-	xmlXPathCompExprPtr comppath;
+	xmlXPathCompExprPtr volatile comppath = NULL;
 	xpath_workspace *workspace = palloc0_object(xpath_workspace);
 
 	workspace->doctree = NULL;
 	workspace->ctxt = NULL;
 	workspace->res = NULL;
 
-	workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
-									   docsize, NULL, NULL,
-									   XML_PARSE_NOENT);
-	if (workspace->doctree != NULL)
+	PG_TRY();
 	{
-		workspace->ctxt = xmlXPathNewContext(workspace->doctree);
-		workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
-
-		/* compile the path */
-		comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
-		if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+		workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
+										   docsize, NULL, NULL,
+										   XML_PARSE_NOENT);
+		if (workspace->doctree != NULL)
 		{
-			if (comppath != NULL)
-				xmlXPathFreeCompExpr(comppath);
-			xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
-						"XPath Syntax Error");
-		}
+			workspace->ctxt = xmlXPathNewContext(workspace->doctree);
+			if (workspace->ctxt == NULL)
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_OUT_OF_MEMORY,
+							"could not allocate XPath context");
 
-		/* Now evaluate the path expression. */
-		workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+			workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
+
+			/* compile the path */
+			comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
+			if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
+							"XPath Syntax Error");
+
+			/* Now evaluate the path expression. */
+			workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+
+			xmlXPathFreeCompExpr(comppath);
+			comppath = NULL;
+		}
+	}
+	PG_CATCH();
+	{
+		if (comppath != NULL)
+			xmlXPathFreeCompExpr(comppath);
+		cleanup_workspace(workspace);
 
-		xmlXPathFreeCompExpr(comppath);
+		PG_RE_THROW();
 	}
+	PG_END_TRY();
 
 	return workspace;
 }
-- 
2.54.0


--MP_/LMSk9=uMhuQ1QiIJDarDO8G--






^ permalink  raw  reply  [nested|flat] 611+ messages in thread

* [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths
@ 2026-06-01 22:41 Andrey Chernyy <andrey.cherny@tantorlabs.com>
  0 siblings, 0 replies; 611+ messages in thread

From: Andrey Chernyy @ 2026-06-01 22:41 UTC (permalink / raw)

pgxml_xpath() builds an xpath_workspace before returning it to
callers.  If an ERROR is thrown before the function returns, callers
have not received the workspace pointer yet and cannot run
cleanup_workspace().

Add local error cleanup for the partially built workspace and the
compiled XPath expression.  Also check xmlXPathNewContext() before
dereferencing the returned context.
---
 contrib/xml2/xpath.c | 51 +++++++++++++++++++++++++++-----------------
 1 file changed, 32 insertions(+), 19 deletions(-)

diff --git a/contrib/xml2/xpath.c b/contrib/xml2/xpath.c
index 9fe75cb5ff4..283bb51178d 100644
--- a/contrib/xml2/xpath.c
+++ b/contrib/xml2/xpath.c
@@ -497,36 +497,49 @@ static xpath_workspace *
 pgxml_xpath(text *document, xmlChar *xpath, PgXmlErrorContext *xmlerrcxt)
 {
 	int32		docsize = VARSIZE_ANY_EXHDR(document);
-	xmlXPathCompExprPtr comppath;
+	xmlXPathCompExprPtr volatile comppath = NULL;
 	xpath_workspace *workspace = palloc0_object(xpath_workspace);
 
 	workspace->doctree = NULL;
 	workspace->ctxt = NULL;
 	workspace->res = NULL;
 
-	workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
-									   docsize, NULL, NULL,
-									   XML_PARSE_NOENT);
-	if (workspace->doctree != NULL)
+	PG_TRY();
 	{
-		workspace->ctxt = xmlXPathNewContext(workspace->doctree);
-		workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
-
-		/* compile the path */
-		comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
-		if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+		workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
+										   docsize, NULL, NULL,
+										   XML_PARSE_NOENT);
+		if (workspace->doctree != NULL)
 		{
-			if (comppath != NULL)
-				xmlXPathFreeCompExpr(comppath);
-			xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
-						"XPath Syntax Error");
-		}
+			workspace->ctxt = xmlXPathNewContext(workspace->doctree);
+			if (workspace->ctxt == NULL)
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_OUT_OF_MEMORY,
+							"could not allocate XPath context");
 
-		/* Now evaluate the path expression. */
-		workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+			workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
+
+			/* compile the path */
+			comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
+			if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
+							"XPath Syntax Error");
+
+			/* Now evaluate the path expression. */
+			workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+
+			xmlXPathFreeCompExpr(comppath);
+			comppath = NULL;
+		}
+	}
+	PG_CATCH();
+	{
+		if (comppath != NULL)
+			xmlXPathFreeCompExpr(comppath);
+		cleanup_workspace(workspace);
 
-		xmlXPathFreeCompExpr(comppath);
+		PG_RE_THROW();
 	}
+	PG_END_TRY();
 
 	return workspace;
 }
-- 
2.54.0


--MP_/LMSk9=uMhuQ1QiIJDarDO8G--






^ permalink  raw  reply  [nested|flat] 611+ messages in thread

* [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths
@ 2026-06-01 22:41 Andrey Chernyy <andrey.cherny@tantorlabs.com>
  0 siblings, 0 replies; 611+ messages in thread

From: Andrey Chernyy @ 2026-06-01 22:41 UTC (permalink / raw)

pgxml_xpath() builds an xpath_workspace before returning it to
callers.  If an ERROR is thrown before the function returns, callers
have not received the workspace pointer yet and cannot run
cleanup_workspace().

Add local error cleanup for the partially built workspace and the
compiled XPath expression.  Also check xmlXPathNewContext() before
dereferencing the returned context.
---
 contrib/xml2/xpath.c | 51 +++++++++++++++++++++++++++-----------------
 1 file changed, 32 insertions(+), 19 deletions(-)

diff --git a/contrib/xml2/xpath.c b/contrib/xml2/xpath.c
index 9fe75cb5ff4..283bb51178d 100644
--- a/contrib/xml2/xpath.c
+++ b/contrib/xml2/xpath.c
@@ -497,36 +497,49 @@ static xpath_workspace *
 pgxml_xpath(text *document, xmlChar *xpath, PgXmlErrorContext *xmlerrcxt)
 {
 	int32		docsize = VARSIZE_ANY_EXHDR(document);
-	xmlXPathCompExprPtr comppath;
+	xmlXPathCompExprPtr volatile comppath = NULL;
 	xpath_workspace *workspace = palloc0_object(xpath_workspace);
 
 	workspace->doctree = NULL;
 	workspace->ctxt = NULL;
 	workspace->res = NULL;
 
-	workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
-									   docsize, NULL, NULL,
-									   XML_PARSE_NOENT);
-	if (workspace->doctree != NULL)
+	PG_TRY();
 	{
-		workspace->ctxt = xmlXPathNewContext(workspace->doctree);
-		workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
-
-		/* compile the path */
-		comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
-		if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+		workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
+										   docsize, NULL, NULL,
+										   XML_PARSE_NOENT);
+		if (workspace->doctree != NULL)
 		{
-			if (comppath != NULL)
-				xmlXPathFreeCompExpr(comppath);
-			xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
-						"XPath Syntax Error");
-		}
+			workspace->ctxt = xmlXPathNewContext(workspace->doctree);
+			if (workspace->ctxt == NULL)
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_OUT_OF_MEMORY,
+							"could not allocate XPath context");
 
-		/* Now evaluate the path expression. */
-		workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+			workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
+
+			/* compile the path */
+			comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
+			if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
+							"XPath Syntax Error");
+
+			/* Now evaluate the path expression. */
+			workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+
+			xmlXPathFreeCompExpr(comppath);
+			comppath = NULL;
+		}
+	}
+	PG_CATCH();
+	{
+		if (comppath != NULL)
+			xmlXPathFreeCompExpr(comppath);
+		cleanup_workspace(workspace);
 
-		xmlXPathFreeCompExpr(comppath);
+		PG_RE_THROW();
 	}
+	PG_END_TRY();
 
 	return workspace;
 }
-- 
2.54.0


--MP_/LMSk9=uMhuQ1QiIJDarDO8G--





^ permalink  raw  reply  [nested|flat] 611+ messages in thread

* [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths
@ 2026-06-01 22:41 Andrey Chernyy <andrey.cherny@tantorlabs.com>
  0 siblings, 0 replies; 611+ messages in thread

From: Andrey Chernyy @ 2026-06-01 22:41 UTC (permalink / raw)

pgxml_xpath() builds an xpath_workspace before returning it to
callers.  If an ERROR is thrown before the function returns, callers
have not received the workspace pointer yet and cannot run
cleanup_workspace().

Add local error cleanup for the partially built workspace and the
compiled XPath expression.  Also check xmlXPathNewContext() before
dereferencing the returned context.
---
 contrib/xml2/xpath.c | 51 +++++++++++++++++++++++++++-----------------
 1 file changed, 32 insertions(+), 19 deletions(-)

diff --git a/contrib/xml2/xpath.c b/contrib/xml2/xpath.c
index 9fe75cb5ff4..283bb51178d 100644
--- a/contrib/xml2/xpath.c
+++ b/contrib/xml2/xpath.c
@@ -497,36 +497,49 @@ static xpath_workspace *
 pgxml_xpath(text *document, xmlChar *xpath, PgXmlErrorContext *xmlerrcxt)
 {
 	int32		docsize = VARSIZE_ANY_EXHDR(document);
-	xmlXPathCompExprPtr comppath;
+	xmlXPathCompExprPtr volatile comppath = NULL;
 	xpath_workspace *workspace = palloc0_object(xpath_workspace);
 
 	workspace->doctree = NULL;
 	workspace->ctxt = NULL;
 	workspace->res = NULL;
 
-	workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
-									   docsize, NULL, NULL,
-									   XML_PARSE_NOENT);
-	if (workspace->doctree != NULL)
+	PG_TRY();
 	{
-		workspace->ctxt = xmlXPathNewContext(workspace->doctree);
-		workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
-
-		/* compile the path */
-		comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
-		if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+		workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
+										   docsize, NULL, NULL,
+										   XML_PARSE_NOENT);
+		if (workspace->doctree != NULL)
 		{
-			if (comppath != NULL)
-				xmlXPathFreeCompExpr(comppath);
-			xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
-						"XPath Syntax Error");
-		}
+			workspace->ctxt = xmlXPathNewContext(workspace->doctree);
+			if (workspace->ctxt == NULL)
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_OUT_OF_MEMORY,
+							"could not allocate XPath context");
 
-		/* Now evaluate the path expression. */
-		workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+			workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
+
+			/* compile the path */
+			comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
+			if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
+							"XPath Syntax Error");
+
+			/* Now evaluate the path expression. */
+			workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+
+			xmlXPathFreeCompExpr(comppath);
+			comppath = NULL;
+		}
+	}
+	PG_CATCH();
+	{
+		if (comppath != NULL)
+			xmlXPathFreeCompExpr(comppath);
+		cleanup_workspace(workspace);
 
-		xmlXPathFreeCompExpr(comppath);
+		PG_RE_THROW();
 	}
+	PG_END_TRY();
 
 	return workspace;
 }
-- 
2.54.0


--MP_/LMSk9=uMhuQ1QiIJDarDO8G--





^ permalink  raw  reply  [nested|flat] 611+ messages in thread

* [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths
@ 2026-06-01 22:41 Andrey Chernyy <andrey.cherny@tantorlabs.com>
  0 siblings, 0 replies; 611+ messages in thread

From: Andrey Chernyy @ 2026-06-01 22:41 UTC (permalink / raw)

pgxml_xpath() builds an xpath_workspace before returning it to
callers.  If an ERROR is thrown before the function returns, callers
have not received the workspace pointer yet and cannot run
cleanup_workspace().

Add local error cleanup for the partially built workspace and the
compiled XPath expression.  Also check xmlXPathNewContext() before
dereferencing the returned context.
---
 contrib/xml2/xpath.c | 51 +++++++++++++++++++++++++++-----------------
 1 file changed, 32 insertions(+), 19 deletions(-)

diff --git a/contrib/xml2/xpath.c b/contrib/xml2/xpath.c
index 9fe75cb5ff4..283bb51178d 100644
--- a/contrib/xml2/xpath.c
+++ b/contrib/xml2/xpath.c
@@ -497,36 +497,49 @@ static xpath_workspace *
 pgxml_xpath(text *document, xmlChar *xpath, PgXmlErrorContext *xmlerrcxt)
 {
 	int32		docsize = VARSIZE_ANY_EXHDR(document);
-	xmlXPathCompExprPtr comppath;
+	xmlXPathCompExprPtr volatile comppath = NULL;
 	xpath_workspace *workspace = palloc0_object(xpath_workspace);
 
 	workspace->doctree = NULL;
 	workspace->ctxt = NULL;
 	workspace->res = NULL;
 
-	workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
-									   docsize, NULL, NULL,
-									   XML_PARSE_NOENT);
-	if (workspace->doctree != NULL)
+	PG_TRY();
 	{
-		workspace->ctxt = xmlXPathNewContext(workspace->doctree);
-		workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
-
-		/* compile the path */
-		comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
-		if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+		workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
+										   docsize, NULL, NULL,
+										   XML_PARSE_NOENT);
+		if (workspace->doctree != NULL)
 		{
-			if (comppath != NULL)
-				xmlXPathFreeCompExpr(comppath);
-			xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
-						"XPath Syntax Error");
-		}
+			workspace->ctxt = xmlXPathNewContext(workspace->doctree);
+			if (workspace->ctxt == NULL)
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_OUT_OF_MEMORY,
+							"could not allocate XPath context");
 
-		/* Now evaluate the path expression. */
-		workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+			workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
+
+			/* compile the path */
+			comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
+			if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
+							"XPath Syntax Error");
+
+			/* Now evaluate the path expression. */
+			workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+
+			xmlXPathFreeCompExpr(comppath);
+			comppath = NULL;
+		}
+	}
+	PG_CATCH();
+	{
+		if (comppath != NULL)
+			xmlXPathFreeCompExpr(comppath);
+		cleanup_workspace(workspace);
 
-		xmlXPathFreeCompExpr(comppath);
+		PG_RE_THROW();
 	}
+	PG_END_TRY();
 
 	return workspace;
 }
-- 
2.54.0


--MP_/LMSk9=uMhuQ1QiIJDarDO8G--





^ permalink  raw  reply  [nested|flat] 611+ messages in thread

* [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths
@ 2026-06-01 22:41 Andrey Chernyy <andrey.cherny@tantorlabs.com>
  0 siblings, 0 replies; 611+ messages in thread

From: Andrey Chernyy @ 2026-06-01 22:41 UTC (permalink / raw)

pgxml_xpath() builds an xpath_workspace before returning it to
callers.  If an ERROR is thrown before the function returns, callers
have not received the workspace pointer yet and cannot run
cleanup_workspace().

Add local error cleanup for the partially built workspace and the
compiled XPath expression.  Also check xmlXPathNewContext() before
dereferencing the returned context.
---
 contrib/xml2/xpath.c | 51 +++++++++++++++++++++++++++-----------------
 1 file changed, 32 insertions(+), 19 deletions(-)

diff --git a/contrib/xml2/xpath.c b/contrib/xml2/xpath.c
index 9fe75cb5ff4..283bb51178d 100644
--- a/contrib/xml2/xpath.c
+++ b/contrib/xml2/xpath.c
@@ -497,36 +497,49 @@ static xpath_workspace *
 pgxml_xpath(text *document, xmlChar *xpath, PgXmlErrorContext *xmlerrcxt)
 {
 	int32		docsize = VARSIZE_ANY_EXHDR(document);
-	xmlXPathCompExprPtr comppath;
+	xmlXPathCompExprPtr volatile comppath = NULL;
 	xpath_workspace *workspace = palloc0_object(xpath_workspace);
 
 	workspace->doctree = NULL;
 	workspace->ctxt = NULL;
 	workspace->res = NULL;
 
-	workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
-									   docsize, NULL, NULL,
-									   XML_PARSE_NOENT);
-	if (workspace->doctree != NULL)
+	PG_TRY();
 	{
-		workspace->ctxt = xmlXPathNewContext(workspace->doctree);
-		workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
-
-		/* compile the path */
-		comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
-		if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+		workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
+										   docsize, NULL, NULL,
+										   XML_PARSE_NOENT);
+		if (workspace->doctree != NULL)
 		{
-			if (comppath != NULL)
-				xmlXPathFreeCompExpr(comppath);
-			xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
-						"XPath Syntax Error");
-		}
+			workspace->ctxt = xmlXPathNewContext(workspace->doctree);
+			if (workspace->ctxt == NULL)
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_OUT_OF_MEMORY,
+							"could not allocate XPath context");
 
-		/* Now evaluate the path expression. */
-		workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+			workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
+
+			/* compile the path */
+			comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
+			if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
+							"XPath Syntax Error");
+
+			/* Now evaluate the path expression. */
+			workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+
+			xmlXPathFreeCompExpr(comppath);
+			comppath = NULL;
+		}
+	}
+	PG_CATCH();
+	{
+		if (comppath != NULL)
+			xmlXPathFreeCompExpr(comppath);
+		cleanup_workspace(workspace);
 
-		xmlXPathFreeCompExpr(comppath);
+		PG_RE_THROW();
 	}
+	PG_END_TRY();
 
 	return workspace;
 }
-- 
2.54.0


--MP_/LMSk9=uMhuQ1QiIJDarDO8G--






^ permalink  raw  reply  [nested|flat] 611+ messages in thread

* [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths
@ 2026-06-01 22:41 Andrey Chernyy <andrey.cherny@tantorlabs.com>
  0 siblings, 0 replies; 611+ messages in thread

From: Andrey Chernyy @ 2026-06-01 22:41 UTC (permalink / raw)

pgxml_xpath() builds an xpath_workspace before returning it to
callers.  If an ERROR is thrown before the function returns, callers
have not received the workspace pointer yet and cannot run
cleanup_workspace().

Add local error cleanup for the partially built workspace and the
compiled XPath expression.  Also check xmlXPathNewContext() before
dereferencing the returned context.
---
 contrib/xml2/xpath.c | 51 +++++++++++++++++++++++++++-----------------
 1 file changed, 32 insertions(+), 19 deletions(-)

diff --git a/contrib/xml2/xpath.c b/contrib/xml2/xpath.c
index 9fe75cb5ff4..283bb51178d 100644
--- a/contrib/xml2/xpath.c
+++ b/contrib/xml2/xpath.c
@@ -497,36 +497,49 @@ static xpath_workspace *
 pgxml_xpath(text *document, xmlChar *xpath, PgXmlErrorContext *xmlerrcxt)
 {
 	int32		docsize = VARSIZE_ANY_EXHDR(document);
-	xmlXPathCompExprPtr comppath;
+	xmlXPathCompExprPtr volatile comppath = NULL;
 	xpath_workspace *workspace = palloc0_object(xpath_workspace);
 
 	workspace->doctree = NULL;
 	workspace->ctxt = NULL;
 	workspace->res = NULL;
 
-	workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
-									   docsize, NULL, NULL,
-									   XML_PARSE_NOENT);
-	if (workspace->doctree != NULL)
+	PG_TRY();
 	{
-		workspace->ctxt = xmlXPathNewContext(workspace->doctree);
-		workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
-
-		/* compile the path */
-		comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
-		if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+		workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
+										   docsize, NULL, NULL,
+										   XML_PARSE_NOENT);
+		if (workspace->doctree != NULL)
 		{
-			if (comppath != NULL)
-				xmlXPathFreeCompExpr(comppath);
-			xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
-						"XPath Syntax Error");
-		}
+			workspace->ctxt = xmlXPathNewContext(workspace->doctree);
+			if (workspace->ctxt == NULL)
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_OUT_OF_MEMORY,
+							"could not allocate XPath context");
 
-		/* Now evaluate the path expression. */
-		workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+			workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
+
+			/* compile the path */
+			comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
+			if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
+							"XPath Syntax Error");
+
+			/* Now evaluate the path expression. */
+			workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+
+			xmlXPathFreeCompExpr(comppath);
+			comppath = NULL;
+		}
+	}
+	PG_CATCH();
+	{
+		if (comppath != NULL)
+			xmlXPathFreeCompExpr(comppath);
+		cleanup_workspace(workspace);
 
-		xmlXPathFreeCompExpr(comppath);
+		PG_RE_THROW();
 	}
+	PG_END_TRY();
 
 	return workspace;
 }
-- 
2.54.0


--MP_/LMSk9=uMhuQ1QiIJDarDO8G--






^ permalink  raw  reply  [nested|flat] 611+ messages in thread

* [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths
@ 2026-06-01 22:41 Andrey Chernyy <andrey.cherny@tantorlabs.com>
  0 siblings, 0 replies; 611+ messages in thread

From: Andrey Chernyy @ 2026-06-01 22:41 UTC (permalink / raw)

pgxml_xpath() builds an xpath_workspace before returning it to
callers.  If an ERROR is thrown before the function returns, callers
have not received the workspace pointer yet and cannot run
cleanup_workspace().

Add local error cleanup for the partially built workspace and the
compiled XPath expression.  Also check xmlXPathNewContext() before
dereferencing the returned context.
---
 contrib/xml2/xpath.c | 51 +++++++++++++++++++++++++++-----------------
 1 file changed, 32 insertions(+), 19 deletions(-)

diff --git a/contrib/xml2/xpath.c b/contrib/xml2/xpath.c
index 9fe75cb5ff4..283bb51178d 100644
--- a/contrib/xml2/xpath.c
+++ b/contrib/xml2/xpath.c
@@ -497,36 +497,49 @@ static xpath_workspace *
 pgxml_xpath(text *document, xmlChar *xpath, PgXmlErrorContext *xmlerrcxt)
 {
 	int32		docsize = VARSIZE_ANY_EXHDR(document);
-	xmlXPathCompExprPtr comppath;
+	xmlXPathCompExprPtr volatile comppath = NULL;
 	xpath_workspace *workspace = palloc0_object(xpath_workspace);
 
 	workspace->doctree = NULL;
 	workspace->ctxt = NULL;
 	workspace->res = NULL;
 
-	workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
-									   docsize, NULL, NULL,
-									   XML_PARSE_NOENT);
-	if (workspace->doctree != NULL)
+	PG_TRY();
 	{
-		workspace->ctxt = xmlXPathNewContext(workspace->doctree);
-		workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
-
-		/* compile the path */
-		comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
-		if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+		workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
+										   docsize, NULL, NULL,
+										   XML_PARSE_NOENT);
+		if (workspace->doctree != NULL)
 		{
-			if (comppath != NULL)
-				xmlXPathFreeCompExpr(comppath);
-			xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
-						"XPath Syntax Error");
-		}
+			workspace->ctxt = xmlXPathNewContext(workspace->doctree);
+			if (workspace->ctxt == NULL)
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_OUT_OF_MEMORY,
+							"could not allocate XPath context");
 
-		/* Now evaluate the path expression. */
-		workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+			workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
+
+			/* compile the path */
+			comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
+			if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
+							"XPath Syntax Error");
+
+			/* Now evaluate the path expression. */
+			workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+
+			xmlXPathFreeCompExpr(comppath);
+			comppath = NULL;
+		}
+	}
+	PG_CATCH();
+	{
+		if (comppath != NULL)
+			xmlXPathFreeCompExpr(comppath);
+		cleanup_workspace(workspace);
 
-		xmlXPathFreeCompExpr(comppath);
+		PG_RE_THROW();
 	}
+	PG_END_TRY();
 
 	return workspace;
 }
-- 
2.54.0


--MP_/LMSk9=uMhuQ1QiIJDarDO8G--





^ permalink  raw  reply  [nested|flat] 611+ messages in thread

* [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths
@ 2026-06-01 22:41 Andrey Chernyy <andrey.cherny@tantorlabs.com>
  0 siblings, 0 replies; 611+ messages in thread

From: Andrey Chernyy @ 2026-06-01 22:41 UTC (permalink / raw)

pgxml_xpath() builds an xpath_workspace before returning it to
callers.  If an ERROR is thrown before the function returns, callers
have not received the workspace pointer yet and cannot run
cleanup_workspace().

Add local error cleanup for the partially built workspace and the
compiled XPath expression.  Also check xmlXPathNewContext() before
dereferencing the returned context.
---
 contrib/xml2/xpath.c | 51 +++++++++++++++++++++++++++-----------------
 1 file changed, 32 insertions(+), 19 deletions(-)

diff --git a/contrib/xml2/xpath.c b/contrib/xml2/xpath.c
index 9fe75cb5ff4..283bb51178d 100644
--- a/contrib/xml2/xpath.c
+++ b/contrib/xml2/xpath.c
@@ -497,36 +497,49 @@ static xpath_workspace *
 pgxml_xpath(text *document, xmlChar *xpath, PgXmlErrorContext *xmlerrcxt)
 {
 	int32		docsize = VARSIZE_ANY_EXHDR(document);
-	xmlXPathCompExprPtr comppath;
+	xmlXPathCompExprPtr volatile comppath = NULL;
 	xpath_workspace *workspace = palloc0_object(xpath_workspace);
 
 	workspace->doctree = NULL;
 	workspace->ctxt = NULL;
 	workspace->res = NULL;
 
-	workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
-									   docsize, NULL, NULL,
-									   XML_PARSE_NOENT);
-	if (workspace->doctree != NULL)
+	PG_TRY();
 	{
-		workspace->ctxt = xmlXPathNewContext(workspace->doctree);
-		workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
-
-		/* compile the path */
-		comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
-		if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+		workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
+										   docsize, NULL, NULL,
+										   XML_PARSE_NOENT);
+		if (workspace->doctree != NULL)
 		{
-			if (comppath != NULL)
-				xmlXPathFreeCompExpr(comppath);
-			xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
-						"XPath Syntax Error");
-		}
+			workspace->ctxt = xmlXPathNewContext(workspace->doctree);
+			if (workspace->ctxt == NULL)
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_OUT_OF_MEMORY,
+							"could not allocate XPath context");
 
-		/* Now evaluate the path expression. */
-		workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+			workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
+
+			/* compile the path */
+			comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
+			if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
+							"XPath Syntax Error");
+
+			/* Now evaluate the path expression. */
+			workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+
+			xmlXPathFreeCompExpr(comppath);
+			comppath = NULL;
+		}
+	}
+	PG_CATCH();
+	{
+		if (comppath != NULL)
+			xmlXPathFreeCompExpr(comppath);
+		cleanup_workspace(workspace);
 
-		xmlXPathFreeCompExpr(comppath);
+		PG_RE_THROW();
 	}
+	PG_END_TRY();
 
 	return workspace;
 }
-- 
2.54.0


--MP_/LMSk9=uMhuQ1QiIJDarDO8G--





^ permalink  raw  reply  [nested|flat] 611+ messages in thread

* [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths
@ 2026-06-01 22:41 Andrey Chernyy <andrey.cherny@tantorlabs.com>
  0 siblings, 0 replies; 611+ messages in thread

From: Andrey Chernyy @ 2026-06-01 22:41 UTC (permalink / raw)

pgxml_xpath() builds an xpath_workspace before returning it to
callers.  If an ERROR is thrown before the function returns, callers
have not received the workspace pointer yet and cannot run
cleanup_workspace().

Add local error cleanup for the partially built workspace and the
compiled XPath expression.  Also check xmlXPathNewContext() before
dereferencing the returned context.
---
 contrib/xml2/xpath.c | 51 +++++++++++++++++++++++++++-----------------
 1 file changed, 32 insertions(+), 19 deletions(-)

diff --git a/contrib/xml2/xpath.c b/contrib/xml2/xpath.c
index 9fe75cb5ff4..283bb51178d 100644
--- a/contrib/xml2/xpath.c
+++ b/contrib/xml2/xpath.c
@@ -497,36 +497,49 @@ static xpath_workspace *
 pgxml_xpath(text *document, xmlChar *xpath, PgXmlErrorContext *xmlerrcxt)
 {
 	int32		docsize = VARSIZE_ANY_EXHDR(document);
-	xmlXPathCompExprPtr comppath;
+	xmlXPathCompExprPtr volatile comppath = NULL;
 	xpath_workspace *workspace = palloc0_object(xpath_workspace);
 
 	workspace->doctree = NULL;
 	workspace->ctxt = NULL;
 	workspace->res = NULL;
 
-	workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
-									   docsize, NULL, NULL,
-									   XML_PARSE_NOENT);
-	if (workspace->doctree != NULL)
+	PG_TRY();
 	{
-		workspace->ctxt = xmlXPathNewContext(workspace->doctree);
-		workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
-
-		/* compile the path */
-		comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
-		if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+		workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
+										   docsize, NULL, NULL,
+										   XML_PARSE_NOENT);
+		if (workspace->doctree != NULL)
 		{
-			if (comppath != NULL)
-				xmlXPathFreeCompExpr(comppath);
-			xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
-						"XPath Syntax Error");
-		}
+			workspace->ctxt = xmlXPathNewContext(workspace->doctree);
+			if (workspace->ctxt == NULL)
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_OUT_OF_MEMORY,
+							"could not allocate XPath context");
 
-		/* Now evaluate the path expression. */
-		workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+			workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
+
+			/* compile the path */
+			comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
+			if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
+							"XPath Syntax Error");
+
+			/* Now evaluate the path expression. */
+			workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+
+			xmlXPathFreeCompExpr(comppath);
+			comppath = NULL;
+		}
+	}
+	PG_CATCH();
+	{
+		if (comppath != NULL)
+			xmlXPathFreeCompExpr(comppath);
+		cleanup_workspace(workspace);
 
-		xmlXPathFreeCompExpr(comppath);
+		PG_RE_THROW();
 	}
+	PG_END_TRY();
 
 	return workspace;
 }
-- 
2.54.0


--MP_/LMSk9=uMhuQ1QiIJDarDO8G--






^ permalink  raw  reply  [nested|flat] 611+ messages in thread

* [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths
@ 2026-06-01 22:41 Andrey Chernyy <andrey.cherny@tantorlabs.com>
  0 siblings, 0 replies; 611+ messages in thread

From: Andrey Chernyy @ 2026-06-01 22:41 UTC (permalink / raw)

pgxml_xpath() builds an xpath_workspace before returning it to
callers.  If an ERROR is thrown before the function returns, callers
have not received the workspace pointer yet and cannot run
cleanup_workspace().

Add local error cleanup for the partially built workspace and the
compiled XPath expression.  Also check xmlXPathNewContext() before
dereferencing the returned context.
---
 contrib/xml2/xpath.c | 51 +++++++++++++++++++++++++++-----------------
 1 file changed, 32 insertions(+), 19 deletions(-)

diff --git a/contrib/xml2/xpath.c b/contrib/xml2/xpath.c
index 9fe75cb5ff4..283bb51178d 100644
--- a/contrib/xml2/xpath.c
+++ b/contrib/xml2/xpath.c
@@ -497,36 +497,49 @@ static xpath_workspace *
 pgxml_xpath(text *document, xmlChar *xpath, PgXmlErrorContext *xmlerrcxt)
 {
 	int32		docsize = VARSIZE_ANY_EXHDR(document);
-	xmlXPathCompExprPtr comppath;
+	xmlXPathCompExprPtr volatile comppath = NULL;
 	xpath_workspace *workspace = palloc0_object(xpath_workspace);
 
 	workspace->doctree = NULL;
 	workspace->ctxt = NULL;
 	workspace->res = NULL;
 
-	workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
-									   docsize, NULL, NULL,
-									   XML_PARSE_NOENT);
-	if (workspace->doctree != NULL)
+	PG_TRY();
 	{
-		workspace->ctxt = xmlXPathNewContext(workspace->doctree);
-		workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
-
-		/* compile the path */
-		comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
-		if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+		workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
+										   docsize, NULL, NULL,
+										   XML_PARSE_NOENT);
+		if (workspace->doctree != NULL)
 		{
-			if (comppath != NULL)
-				xmlXPathFreeCompExpr(comppath);
-			xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
-						"XPath Syntax Error");
-		}
+			workspace->ctxt = xmlXPathNewContext(workspace->doctree);
+			if (workspace->ctxt == NULL)
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_OUT_OF_MEMORY,
+							"could not allocate XPath context");
 
-		/* Now evaluate the path expression. */
-		workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+			workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
+
+			/* compile the path */
+			comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
+			if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
+							"XPath Syntax Error");
+
+			/* Now evaluate the path expression. */
+			workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+
+			xmlXPathFreeCompExpr(comppath);
+			comppath = NULL;
+		}
+	}
+	PG_CATCH();
+	{
+		if (comppath != NULL)
+			xmlXPathFreeCompExpr(comppath);
+		cleanup_workspace(workspace);
 
-		xmlXPathFreeCompExpr(comppath);
+		PG_RE_THROW();
 	}
+	PG_END_TRY();
 
 	return workspace;
 }
-- 
2.54.0


--MP_/LMSk9=uMhuQ1QiIJDarDO8G--





^ permalink  raw  reply  [nested|flat] 611+ messages in thread

* [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths
@ 2026-06-01 22:41 Andrey Chernyy <andrey.cherny@tantorlabs.com>
  0 siblings, 0 replies; 611+ messages in thread

From: Andrey Chernyy @ 2026-06-01 22:41 UTC (permalink / raw)

pgxml_xpath() builds an xpath_workspace before returning it to
callers.  If an ERROR is thrown before the function returns, callers
have not received the workspace pointer yet and cannot run
cleanup_workspace().

Add local error cleanup for the partially built workspace and the
compiled XPath expression.  Also check xmlXPathNewContext() before
dereferencing the returned context.
---
 contrib/xml2/xpath.c | 51 +++++++++++++++++++++++++++-----------------
 1 file changed, 32 insertions(+), 19 deletions(-)

diff --git a/contrib/xml2/xpath.c b/contrib/xml2/xpath.c
index 9fe75cb5ff4..283bb51178d 100644
--- a/contrib/xml2/xpath.c
+++ b/contrib/xml2/xpath.c
@@ -497,36 +497,49 @@ static xpath_workspace *
 pgxml_xpath(text *document, xmlChar *xpath, PgXmlErrorContext *xmlerrcxt)
 {
 	int32		docsize = VARSIZE_ANY_EXHDR(document);
-	xmlXPathCompExprPtr comppath;
+	xmlXPathCompExprPtr volatile comppath = NULL;
 	xpath_workspace *workspace = palloc0_object(xpath_workspace);
 
 	workspace->doctree = NULL;
 	workspace->ctxt = NULL;
 	workspace->res = NULL;
 
-	workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
-									   docsize, NULL, NULL,
-									   XML_PARSE_NOENT);
-	if (workspace->doctree != NULL)
+	PG_TRY();
 	{
-		workspace->ctxt = xmlXPathNewContext(workspace->doctree);
-		workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
-
-		/* compile the path */
-		comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
-		if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+		workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
+										   docsize, NULL, NULL,
+										   XML_PARSE_NOENT);
+		if (workspace->doctree != NULL)
 		{
-			if (comppath != NULL)
-				xmlXPathFreeCompExpr(comppath);
-			xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
-						"XPath Syntax Error");
-		}
+			workspace->ctxt = xmlXPathNewContext(workspace->doctree);
+			if (workspace->ctxt == NULL)
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_OUT_OF_MEMORY,
+							"could not allocate XPath context");
 
-		/* Now evaluate the path expression. */
-		workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+			workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
+
+			/* compile the path */
+			comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
+			if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
+							"XPath Syntax Error");
+
+			/* Now evaluate the path expression. */
+			workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+
+			xmlXPathFreeCompExpr(comppath);
+			comppath = NULL;
+		}
+	}
+	PG_CATCH();
+	{
+		if (comppath != NULL)
+			xmlXPathFreeCompExpr(comppath);
+		cleanup_workspace(workspace);
 
-		xmlXPathFreeCompExpr(comppath);
+		PG_RE_THROW();
 	}
+	PG_END_TRY();
 
 	return workspace;
 }
-- 
2.54.0


--MP_/LMSk9=uMhuQ1QiIJDarDO8G--





^ permalink  raw  reply  [nested|flat] 611+ messages in thread

* [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths
@ 2026-06-01 22:41 Andrey Chernyy <andrey.cherny@tantorlabs.com>
  0 siblings, 0 replies; 611+ messages in thread

From: Andrey Chernyy @ 2026-06-01 22:41 UTC (permalink / raw)

pgxml_xpath() builds an xpath_workspace before returning it to
callers.  If an ERROR is thrown before the function returns, callers
have not received the workspace pointer yet and cannot run
cleanup_workspace().

Add local error cleanup for the partially built workspace and the
compiled XPath expression.  Also check xmlXPathNewContext() before
dereferencing the returned context.
---
 contrib/xml2/xpath.c | 51 +++++++++++++++++++++++++++-----------------
 1 file changed, 32 insertions(+), 19 deletions(-)

diff --git a/contrib/xml2/xpath.c b/contrib/xml2/xpath.c
index 9fe75cb5ff4..283bb51178d 100644
--- a/contrib/xml2/xpath.c
+++ b/contrib/xml2/xpath.c
@@ -497,36 +497,49 @@ static xpath_workspace *
 pgxml_xpath(text *document, xmlChar *xpath, PgXmlErrorContext *xmlerrcxt)
 {
 	int32		docsize = VARSIZE_ANY_EXHDR(document);
-	xmlXPathCompExprPtr comppath;
+	xmlXPathCompExprPtr volatile comppath = NULL;
 	xpath_workspace *workspace = palloc0_object(xpath_workspace);
 
 	workspace->doctree = NULL;
 	workspace->ctxt = NULL;
 	workspace->res = NULL;
 
-	workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
-									   docsize, NULL, NULL,
-									   XML_PARSE_NOENT);
-	if (workspace->doctree != NULL)
+	PG_TRY();
 	{
-		workspace->ctxt = xmlXPathNewContext(workspace->doctree);
-		workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
-
-		/* compile the path */
-		comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
-		if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+		workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
+										   docsize, NULL, NULL,
+										   XML_PARSE_NOENT);
+		if (workspace->doctree != NULL)
 		{
-			if (comppath != NULL)
-				xmlXPathFreeCompExpr(comppath);
-			xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
-						"XPath Syntax Error");
-		}
+			workspace->ctxt = xmlXPathNewContext(workspace->doctree);
+			if (workspace->ctxt == NULL)
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_OUT_OF_MEMORY,
+							"could not allocate XPath context");
 
-		/* Now evaluate the path expression. */
-		workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+			workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
+
+			/* compile the path */
+			comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
+			if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
+							"XPath Syntax Error");
+
+			/* Now evaluate the path expression. */
+			workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+
+			xmlXPathFreeCompExpr(comppath);
+			comppath = NULL;
+		}
+	}
+	PG_CATCH();
+	{
+		if (comppath != NULL)
+			xmlXPathFreeCompExpr(comppath);
+		cleanup_workspace(workspace);
 
-		xmlXPathFreeCompExpr(comppath);
+		PG_RE_THROW();
 	}
+	PG_END_TRY();
 
 	return workspace;
 }
-- 
2.54.0


--MP_/LMSk9=uMhuQ1QiIJDarDO8G--





^ permalink  raw  reply  [nested|flat] 611+ messages in thread

* [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths
@ 2026-06-01 22:41 Andrey Chernyy <andrey.cherny@tantorlabs.com>
  0 siblings, 0 replies; 611+ messages in thread

From: Andrey Chernyy @ 2026-06-01 22:41 UTC (permalink / raw)

pgxml_xpath() builds an xpath_workspace before returning it to
callers.  If an ERROR is thrown before the function returns, callers
have not received the workspace pointer yet and cannot run
cleanup_workspace().

Add local error cleanup for the partially built workspace and the
compiled XPath expression.  Also check xmlXPathNewContext() before
dereferencing the returned context.
---
 contrib/xml2/xpath.c | 51 +++++++++++++++++++++++++++-----------------
 1 file changed, 32 insertions(+), 19 deletions(-)

diff --git a/contrib/xml2/xpath.c b/contrib/xml2/xpath.c
index 9fe75cb5ff4..283bb51178d 100644
--- a/contrib/xml2/xpath.c
+++ b/contrib/xml2/xpath.c
@@ -497,36 +497,49 @@ static xpath_workspace *
 pgxml_xpath(text *document, xmlChar *xpath, PgXmlErrorContext *xmlerrcxt)
 {
 	int32		docsize = VARSIZE_ANY_EXHDR(document);
-	xmlXPathCompExprPtr comppath;
+	xmlXPathCompExprPtr volatile comppath = NULL;
 	xpath_workspace *workspace = palloc0_object(xpath_workspace);
 
 	workspace->doctree = NULL;
 	workspace->ctxt = NULL;
 	workspace->res = NULL;
 
-	workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
-									   docsize, NULL, NULL,
-									   XML_PARSE_NOENT);
-	if (workspace->doctree != NULL)
+	PG_TRY();
 	{
-		workspace->ctxt = xmlXPathNewContext(workspace->doctree);
-		workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
-
-		/* compile the path */
-		comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
-		if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+		workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
+										   docsize, NULL, NULL,
+										   XML_PARSE_NOENT);
+		if (workspace->doctree != NULL)
 		{
-			if (comppath != NULL)
-				xmlXPathFreeCompExpr(comppath);
-			xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
-						"XPath Syntax Error");
-		}
+			workspace->ctxt = xmlXPathNewContext(workspace->doctree);
+			if (workspace->ctxt == NULL)
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_OUT_OF_MEMORY,
+							"could not allocate XPath context");
 
-		/* Now evaluate the path expression. */
-		workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+			workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
+
+			/* compile the path */
+			comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
+			if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
+							"XPath Syntax Error");
+
+			/* Now evaluate the path expression. */
+			workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+
+			xmlXPathFreeCompExpr(comppath);
+			comppath = NULL;
+		}
+	}
+	PG_CATCH();
+	{
+		if (comppath != NULL)
+			xmlXPathFreeCompExpr(comppath);
+		cleanup_workspace(workspace);
 
-		xmlXPathFreeCompExpr(comppath);
+		PG_RE_THROW();
 	}
+	PG_END_TRY();
 
 	return workspace;
 }
-- 
2.54.0


--MP_/LMSk9=uMhuQ1QiIJDarDO8G--






^ permalink  raw  reply  [nested|flat] 611+ messages in thread

* [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths
@ 2026-06-01 22:41 Andrey Chernyy <andrey.cherny@tantorlabs.com>
  0 siblings, 0 replies; 611+ messages in thread

From: Andrey Chernyy @ 2026-06-01 22:41 UTC (permalink / raw)

pgxml_xpath() builds an xpath_workspace before returning it to
callers.  If an ERROR is thrown before the function returns, callers
have not received the workspace pointer yet and cannot run
cleanup_workspace().

Add local error cleanup for the partially built workspace and the
compiled XPath expression.  Also check xmlXPathNewContext() before
dereferencing the returned context.
---
 contrib/xml2/xpath.c | 51 +++++++++++++++++++++++++++-----------------
 1 file changed, 32 insertions(+), 19 deletions(-)

diff --git a/contrib/xml2/xpath.c b/contrib/xml2/xpath.c
index 9fe75cb5ff4..283bb51178d 100644
--- a/contrib/xml2/xpath.c
+++ b/contrib/xml2/xpath.c
@@ -497,36 +497,49 @@ static xpath_workspace *
 pgxml_xpath(text *document, xmlChar *xpath, PgXmlErrorContext *xmlerrcxt)
 {
 	int32		docsize = VARSIZE_ANY_EXHDR(document);
-	xmlXPathCompExprPtr comppath;
+	xmlXPathCompExprPtr volatile comppath = NULL;
 	xpath_workspace *workspace = palloc0_object(xpath_workspace);
 
 	workspace->doctree = NULL;
 	workspace->ctxt = NULL;
 	workspace->res = NULL;
 
-	workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
-									   docsize, NULL, NULL,
-									   XML_PARSE_NOENT);
-	if (workspace->doctree != NULL)
+	PG_TRY();
 	{
-		workspace->ctxt = xmlXPathNewContext(workspace->doctree);
-		workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
-
-		/* compile the path */
-		comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
-		if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+		workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
+										   docsize, NULL, NULL,
+										   XML_PARSE_NOENT);
+		if (workspace->doctree != NULL)
 		{
-			if (comppath != NULL)
-				xmlXPathFreeCompExpr(comppath);
-			xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
-						"XPath Syntax Error");
-		}
+			workspace->ctxt = xmlXPathNewContext(workspace->doctree);
+			if (workspace->ctxt == NULL)
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_OUT_OF_MEMORY,
+							"could not allocate XPath context");
 
-		/* Now evaluate the path expression. */
-		workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+			workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
+
+			/* compile the path */
+			comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
+			if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
+							"XPath Syntax Error");
+
+			/* Now evaluate the path expression. */
+			workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+
+			xmlXPathFreeCompExpr(comppath);
+			comppath = NULL;
+		}
+	}
+	PG_CATCH();
+	{
+		if (comppath != NULL)
+			xmlXPathFreeCompExpr(comppath);
+		cleanup_workspace(workspace);
 
-		xmlXPathFreeCompExpr(comppath);
+		PG_RE_THROW();
 	}
+	PG_END_TRY();
 
 	return workspace;
 }
-- 
2.54.0


--MP_/LMSk9=uMhuQ1QiIJDarDO8G--





^ permalink  raw  reply  [nested|flat] 611+ messages in thread

* [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths
@ 2026-06-01 22:41 Andrey Chernyy <andrey.cherny@tantorlabs.com>
  0 siblings, 0 replies; 611+ messages in thread

From: Andrey Chernyy @ 2026-06-01 22:41 UTC (permalink / raw)

pgxml_xpath() builds an xpath_workspace before returning it to
callers.  If an ERROR is thrown before the function returns, callers
have not received the workspace pointer yet and cannot run
cleanup_workspace().

Add local error cleanup for the partially built workspace and the
compiled XPath expression.  Also check xmlXPathNewContext() before
dereferencing the returned context.
---
 contrib/xml2/xpath.c | 51 +++++++++++++++++++++++++++-----------------
 1 file changed, 32 insertions(+), 19 deletions(-)

diff --git a/contrib/xml2/xpath.c b/contrib/xml2/xpath.c
index 9fe75cb5ff4..283bb51178d 100644
--- a/contrib/xml2/xpath.c
+++ b/contrib/xml2/xpath.c
@@ -497,36 +497,49 @@ static xpath_workspace *
 pgxml_xpath(text *document, xmlChar *xpath, PgXmlErrorContext *xmlerrcxt)
 {
 	int32		docsize = VARSIZE_ANY_EXHDR(document);
-	xmlXPathCompExprPtr comppath;
+	xmlXPathCompExprPtr volatile comppath = NULL;
 	xpath_workspace *workspace = palloc0_object(xpath_workspace);
 
 	workspace->doctree = NULL;
 	workspace->ctxt = NULL;
 	workspace->res = NULL;
 
-	workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
-									   docsize, NULL, NULL,
-									   XML_PARSE_NOENT);
-	if (workspace->doctree != NULL)
+	PG_TRY();
 	{
-		workspace->ctxt = xmlXPathNewContext(workspace->doctree);
-		workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
-
-		/* compile the path */
-		comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
-		if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+		workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
+										   docsize, NULL, NULL,
+										   XML_PARSE_NOENT);
+		if (workspace->doctree != NULL)
 		{
-			if (comppath != NULL)
-				xmlXPathFreeCompExpr(comppath);
-			xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
-						"XPath Syntax Error");
-		}
+			workspace->ctxt = xmlXPathNewContext(workspace->doctree);
+			if (workspace->ctxt == NULL)
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_OUT_OF_MEMORY,
+							"could not allocate XPath context");
 
-		/* Now evaluate the path expression. */
-		workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+			workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
+
+			/* compile the path */
+			comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
+			if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
+							"XPath Syntax Error");
+
+			/* Now evaluate the path expression. */
+			workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+
+			xmlXPathFreeCompExpr(comppath);
+			comppath = NULL;
+		}
+	}
+	PG_CATCH();
+	{
+		if (comppath != NULL)
+			xmlXPathFreeCompExpr(comppath);
+		cleanup_workspace(workspace);
 
-		xmlXPathFreeCompExpr(comppath);
+		PG_RE_THROW();
 	}
+	PG_END_TRY();
 
 	return workspace;
 }
-- 
2.54.0


--MP_/LMSk9=uMhuQ1QiIJDarDO8G--






^ permalink  raw  reply  [nested|flat] 611+ messages in thread

* [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths
@ 2026-06-01 22:41 Andrey Chernyy <andrey.cherny@tantorlabs.com>
  0 siblings, 0 replies; 611+ messages in thread

From: Andrey Chernyy @ 2026-06-01 22:41 UTC (permalink / raw)

pgxml_xpath() builds an xpath_workspace before returning it to
callers.  If an ERROR is thrown before the function returns, callers
have not received the workspace pointer yet and cannot run
cleanup_workspace().

Add local error cleanup for the partially built workspace and the
compiled XPath expression.  Also check xmlXPathNewContext() before
dereferencing the returned context.
---
 contrib/xml2/xpath.c | 51 +++++++++++++++++++++++++++-----------------
 1 file changed, 32 insertions(+), 19 deletions(-)

diff --git a/contrib/xml2/xpath.c b/contrib/xml2/xpath.c
index 9fe75cb5ff4..283bb51178d 100644
--- a/contrib/xml2/xpath.c
+++ b/contrib/xml2/xpath.c
@@ -497,36 +497,49 @@ static xpath_workspace *
 pgxml_xpath(text *document, xmlChar *xpath, PgXmlErrorContext *xmlerrcxt)
 {
 	int32		docsize = VARSIZE_ANY_EXHDR(document);
-	xmlXPathCompExprPtr comppath;
+	xmlXPathCompExprPtr volatile comppath = NULL;
 	xpath_workspace *workspace = palloc0_object(xpath_workspace);
 
 	workspace->doctree = NULL;
 	workspace->ctxt = NULL;
 	workspace->res = NULL;
 
-	workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
-									   docsize, NULL, NULL,
-									   XML_PARSE_NOENT);
-	if (workspace->doctree != NULL)
+	PG_TRY();
 	{
-		workspace->ctxt = xmlXPathNewContext(workspace->doctree);
-		workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
-
-		/* compile the path */
-		comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
-		if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+		workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
+										   docsize, NULL, NULL,
+										   XML_PARSE_NOENT);
+		if (workspace->doctree != NULL)
 		{
-			if (comppath != NULL)
-				xmlXPathFreeCompExpr(comppath);
-			xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
-						"XPath Syntax Error");
-		}
+			workspace->ctxt = xmlXPathNewContext(workspace->doctree);
+			if (workspace->ctxt == NULL)
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_OUT_OF_MEMORY,
+							"could not allocate XPath context");
 
-		/* Now evaluate the path expression. */
-		workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+			workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
+
+			/* compile the path */
+			comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
+			if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
+							"XPath Syntax Error");
+
+			/* Now evaluate the path expression. */
+			workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+
+			xmlXPathFreeCompExpr(comppath);
+			comppath = NULL;
+		}
+	}
+	PG_CATCH();
+	{
+		if (comppath != NULL)
+			xmlXPathFreeCompExpr(comppath);
+		cleanup_workspace(workspace);
 
-		xmlXPathFreeCompExpr(comppath);
+		PG_RE_THROW();
 	}
+	PG_END_TRY();
 
 	return workspace;
 }
-- 
2.54.0


--MP_/LMSk9=uMhuQ1QiIJDarDO8G--





^ permalink  raw  reply  [nested|flat] 611+ messages in thread

* [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths
@ 2026-06-01 22:41 Andrey Chernyy <andrey.cherny@tantorlabs.com>
  0 siblings, 0 replies; 611+ messages in thread

From: Andrey Chernyy @ 2026-06-01 22:41 UTC (permalink / raw)

pgxml_xpath() builds an xpath_workspace before returning it to
callers.  If an ERROR is thrown before the function returns, callers
have not received the workspace pointer yet and cannot run
cleanup_workspace().

Add local error cleanup for the partially built workspace and the
compiled XPath expression.  Also check xmlXPathNewContext() before
dereferencing the returned context.
---
 contrib/xml2/xpath.c | 51 +++++++++++++++++++++++++++-----------------
 1 file changed, 32 insertions(+), 19 deletions(-)

diff --git a/contrib/xml2/xpath.c b/contrib/xml2/xpath.c
index 9fe75cb5ff4..283bb51178d 100644
--- a/contrib/xml2/xpath.c
+++ b/contrib/xml2/xpath.c
@@ -497,36 +497,49 @@ static xpath_workspace *
 pgxml_xpath(text *document, xmlChar *xpath, PgXmlErrorContext *xmlerrcxt)
 {
 	int32		docsize = VARSIZE_ANY_EXHDR(document);
-	xmlXPathCompExprPtr comppath;
+	xmlXPathCompExprPtr volatile comppath = NULL;
 	xpath_workspace *workspace = palloc0_object(xpath_workspace);
 
 	workspace->doctree = NULL;
 	workspace->ctxt = NULL;
 	workspace->res = NULL;
 
-	workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
-									   docsize, NULL, NULL,
-									   XML_PARSE_NOENT);
-	if (workspace->doctree != NULL)
+	PG_TRY();
 	{
-		workspace->ctxt = xmlXPathNewContext(workspace->doctree);
-		workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
-
-		/* compile the path */
-		comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
-		if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+		workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
+										   docsize, NULL, NULL,
+										   XML_PARSE_NOENT);
+		if (workspace->doctree != NULL)
 		{
-			if (comppath != NULL)
-				xmlXPathFreeCompExpr(comppath);
-			xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
-						"XPath Syntax Error");
-		}
+			workspace->ctxt = xmlXPathNewContext(workspace->doctree);
+			if (workspace->ctxt == NULL)
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_OUT_OF_MEMORY,
+							"could not allocate XPath context");
 
-		/* Now evaluate the path expression. */
-		workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+			workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
+
+			/* compile the path */
+			comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
+			if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
+							"XPath Syntax Error");
+
+			/* Now evaluate the path expression. */
+			workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+
+			xmlXPathFreeCompExpr(comppath);
+			comppath = NULL;
+		}
+	}
+	PG_CATCH();
+	{
+		if (comppath != NULL)
+			xmlXPathFreeCompExpr(comppath);
+		cleanup_workspace(workspace);
 
-		xmlXPathFreeCompExpr(comppath);
+		PG_RE_THROW();
 	}
+	PG_END_TRY();
 
 	return workspace;
 }
-- 
2.54.0


--MP_/LMSk9=uMhuQ1QiIJDarDO8G--





^ permalink  raw  reply  [nested|flat] 611+ messages in thread

* [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths
@ 2026-06-01 22:41 Andrey Chernyy <andrey.cherny@tantorlabs.com>
  0 siblings, 0 replies; 611+ messages in thread

From: Andrey Chernyy @ 2026-06-01 22:41 UTC (permalink / raw)

pgxml_xpath() builds an xpath_workspace before returning it to
callers.  If an ERROR is thrown before the function returns, callers
have not received the workspace pointer yet and cannot run
cleanup_workspace().

Add local error cleanup for the partially built workspace and the
compiled XPath expression.  Also check xmlXPathNewContext() before
dereferencing the returned context.
---
 contrib/xml2/xpath.c | 51 +++++++++++++++++++++++++++-----------------
 1 file changed, 32 insertions(+), 19 deletions(-)

diff --git a/contrib/xml2/xpath.c b/contrib/xml2/xpath.c
index 9fe75cb5ff4..283bb51178d 100644
--- a/contrib/xml2/xpath.c
+++ b/contrib/xml2/xpath.c
@@ -497,36 +497,49 @@ static xpath_workspace *
 pgxml_xpath(text *document, xmlChar *xpath, PgXmlErrorContext *xmlerrcxt)
 {
 	int32		docsize = VARSIZE_ANY_EXHDR(document);
-	xmlXPathCompExprPtr comppath;
+	xmlXPathCompExprPtr volatile comppath = NULL;
 	xpath_workspace *workspace = palloc0_object(xpath_workspace);
 
 	workspace->doctree = NULL;
 	workspace->ctxt = NULL;
 	workspace->res = NULL;
 
-	workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
-									   docsize, NULL, NULL,
-									   XML_PARSE_NOENT);
-	if (workspace->doctree != NULL)
+	PG_TRY();
 	{
-		workspace->ctxt = xmlXPathNewContext(workspace->doctree);
-		workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
-
-		/* compile the path */
-		comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
-		if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+		workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
+										   docsize, NULL, NULL,
+										   XML_PARSE_NOENT);
+		if (workspace->doctree != NULL)
 		{
-			if (comppath != NULL)
-				xmlXPathFreeCompExpr(comppath);
-			xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
-						"XPath Syntax Error");
-		}
+			workspace->ctxt = xmlXPathNewContext(workspace->doctree);
+			if (workspace->ctxt == NULL)
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_OUT_OF_MEMORY,
+							"could not allocate XPath context");
 
-		/* Now evaluate the path expression. */
-		workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+			workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
+
+			/* compile the path */
+			comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
+			if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
+							"XPath Syntax Error");
+
+			/* Now evaluate the path expression. */
+			workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+
+			xmlXPathFreeCompExpr(comppath);
+			comppath = NULL;
+		}
+	}
+	PG_CATCH();
+	{
+		if (comppath != NULL)
+			xmlXPathFreeCompExpr(comppath);
+		cleanup_workspace(workspace);
 
-		xmlXPathFreeCompExpr(comppath);
+		PG_RE_THROW();
 	}
+	PG_END_TRY();
 
 	return workspace;
 }
-- 
2.54.0


--MP_/LMSk9=uMhuQ1QiIJDarDO8G--






^ permalink  raw  reply  [nested|flat] 611+ messages in thread

* [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths
@ 2026-06-01 22:41 Andrey Chernyy <andrey.cherny@tantorlabs.com>
  0 siblings, 0 replies; 611+ messages in thread

From: Andrey Chernyy @ 2026-06-01 22:41 UTC (permalink / raw)

pgxml_xpath() builds an xpath_workspace before returning it to
callers.  If an ERROR is thrown before the function returns, callers
have not received the workspace pointer yet and cannot run
cleanup_workspace().

Add local error cleanup for the partially built workspace and the
compiled XPath expression.  Also check xmlXPathNewContext() before
dereferencing the returned context.
---
 contrib/xml2/xpath.c | 51 +++++++++++++++++++++++++++-----------------
 1 file changed, 32 insertions(+), 19 deletions(-)

diff --git a/contrib/xml2/xpath.c b/contrib/xml2/xpath.c
index 9fe75cb5ff4..283bb51178d 100644
--- a/contrib/xml2/xpath.c
+++ b/contrib/xml2/xpath.c
@@ -497,36 +497,49 @@ static xpath_workspace *
 pgxml_xpath(text *document, xmlChar *xpath, PgXmlErrorContext *xmlerrcxt)
 {
 	int32		docsize = VARSIZE_ANY_EXHDR(document);
-	xmlXPathCompExprPtr comppath;
+	xmlXPathCompExprPtr volatile comppath = NULL;
 	xpath_workspace *workspace = palloc0_object(xpath_workspace);
 
 	workspace->doctree = NULL;
 	workspace->ctxt = NULL;
 	workspace->res = NULL;
 
-	workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
-									   docsize, NULL, NULL,
-									   XML_PARSE_NOENT);
-	if (workspace->doctree != NULL)
+	PG_TRY();
 	{
-		workspace->ctxt = xmlXPathNewContext(workspace->doctree);
-		workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
-
-		/* compile the path */
-		comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
-		if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+		workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
+										   docsize, NULL, NULL,
+										   XML_PARSE_NOENT);
+		if (workspace->doctree != NULL)
 		{
-			if (comppath != NULL)
-				xmlXPathFreeCompExpr(comppath);
-			xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
-						"XPath Syntax Error");
-		}
+			workspace->ctxt = xmlXPathNewContext(workspace->doctree);
+			if (workspace->ctxt == NULL)
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_OUT_OF_MEMORY,
+							"could not allocate XPath context");
 
-		/* Now evaluate the path expression. */
-		workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+			workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
+
+			/* compile the path */
+			comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
+			if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
+							"XPath Syntax Error");
+
+			/* Now evaluate the path expression. */
+			workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+
+			xmlXPathFreeCompExpr(comppath);
+			comppath = NULL;
+		}
+	}
+	PG_CATCH();
+	{
+		if (comppath != NULL)
+			xmlXPathFreeCompExpr(comppath);
+		cleanup_workspace(workspace);
 
-		xmlXPathFreeCompExpr(comppath);
+		PG_RE_THROW();
 	}
+	PG_END_TRY();
 
 	return workspace;
 }
-- 
2.54.0


--MP_/LMSk9=uMhuQ1QiIJDarDO8G--






^ permalink  raw  reply  [nested|flat] 611+ messages in thread

* [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths
@ 2026-06-01 22:41 Andrey Chernyy <andrey.cherny@tantorlabs.com>
  0 siblings, 0 replies; 611+ messages in thread

From: Andrey Chernyy @ 2026-06-01 22:41 UTC (permalink / raw)

pgxml_xpath() builds an xpath_workspace before returning it to
callers.  If an ERROR is thrown before the function returns, callers
have not received the workspace pointer yet and cannot run
cleanup_workspace().

Add local error cleanup for the partially built workspace and the
compiled XPath expression.  Also check xmlXPathNewContext() before
dereferencing the returned context.
---
 contrib/xml2/xpath.c | 51 +++++++++++++++++++++++++++-----------------
 1 file changed, 32 insertions(+), 19 deletions(-)

diff --git a/contrib/xml2/xpath.c b/contrib/xml2/xpath.c
index 9fe75cb5ff4..283bb51178d 100644
--- a/contrib/xml2/xpath.c
+++ b/contrib/xml2/xpath.c
@@ -497,36 +497,49 @@ static xpath_workspace *
 pgxml_xpath(text *document, xmlChar *xpath, PgXmlErrorContext *xmlerrcxt)
 {
 	int32		docsize = VARSIZE_ANY_EXHDR(document);
-	xmlXPathCompExprPtr comppath;
+	xmlXPathCompExprPtr volatile comppath = NULL;
 	xpath_workspace *workspace = palloc0_object(xpath_workspace);
 
 	workspace->doctree = NULL;
 	workspace->ctxt = NULL;
 	workspace->res = NULL;
 
-	workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
-									   docsize, NULL, NULL,
-									   XML_PARSE_NOENT);
-	if (workspace->doctree != NULL)
+	PG_TRY();
 	{
-		workspace->ctxt = xmlXPathNewContext(workspace->doctree);
-		workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
-
-		/* compile the path */
-		comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
-		if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+		workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
+										   docsize, NULL, NULL,
+										   XML_PARSE_NOENT);
+		if (workspace->doctree != NULL)
 		{
-			if (comppath != NULL)
-				xmlXPathFreeCompExpr(comppath);
-			xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
-						"XPath Syntax Error");
-		}
+			workspace->ctxt = xmlXPathNewContext(workspace->doctree);
+			if (workspace->ctxt == NULL)
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_OUT_OF_MEMORY,
+							"could not allocate XPath context");
 
-		/* Now evaluate the path expression. */
-		workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+			workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
+
+			/* compile the path */
+			comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
+			if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
+							"XPath Syntax Error");
+
+			/* Now evaluate the path expression. */
+			workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+
+			xmlXPathFreeCompExpr(comppath);
+			comppath = NULL;
+		}
+	}
+	PG_CATCH();
+	{
+		if (comppath != NULL)
+			xmlXPathFreeCompExpr(comppath);
+		cleanup_workspace(workspace);
 
-		xmlXPathFreeCompExpr(comppath);
+		PG_RE_THROW();
 	}
+	PG_END_TRY();
 
 	return workspace;
 }
-- 
2.54.0


--MP_/LMSk9=uMhuQ1QiIJDarDO8G--





^ permalink  raw  reply  [nested|flat] 611+ messages in thread

* [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths
@ 2026-06-01 22:41 Andrey Chernyy <andrey.cherny@tantorlabs.com>
  0 siblings, 0 replies; 611+ messages in thread

From: Andrey Chernyy @ 2026-06-01 22:41 UTC (permalink / raw)

pgxml_xpath() builds an xpath_workspace before returning it to
callers.  If an ERROR is thrown before the function returns, callers
have not received the workspace pointer yet and cannot run
cleanup_workspace().

Add local error cleanup for the partially built workspace and the
compiled XPath expression.  Also check xmlXPathNewContext() before
dereferencing the returned context.
---
 contrib/xml2/xpath.c | 51 +++++++++++++++++++++++++++-----------------
 1 file changed, 32 insertions(+), 19 deletions(-)

diff --git a/contrib/xml2/xpath.c b/contrib/xml2/xpath.c
index 9fe75cb5ff4..283bb51178d 100644
--- a/contrib/xml2/xpath.c
+++ b/contrib/xml2/xpath.c
@@ -497,36 +497,49 @@ static xpath_workspace *
 pgxml_xpath(text *document, xmlChar *xpath, PgXmlErrorContext *xmlerrcxt)
 {
 	int32		docsize = VARSIZE_ANY_EXHDR(document);
-	xmlXPathCompExprPtr comppath;
+	xmlXPathCompExprPtr volatile comppath = NULL;
 	xpath_workspace *workspace = palloc0_object(xpath_workspace);
 
 	workspace->doctree = NULL;
 	workspace->ctxt = NULL;
 	workspace->res = NULL;
 
-	workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
-									   docsize, NULL, NULL,
-									   XML_PARSE_NOENT);
-	if (workspace->doctree != NULL)
+	PG_TRY();
 	{
-		workspace->ctxt = xmlXPathNewContext(workspace->doctree);
-		workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
-
-		/* compile the path */
-		comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
-		if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+		workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
+										   docsize, NULL, NULL,
+										   XML_PARSE_NOENT);
+		if (workspace->doctree != NULL)
 		{
-			if (comppath != NULL)
-				xmlXPathFreeCompExpr(comppath);
-			xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
-						"XPath Syntax Error");
-		}
+			workspace->ctxt = xmlXPathNewContext(workspace->doctree);
+			if (workspace->ctxt == NULL)
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_OUT_OF_MEMORY,
+							"could not allocate XPath context");
 
-		/* Now evaluate the path expression. */
-		workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+			workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
+
+			/* compile the path */
+			comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
+			if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
+							"XPath Syntax Error");
+
+			/* Now evaluate the path expression. */
+			workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+
+			xmlXPathFreeCompExpr(comppath);
+			comppath = NULL;
+		}
+	}
+	PG_CATCH();
+	{
+		if (comppath != NULL)
+			xmlXPathFreeCompExpr(comppath);
+		cleanup_workspace(workspace);
 
-		xmlXPathFreeCompExpr(comppath);
+		PG_RE_THROW();
 	}
+	PG_END_TRY();
 
 	return workspace;
 }
-- 
2.54.0


--MP_/LMSk9=uMhuQ1QiIJDarDO8G--





^ permalink  raw  reply  [nested|flat] 611+ messages in thread

* [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths
@ 2026-06-01 22:41 Andrey Chernyy <andrey.cherny@tantorlabs.com>
  0 siblings, 0 replies; 611+ messages in thread

From: Andrey Chernyy @ 2026-06-01 22:41 UTC (permalink / raw)

pgxml_xpath() builds an xpath_workspace before returning it to
callers.  If an ERROR is thrown before the function returns, callers
have not received the workspace pointer yet and cannot run
cleanup_workspace().

Add local error cleanup for the partially built workspace and the
compiled XPath expression.  Also check xmlXPathNewContext() before
dereferencing the returned context.
---
 contrib/xml2/xpath.c | 51 +++++++++++++++++++++++++++-----------------
 1 file changed, 32 insertions(+), 19 deletions(-)

diff --git a/contrib/xml2/xpath.c b/contrib/xml2/xpath.c
index 9fe75cb5ff4..283bb51178d 100644
--- a/contrib/xml2/xpath.c
+++ b/contrib/xml2/xpath.c
@@ -497,36 +497,49 @@ static xpath_workspace *
 pgxml_xpath(text *document, xmlChar *xpath, PgXmlErrorContext *xmlerrcxt)
 {
 	int32		docsize = VARSIZE_ANY_EXHDR(document);
-	xmlXPathCompExprPtr comppath;
+	xmlXPathCompExprPtr volatile comppath = NULL;
 	xpath_workspace *workspace = palloc0_object(xpath_workspace);
 
 	workspace->doctree = NULL;
 	workspace->ctxt = NULL;
 	workspace->res = NULL;
 
-	workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
-									   docsize, NULL, NULL,
-									   XML_PARSE_NOENT);
-	if (workspace->doctree != NULL)
+	PG_TRY();
 	{
-		workspace->ctxt = xmlXPathNewContext(workspace->doctree);
-		workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
-
-		/* compile the path */
-		comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
-		if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+		workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
+										   docsize, NULL, NULL,
+										   XML_PARSE_NOENT);
+		if (workspace->doctree != NULL)
 		{
-			if (comppath != NULL)
-				xmlXPathFreeCompExpr(comppath);
-			xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
-						"XPath Syntax Error");
-		}
+			workspace->ctxt = xmlXPathNewContext(workspace->doctree);
+			if (workspace->ctxt == NULL)
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_OUT_OF_MEMORY,
+							"could not allocate XPath context");
 
-		/* Now evaluate the path expression. */
-		workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+			workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
+
+			/* compile the path */
+			comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
+			if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
+							"XPath Syntax Error");
+
+			/* Now evaluate the path expression. */
+			workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+
+			xmlXPathFreeCompExpr(comppath);
+			comppath = NULL;
+		}
+	}
+	PG_CATCH();
+	{
+		if (comppath != NULL)
+			xmlXPathFreeCompExpr(comppath);
+		cleanup_workspace(workspace);
 
-		xmlXPathFreeCompExpr(comppath);
+		PG_RE_THROW();
 	}
+	PG_END_TRY();
 
 	return workspace;
 }
-- 
2.54.0


--MP_/LMSk9=uMhuQ1QiIJDarDO8G--





^ permalink  raw  reply  [nested|flat] 611+ messages in thread

* [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths
@ 2026-06-01 22:41 Andrey Chernyy <andrey.cherny@tantorlabs.com>
  0 siblings, 0 replies; 611+ messages in thread

From: Andrey Chernyy @ 2026-06-01 22:41 UTC (permalink / raw)

pgxml_xpath() builds an xpath_workspace before returning it to
callers.  If an ERROR is thrown before the function returns, callers
have not received the workspace pointer yet and cannot run
cleanup_workspace().

Add local error cleanup for the partially built workspace and the
compiled XPath expression.  Also check xmlXPathNewContext() before
dereferencing the returned context.
---
 contrib/xml2/xpath.c | 51 +++++++++++++++++++++++++++-----------------
 1 file changed, 32 insertions(+), 19 deletions(-)

diff --git a/contrib/xml2/xpath.c b/contrib/xml2/xpath.c
index 9fe75cb5ff4..283bb51178d 100644
--- a/contrib/xml2/xpath.c
+++ b/contrib/xml2/xpath.c
@@ -497,36 +497,49 @@ static xpath_workspace *
 pgxml_xpath(text *document, xmlChar *xpath, PgXmlErrorContext *xmlerrcxt)
 {
 	int32		docsize = VARSIZE_ANY_EXHDR(document);
-	xmlXPathCompExprPtr comppath;
+	xmlXPathCompExprPtr volatile comppath = NULL;
 	xpath_workspace *workspace = palloc0_object(xpath_workspace);
 
 	workspace->doctree = NULL;
 	workspace->ctxt = NULL;
 	workspace->res = NULL;
 
-	workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
-									   docsize, NULL, NULL,
-									   XML_PARSE_NOENT);
-	if (workspace->doctree != NULL)
+	PG_TRY();
 	{
-		workspace->ctxt = xmlXPathNewContext(workspace->doctree);
-		workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
-
-		/* compile the path */
-		comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
-		if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+		workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
+										   docsize, NULL, NULL,
+										   XML_PARSE_NOENT);
+		if (workspace->doctree != NULL)
 		{
-			if (comppath != NULL)
-				xmlXPathFreeCompExpr(comppath);
-			xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
-						"XPath Syntax Error");
-		}
+			workspace->ctxt = xmlXPathNewContext(workspace->doctree);
+			if (workspace->ctxt == NULL)
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_OUT_OF_MEMORY,
+							"could not allocate XPath context");
 
-		/* Now evaluate the path expression. */
-		workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+			workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
+
+			/* compile the path */
+			comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
+			if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
+							"XPath Syntax Error");
+
+			/* Now evaluate the path expression. */
+			workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+
+			xmlXPathFreeCompExpr(comppath);
+			comppath = NULL;
+		}
+	}
+	PG_CATCH();
+	{
+		if (comppath != NULL)
+			xmlXPathFreeCompExpr(comppath);
+		cleanup_workspace(workspace);
 
-		xmlXPathFreeCompExpr(comppath);
+		PG_RE_THROW();
 	}
+	PG_END_TRY();
 
 	return workspace;
 }
-- 
2.54.0


--MP_/LMSk9=uMhuQ1QiIJDarDO8G--






^ permalink  raw  reply  [nested|flat] 611+ messages in thread

* [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths
@ 2026-06-01 22:41 Andrey Chernyy <andrey.cherny@tantorlabs.com>
  0 siblings, 0 replies; 611+ messages in thread

From: Andrey Chernyy @ 2026-06-01 22:41 UTC (permalink / raw)

pgxml_xpath() builds an xpath_workspace before returning it to
callers.  If an ERROR is thrown before the function returns, callers
have not received the workspace pointer yet and cannot run
cleanup_workspace().

Add local error cleanup for the partially built workspace and the
compiled XPath expression.  Also check xmlXPathNewContext() before
dereferencing the returned context.
---
 contrib/xml2/xpath.c | 51 +++++++++++++++++++++++++++-----------------
 1 file changed, 32 insertions(+), 19 deletions(-)

diff --git a/contrib/xml2/xpath.c b/contrib/xml2/xpath.c
index 9fe75cb5ff4..283bb51178d 100644
--- a/contrib/xml2/xpath.c
+++ b/contrib/xml2/xpath.c
@@ -497,36 +497,49 @@ static xpath_workspace *
 pgxml_xpath(text *document, xmlChar *xpath, PgXmlErrorContext *xmlerrcxt)
 {
 	int32		docsize = VARSIZE_ANY_EXHDR(document);
-	xmlXPathCompExprPtr comppath;
+	xmlXPathCompExprPtr volatile comppath = NULL;
 	xpath_workspace *workspace = palloc0_object(xpath_workspace);
 
 	workspace->doctree = NULL;
 	workspace->ctxt = NULL;
 	workspace->res = NULL;
 
-	workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
-									   docsize, NULL, NULL,
-									   XML_PARSE_NOENT);
-	if (workspace->doctree != NULL)
+	PG_TRY();
 	{
-		workspace->ctxt = xmlXPathNewContext(workspace->doctree);
-		workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
-
-		/* compile the path */
-		comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
-		if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+		workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
+										   docsize, NULL, NULL,
+										   XML_PARSE_NOENT);
+		if (workspace->doctree != NULL)
 		{
-			if (comppath != NULL)
-				xmlXPathFreeCompExpr(comppath);
-			xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
-						"XPath Syntax Error");
-		}
+			workspace->ctxt = xmlXPathNewContext(workspace->doctree);
+			if (workspace->ctxt == NULL)
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_OUT_OF_MEMORY,
+							"could not allocate XPath context");
 
-		/* Now evaluate the path expression. */
-		workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+			workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
+
+			/* compile the path */
+			comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
+			if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
+							"XPath Syntax Error");
+
+			/* Now evaluate the path expression. */
+			workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+
+			xmlXPathFreeCompExpr(comppath);
+			comppath = NULL;
+		}
+	}
+	PG_CATCH();
+	{
+		if (comppath != NULL)
+			xmlXPathFreeCompExpr(comppath);
+		cleanup_workspace(workspace);
 
-		xmlXPathFreeCompExpr(comppath);
+		PG_RE_THROW();
 	}
+	PG_END_TRY();
 
 	return workspace;
 }
-- 
2.54.0


--MP_/LMSk9=uMhuQ1QiIJDarDO8G--






^ permalink  raw  reply  [nested|flat] 611+ messages in thread

* [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths
@ 2026-06-01 22:41 Andrey Chernyy <andrey.cherny@tantorlabs.com>
  0 siblings, 0 replies; 611+ messages in thread

From: Andrey Chernyy @ 2026-06-01 22:41 UTC (permalink / raw)

pgxml_xpath() builds an xpath_workspace before returning it to
callers.  If an ERROR is thrown before the function returns, callers
have not received the workspace pointer yet and cannot run
cleanup_workspace().

Add local error cleanup for the partially built workspace and the
compiled XPath expression.  Also check xmlXPathNewContext() before
dereferencing the returned context.
---
 contrib/xml2/xpath.c | 51 +++++++++++++++++++++++++++-----------------
 1 file changed, 32 insertions(+), 19 deletions(-)

diff --git a/contrib/xml2/xpath.c b/contrib/xml2/xpath.c
index 9fe75cb5ff4..283bb51178d 100644
--- a/contrib/xml2/xpath.c
+++ b/contrib/xml2/xpath.c
@@ -497,36 +497,49 @@ static xpath_workspace *
 pgxml_xpath(text *document, xmlChar *xpath, PgXmlErrorContext *xmlerrcxt)
 {
 	int32		docsize = VARSIZE_ANY_EXHDR(document);
-	xmlXPathCompExprPtr comppath;
+	xmlXPathCompExprPtr volatile comppath = NULL;
 	xpath_workspace *workspace = palloc0_object(xpath_workspace);
 
 	workspace->doctree = NULL;
 	workspace->ctxt = NULL;
 	workspace->res = NULL;
 
-	workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
-									   docsize, NULL, NULL,
-									   XML_PARSE_NOENT);
-	if (workspace->doctree != NULL)
+	PG_TRY();
 	{
-		workspace->ctxt = xmlXPathNewContext(workspace->doctree);
-		workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
-
-		/* compile the path */
-		comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
-		if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+		workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
+										   docsize, NULL, NULL,
+										   XML_PARSE_NOENT);
+		if (workspace->doctree != NULL)
 		{
-			if (comppath != NULL)
-				xmlXPathFreeCompExpr(comppath);
-			xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
-						"XPath Syntax Error");
-		}
+			workspace->ctxt = xmlXPathNewContext(workspace->doctree);
+			if (workspace->ctxt == NULL)
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_OUT_OF_MEMORY,
+							"could not allocate XPath context");
 
-		/* Now evaluate the path expression. */
-		workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+			workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
+
+			/* compile the path */
+			comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
+			if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
+							"XPath Syntax Error");
+
+			/* Now evaluate the path expression. */
+			workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+
+			xmlXPathFreeCompExpr(comppath);
+			comppath = NULL;
+		}
+	}
+	PG_CATCH();
+	{
+		if (comppath != NULL)
+			xmlXPathFreeCompExpr(comppath);
+		cleanup_workspace(workspace);
 
-		xmlXPathFreeCompExpr(comppath);
+		PG_RE_THROW();
 	}
+	PG_END_TRY();
 
 	return workspace;
 }
-- 
2.54.0


--MP_/LMSk9=uMhuQ1QiIJDarDO8G--






^ permalink  raw  reply  [nested|flat] 611+ messages in thread

* [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths
@ 2026-06-01 22:41 Andrey Chernyy <andrey.cherny@tantorlabs.com>
  0 siblings, 0 replies; 611+ messages in thread

From: Andrey Chernyy @ 2026-06-01 22:41 UTC (permalink / raw)

pgxml_xpath() builds an xpath_workspace before returning it to
callers.  If an ERROR is thrown before the function returns, callers
have not received the workspace pointer yet and cannot run
cleanup_workspace().

Add local error cleanup for the partially built workspace and the
compiled XPath expression.  Also check xmlXPathNewContext() before
dereferencing the returned context.
---
 contrib/xml2/xpath.c | 51 +++++++++++++++++++++++++++-----------------
 1 file changed, 32 insertions(+), 19 deletions(-)

diff --git a/contrib/xml2/xpath.c b/contrib/xml2/xpath.c
index 9fe75cb5ff4..283bb51178d 100644
--- a/contrib/xml2/xpath.c
+++ b/contrib/xml2/xpath.c
@@ -497,36 +497,49 @@ static xpath_workspace *
 pgxml_xpath(text *document, xmlChar *xpath, PgXmlErrorContext *xmlerrcxt)
 {
 	int32		docsize = VARSIZE_ANY_EXHDR(document);
-	xmlXPathCompExprPtr comppath;
+	xmlXPathCompExprPtr volatile comppath = NULL;
 	xpath_workspace *workspace = palloc0_object(xpath_workspace);
 
 	workspace->doctree = NULL;
 	workspace->ctxt = NULL;
 	workspace->res = NULL;
 
-	workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
-									   docsize, NULL, NULL,
-									   XML_PARSE_NOENT);
-	if (workspace->doctree != NULL)
+	PG_TRY();
 	{
-		workspace->ctxt = xmlXPathNewContext(workspace->doctree);
-		workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
-
-		/* compile the path */
-		comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
-		if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+		workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
+										   docsize, NULL, NULL,
+										   XML_PARSE_NOENT);
+		if (workspace->doctree != NULL)
 		{
-			if (comppath != NULL)
-				xmlXPathFreeCompExpr(comppath);
-			xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
-						"XPath Syntax Error");
-		}
+			workspace->ctxt = xmlXPathNewContext(workspace->doctree);
+			if (workspace->ctxt == NULL)
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_OUT_OF_MEMORY,
+							"could not allocate XPath context");
 
-		/* Now evaluate the path expression. */
-		workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+			workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
+
+			/* compile the path */
+			comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
+			if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
+							"XPath Syntax Error");
+
+			/* Now evaluate the path expression. */
+			workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+
+			xmlXPathFreeCompExpr(comppath);
+			comppath = NULL;
+		}
+	}
+	PG_CATCH();
+	{
+		if (comppath != NULL)
+			xmlXPathFreeCompExpr(comppath);
+		cleanup_workspace(workspace);
 
-		xmlXPathFreeCompExpr(comppath);
+		PG_RE_THROW();
 	}
+	PG_END_TRY();
 
 	return workspace;
 }
-- 
2.54.0


--MP_/LMSk9=uMhuQ1QiIJDarDO8G--






^ permalink  raw  reply  [nested|flat] 611+ messages in thread

* [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths
@ 2026-06-01 22:41 Andrey Chernyy <andrey.cherny@tantorlabs.com>
  0 siblings, 0 replies; 611+ messages in thread

From: Andrey Chernyy @ 2026-06-01 22:41 UTC (permalink / raw)

pgxml_xpath() builds an xpath_workspace before returning it to
callers.  If an ERROR is thrown before the function returns, callers
have not received the workspace pointer yet and cannot run
cleanup_workspace().

Add local error cleanup for the partially built workspace and the
compiled XPath expression.  Also check xmlXPathNewContext() before
dereferencing the returned context.
---
 contrib/xml2/xpath.c | 51 +++++++++++++++++++++++++++-----------------
 1 file changed, 32 insertions(+), 19 deletions(-)

diff --git a/contrib/xml2/xpath.c b/contrib/xml2/xpath.c
index 9fe75cb5ff4..283bb51178d 100644
--- a/contrib/xml2/xpath.c
+++ b/contrib/xml2/xpath.c
@@ -497,36 +497,49 @@ static xpath_workspace *
 pgxml_xpath(text *document, xmlChar *xpath, PgXmlErrorContext *xmlerrcxt)
 {
 	int32		docsize = VARSIZE_ANY_EXHDR(document);
-	xmlXPathCompExprPtr comppath;
+	xmlXPathCompExprPtr volatile comppath = NULL;
 	xpath_workspace *workspace = palloc0_object(xpath_workspace);
 
 	workspace->doctree = NULL;
 	workspace->ctxt = NULL;
 	workspace->res = NULL;
 
-	workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
-									   docsize, NULL, NULL,
-									   XML_PARSE_NOENT);
-	if (workspace->doctree != NULL)
+	PG_TRY();
 	{
-		workspace->ctxt = xmlXPathNewContext(workspace->doctree);
-		workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
-
-		/* compile the path */
-		comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
-		if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+		workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
+										   docsize, NULL, NULL,
+										   XML_PARSE_NOENT);
+		if (workspace->doctree != NULL)
 		{
-			if (comppath != NULL)
-				xmlXPathFreeCompExpr(comppath);
-			xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
-						"XPath Syntax Error");
-		}
+			workspace->ctxt = xmlXPathNewContext(workspace->doctree);
+			if (workspace->ctxt == NULL)
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_OUT_OF_MEMORY,
+							"could not allocate XPath context");
 
-		/* Now evaluate the path expression. */
-		workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+			workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
+
+			/* compile the path */
+			comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
+			if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
+							"XPath Syntax Error");
+
+			/* Now evaluate the path expression. */
+			workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+
+			xmlXPathFreeCompExpr(comppath);
+			comppath = NULL;
+		}
+	}
+	PG_CATCH();
+	{
+		if (comppath != NULL)
+			xmlXPathFreeCompExpr(comppath);
+		cleanup_workspace(workspace);
 
-		xmlXPathFreeCompExpr(comppath);
+		PG_RE_THROW();
 	}
+	PG_END_TRY();
 
 	return workspace;
 }
-- 
2.54.0


--MP_/LMSk9=uMhuQ1QiIJDarDO8G--






^ permalink  raw  reply  [nested|flat] 611+ messages in thread

* [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths
@ 2026-06-01 22:41 Andrey Chernyy <andrey.cherny@tantorlabs.com>
  0 siblings, 0 replies; 611+ messages in thread

From: Andrey Chernyy @ 2026-06-01 22:41 UTC (permalink / raw)

pgxml_xpath() builds an xpath_workspace before returning it to
callers.  If an ERROR is thrown before the function returns, callers
have not received the workspace pointer yet and cannot run
cleanup_workspace().

Add local error cleanup for the partially built workspace and the
compiled XPath expression.  Also check xmlXPathNewContext() before
dereferencing the returned context.
---
 contrib/xml2/xpath.c | 51 +++++++++++++++++++++++++++-----------------
 1 file changed, 32 insertions(+), 19 deletions(-)

diff --git a/contrib/xml2/xpath.c b/contrib/xml2/xpath.c
index 9fe75cb5ff4..283bb51178d 100644
--- a/contrib/xml2/xpath.c
+++ b/contrib/xml2/xpath.c
@@ -497,36 +497,49 @@ static xpath_workspace *
 pgxml_xpath(text *document, xmlChar *xpath, PgXmlErrorContext *xmlerrcxt)
 {
 	int32		docsize = VARSIZE_ANY_EXHDR(document);
-	xmlXPathCompExprPtr comppath;
+	xmlXPathCompExprPtr volatile comppath = NULL;
 	xpath_workspace *workspace = palloc0_object(xpath_workspace);
 
 	workspace->doctree = NULL;
 	workspace->ctxt = NULL;
 	workspace->res = NULL;
 
-	workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
-									   docsize, NULL, NULL,
-									   XML_PARSE_NOENT);
-	if (workspace->doctree != NULL)
+	PG_TRY();
 	{
-		workspace->ctxt = xmlXPathNewContext(workspace->doctree);
-		workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
-
-		/* compile the path */
-		comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
-		if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+		workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
+										   docsize, NULL, NULL,
+										   XML_PARSE_NOENT);
+		if (workspace->doctree != NULL)
 		{
-			if (comppath != NULL)
-				xmlXPathFreeCompExpr(comppath);
-			xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
-						"XPath Syntax Error");
-		}
+			workspace->ctxt = xmlXPathNewContext(workspace->doctree);
+			if (workspace->ctxt == NULL)
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_OUT_OF_MEMORY,
+							"could not allocate XPath context");
 
-		/* Now evaluate the path expression. */
-		workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+			workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
+
+			/* compile the path */
+			comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
+			if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
+							"XPath Syntax Error");
+
+			/* Now evaluate the path expression. */
+			workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+
+			xmlXPathFreeCompExpr(comppath);
+			comppath = NULL;
+		}
+	}
+	PG_CATCH();
+	{
+		if (comppath != NULL)
+			xmlXPathFreeCompExpr(comppath);
+		cleanup_workspace(workspace);
 
-		xmlXPathFreeCompExpr(comppath);
+		PG_RE_THROW();
 	}
+	PG_END_TRY();
 
 	return workspace;
 }
-- 
2.54.0


--MP_/LMSk9=uMhuQ1QiIJDarDO8G--






^ permalink  raw  reply  [nested|flat] 611+ messages in thread

* [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths
@ 2026-06-01 22:41 Andrey Chernyy <andrey.cherny@tantorlabs.com>
  0 siblings, 0 replies; 611+ messages in thread

From: Andrey Chernyy @ 2026-06-01 22:41 UTC (permalink / raw)

pgxml_xpath() builds an xpath_workspace before returning it to
callers.  If an ERROR is thrown before the function returns, callers
have not received the workspace pointer yet and cannot run
cleanup_workspace().

Add local error cleanup for the partially built workspace and the
compiled XPath expression.  Also check xmlXPathNewContext() before
dereferencing the returned context.
---
 contrib/xml2/xpath.c | 51 +++++++++++++++++++++++++++-----------------
 1 file changed, 32 insertions(+), 19 deletions(-)

diff --git a/contrib/xml2/xpath.c b/contrib/xml2/xpath.c
index 9fe75cb5ff4..283bb51178d 100644
--- a/contrib/xml2/xpath.c
+++ b/contrib/xml2/xpath.c
@@ -497,36 +497,49 @@ static xpath_workspace *
 pgxml_xpath(text *document, xmlChar *xpath, PgXmlErrorContext *xmlerrcxt)
 {
 	int32		docsize = VARSIZE_ANY_EXHDR(document);
-	xmlXPathCompExprPtr comppath;
+	xmlXPathCompExprPtr volatile comppath = NULL;
 	xpath_workspace *workspace = palloc0_object(xpath_workspace);
 
 	workspace->doctree = NULL;
 	workspace->ctxt = NULL;
 	workspace->res = NULL;
 
-	workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
-									   docsize, NULL, NULL,
-									   XML_PARSE_NOENT);
-	if (workspace->doctree != NULL)
+	PG_TRY();
 	{
-		workspace->ctxt = xmlXPathNewContext(workspace->doctree);
-		workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
-
-		/* compile the path */
-		comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
-		if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+		workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
+										   docsize, NULL, NULL,
+										   XML_PARSE_NOENT);
+		if (workspace->doctree != NULL)
 		{
-			if (comppath != NULL)
-				xmlXPathFreeCompExpr(comppath);
-			xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
-						"XPath Syntax Error");
-		}
+			workspace->ctxt = xmlXPathNewContext(workspace->doctree);
+			if (workspace->ctxt == NULL)
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_OUT_OF_MEMORY,
+							"could not allocate XPath context");
 
-		/* Now evaluate the path expression. */
-		workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+			workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
+
+			/* compile the path */
+			comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
+			if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
+							"XPath Syntax Error");
+
+			/* Now evaluate the path expression. */
+			workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+
+			xmlXPathFreeCompExpr(comppath);
+			comppath = NULL;
+		}
+	}
+	PG_CATCH();
+	{
+		if (comppath != NULL)
+			xmlXPathFreeCompExpr(comppath);
+		cleanup_workspace(workspace);
 
-		xmlXPathFreeCompExpr(comppath);
+		PG_RE_THROW();
 	}
+	PG_END_TRY();
 
 	return workspace;
 }
-- 
2.54.0


--MP_/LMSk9=uMhuQ1QiIJDarDO8G--






^ permalink  raw  reply  [nested|flat] 611+ messages in thread

* [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths
@ 2026-06-01 22:41 Andrey Chernyy <andrey.cherny@tantorlabs.com>
  0 siblings, 0 replies; 611+ messages in thread

From: Andrey Chernyy @ 2026-06-01 22:41 UTC (permalink / raw)

pgxml_xpath() builds an xpath_workspace before returning it to
callers.  If an ERROR is thrown before the function returns, callers
have not received the workspace pointer yet and cannot run
cleanup_workspace().

Add local error cleanup for the partially built workspace and the
compiled XPath expression.  Also check xmlXPathNewContext() before
dereferencing the returned context.
---
 contrib/xml2/xpath.c | 51 +++++++++++++++++++++++++++-----------------
 1 file changed, 32 insertions(+), 19 deletions(-)

diff --git a/contrib/xml2/xpath.c b/contrib/xml2/xpath.c
index 9fe75cb5ff4..283bb51178d 100644
--- a/contrib/xml2/xpath.c
+++ b/contrib/xml2/xpath.c
@@ -497,36 +497,49 @@ static xpath_workspace *
 pgxml_xpath(text *document, xmlChar *xpath, PgXmlErrorContext *xmlerrcxt)
 {
 	int32		docsize = VARSIZE_ANY_EXHDR(document);
-	xmlXPathCompExprPtr comppath;
+	xmlXPathCompExprPtr volatile comppath = NULL;
 	xpath_workspace *workspace = palloc0_object(xpath_workspace);
 
 	workspace->doctree = NULL;
 	workspace->ctxt = NULL;
 	workspace->res = NULL;
 
-	workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
-									   docsize, NULL, NULL,
-									   XML_PARSE_NOENT);
-	if (workspace->doctree != NULL)
+	PG_TRY();
 	{
-		workspace->ctxt = xmlXPathNewContext(workspace->doctree);
-		workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
-
-		/* compile the path */
-		comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
-		if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+		workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
+										   docsize, NULL, NULL,
+										   XML_PARSE_NOENT);
+		if (workspace->doctree != NULL)
 		{
-			if (comppath != NULL)
-				xmlXPathFreeCompExpr(comppath);
-			xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
-						"XPath Syntax Error");
-		}
+			workspace->ctxt = xmlXPathNewContext(workspace->doctree);
+			if (workspace->ctxt == NULL)
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_OUT_OF_MEMORY,
+							"could not allocate XPath context");
 
-		/* Now evaluate the path expression. */
-		workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+			workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
+
+			/* compile the path */
+			comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
+			if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
+							"XPath Syntax Error");
+
+			/* Now evaluate the path expression. */
+			workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+
+			xmlXPathFreeCompExpr(comppath);
+			comppath = NULL;
+		}
+	}
+	PG_CATCH();
+	{
+		if (comppath != NULL)
+			xmlXPathFreeCompExpr(comppath);
+		cleanup_workspace(workspace);
 
-		xmlXPathFreeCompExpr(comppath);
+		PG_RE_THROW();
 	}
+	PG_END_TRY();
 
 	return workspace;
 }
-- 
2.54.0


--MP_/LMSk9=uMhuQ1QiIJDarDO8G--






^ permalink  raw  reply  [nested|flat] 611+ messages in thread

* [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths
@ 2026-06-01 22:41 Andrey Chernyy <andrey.cherny@tantorlabs.com>
  0 siblings, 0 replies; 611+ messages in thread

From: Andrey Chernyy @ 2026-06-01 22:41 UTC (permalink / raw)

pgxml_xpath() builds an xpath_workspace before returning it to
callers.  If an ERROR is thrown before the function returns, callers
have not received the workspace pointer yet and cannot run
cleanup_workspace().

Add local error cleanup for the partially built workspace and the
compiled XPath expression.  Also check xmlXPathNewContext() before
dereferencing the returned context.
---
 contrib/xml2/xpath.c | 51 +++++++++++++++++++++++++++-----------------
 1 file changed, 32 insertions(+), 19 deletions(-)

diff --git a/contrib/xml2/xpath.c b/contrib/xml2/xpath.c
index 9fe75cb5ff4..283bb51178d 100644
--- a/contrib/xml2/xpath.c
+++ b/contrib/xml2/xpath.c
@@ -497,36 +497,49 @@ static xpath_workspace *
 pgxml_xpath(text *document, xmlChar *xpath, PgXmlErrorContext *xmlerrcxt)
 {
 	int32		docsize = VARSIZE_ANY_EXHDR(document);
-	xmlXPathCompExprPtr comppath;
+	xmlXPathCompExprPtr volatile comppath = NULL;
 	xpath_workspace *workspace = palloc0_object(xpath_workspace);
 
 	workspace->doctree = NULL;
 	workspace->ctxt = NULL;
 	workspace->res = NULL;
 
-	workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
-									   docsize, NULL, NULL,
-									   XML_PARSE_NOENT);
-	if (workspace->doctree != NULL)
+	PG_TRY();
 	{
-		workspace->ctxt = xmlXPathNewContext(workspace->doctree);
-		workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
-
-		/* compile the path */
-		comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
-		if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+		workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
+										   docsize, NULL, NULL,
+										   XML_PARSE_NOENT);
+		if (workspace->doctree != NULL)
 		{
-			if (comppath != NULL)
-				xmlXPathFreeCompExpr(comppath);
-			xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
-						"XPath Syntax Error");
-		}
+			workspace->ctxt = xmlXPathNewContext(workspace->doctree);
+			if (workspace->ctxt == NULL)
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_OUT_OF_MEMORY,
+							"could not allocate XPath context");
 
-		/* Now evaluate the path expression. */
-		workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+			workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
+
+			/* compile the path */
+			comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
+			if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
+							"XPath Syntax Error");
+
+			/* Now evaluate the path expression. */
+			workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+
+			xmlXPathFreeCompExpr(comppath);
+			comppath = NULL;
+		}
+	}
+	PG_CATCH();
+	{
+		if (comppath != NULL)
+			xmlXPathFreeCompExpr(comppath);
+		cleanup_workspace(workspace);
 
-		xmlXPathFreeCompExpr(comppath);
+		PG_RE_THROW();
 	}
+	PG_END_TRY();
 
 	return workspace;
 }
-- 
2.54.0


--MP_/LMSk9=uMhuQ1QiIJDarDO8G--






^ permalink  raw  reply  [nested|flat] 611+ messages in thread

* [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths
@ 2026-06-01 22:41 Andrey Chernyy <andrey.cherny@tantorlabs.com>
  0 siblings, 0 replies; 611+ messages in thread

From: Andrey Chernyy @ 2026-06-01 22:41 UTC (permalink / raw)

pgxml_xpath() builds an xpath_workspace before returning it to
callers.  If an ERROR is thrown before the function returns, callers
have not received the workspace pointer yet and cannot run
cleanup_workspace().

Add local error cleanup for the partially built workspace and the
compiled XPath expression.  Also check xmlXPathNewContext() before
dereferencing the returned context.
---
 contrib/xml2/xpath.c | 51 +++++++++++++++++++++++++++-----------------
 1 file changed, 32 insertions(+), 19 deletions(-)

diff --git a/contrib/xml2/xpath.c b/contrib/xml2/xpath.c
index 9fe75cb5ff4..283bb51178d 100644
--- a/contrib/xml2/xpath.c
+++ b/contrib/xml2/xpath.c
@@ -497,36 +497,49 @@ static xpath_workspace *
 pgxml_xpath(text *document, xmlChar *xpath, PgXmlErrorContext *xmlerrcxt)
 {
 	int32		docsize = VARSIZE_ANY_EXHDR(document);
-	xmlXPathCompExprPtr comppath;
+	xmlXPathCompExprPtr volatile comppath = NULL;
 	xpath_workspace *workspace = palloc0_object(xpath_workspace);
 
 	workspace->doctree = NULL;
 	workspace->ctxt = NULL;
 	workspace->res = NULL;
 
-	workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
-									   docsize, NULL, NULL,
-									   XML_PARSE_NOENT);
-	if (workspace->doctree != NULL)
+	PG_TRY();
 	{
-		workspace->ctxt = xmlXPathNewContext(workspace->doctree);
-		workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
-
-		/* compile the path */
-		comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
-		if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+		workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
+										   docsize, NULL, NULL,
+										   XML_PARSE_NOENT);
+		if (workspace->doctree != NULL)
 		{
-			if (comppath != NULL)
-				xmlXPathFreeCompExpr(comppath);
-			xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
-						"XPath Syntax Error");
-		}
+			workspace->ctxt = xmlXPathNewContext(workspace->doctree);
+			if (workspace->ctxt == NULL)
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_OUT_OF_MEMORY,
+							"could not allocate XPath context");
 
-		/* Now evaluate the path expression. */
-		workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+			workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
+
+			/* compile the path */
+			comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
+			if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
+							"XPath Syntax Error");
+
+			/* Now evaluate the path expression. */
+			workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+
+			xmlXPathFreeCompExpr(comppath);
+			comppath = NULL;
+		}
+	}
+	PG_CATCH();
+	{
+		if (comppath != NULL)
+			xmlXPathFreeCompExpr(comppath);
+		cleanup_workspace(workspace);
 
-		xmlXPathFreeCompExpr(comppath);
+		PG_RE_THROW();
 	}
+	PG_END_TRY();
 
 	return workspace;
 }
-- 
2.54.0


--MP_/LMSk9=uMhuQ1QiIJDarDO8G--






^ permalink  raw  reply  [nested|flat] 611+ messages in thread

* [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths
@ 2026-06-01 22:41 Andrey Chernyy <andrey.cherny@tantorlabs.com>
  0 siblings, 0 replies; 611+ messages in thread

From: Andrey Chernyy @ 2026-06-01 22:41 UTC (permalink / raw)

pgxml_xpath() builds an xpath_workspace before returning it to
callers.  If an ERROR is thrown before the function returns, callers
have not received the workspace pointer yet and cannot run
cleanup_workspace().

Add local error cleanup for the partially built workspace and the
compiled XPath expression.  Also check xmlXPathNewContext() before
dereferencing the returned context.
---
 contrib/xml2/xpath.c | 51 +++++++++++++++++++++++++++-----------------
 1 file changed, 32 insertions(+), 19 deletions(-)

diff --git a/contrib/xml2/xpath.c b/contrib/xml2/xpath.c
index 9fe75cb5ff4..283bb51178d 100644
--- a/contrib/xml2/xpath.c
+++ b/contrib/xml2/xpath.c
@@ -497,36 +497,49 @@ static xpath_workspace *
 pgxml_xpath(text *document, xmlChar *xpath, PgXmlErrorContext *xmlerrcxt)
 {
 	int32		docsize = VARSIZE_ANY_EXHDR(document);
-	xmlXPathCompExprPtr comppath;
+	xmlXPathCompExprPtr volatile comppath = NULL;
 	xpath_workspace *workspace = palloc0_object(xpath_workspace);
 
 	workspace->doctree = NULL;
 	workspace->ctxt = NULL;
 	workspace->res = NULL;
 
-	workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
-									   docsize, NULL, NULL,
-									   XML_PARSE_NOENT);
-	if (workspace->doctree != NULL)
+	PG_TRY();
 	{
-		workspace->ctxt = xmlXPathNewContext(workspace->doctree);
-		workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
-
-		/* compile the path */
-		comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
-		if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+		workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
+										   docsize, NULL, NULL,
+										   XML_PARSE_NOENT);
+		if (workspace->doctree != NULL)
 		{
-			if (comppath != NULL)
-				xmlXPathFreeCompExpr(comppath);
-			xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
-						"XPath Syntax Error");
-		}
+			workspace->ctxt = xmlXPathNewContext(workspace->doctree);
+			if (workspace->ctxt == NULL)
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_OUT_OF_MEMORY,
+							"could not allocate XPath context");
 
-		/* Now evaluate the path expression. */
-		workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+			workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
+
+			/* compile the path */
+			comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
+			if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
+							"XPath Syntax Error");
+
+			/* Now evaluate the path expression. */
+			workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+
+			xmlXPathFreeCompExpr(comppath);
+			comppath = NULL;
+		}
+	}
+	PG_CATCH();
+	{
+		if (comppath != NULL)
+			xmlXPathFreeCompExpr(comppath);
+		cleanup_workspace(workspace);
 
-		xmlXPathFreeCompExpr(comppath);
+		PG_RE_THROW();
 	}
+	PG_END_TRY();
 
 	return workspace;
 }
-- 
2.54.0


--MP_/LMSk9=uMhuQ1QiIJDarDO8G--






^ permalink  raw  reply  [nested|flat] 611+ messages in thread

* [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths
@ 2026-06-01 22:41 Andrey Chernyy <andrey.cherny@tantorlabs.com>
  0 siblings, 0 replies; 611+ messages in thread

From: Andrey Chernyy @ 2026-06-01 22:41 UTC (permalink / raw)

pgxml_xpath() builds an xpath_workspace before returning it to
callers.  If an ERROR is thrown before the function returns, callers
have not received the workspace pointer yet and cannot run
cleanup_workspace().

Add local error cleanup for the partially built workspace and the
compiled XPath expression.  Also check xmlXPathNewContext() before
dereferencing the returned context.
---
 contrib/xml2/xpath.c | 51 +++++++++++++++++++++++++++-----------------
 1 file changed, 32 insertions(+), 19 deletions(-)

diff --git a/contrib/xml2/xpath.c b/contrib/xml2/xpath.c
index 9fe75cb5ff4..283bb51178d 100644
--- a/contrib/xml2/xpath.c
+++ b/contrib/xml2/xpath.c
@@ -497,36 +497,49 @@ static xpath_workspace *
 pgxml_xpath(text *document, xmlChar *xpath, PgXmlErrorContext *xmlerrcxt)
 {
 	int32		docsize = VARSIZE_ANY_EXHDR(document);
-	xmlXPathCompExprPtr comppath;
+	xmlXPathCompExprPtr volatile comppath = NULL;
 	xpath_workspace *workspace = palloc0_object(xpath_workspace);
 
 	workspace->doctree = NULL;
 	workspace->ctxt = NULL;
 	workspace->res = NULL;
 
-	workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
-									   docsize, NULL, NULL,
-									   XML_PARSE_NOENT);
-	if (workspace->doctree != NULL)
+	PG_TRY();
 	{
-		workspace->ctxt = xmlXPathNewContext(workspace->doctree);
-		workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
-
-		/* compile the path */
-		comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
-		if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+		workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
+										   docsize, NULL, NULL,
+										   XML_PARSE_NOENT);
+		if (workspace->doctree != NULL)
 		{
-			if (comppath != NULL)
-				xmlXPathFreeCompExpr(comppath);
-			xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
-						"XPath Syntax Error");
-		}
+			workspace->ctxt = xmlXPathNewContext(workspace->doctree);
+			if (workspace->ctxt == NULL)
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_OUT_OF_MEMORY,
+							"could not allocate XPath context");
 
-		/* Now evaluate the path expression. */
-		workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+			workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
+
+			/* compile the path */
+			comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
+			if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
+							"XPath Syntax Error");
+
+			/* Now evaluate the path expression. */
+			workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+
+			xmlXPathFreeCompExpr(comppath);
+			comppath = NULL;
+		}
+	}
+	PG_CATCH();
+	{
+		if (comppath != NULL)
+			xmlXPathFreeCompExpr(comppath);
+		cleanup_workspace(workspace);
 
-		xmlXPathFreeCompExpr(comppath);
+		PG_RE_THROW();
 	}
+	PG_END_TRY();
 
 	return workspace;
 }
-- 
2.54.0


--MP_/LMSk9=uMhuQ1QiIJDarDO8G--





^ permalink  raw  reply  [nested|flat] 611+ messages in thread

* [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths
@ 2026-06-01 22:41 Andrey Chernyy <andrey.cherny@tantorlabs.com>
  0 siblings, 0 replies; 611+ messages in thread

From: Andrey Chernyy @ 2026-06-01 22:41 UTC (permalink / raw)

pgxml_xpath() builds an xpath_workspace before returning it to
callers.  If an ERROR is thrown before the function returns, callers
have not received the workspace pointer yet and cannot run
cleanup_workspace().

Add local error cleanup for the partially built workspace and the
compiled XPath expression.  Also check xmlXPathNewContext() before
dereferencing the returned context.
---
 contrib/xml2/xpath.c | 51 +++++++++++++++++++++++++++-----------------
 1 file changed, 32 insertions(+), 19 deletions(-)

diff --git a/contrib/xml2/xpath.c b/contrib/xml2/xpath.c
index 9fe75cb5ff4..283bb51178d 100644
--- a/contrib/xml2/xpath.c
+++ b/contrib/xml2/xpath.c
@@ -497,36 +497,49 @@ static xpath_workspace *
 pgxml_xpath(text *document, xmlChar *xpath, PgXmlErrorContext *xmlerrcxt)
 {
 	int32		docsize = VARSIZE_ANY_EXHDR(document);
-	xmlXPathCompExprPtr comppath;
+	xmlXPathCompExprPtr volatile comppath = NULL;
 	xpath_workspace *workspace = palloc0_object(xpath_workspace);
 
 	workspace->doctree = NULL;
 	workspace->ctxt = NULL;
 	workspace->res = NULL;
 
-	workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
-									   docsize, NULL, NULL,
-									   XML_PARSE_NOENT);
-	if (workspace->doctree != NULL)
+	PG_TRY();
 	{
-		workspace->ctxt = xmlXPathNewContext(workspace->doctree);
-		workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
-
-		/* compile the path */
-		comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
-		if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+		workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
+										   docsize, NULL, NULL,
+										   XML_PARSE_NOENT);
+		if (workspace->doctree != NULL)
 		{
-			if (comppath != NULL)
-				xmlXPathFreeCompExpr(comppath);
-			xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
-						"XPath Syntax Error");
-		}
+			workspace->ctxt = xmlXPathNewContext(workspace->doctree);
+			if (workspace->ctxt == NULL)
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_OUT_OF_MEMORY,
+							"could not allocate XPath context");
 
-		/* Now evaluate the path expression. */
-		workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+			workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
+
+			/* compile the path */
+			comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
+			if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
+							"XPath Syntax Error");
+
+			/* Now evaluate the path expression. */
+			workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+
+			xmlXPathFreeCompExpr(comppath);
+			comppath = NULL;
+		}
+	}
+	PG_CATCH();
+	{
+		if (comppath != NULL)
+			xmlXPathFreeCompExpr(comppath);
+		cleanup_workspace(workspace);
 
-		xmlXPathFreeCompExpr(comppath);
+		PG_RE_THROW();
 	}
+	PG_END_TRY();
 
 	return workspace;
 }
-- 
2.54.0


--MP_/LMSk9=uMhuQ1QiIJDarDO8G--





^ permalink  raw  reply  [nested|flat] 611+ messages in thread

* [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths
@ 2026-06-01 22:41 Andrey Chernyy <andrey.cherny@tantorlabs.com>
  0 siblings, 0 replies; 611+ messages in thread

From: Andrey Chernyy @ 2026-06-01 22:41 UTC (permalink / raw)

pgxml_xpath() builds an xpath_workspace before returning it to
callers.  If an ERROR is thrown before the function returns, callers
have not received the workspace pointer yet and cannot run
cleanup_workspace().

Add local error cleanup for the partially built workspace and the
compiled XPath expression.  Also check xmlXPathNewContext() before
dereferencing the returned context.
---
 contrib/xml2/xpath.c | 51 +++++++++++++++++++++++++++-----------------
 1 file changed, 32 insertions(+), 19 deletions(-)

diff --git a/contrib/xml2/xpath.c b/contrib/xml2/xpath.c
index 9fe75cb5ff4..283bb51178d 100644
--- a/contrib/xml2/xpath.c
+++ b/contrib/xml2/xpath.c
@@ -497,36 +497,49 @@ static xpath_workspace *
 pgxml_xpath(text *document, xmlChar *xpath, PgXmlErrorContext *xmlerrcxt)
 {
 	int32		docsize = VARSIZE_ANY_EXHDR(document);
-	xmlXPathCompExprPtr comppath;
+	xmlXPathCompExprPtr volatile comppath = NULL;
 	xpath_workspace *workspace = palloc0_object(xpath_workspace);
 
 	workspace->doctree = NULL;
 	workspace->ctxt = NULL;
 	workspace->res = NULL;
 
-	workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
-									   docsize, NULL, NULL,
-									   XML_PARSE_NOENT);
-	if (workspace->doctree != NULL)
+	PG_TRY();
 	{
-		workspace->ctxt = xmlXPathNewContext(workspace->doctree);
-		workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
-
-		/* compile the path */
-		comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
-		if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+		workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
+										   docsize, NULL, NULL,
+										   XML_PARSE_NOENT);
+		if (workspace->doctree != NULL)
 		{
-			if (comppath != NULL)
-				xmlXPathFreeCompExpr(comppath);
-			xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
-						"XPath Syntax Error");
-		}
+			workspace->ctxt = xmlXPathNewContext(workspace->doctree);
+			if (workspace->ctxt == NULL)
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_OUT_OF_MEMORY,
+							"could not allocate XPath context");
 
-		/* Now evaluate the path expression. */
-		workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+			workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
+
+			/* compile the path */
+			comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
+			if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
+							"XPath Syntax Error");
+
+			/* Now evaluate the path expression. */
+			workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+
+			xmlXPathFreeCompExpr(comppath);
+			comppath = NULL;
+		}
+	}
+	PG_CATCH();
+	{
+		if (comppath != NULL)
+			xmlXPathFreeCompExpr(comppath);
+		cleanup_workspace(workspace);
 
-		xmlXPathFreeCompExpr(comppath);
+		PG_RE_THROW();
 	}
+	PG_END_TRY();
 
 	return workspace;
 }
-- 
2.54.0


--MP_/LMSk9=uMhuQ1QiIJDarDO8G--





^ permalink  raw  reply  [nested|flat] 611+ messages in thread

* [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths
@ 2026-06-01 22:41 Andrey Chernyy <andrey.cherny@tantorlabs.com>
  0 siblings, 0 replies; 611+ messages in thread

From: Andrey Chernyy @ 2026-06-01 22:41 UTC (permalink / raw)

pgxml_xpath() builds an xpath_workspace before returning it to
callers.  If an ERROR is thrown before the function returns, callers
have not received the workspace pointer yet and cannot run
cleanup_workspace().

Add local error cleanup for the partially built workspace and the
compiled XPath expression.  Also check xmlXPathNewContext() before
dereferencing the returned context.
---
 contrib/xml2/xpath.c | 51 +++++++++++++++++++++++++++-----------------
 1 file changed, 32 insertions(+), 19 deletions(-)

diff --git a/contrib/xml2/xpath.c b/contrib/xml2/xpath.c
index 9fe75cb5ff4..283bb51178d 100644
--- a/contrib/xml2/xpath.c
+++ b/contrib/xml2/xpath.c
@@ -497,36 +497,49 @@ static xpath_workspace *
 pgxml_xpath(text *document, xmlChar *xpath, PgXmlErrorContext *xmlerrcxt)
 {
 	int32		docsize = VARSIZE_ANY_EXHDR(document);
-	xmlXPathCompExprPtr comppath;
+	xmlXPathCompExprPtr volatile comppath = NULL;
 	xpath_workspace *workspace = palloc0_object(xpath_workspace);
 
 	workspace->doctree = NULL;
 	workspace->ctxt = NULL;
 	workspace->res = NULL;
 
-	workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
-									   docsize, NULL, NULL,
-									   XML_PARSE_NOENT);
-	if (workspace->doctree != NULL)
+	PG_TRY();
 	{
-		workspace->ctxt = xmlXPathNewContext(workspace->doctree);
-		workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
-
-		/* compile the path */
-		comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
-		if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+		workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
+										   docsize, NULL, NULL,
+										   XML_PARSE_NOENT);
+		if (workspace->doctree != NULL)
 		{
-			if (comppath != NULL)
-				xmlXPathFreeCompExpr(comppath);
-			xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
-						"XPath Syntax Error");
-		}
+			workspace->ctxt = xmlXPathNewContext(workspace->doctree);
+			if (workspace->ctxt == NULL)
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_OUT_OF_MEMORY,
+							"could not allocate XPath context");
 
-		/* Now evaluate the path expression. */
-		workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+			workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
+
+			/* compile the path */
+			comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
+			if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
+							"XPath Syntax Error");
+
+			/* Now evaluate the path expression. */
+			workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+
+			xmlXPathFreeCompExpr(comppath);
+			comppath = NULL;
+		}
+	}
+	PG_CATCH();
+	{
+		if (comppath != NULL)
+			xmlXPathFreeCompExpr(comppath);
+		cleanup_workspace(workspace);
 
-		xmlXPathFreeCompExpr(comppath);
+		PG_RE_THROW();
 	}
+	PG_END_TRY();
 
 	return workspace;
 }
-- 
2.54.0


--MP_/LMSk9=uMhuQ1QiIJDarDO8G--






^ permalink  raw  reply  [nested|flat] 611+ messages in thread

* [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths
@ 2026-06-01 22:41 Andrey Chernyy <andrey.cherny@tantorlabs.com>
  0 siblings, 0 replies; 611+ messages in thread

From: Andrey Chernyy @ 2026-06-01 22:41 UTC (permalink / raw)

pgxml_xpath() builds an xpath_workspace before returning it to
callers.  If an ERROR is thrown before the function returns, callers
have not received the workspace pointer yet and cannot run
cleanup_workspace().

Add local error cleanup for the partially built workspace and the
compiled XPath expression.  Also check xmlXPathNewContext() before
dereferencing the returned context.
---
 contrib/xml2/xpath.c | 51 +++++++++++++++++++++++++++-----------------
 1 file changed, 32 insertions(+), 19 deletions(-)

diff --git a/contrib/xml2/xpath.c b/contrib/xml2/xpath.c
index 9fe75cb5ff4..283bb51178d 100644
--- a/contrib/xml2/xpath.c
+++ b/contrib/xml2/xpath.c
@@ -497,36 +497,49 @@ static xpath_workspace *
 pgxml_xpath(text *document, xmlChar *xpath, PgXmlErrorContext *xmlerrcxt)
 {
 	int32		docsize = VARSIZE_ANY_EXHDR(document);
-	xmlXPathCompExprPtr comppath;
+	xmlXPathCompExprPtr volatile comppath = NULL;
 	xpath_workspace *workspace = palloc0_object(xpath_workspace);
 
 	workspace->doctree = NULL;
 	workspace->ctxt = NULL;
 	workspace->res = NULL;
 
-	workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
-									   docsize, NULL, NULL,
-									   XML_PARSE_NOENT);
-	if (workspace->doctree != NULL)
+	PG_TRY();
 	{
-		workspace->ctxt = xmlXPathNewContext(workspace->doctree);
-		workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
-
-		/* compile the path */
-		comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
-		if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+		workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
+										   docsize, NULL, NULL,
+										   XML_PARSE_NOENT);
+		if (workspace->doctree != NULL)
 		{
-			if (comppath != NULL)
-				xmlXPathFreeCompExpr(comppath);
-			xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
-						"XPath Syntax Error");
-		}
+			workspace->ctxt = xmlXPathNewContext(workspace->doctree);
+			if (workspace->ctxt == NULL)
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_OUT_OF_MEMORY,
+							"could not allocate XPath context");
 
-		/* Now evaluate the path expression. */
-		workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+			workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
+
+			/* compile the path */
+			comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
+			if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
+							"XPath Syntax Error");
+
+			/* Now evaluate the path expression. */
+			workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+
+			xmlXPathFreeCompExpr(comppath);
+			comppath = NULL;
+		}
+	}
+	PG_CATCH();
+	{
+		if (comppath != NULL)
+			xmlXPathFreeCompExpr(comppath);
+		cleanup_workspace(workspace);
 
-		xmlXPathFreeCompExpr(comppath);
+		PG_RE_THROW();
 	}
+	PG_END_TRY();
 
 	return workspace;
 }
-- 
2.54.0


--MP_/LMSk9=uMhuQ1QiIJDarDO8G--






^ permalink  raw  reply  [nested|flat] 611+ messages in thread

* [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths
@ 2026-06-01 22:41 Andrey Chernyy <andrey.cherny@tantorlabs.com>
  0 siblings, 0 replies; 611+ messages in thread

From: Andrey Chernyy @ 2026-06-01 22:41 UTC (permalink / raw)

pgxml_xpath() builds an xpath_workspace before returning it to
callers.  If an ERROR is thrown before the function returns, callers
have not received the workspace pointer yet and cannot run
cleanup_workspace().

Add local error cleanup for the partially built workspace and the
compiled XPath expression.  Also check xmlXPathNewContext() before
dereferencing the returned context.
---
 contrib/xml2/xpath.c | 51 +++++++++++++++++++++++++++-----------------
 1 file changed, 32 insertions(+), 19 deletions(-)

diff --git a/contrib/xml2/xpath.c b/contrib/xml2/xpath.c
index 9fe75cb5ff4..283bb51178d 100644
--- a/contrib/xml2/xpath.c
+++ b/contrib/xml2/xpath.c
@@ -497,36 +497,49 @@ static xpath_workspace *
 pgxml_xpath(text *document, xmlChar *xpath, PgXmlErrorContext *xmlerrcxt)
 {
 	int32		docsize = VARSIZE_ANY_EXHDR(document);
-	xmlXPathCompExprPtr comppath;
+	xmlXPathCompExprPtr volatile comppath = NULL;
 	xpath_workspace *workspace = palloc0_object(xpath_workspace);
 
 	workspace->doctree = NULL;
 	workspace->ctxt = NULL;
 	workspace->res = NULL;
 
-	workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
-									   docsize, NULL, NULL,
-									   XML_PARSE_NOENT);
-	if (workspace->doctree != NULL)
+	PG_TRY();
 	{
-		workspace->ctxt = xmlXPathNewContext(workspace->doctree);
-		workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
-
-		/* compile the path */
-		comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
-		if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+		workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
+										   docsize, NULL, NULL,
+										   XML_PARSE_NOENT);
+		if (workspace->doctree != NULL)
 		{
-			if (comppath != NULL)
-				xmlXPathFreeCompExpr(comppath);
-			xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
-						"XPath Syntax Error");
-		}
+			workspace->ctxt = xmlXPathNewContext(workspace->doctree);
+			if (workspace->ctxt == NULL)
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_OUT_OF_MEMORY,
+							"could not allocate XPath context");
 
-		/* Now evaluate the path expression. */
-		workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+			workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
+
+			/* compile the path */
+			comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
+			if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
+							"XPath Syntax Error");
+
+			/* Now evaluate the path expression. */
+			workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+
+			xmlXPathFreeCompExpr(comppath);
+			comppath = NULL;
+		}
+	}
+	PG_CATCH();
+	{
+		if (comppath != NULL)
+			xmlXPathFreeCompExpr(comppath);
+		cleanup_workspace(workspace);
 
-		xmlXPathFreeCompExpr(comppath);
+		PG_RE_THROW();
 	}
+	PG_END_TRY();
 
 	return workspace;
 }
-- 
2.54.0


--MP_/LMSk9=uMhuQ1QiIJDarDO8G--






^ permalink  raw  reply  [nested|flat] 611+ messages in thread

* [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths
@ 2026-06-01 22:41 Andrey Chernyy <andrey.cherny@tantorlabs.com>
  0 siblings, 0 replies; 611+ messages in thread

From: Andrey Chernyy @ 2026-06-01 22:41 UTC (permalink / raw)

pgxml_xpath() builds an xpath_workspace before returning it to
callers.  If an ERROR is thrown before the function returns, callers
have not received the workspace pointer yet and cannot run
cleanup_workspace().

Add local error cleanup for the partially built workspace and the
compiled XPath expression.  Also check xmlXPathNewContext() before
dereferencing the returned context.
---
 contrib/xml2/xpath.c | 51 +++++++++++++++++++++++++++-----------------
 1 file changed, 32 insertions(+), 19 deletions(-)

diff --git a/contrib/xml2/xpath.c b/contrib/xml2/xpath.c
index 9fe75cb5ff4..283bb51178d 100644
--- a/contrib/xml2/xpath.c
+++ b/contrib/xml2/xpath.c
@@ -497,36 +497,49 @@ static xpath_workspace *
 pgxml_xpath(text *document, xmlChar *xpath, PgXmlErrorContext *xmlerrcxt)
 {
 	int32		docsize = VARSIZE_ANY_EXHDR(document);
-	xmlXPathCompExprPtr comppath;
+	xmlXPathCompExprPtr volatile comppath = NULL;
 	xpath_workspace *workspace = palloc0_object(xpath_workspace);
 
 	workspace->doctree = NULL;
 	workspace->ctxt = NULL;
 	workspace->res = NULL;
 
-	workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
-									   docsize, NULL, NULL,
-									   XML_PARSE_NOENT);
-	if (workspace->doctree != NULL)
+	PG_TRY();
 	{
-		workspace->ctxt = xmlXPathNewContext(workspace->doctree);
-		workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
-
-		/* compile the path */
-		comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
-		if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+		workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
+										   docsize, NULL, NULL,
+										   XML_PARSE_NOENT);
+		if (workspace->doctree != NULL)
 		{
-			if (comppath != NULL)
-				xmlXPathFreeCompExpr(comppath);
-			xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
-						"XPath Syntax Error");
-		}
+			workspace->ctxt = xmlXPathNewContext(workspace->doctree);
+			if (workspace->ctxt == NULL)
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_OUT_OF_MEMORY,
+							"could not allocate XPath context");
 
-		/* Now evaluate the path expression. */
-		workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+			workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
+
+			/* compile the path */
+			comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
+			if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
+							"XPath Syntax Error");
+
+			/* Now evaluate the path expression. */
+			workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+
+			xmlXPathFreeCompExpr(comppath);
+			comppath = NULL;
+		}
+	}
+	PG_CATCH();
+	{
+		if (comppath != NULL)
+			xmlXPathFreeCompExpr(comppath);
+		cleanup_workspace(workspace);
 
-		xmlXPathFreeCompExpr(comppath);
+		PG_RE_THROW();
 	}
+	PG_END_TRY();
 
 	return workspace;
 }
-- 
2.54.0


--MP_/LMSk9=uMhuQ1QiIJDarDO8G--





^ permalink  raw  reply  [nested|flat] 611+ messages in thread

* [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths
@ 2026-06-01 22:41 Andrey Chernyy <andrey.cherny@tantorlabs.com>
  0 siblings, 0 replies; 611+ messages in thread

From: Andrey Chernyy @ 2026-06-01 22:41 UTC (permalink / raw)

pgxml_xpath() builds an xpath_workspace before returning it to
callers.  If an ERROR is thrown before the function returns, callers
have not received the workspace pointer yet and cannot run
cleanup_workspace().

Add local error cleanup for the partially built workspace and the
compiled XPath expression.  Also check xmlXPathNewContext() before
dereferencing the returned context.
---
 contrib/xml2/xpath.c | 51 +++++++++++++++++++++++++++-----------------
 1 file changed, 32 insertions(+), 19 deletions(-)

diff --git a/contrib/xml2/xpath.c b/contrib/xml2/xpath.c
index 9fe75cb5ff4..283bb51178d 100644
--- a/contrib/xml2/xpath.c
+++ b/contrib/xml2/xpath.c
@@ -497,36 +497,49 @@ static xpath_workspace *
 pgxml_xpath(text *document, xmlChar *xpath, PgXmlErrorContext *xmlerrcxt)
 {
 	int32		docsize = VARSIZE_ANY_EXHDR(document);
-	xmlXPathCompExprPtr comppath;
+	xmlXPathCompExprPtr volatile comppath = NULL;
 	xpath_workspace *workspace = palloc0_object(xpath_workspace);
 
 	workspace->doctree = NULL;
 	workspace->ctxt = NULL;
 	workspace->res = NULL;
 
-	workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
-									   docsize, NULL, NULL,
-									   XML_PARSE_NOENT);
-	if (workspace->doctree != NULL)
+	PG_TRY();
 	{
-		workspace->ctxt = xmlXPathNewContext(workspace->doctree);
-		workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
-
-		/* compile the path */
-		comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
-		if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+		workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
+										   docsize, NULL, NULL,
+										   XML_PARSE_NOENT);
+		if (workspace->doctree != NULL)
 		{
-			if (comppath != NULL)
-				xmlXPathFreeCompExpr(comppath);
-			xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
-						"XPath Syntax Error");
-		}
+			workspace->ctxt = xmlXPathNewContext(workspace->doctree);
+			if (workspace->ctxt == NULL)
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_OUT_OF_MEMORY,
+							"could not allocate XPath context");
 
-		/* Now evaluate the path expression. */
-		workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+			workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
+
+			/* compile the path */
+			comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
+			if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
+							"XPath Syntax Error");
+
+			/* Now evaluate the path expression. */
+			workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+
+			xmlXPathFreeCompExpr(comppath);
+			comppath = NULL;
+		}
+	}
+	PG_CATCH();
+	{
+		if (comppath != NULL)
+			xmlXPathFreeCompExpr(comppath);
+		cleanup_workspace(workspace);
 
-		xmlXPathFreeCompExpr(comppath);
+		PG_RE_THROW();
 	}
+	PG_END_TRY();
 
 	return workspace;
 }
-- 
2.54.0


--MP_/LMSk9=uMhuQ1QiIJDarDO8G--





^ permalink  raw  reply  [nested|flat] 611+ messages in thread

* [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths
@ 2026-06-01 22:41 Andrey Chernyy <andrey.cherny@tantorlabs.com>
  0 siblings, 0 replies; 611+ messages in thread

From: Andrey Chernyy @ 2026-06-01 22:41 UTC (permalink / raw)

pgxml_xpath() builds an xpath_workspace before returning it to
callers.  If an ERROR is thrown before the function returns, callers
have not received the workspace pointer yet and cannot run
cleanup_workspace().

Add local error cleanup for the partially built workspace and the
compiled XPath expression.  Also check xmlXPathNewContext() before
dereferencing the returned context.
---
 contrib/xml2/xpath.c | 51 +++++++++++++++++++++++++++-----------------
 1 file changed, 32 insertions(+), 19 deletions(-)

diff --git a/contrib/xml2/xpath.c b/contrib/xml2/xpath.c
index 9fe75cb5ff4..283bb51178d 100644
--- a/contrib/xml2/xpath.c
+++ b/contrib/xml2/xpath.c
@@ -497,36 +497,49 @@ static xpath_workspace *
 pgxml_xpath(text *document, xmlChar *xpath, PgXmlErrorContext *xmlerrcxt)
 {
 	int32		docsize = VARSIZE_ANY_EXHDR(document);
-	xmlXPathCompExprPtr comppath;
+	xmlXPathCompExprPtr volatile comppath = NULL;
 	xpath_workspace *workspace = palloc0_object(xpath_workspace);
 
 	workspace->doctree = NULL;
 	workspace->ctxt = NULL;
 	workspace->res = NULL;
 
-	workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
-									   docsize, NULL, NULL,
-									   XML_PARSE_NOENT);
-	if (workspace->doctree != NULL)
+	PG_TRY();
 	{
-		workspace->ctxt = xmlXPathNewContext(workspace->doctree);
-		workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
-
-		/* compile the path */
-		comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
-		if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+		workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
+										   docsize, NULL, NULL,
+										   XML_PARSE_NOENT);
+		if (workspace->doctree != NULL)
 		{
-			if (comppath != NULL)
-				xmlXPathFreeCompExpr(comppath);
-			xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
-						"XPath Syntax Error");
-		}
+			workspace->ctxt = xmlXPathNewContext(workspace->doctree);
+			if (workspace->ctxt == NULL)
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_OUT_OF_MEMORY,
+							"could not allocate XPath context");
 
-		/* Now evaluate the path expression. */
-		workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+			workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
+
+			/* compile the path */
+			comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
+			if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
+							"XPath Syntax Error");
+
+			/* Now evaluate the path expression. */
+			workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+
+			xmlXPathFreeCompExpr(comppath);
+			comppath = NULL;
+		}
+	}
+	PG_CATCH();
+	{
+		if (comppath != NULL)
+			xmlXPathFreeCompExpr(comppath);
+		cleanup_workspace(workspace);
 
-		xmlXPathFreeCompExpr(comppath);
+		PG_RE_THROW();
 	}
+	PG_END_TRY();
 
 	return workspace;
 }
-- 
2.54.0


--MP_/LMSk9=uMhuQ1QiIJDarDO8G--





^ permalink  raw  reply  [nested|flat] 611+ messages in thread

* [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths
@ 2026-06-01 22:41 Andrey Chernyy <andrey.cherny@tantorlabs.com>
  0 siblings, 0 replies; 611+ messages in thread

From: Andrey Chernyy @ 2026-06-01 22:41 UTC (permalink / raw)

pgxml_xpath() builds an xpath_workspace before returning it to
callers.  If an ERROR is thrown before the function returns, callers
have not received the workspace pointer yet and cannot run
cleanup_workspace().

Add local error cleanup for the partially built workspace and the
compiled XPath expression.  Also check xmlXPathNewContext() before
dereferencing the returned context.
---
 contrib/xml2/xpath.c | 51 +++++++++++++++++++++++++++-----------------
 1 file changed, 32 insertions(+), 19 deletions(-)

diff --git a/contrib/xml2/xpath.c b/contrib/xml2/xpath.c
index 9fe75cb5ff4..283bb51178d 100644
--- a/contrib/xml2/xpath.c
+++ b/contrib/xml2/xpath.c
@@ -497,36 +497,49 @@ static xpath_workspace *
 pgxml_xpath(text *document, xmlChar *xpath, PgXmlErrorContext *xmlerrcxt)
 {
 	int32		docsize = VARSIZE_ANY_EXHDR(document);
-	xmlXPathCompExprPtr comppath;
+	xmlXPathCompExprPtr volatile comppath = NULL;
 	xpath_workspace *workspace = palloc0_object(xpath_workspace);
 
 	workspace->doctree = NULL;
 	workspace->ctxt = NULL;
 	workspace->res = NULL;
 
-	workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
-									   docsize, NULL, NULL,
-									   XML_PARSE_NOENT);
-	if (workspace->doctree != NULL)
+	PG_TRY();
 	{
-		workspace->ctxt = xmlXPathNewContext(workspace->doctree);
-		workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
-
-		/* compile the path */
-		comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
-		if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+		workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
+										   docsize, NULL, NULL,
+										   XML_PARSE_NOENT);
+		if (workspace->doctree != NULL)
 		{
-			if (comppath != NULL)
-				xmlXPathFreeCompExpr(comppath);
-			xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
-						"XPath Syntax Error");
-		}
+			workspace->ctxt = xmlXPathNewContext(workspace->doctree);
+			if (workspace->ctxt == NULL)
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_OUT_OF_MEMORY,
+							"could not allocate XPath context");
 
-		/* Now evaluate the path expression. */
-		workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+			workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
+
+			/* compile the path */
+			comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
+			if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
+							"XPath Syntax Error");
+
+			/* Now evaluate the path expression. */
+			workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+
+			xmlXPathFreeCompExpr(comppath);
+			comppath = NULL;
+		}
+	}
+	PG_CATCH();
+	{
+		if (comppath != NULL)
+			xmlXPathFreeCompExpr(comppath);
+		cleanup_workspace(workspace);
 
-		xmlXPathFreeCompExpr(comppath);
+		PG_RE_THROW();
 	}
+	PG_END_TRY();
 
 	return workspace;
 }
-- 
2.54.0


--MP_/LMSk9=uMhuQ1QiIJDarDO8G--





^ permalink  raw  reply  [nested|flat] 611+ messages in thread

* [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths
@ 2026-06-01 22:41 Andrey Chernyy <andrey.cherny@tantorlabs.com>
  0 siblings, 0 replies; 611+ messages in thread

From: Andrey Chernyy @ 2026-06-01 22:41 UTC (permalink / raw)

pgxml_xpath() builds an xpath_workspace before returning it to
callers.  If an ERROR is thrown before the function returns, callers
have not received the workspace pointer yet and cannot run
cleanup_workspace().

Add local error cleanup for the partially built workspace and the
compiled XPath expression.  Also check xmlXPathNewContext() before
dereferencing the returned context.
---
 contrib/xml2/xpath.c | 51 +++++++++++++++++++++++++++-----------------
 1 file changed, 32 insertions(+), 19 deletions(-)

diff --git a/contrib/xml2/xpath.c b/contrib/xml2/xpath.c
index 9fe75cb5ff4..283bb51178d 100644
--- a/contrib/xml2/xpath.c
+++ b/contrib/xml2/xpath.c
@@ -497,36 +497,49 @@ static xpath_workspace *
 pgxml_xpath(text *document, xmlChar *xpath, PgXmlErrorContext *xmlerrcxt)
 {
 	int32		docsize = VARSIZE_ANY_EXHDR(document);
-	xmlXPathCompExprPtr comppath;
+	xmlXPathCompExprPtr volatile comppath = NULL;
 	xpath_workspace *workspace = palloc0_object(xpath_workspace);
 
 	workspace->doctree = NULL;
 	workspace->ctxt = NULL;
 	workspace->res = NULL;
 
-	workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
-									   docsize, NULL, NULL,
-									   XML_PARSE_NOENT);
-	if (workspace->doctree != NULL)
+	PG_TRY();
 	{
-		workspace->ctxt = xmlXPathNewContext(workspace->doctree);
-		workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
-
-		/* compile the path */
-		comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
-		if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+		workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
+										   docsize, NULL, NULL,
+										   XML_PARSE_NOENT);
+		if (workspace->doctree != NULL)
 		{
-			if (comppath != NULL)
-				xmlXPathFreeCompExpr(comppath);
-			xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
-						"XPath Syntax Error");
-		}
+			workspace->ctxt = xmlXPathNewContext(workspace->doctree);
+			if (workspace->ctxt == NULL)
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_OUT_OF_MEMORY,
+							"could not allocate XPath context");
 
-		/* Now evaluate the path expression. */
-		workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+			workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
+
+			/* compile the path */
+			comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
+			if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
+							"XPath Syntax Error");
+
+			/* Now evaluate the path expression. */
+			workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+
+			xmlXPathFreeCompExpr(comppath);
+			comppath = NULL;
+		}
+	}
+	PG_CATCH();
+	{
+		if (comppath != NULL)
+			xmlXPathFreeCompExpr(comppath);
+		cleanup_workspace(workspace);
 
-		xmlXPathFreeCompExpr(comppath);
+		PG_RE_THROW();
 	}
+	PG_END_TRY();
 
 	return workspace;
 }
-- 
2.54.0


--MP_/LMSk9=uMhuQ1QiIJDarDO8G--






^ permalink  raw  reply  [nested|flat] 611+ messages in thread

* [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths
@ 2026-06-01 22:41 Andrey Chernyy <andrey.cherny@tantorlabs.com>
  0 siblings, 0 replies; 611+ messages in thread

From: Andrey Chernyy @ 2026-06-01 22:41 UTC (permalink / raw)

pgxml_xpath() builds an xpath_workspace before returning it to
callers.  If an ERROR is thrown before the function returns, callers
have not received the workspace pointer yet and cannot run
cleanup_workspace().

Add local error cleanup for the partially built workspace and the
compiled XPath expression.  Also check xmlXPathNewContext() before
dereferencing the returned context.
---
 contrib/xml2/xpath.c | 51 +++++++++++++++++++++++++++-----------------
 1 file changed, 32 insertions(+), 19 deletions(-)

diff --git a/contrib/xml2/xpath.c b/contrib/xml2/xpath.c
index 9fe75cb5ff4..283bb51178d 100644
--- a/contrib/xml2/xpath.c
+++ b/contrib/xml2/xpath.c
@@ -497,36 +497,49 @@ static xpath_workspace *
 pgxml_xpath(text *document, xmlChar *xpath, PgXmlErrorContext *xmlerrcxt)
 {
 	int32		docsize = VARSIZE_ANY_EXHDR(document);
-	xmlXPathCompExprPtr comppath;
+	xmlXPathCompExprPtr volatile comppath = NULL;
 	xpath_workspace *workspace = palloc0_object(xpath_workspace);
 
 	workspace->doctree = NULL;
 	workspace->ctxt = NULL;
 	workspace->res = NULL;
 
-	workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
-									   docsize, NULL, NULL,
-									   XML_PARSE_NOENT);
-	if (workspace->doctree != NULL)
+	PG_TRY();
 	{
-		workspace->ctxt = xmlXPathNewContext(workspace->doctree);
-		workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
-
-		/* compile the path */
-		comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
-		if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+		workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
+										   docsize, NULL, NULL,
+										   XML_PARSE_NOENT);
+		if (workspace->doctree != NULL)
 		{
-			if (comppath != NULL)
-				xmlXPathFreeCompExpr(comppath);
-			xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
-						"XPath Syntax Error");
-		}
+			workspace->ctxt = xmlXPathNewContext(workspace->doctree);
+			if (workspace->ctxt == NULL)
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_OUT_OF_MEMORY,
+							"could not allocate XPath context");
 
-		/* Now evaluate the path expression. */
-		workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+			workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
+
+			/* compile the path */
+			comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
+			if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
+							"XPath Syntax Error");
+
+			/* Now evaluate the path expression. */
+			workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+
+			xmlXPathFreeCompExpr(comppath);
+			comppath = NULL;
+		}
+	}
+	PG_CATCH();
+	{
+		if (comppath != NULL)
+			xmlXPathFreeCompExpr(comppath);
+		cleanup_workspace(workspace);
 
-		xmlXPathFreeCompExpr(comppath);
+		PG_RE_THROW();
 	}
+	PG_END_TRY();
 
 	return workspace;
 }
-- 
2.54.0


--MP_/LMSk9=uMhuQ1QiIJDarDO8G--






^ permalink  raw  reply  [nested|flat] 611+ messages in thread

* [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths
@ 2026-06-01 22:41 Andrey Chernyy <andrey.cherny@tantorlabs.com>
  0 siblings, 0 replies; 611+ messages in thread

From: Andrey Chernyy @ 2026-06-01 22:41 UTC (permalink / raw)

pgxml_xpath() builds an xpath_workspace before returning it to
callers.  If an ERROR is thrown before the function returns, callers
have not received the workspace pointer yet and cannot run
cleanup_workspace().

Add local error cleanup for the partially built workspace and the
compiled XPath expression.  Also check xmlXPathNewContext() before
dereferencing the returned context.
---
 contrib/xml2/xpath.c | 51 +++++++++++++++++++++++++++-----------------
 1 file changed, 32 insertions(+), 19 deletions(-)

diff --git a/contrib/xml2/xpath.c b/contrib/xml2/xpath.c
index 9fe75cb5ff4..283bb51178d 100644
--- a/contrib/xml2/xpath.c
+++ b/contrib/xml2/xpath.c
@@ -497,36 +497,49 @@ static xpath_workspace *
 pgxml_xpath(text *document, xmlChar *xpath, PgXmlErrorContext *xmlerrcxt)
 {
 	int32		docsize = VARSIZE_ANY_EXHDR(document);
-	xmlXPathCompExprPtr comppath;
+	xmlXPathCompExprPtr volatile comppath = NULL;
 	xpath_workspace *workspace = palloc0_object(xpath_workspace);
 
 	workspace->doctree = NULL;
 	workspace->ctxt = NULL;
 	workspace->res = NULL;
 
-	workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
-									   docsize, NULL, NULL,
-									   XML_PARSE_NOENT);
-	if (workspace->doctree != NULL)
+	PG_TRY();
 	{
-		workspace->ctxt = xmlXPathNewContext(workspace->doctree);
-		workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
-
-		/* compile the path */
-		comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
-		if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+		workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
+										   docsize, NULL, NULL,
+										   XML_PARSE_NOENT);
+		if (workspace->doctree != NULL)
 		{
-			if (comppath != NULL)
-				xmlXPathFreeCompExpr(comppath);
-			xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
-						"XPath Syntax Error");
-		}
+			workspace->ctxt = xmlXPathNewContext(workspace->doctree);
+			if (workspace->ctxt == NULL)
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_OUT_OF_MEMORY,
+							"could not allocate XPath context");
 
-		/* Now evaluate the path expression. */
-		workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+			workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
+
+			/* compile the path */
+			comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
+			if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
+							"XPath Syntax Error");
+
+			/* Now evaluate the path expression. */
+			workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+
+			xmlXPathFreeCompExpr(comppath);
+			comppath = NULL;
+		}
+	}
+	PG_CATCH();
+	{
+		if (comppath != NULL)
+			xmlXPathFreeCompExpr(comppath);
+		cleanup_workspace(workspace);
 
-		xmlXPathFreeCompExpr(comppath);
+		PG_RE_THROW();
 	}
+	PG_END_TRY();
 
 	return workspace;
 }
-- 
2.54.0


--MP_/LMSk9=uMhuQ1QiIJDarDO8G--





^ permalink  raw  reply  [nested|flat] 611+ messages in thread

* [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths
@ 2026-06-01 22:41 Andrey Chernyy <andrey.cherny@tantorlabs.com>
  0 siblings, 0 replies; 611+ messages in thread

From: Andrey Chernyy @ 2026-06-01 22:41 UTC (permalink / raw)

pgxml_xpath() builds an xpath_workspace before returning it to
callers.  If an ERROR is thrown before the function returns, callers
have not received the workspace pointer yet and cannot run
cleanup_workspace().

Add local error cleanup for the partially built workspace and the
compiled XPath expression.  Also check xmlXPathNewContext() before
dereferencing the returned context.
---
 contrib/xml2/xpath.c | 51 +++++++++++++++++++++++++++-----------------
 1 file changed, 32 insertions(+), 19 deletions(-)

diff --git a/contrib/xml2/xpath.c b/contrib/xml2/xpath.c
index 9fe75cb5ff4..283bb51178d 100644
--- a/contrib/xml2/xpath.c
+++ b/contrib/xml2/xpath.c
@@ -497,36 +497,49 @@ static xpath_workspace *
 pgxml_xpath(text *document, xmlChar *xpath, PgXmlErrorContext *xmlerrcxt)
 {
 	int32		docsize = VARSIZE_ANY_EXHDR(document);
-	xmlXPathCompExprPtr comppath;
+	xmlXPathCompExprPtr volatile comppath = NULL;
 	xpath_workspace *workspace = palloc0_object(xpath_workspace);
 
 	workspace->doctree = NULL;
 	workspace->ctxt = NULL;
 	workspace->res = NULL;
 
-	workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
-									   docsize, NULL, NULL,
-									   XML_PARSE_NOENT);
-	if (workspace->doctree != NULL)
+	PG_TRY();
 	{
-		workspace->ctxt = xmlXPathNewContext(workspace->doctree);
-		workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
-
-		/* compile the path */
-		comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
-		if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+		workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
+										   docsize, NULL, NULL,
+										   XML_PARSE_NOENT);
+		if (workspace->doctree != NULL)
 		{
-			if (comppath != NULL)
-				xmlXPathFreeCompExpr(comppath);
-			xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
-						"XPath Syntax Error");
-		}
+			workspace->ctxt = xmlXPathNewContext(workspace->doctree);
+			if (workspace->ctxt == NULL)
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_OUT_OF_MEMORY,
+							"could not allocate XPath context");
 
-		/* Now evaluate the path expression. */
-		workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+			workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
+
+			/* compile the path */
+			comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
+			if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
+							"XPath Syntax Error");
+
+			/* Now evaluate the path expression. */
+			workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+
+			xmlXPathFreeCompExpr(comppath);
+			comppath = NULL;
+		}
+	}
+	PG_CATCH();
+	{
+		if (comppath != NULL)
+			xmlXPathFreeCompExpr(comppath);
+		cleanup_workspace(workspace);
 
-		xmlXPathFreeCompExpr(comppath);
+		PG_RE_THROW();
 	}
+	PG_END_TRY();
 
 	return workspace;
 }
-- 
2.54.0


--MP_/LMSk9=uMhuQ1QiIJDarDO8G--






^ permalink  raw  reply  [nested|flat] 611+ messages in thread

* [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths
@ 2026-06-01 22:41 Andrey Chernyy <andrey.cherny@tantorlabs.com>
  0 siblings, 0 replies; 611+ messages in thread

From: Andrey Chernyy @ 2026-06-01 22:41 UTC (permalink / raw)

pgxml_xpath() builds an xpath_workspace before returning it to
callers.  If an ERROR is thrown before the function returns, callers
have not received the workspace pointer yet and cannot run
cleanup_workspace().

Add local error cleanup for the partially built workspace and the
compiled XPath expression.  Also check xmlXPathNewContext() before
dereferencing the returned context.
---
 contrib/xml2/xpath.c | 51 +++++++++++++++++++++++++++-----------------
 1 file changed, 32 insertions(+), 19 deletions(-)

diff --git a/contrib/xml2/xpath.c b/contrib/xml2/xpath.c
index 9fe75cb5ff4..283bb51178d 100644
--- a/contrib/xml2/xpath.c
+++ b/contrib/xml2/xpath.c
@@ -497,36 +497,49 @@ static xpath_workspace *
 pgxml_xpath(text *document, xmlChar *xpath, PgXmlErrorContext *xmlerrcxt)
 {
 	int32		docsize = VARSIZE_ANY_EXHDR(document);
-	xmlXPathCompExprPtr comppath;
+	xmlXPathCompExprPtr volatile comppath = NULL;
 	xpath_workspace *workspace = palloc0_object(xpath_workspace);
 
 	workspace->doctree = NULL;
 	workspace->ctxt = NULL;
 	workspace->res = NULL;
 
-	workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
-									   docsize, NULL, NULL,
-									   XML_PARSE_NOENT);
-	if (workspace->doctree != NULL)
+	PG_TRY();
 	{
-		workspace->ctxt = xmlXPathNewContext(workspace->doctree);
-		workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
-
-		/* compile the path */
-		comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
-		if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+		workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
+										   docsize, NULL, NULL,
+										   XML_PARSE_NOENT);
+		if (workspace->doctree != NULL)
 		{
-			if (comppath != NULL)
-				xmlXPathFreeCompExpr(comppath);
-			xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
-						"XPath Syntax Error");
-		}
+			workspace->ctxt = xmlXPathNewContext(workspace->doctree);
+			if (workspace->ctxt == NULL)
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_OUT_OF_MEMORY,
+							"could not allocate XPath context");
 
-		/* Now evaluate the path expression. */
-		workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+			workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
+
+			/* compile the path */
+			comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
+			if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
+							"XPath Syntax Error");
+
+			/* Now evaluate the path expression. */
+			workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+
+			xmlXPathFreeCompExpr(comppath);
+			comppath = NULL;
+		}
+	}
+	PG_CATCH();
+	{
+		if (comppath != NULL)
+			xmlXPathFreeCompExpr(comppath);
+		cleanup_workspace(workspace);
 
-		xmlXPathFreeCompExpr(comppath);
+		PG_RE_THROW();
 	}
+	PG_END_TRY();
 
 	return workspace;
 }
-- 
2.54.0


--MP_/LMSk9=uMhuQ1QiIJDarDO8G--






^ permalink  raw  reply  [nested|flat] 611+ messages in thread

* [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths
@ 2026-06-01 22:41 Andrey Chernyy <andrey.cherny@tantorlabs.com>
  0 siblings, 0 replies; 611+ messages in thread

From: Andrey Chernyy @ 2026-06-01 22:41 UTC (permalink / raw)

pgxml_xpath() builds an xpath_workspace before returning it to
callers.  If an ERROR is thrown before the function returns, callers
have not received the workspace pointer yet and cannot run
cleanup_workspace().

Add local error cleanup for the partially built workspace and the
compiled XPath expression.  Also check xmlXPathNewContext() before
dereferencing the returned context.
---
 contrib/xml2/xpath.c | 51 +++++++++++++++++++++++++++-----------------
 1 file changed, 32 insertions(+), 19 deletions(-)

diff --git a/contrib/xml2/xpath.c b/contrib/xml2/xpath.c
index 9fe75cb5ff4..283bb51178d 100644
--- a/contrib/xml2/xpath.c
+++ b/contrib/xml2/xpath.c
@@ -497,36 +497,49 @@ static xpath_workspace *
 pgxml_xpath(text *document, xmlChar *xpath, PgXmlErrorContext *xmlerrcxt)
 {
 	int32		docsize = VARSIZE_ANY_EXHDR(document);
-	xmlXPathCompExprPtr comppath;
+	xmlXPathCompExprPtr volatile comppath = NULL;
 	xpath_workspace *workspace = palloc0_object(xpath_workspace);
 
 	workspace->doctree = NULL;
 	workspace->ctxt = NULL;
 	workspace->res = NULL;
 
-	workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
-									   docsize, NULL, NULL,
-									   XML_PARSE_NOENT);
-	if (workspace->doctree != NULL)
+	PG_TRY();
 	{
-		workspace->ctxt = xmlXPathNewContext(workspace->doctree);
-		workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
-
-		/* compile the path */
-		comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
-		if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+		workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
+										   docsize, NULL, NULL,
+										   XML_PARSE_NOENT);
+		if (workspace->doctree != NULL)
 		{
-			if (comppath != NULL)
-				xmlXPathFreeCompExpr(comppath);
-			xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
-						"XPath Syntax Error");
-		}
+			workspace->ctxt = xmlXPathNewContext(workspace->doctree);
+			if (workspace->ctxt == NULL)
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_OUT_OF_MEMORY,
+							"could not allocate XPath context");
 
-		/* Now evaluate the path expression. */
-		workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+			workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
+
+			/* compile the path */
+			comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
+			if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
+							"XPath Syntax Error");
+
+			/* Now evaluate the path expression. */
+			workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+
+			xmlXPathFreeCompExpr(comppath);
+			comppath = NULL;
+		}
+	}
+	PG_CATCH();
+	{
+		if (comppath != NULL)
+			xmlXPathFreeCompExpr(comppath);
+		cleanup_workspace(workspace);
 
-		xmlXPathFreeCompExpr(comppath);
+		PG_RE_THROW();
 	}
+	PG_END_TRY();
 
 	return workspace;
 }
-- 
2.54.0


--MP_/LMSk9=uMhuQ1QiIJDarDO8G--






^ permalink  raw  reply  [nested|flat] 611+ messages in thread

* [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths
@ 2026-06-01 22:41 Andrey Chernyy <andrey.cherny@tantorlabs.com>
  0 siblings, 0 replies; 611+ messages in thread

From: Andrey Chernyy @ 2026-06-01 22:41 UTC (permalink / raw)

pgxml_xpath() builds an xpath_workspace before returning it to
callers.  If an ERROR is thrown before the function returns, callers
have not received the workspace pointer yet and cannot run
cleanup_workspace().

Add local error cleanup for the partially built workspace and the
compiled XPath expression.  Also check xmlXPathNewContext() before
dereferencing the returned context.
---
 contrib/xml2/xpath.c | 51 +++++++++++++++++++++++++++-----------------
 1 file changed, 32 insertions(+), 19 deletions(-)

diff --git a/contrib/xml2/xpath.c b/contrib/xml2/xpath.c
index 9fe75cb5ff4..283bb51178d 100644
--- a/contrib/xml2/xpath.c
+++ b/contrib/xml2/xpath.c
@@ -497,36 +497,49 @@ static xpath_workspace *
 pgxml_xpath(text *document, xmlChar *xpath, PgXmlErrorContext *xmlerrcxt)
 {
 	int32		docsize = VARSIZE_ANY_EXHDR(document);
-	xmlXPathCompExprPtr comppath;
+	xmlXPathCompExprPtr volatile comppath = NULL;
 	xpath_workspace *workspace = palloc0_object(xpath_workspace);
 
 	workspace->doctree = NULL;
 	workspace->ctxt = NULL;
 	workspace->res = NULL;
 
-	workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
-									   docsize, NULL, NULL,
-									   XML_PARSE_NOENT);
-	if (workspace->doctree != NULL)
+	PG_TRY();
 	{
-		workspace->ctxt = xmlXPathNewContext(workspace->doctree);
-		workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
-
-		/* compile the path */
-		comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
-		if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+		workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
+										   docsize, NULL, NULL,
+										   XML_PARSE_NOENT);
+		if (workspace->doctree != NULL)
 		{
-			if (comppath != NULL)
-				xmlXPathFreeCompExpr(comppath);
-			xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
-						"XPath Syntax Error");
-		}
+			workspace->ctxt = xmlXPathNewContext(workspace->doctree);
+			if (workspace->ctxt == NULL)
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_OUT_OF_MEMORY,
+							"could not allocate XPath context");
 
-		/* Now evaluate the path expression. */
-		workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+			workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
+
+			/* compile the path */
+			comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
+			if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
+							"XPath Syntax Error");
+
+			/* Now evaluate the path expression. */
+			workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+
+			xmlXPathFreeCompExpr(comppath);
+			comppath = NULL;
+		}
+	}
+	PG_CATCH();
+	{
+		if (comppath != NULL)
+			xmlXPathFreeCompExpr(comppath);
+		cleanup_workspace(workspace);
 
-		xmlXPathFreeCompExpr(comppath);
+		PG_RE_THROW();
 	}
+	PG_END_TRY();
 
 	return workspace;
 }
-- 
2.54.0


--MP_/LMSk9=uMhuQ1QiIJDarDO8G--





^ permalink  raw  reply  [nested|flat] 611+ messages in thread

* [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths
@ 2026-06-01 22:41 Andrey Chernyy <andrey.cherny@tantorlabs.com>
  0 siblings, 0 replies; 611+ messages in thread

From: Andrey Chernyy @ 2026-06-01 22:41 UTC (permalink / raw)

pgxml_xpath() builds an xpath_workspace before returning it to
callers.  If an ERROR is thrown before the function returns, callers
have not received the workspace pointer yet and cannot run
cleanup_workspace().

Add local error cleanup for the partially built workspace and the
compiled XPath expression.  Also check xmlXPathNewContext() before
dereferencing the returned context.
---
 contrib/xml2/xpath.c | 51 +++++++++++++++++++++++++++-----------------
 1 file changed, 32 insertions(+), 19 deletions(-)

diff --git a/contrib/xml2/xpath.c b/contrib/xml2/xpath.c
index 9fe75cb5ff4..283bb51178d 100644
--- a/contrib/xml2/xpath.c
+++ b/contrib/xml2/xpath.c
@@ -497,36 +497,49 @@ static xpath_workspace *
 pgxml_xpath(text *document, xmlChar *xpath, PgXmlErrorContext *xmlerrcxt)
 {
 	int32		docsize = VARSIZE_ANY_EXHDR(document);
-	xmlXPathCompExprPtr comppath;
+	xmlXPathCompExprPtr volatile comppath = NULL;
 	xpath_workspace *workspace = palloc0_object(xpath_workspace);
 
 	workspace->doctree = NULL;
 	workspace->ctxt = NULL;
 	workspace->res = NULL;
 
-	workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
-									   docsize, NULL, NULL,
-									   XML_PARSE_NOENT);
-	if (workspace->doctree != NULL)
+	PG_TRY();
 	{
-		workspace->ctxt = xmlXPathNewContext(workspace->doctree);
-		workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
-
-		/* compile the path */
-		comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
-		if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+		workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
+										   docsize, NULL, NULL,
+										   XML_PARSE_NOENT);
+		if (workspace->doctree != NULL)
 		{
-			if (comppath != NULL)
-				xmlXPathFreeCompExpr(comppath);
-			xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
-						"XPath Syntax Error");
-		}
+			workspace->ctxt = xmlXPathNewContext(workspace->doctree);
+			if (workspace->ctxt == NULL)
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_OUT_OF_MEMORY,
+							"could not allocate XPath context");
 
-		/* Now evaluate the path expression. */
-		workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+			workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
+
+			/* compile the path */
+			comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
+			if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
+							"XPath Syntax Error");
+
+			/* Now evaluate the path expression. */
+			workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+
+			xmlXPathFreeCompExpr(comppath);
+			comppath = NULL;
+		}
+	}
+	PG_CATCH();
+	{
+		if (comppath != NULL)
+			xmlXPathFreeCompExpr(comppath);
+		cleanup_workspace(workspace);
 
-		xmlXPathFreeCompExpr(comppath);
+		PG_RE_THROW();
 	}
+	PG_END_TRY();
 
 	return workspace;
 }
-- 
2.54.0


--MP_/LMSk9=uMhuQ1QiIJDarDO8G--






^ permalink  raw  reply  [nested|flat] 611+ messages in thread

* [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths
@ 2026-06-01 22:41 Andrey Chernyy <andrey.cherny@tantorlabs.com>
  0 siblings, 0 replies; 611+ messages in thread

From: Andrey Chernyy @ 2026-06-01 22:41 UTC (permalink / raw)

pgxml_xpath() builds an xpath_workspace before returning it to
callers.  If an ERROR is thrown before the function returns, callers
have not received the workspace pointer yet and cannot run
cleanup_workspace().

Add local error cleanup for the partially built workspace and the
compiled XPath expression.  Also check xmlXPathNewContext() before
dereferencing the returned context.
---
 contrib/xml2/xpath.c | 51 +++++++++++++++++++++++++++-----------------
 1 file changed, 32 insertions(+), 19 deletions(-)

diff --git a/contrib/xml2/xpath.c b/contrib/xml2/xpath.c
index 9fe75cb5ff4..283bb51178d 100644
--- a/contrib/xml2/xpath.c
+++ b/contrib/xml2/xpath.c
@@ -497,36 +497,49 @@ static xpath_workspace *
 pgxml_xpath(text *document, xmlChar *xpath, PgXmlErrorContext *xmlerrcxt)
 {
 	int32		docsize = VARSIZE_ANY_EXHDR(document);
-	xmlXPathCompExprPtr comppath;
+	xmlXPathCompExprPtr volatile comppath = NULL;
 	xpath_workspace *workspace = palloc0_object(xpath_workspace);
 
 	workspace->doctree = NULL;
 	workspace->ctxt = NULL;
 	workspace->res = NULL;
 
-	workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
-									   docsize, NULL, NULL,
-									   XML_PARSE_NOENT);
-	if (workspace->doctree != NULL)
+	PG_TRY();
 	{
-		workspace->ctxt = xmlXPathNewContext(workspace->doctree);
-		workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
-
-		/* compile the path */
-		comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
-		if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+		workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
+										   docsize, NULL, NULL,
+										   XML_PARSE_NOENT);
+		if (workspace->doctree != NULL)
 		{
-			if (comppath != NULL)
-				xmlXPathFreeCompExpr(comppath);
-			xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
-						"XPath Syntax Error");
-		}
+			workspace->ctxt = xmlXPathNewContext(workspace->doctree);
+			if (workspace->ctxt == NULL)
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_OUT_OF_MEMORY,
+							"could not allocate XPath context");
 
-		/* Now evaluate the path expression. */
-		workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+			workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
+
+			/* compile the path */
+			comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
+			if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
+							"XPath Syntax Error");
+
+			/* Now evaluate the path expression. */
+			workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+
+			xmlXPathFreeCompExpr(comppath);
+			comppath = NULL;
+		}
+	}
+	PG_CATCH();
+	{
+		if (comppath != NULL)
+			xmlXPathFreeCompExpr(comppath);
+		cleanup_workspace(workspace);
 
-		xmlXPathFreeCompExpr(comppath);
+		PG_RE_THROW();
 	}
+	PG_END_TRY();
 
 	return workspace;
 }
-- 
2.54.0


--MP_/LMSk9=uMhuQ1QiIJDarDO8G--





^ permalink  raw  reply  [nested|flat] 611+ messages in thread

* [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths
@ 2026-06-01 22:41 Andrey Chernyy <andrey.cherny@tantorlabs.com>
  0 siblings, 0 replies; 611+ messages in thread

From: Andrey Chernyy @ 2026-06-01 22:41 UTC (permalink / raw)

pgxml_xpath() builds an xpath_workspace before returning it to
callers.  If an ERROR is thrown before the function returns, callers
have not received the workspace pointer yet and cannot run
cleanup_workspace().

Add local error cleanup for the partially built workspace and the
compiled XPath expression.  Also check xmlXPathNewContext() before
dereferencing the returned context.
---
 contrib/xml2/xpath.c | 51 +++++++++++++++++++++++++++-----------------
 1 file changed, 32 insertions(+), 19 deletions(-)

diff --git a/contrib/xml2/xpath.c b/contrib/xml2/xpath.c
index 9fe75cb5ff4..283bb51178d 100644
--- a/contrib/xml2/xpath.c
+++ b/contrib/xml2/xpath.c
@@ -497,36 +497,49 @@ static xpath_workspace *
 pgxml_xpath(text *document, xmlChar *xpath, PgXmlErrorContext *xmlerrcxt)
 {
 	int32		docsize = VARSIZE_ANY_EXHDR(document);
-	xmlXPathCompExprPtr comppath;
+	xmlXPathCompExprPtr volatile comppath = NULL;
 	xpath_workspace *workspace = palloc0_object(xpath_workspace);
 
 	workspace->doctree = NULL;
 	workspace->ctxt = NULL;
 	workspace->res = NULL;
 
-	workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
-									   docsize, NULL, NULL,
-									   XML_PARSE_NOENT);
-	if (workspace->doctree != NULL)
+	PG_TRY();
 	{
-		workspace->ctxt = xmlXPathNewContext(workspace->doctree);
-		workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
-
-		/* compile the path */
-		comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
-		if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+		workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
+										   docsize, NULL, NULL,
+										   XML_PARSE_NOENT);
+		if (workspace->doctree != NULL)
 		{
-			if (comppath != NULL)
-				xmlXPathFreeCompExpr(comppath);
-			xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
-						"XPath Syntax Error");
-		}
+			workspace->ctxt = xmlXPathNewContext(workspace->doctree);
+			if (workspace->ctxt == NULL)
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_OUT_OF_MEMORY,
+							"could not allocate XPath context");
 
-		/* Now evaluate the path expression. */
-		workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+			workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
+
+			/* compile the path */
+			comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
+			if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
+							"XPath Syntax Error");
+
+			/* Now evaluate the path expression. */
+			workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+
+			xmlXPathFreeCompExpr(comppath);
+			comppath = NULL;
+		}
+	}
+	PG_CATCH();
+	{
+		if (comppath != NULL)
+			xmlXPathFreeCompExpr(comppath);
+		cleanup_workspace(workspace);
 
-		xmlXPathFreeCompExpr(comppath);
+		PG_RE_THROW();
 	}
+	PG_END_TRY();
 
 	return workspace;
 }
-- 
2.54.0


--MP_/LMSk9=uMhuQ1QiIJDarDO8G--





^ permalink  raw  reply  [nested|flat] 611+ messages in thread

* [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths
@ 2026-06-01 22:41 Andrey Chernyy <andrey.cherny@tantorlabs.com>
  0 siblings, 0 replies; 611+ messages in thread

From: Andrey Chernyy @ 2026-06-01 22:41 UTC (permalink / raw)

pgxml_xpath() builds an xpath_workspace before returning it to
callers.  If an ERROR is thrown before the function returns, callers
have not received the workspace pointer yet and cannot run
cleanup_workspace().

Add local error cleanup for the partially built workspace and the
compiled XPath expression.  Also check xmlXPathNewContext() before
dereferencing the returned context.
---
 contrib/xml2/xpath.c | 51 +++++++++++++++++++++++++++-----------------
 1 file changed, 32 insertions(+), 19 deletions(-)

diff --git a/contrib/xml2/xpath.c b/contrib/xml2/xpath.c
index 9fe75cb5ff4..283bb51178d 100644
--- a/contrib/xml2/xpath.c
+++ b/contrib/xml2/xpath.c
@@ -497,36 +497,49 @@ static xpath_workspace *
 pgxml_xpath(text *document, xmlChar *xpath, PgXmlErrorContext *xmlerrcxt)
 {
 	int32		docsize = VARSIZE_ANY_EXHDR(document);
-	xmlXPathCompExprPtr comppath;
+	xmlXPathCompExprPtr volatile comppath = NULL;
 	xpath_workspace *workspace = palloc0_object(xpath_workspace);
 
 	workspace->doctree = NULL;
 	workspace->ctxt = NULL;
 	workspace->res = NULL;
 
-	workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
-									   docsize, NULL, NULL,
-									   XML_PARSE_NOENT);
-	if (workspace->doctree != NULL)
+	PG_TRY();
 	{
-		workspace->ctxt = xmlXPathNewContext(workspace->doctree);
-		workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
-
-		/* compile the path */
-		comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
-		if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+		workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
+										   docsize, NULL, NULL,
+										   XML_PARSE_NOENT);
+		if (workspace->doctree != NULL)
 		{
-			if (comppath != NULL)
-				xmlXPathFreeCompExpr(comppath);
-			xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
-						"XPath Syntax Error");
-		}
+			workspace->ctxt = xmlXPathNewContext(workspace->doctree);
+			if (workspace->ctxt == NULL)
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_OUT_OF_MEMORY,
+							"could not allocate XPath context");
 
-		/* Now evaluate the path expression. */
-		workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+			workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
+
+			/* compile the path */
+			comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
+			if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
+							"XPath Syntax Error");
+
+			/* Now evaluate the path expression. */
+			workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+
+			xmlXPathFreeCompExpr(comppath);
+			comppath = NULL;
+		}
+	}
+	PG_CATCH();
+	{
+		if (comppath != NULL)
+			xmlXPathFreeCompExpr(comppath);
+		cleanup_workspace(workspace);
 
-		xmlXPathFreeCompExpr(comppath);
+		PG_RE_THROW();
 	}
+	PG_END_TRY();
 
 	return workspace;
 }
-- 
2.54.0


--MP_/LMSk9=uMhuQ1QiIJDarDO8G--





^ permalink  raw  reply  [nested|flat] 611+ messages in thread

* [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths
@ 2026-06-01 22:41 Andrey Chernyy <andrey.cherny@tantorlabs.com>
  0 siblings, 0 replies; 611+ messages in thread

From: Andrey Chernyy @ 2026-06-01 22:41 UTC (permalink / raw)

pgxml_xpath() builds an xpath_workspace before returning it to
callers.  If an ERROR is thrown before the function returns, callers
have not received the workspace pointer yet and cannot run
cleanup_workspace().

Add local error cleanup for the partially built workspace and the
compiled XPath expression.  Also check xmlXPathNewContext() before
dereferencing the returned context.
---
 contrib/xml2/xpath.c | 51 +++++++++++++++++++++++++++-----------------
 1 file changed, 32 insertions(+), 19 deletions(-)

diff --git a/contrib/xml2/xpath.c b/contrib/xml2/xpath.c
index 9fe75cb5ff4..283bb51178d 100644
--- a/contrib/xml2/xpath.c
+++ b/contrib/xml2/xpath.c
@@ -497,36 +497,49 @@ static xpath_workspace *
 pgxml_xpath(text *document, xmlChar *xpath, PgXmlErrorContext *xmlerrcxt)
 {
 	int32		docsize = VARSIZE_ANY_EXHDR(document);
-	xmlXPathCompExprPtr comppath;
+	xmlXPathCompExprPtr volatile comppath = NULL;
 	xpath_workspace *workspace = palloc0_object(xpath_workspace);
 
 	workspace->doctree = NULL;
 	workspace->ctxt = NULL;
 	workspace->res = NULL;
 
-	workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
-									   docsize, NULL, NULL,
-									   XML_PARSE_NOENT);
-	if (workspace->doctree != NULL)
+	PG_TRY();
 	{
-		workspace->ctxt = xmlXPathNewContext(workspace->doctree);
-		workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
-
-		/* compile the path */
-		comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
-		if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+		workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
+										   docsize, NULL, NULL,
+										   XML_PARSE_NOENT);
+		if (workspace->doctree != NULL)
 		{
-			if (comppath != NULL)
-				xmlXPathFreeCompExpr(comppath);
-			xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
-						"XPath Syntax Error");
-		}
+			workspace->ctxt = xmlXPathNewContext(workspace->doctree);
+			if (workspace->ctxt == NULL)
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_OUT_OF_MEMORY,
+							"could not allocate XPath context");
 
-		/* Now evaluate the path expression. */
-		workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+			workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
+
+			/* compile the path */
+			comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
+			if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
+							"XPath Syntax Error");
+
+			/* Now evaluate the path expression. */
+			workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+
+			xmlXPathFreeCompExpr(comppath);
+			comppath = NULL;
+		}
+	}
+	PG_CATCH();
+	{
+		if (comppath != NULL)
+			xmlXPathFreeCompExpr(comppath);
+		cleanup_workspace(workspace);
 
-		xmlXPathFreeCompExpr(comppath);
+		PG_RE_THROW();
 	}
+	PG_END_TRY();
 
 	return workspace;
 }
-- 
2.54.0


--MP_/LMSk9=uMhuQ1QiIJDarDO8G--






^ permalink  raw  reply  [nested|flat] 611+ messages in thread

* [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths
@ 2026-06-01 22:41 Andrey Chernyy <andrey.cherny@tantorlabs.com>
  0 siblings, 0 replies; 611+ messages in thread

From: Andrey Chernyy @ 2026-06-01 22:41 UTC (permalink / raw)

pgxml_xpath() builds an xpath_workspace before returning it to
callers.  If an ERROR is thrown before the function returns, callers
have not received the workspace pointer yet and cannot run
cleanup_workspace().

Add local error cleanup for the partially built workspace and the
compiled XPath expression.  Also check xmlXPathNewContext() before
dereferencing the returned context.
---
 contrib/xml2/xpath.c | 51 +++++++++++++++++++++++++++-----------------
 1 file changed, 32 insertions(+), 19 deletions(-)

diff --git a/contrib/xml2/xpath.c b/contrib/xml2/xpath.c
index 9fe75cb5ff4..283bb51178d 100644
--- a/contrib/xml2/xpath.c
+++ b/contrib/xml2/xpath.c
@@ -497,36 +497,49 @@ static xpath_workspace *
 pgxml_xpath(text *document, xmlChar *xpath, PgXmlErrorContext *xmlerrcxt)
 {
 	int32		docsize = VARSIZE_ANY_EXHDR(document);
-	xmlXPathCompExprPtr comppath;
+	xmlXPathCompExprPtr volatile comppath = NULL;
 	xpath_workspace *workspace = palloc0_object(xpath_workspace);
 
 	workspace->doctree = NULL;
 	workspace->ctxt = NULL;
 	workspace->res = NULL;
 
-	workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
-									   docsize, NULL, NULL,
-									   XML_PARSE_NOENT);
-	if (workspace->doctree != NULL)
+	PG_TRY();
 	{
-		workspace->ctxt = xmlXPathNewContext(workspace->doctree);
-		workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
-
-		/* compile the path */
-		comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
-		if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+		workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
+										   docsize, NULL, NULL,
+										   XML_PARSE_NOENT);
+		if (workspace->doctree != NULL)
 		{
-			if (comppath != NULL)
-				xmlXPathFreeCompExpr(comppath);
-			xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
-						"XPath Syntax Error");
-		}
+			workspace->ctxt = xmlXPathNewContext(workspace->doctree);
+			if (workspace->ctxt == NULL)
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_OUT_OF_MEMORY,
+							"could not allocate XPath context");
 
-		/* Now evaluate the path expression. */
-		workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+			workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
+
+			/* compile the path */
+			comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
+			if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
+							"XPath Syntax Error");
+
+			/* Now evaluate the path expression. */
+			workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+
+			xmlXPathFreeCompExpr(comppath);
+			comppath = NULL;
+		}
+	}
+	PG_CATCH();
+	{
+		if (comppath != NULL)
+			xmlXPathFreeCompExpr(comppath);
+		cleanup_workspace(workspace);
 
-		xmlXPathFreeCompExpr(comppath);
+		PG_RE_THROW();
 	}
+	PG_END_TRY();
 
 	return workspace;
 }
-- 
2.54.0


--MP_/LMSk9=uMhuQ1QiIJDarDO8G--






^ permalink  raw  reply  [nested|flat] 611+ messages in thread

* [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths
@ 2026-06-01 22:41 Andrey Chernyy <andrey.cherny@tantorlabs.com>
  0 siblings, 0 replies; 611+ messages in thread

From: Andrey Chernyy @ 2026-06-01 22:41 UTC (permalink / raw)

pgxml_xpath() builds an xpath_workspace before returning it to
callers.  If an ERROR is thrown before the function returns, callers
have not received the workspace pointer yet and cannot run
cleanup_workspace().

Add local error cleanup for the partially built workspace and the
compiled XPath expression.  Also check xmlXPathNewContext() before
dereferencing the returned context.
---
 contrib/xml2/xpath.c | 51 +++++++++++++++++++++++++++-----------------
 1 file changed, 32 insertions(+), 19 deletions(-)

diff --git a/contrib/xml2/xpath.c b/contrib/xml2/xpath.c
index 9fe75cb5ff4..283bb51178d 100644
--- a/contrib/xml2/xpath.c
+++ b/contrib/xml2/xpath.c
@@ -497,36 +497,49 @@ static xpath_workspace *
 pgxml_xpath(text *document, xmlChar *xpath, PgXmlErrorContext *xmlerrcxt)
 {
 	int32		docsize = VARSIZE_ANY_EXHDR(document);
-	xmlXPathCompExprPtr comppath;
+	xmlXPathCompExprPtr volatile comppath = NULL;
 	xpath_workspace *workspace = palloc0_object(xpath_workspace);
 
 	workspace->doctree = NULL;
 	workspace->ctxt = NULL;
 	workspace->res = NULL;
 
-	workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
-									   docsize, NULL, NULL,
-									   XML_PARSE_NOENT);
-	if (workspace->doctree != NULL)
+	PG_TRY();
 	{
-		workspace->ctxt = xmlXPathNewContext(workspace->doctree);
-		workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
-
-		/* compile the path */
-		comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
-		if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+		workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
+										   docsize, NULL, NULL,
+										   XML_PARSE_NOENT);
+		if (workspace->doctree != NULL)
 		{
-			if (comppath != NULL)
-				xmlXPathFreeCompExpr(comppath);
-			xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
-						"XPath Syntax Error");
-		}
+			workspace->ctxt = xmlXPathNewContext(workspace->doctree);
+			if (workspace->ctxt == NULL)
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_OUT_OF_MEMORY,
+							"could not allocate XPath context");
 
-		/* Now evaluate the path expression. */
-		workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+			workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
+
+			/* compile the path */
+			comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
+			if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
+							"XPath Syntax Error");
+
+			/* Now evaluate the path expression. */
+			workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+
+			xmlXPathFreeCompExpr(comppath);
+			comppath = NULL;
+		}
+	}
+	PG_CATCH();
+	{
+		if (comppath != NULL)
+			xmlXPathFreeCompExpr(comppath);
+		cleanup_workspace(workspace);
 
-		xmlXPathFreeCompExpr(comppath);
+		PG_RE_THROW();
 	}
+	PG_END_TRY();
 
 	return workspace;
 }
-- 
2.54.0


--MP_/LMSk9=uMhuQ1QiIJDarDO8G--





^ permalink  raw  reply  [nested|flat] 611+ messages in thread

* [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths
@ 2026-06-01 22:41 Andrey Chernyy <andrey.cherny@tantorlabs.com>
  0 siblings, 0 replies; 611+ messages in thread

From: Andrey Chernyy @ 2026-06-01 22:41 UTC (permalink / raw)

pgxml_xpath() builds an xpath_workspace before returning it to
callers.  If an ERROR is thrown before the function returns, callers
have not received the workspace pointer yet and cannot run
cleanup_workspace().

Add local error cleanup for the partially built workspace and the
compiled XPath expression.  Also check xmlXPathNewContext() before
dereferencing the returned context.
---
 contrib/xml2/xpath.c | 51 +++++++++++++++++++++++++++-----------------
 1 file changed, 32 insertions(+), 19 deletions(-)

diff --git a/contrib/xml2/xpath.c b/contrib/xml2/xpath.c
index 9fe75cb5ff4..283bb51178d 100644
--- a/contrib/xml2/xpath.c
+++ b/contrib/xml2/xpath.c
@@ -497,36 +497,49 @@ static xpath_workspace *
 pgxml_xpath(text *document, xmlChar *xpath, PgXmlErrorContext *xmlerrcxt)
 {
 	int32		docsize = VARSIZE_ANY_EXHDR(document);
-	xmlXPathCompExprPtr comppath;
+	xmlXPathCompExprPtr volatile comppath = NULL;
 	xpath_workspace *workspace = palloc0_object(xpath_workspace);
 
 	workspace->doctree = NULL;
 	workspace->ctxt = NULL;
 	workspace->res = NULL;
 
-	workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
-									   docsize, NULL, NULL,
-									   XML_PARSE_NOENT);
-	if (workspace->doctree != NULL)
+	PG_TRY();
 	{
-		workspace->ctxt = xmlXPathNewContext(workspace->doctree);
-		workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
-
-		/* compile the path */
-		comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
-		if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+		workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
+										   docsize, NULL, NULL,
+										   XML_PARSE_NOENT);
+		if (workspace->doctree != NULL)
 		{
-			if (comppath != NULL)
-				xmlXPathFreeCompExpr(comppath);
-			xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
-						"XPath Syntax Error");
-		}
+			workspace->ctxt = xmlXPathNewContext(workspace->doctree);
+			if (workspace->ctxt == NULL)
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_OUT_OF_MEMORY,
+							"could not allocate XPath context");
 
-		/* Now evaluate the path expression. */
-		workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+			workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
+
+			/* compile the path */
+			comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
+			if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
+							"XPath Syntax Error");
+
+			/* Now evaluate the path expression. */
+			workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+
+			xmlXPathFreeCompExpr(comppath);
+			comppath = NULL;
+		}
+	}
+	PG_CATCH();
+	{
+		if (comppath != NULL)
+			xmlXPathFreeCompExpr(comppath);
+		cleanup_workspace(workspace);
 
-		xmlXPathFreeCompExpr(comppath);
+		PG_RE_THROW();
 	}
+	PG_END_TRY();
 
 	return workspace;
 }
-- 
2.54.0


--MP_/LMSk9=uMhuQ1QiIJDarDO8G--






^ permalink  raw  reply  [nested|flat] 611+ messages in thread

* [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths
@ 2026-06-01 22:41 Andrey Chernyy <andrey.cherny@tantorlabs.com>
  0 siblings, 0 replies; 611+ messages in thread

From: Andrey Chernyy @ 2026-06-01 22:41 UTC (permalink / raw)

pgxml_xpath() builds an xpath_workspace before returning it to
callers.  If an ERROR is thrown before the function returns, callers
have not received the workspace pointer yet and cannot run
cleanup_workspace().

Add local error cleanup for the partially built workspace and the
compiled XPath expression.  Also check xmlXPathNewContext() before
dereferencing the returned context.
---
 contrib/xml2/xpath.c | 51 +++++++++++++++++++++++++++-----------------
 1 file changed, 32 insertions(+), 19 deletions(-)

diff --git a/contrib/xml2/xpath.c b/contrib/xml2/xpath.c
index 9fe75cb5ff4..283bb51178d 100644
--- a/contrib/xml2/xpath.c
+++ b/contrib/xml2/xpath.c
@@ -497,36 +497,49 @@ static xpath_workspace *
 pgxml_xpath(text *document, xmlChar *xpath, PgXmlErrorContext *xmlerrcxt)
 {
 	int32		docsize = VARSIZE_ANY_EXHDR(document);
-	xmlXPathCompExprPtr comppath;
+	xmlXPathCompExprPtr volatile comppath = NULL;
 	xpath_workspace *workspace = palloc0_object(xpath_workspace);
 
 	workspace->doctree = NULL;
 	workspace->ctxt = NULL;
 	workspace->res = NULL;
 
-	workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
-									   docsize, NULL, NULL,
-									   XML_PARSE_NOENT);
-	if (workspace->doctree != NULL)
+	PG_TRY();
 	{
-		workspace->ctxt = xmlXPathNewContext(workspace->doctree);
-		workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
-
-		/* compile the path */
-		comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
-		if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+		workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
+										   docsize, NULL, NULL,
+										   XML_PARSE_NOENT);
+		if (workspace->doctree != NULL)
 		{
-			if (comppath != NULL)
-				xmlXPathFreeCompExpr(comppath);
-			xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
-						"XPath Syntax Error");
-		}
+			workspace->ctxt = xmlXPathNewContext(workspace->doctree);
+			if (workspace->ctxt == NULL)
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_OUT_OF_MEMORY,
+							"could not allocate XPath context");
 
-		/* Now evaluate the path expression. */
-		workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+			workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
+
+			/* compile the path */
+			comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
+			if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
+							"XPath Syntax Error");
+
+			/* Now evaluate the path expression. */
+			workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+
+			xmlXPathFreeCompExpr(comppath);
+			comppath = NULL;
+		}
+	}
+	PG_CATCH();
+	{
+		if (comppath != NULL)
+			xmlXPathFreeCompExpr(comppath);
+		cleanup_workspace(workspace);
 
-		xmlXPathFreeCompExpr(comppath);
+		PG_RE_THROW();
 	}
+	PG_END_TRY();
 
 	return workspace;
 }
-- 
2.54.0


--MP_/LMSk9=uMhuQ1QiIJDarDO8G--






^ permalink  raw  reply  [nested|flat] 611+ messages in thread

* [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths
@ 2026-06-01 22:41 Andrey Chernyy <andrey.cherny@tantorlabs.com>
  0 siblings, 0 replies; 611+ messages in thread

From: Andrey Chernyy @ 2026-06-01 22:41 UTC (permalink / raw)

pgxml_xpath() builds an xpath_workspace before returning it to
callers.  If an ERROR is thrown before the function returns, callers
have not received the workspace pointer yet and cannot run
cleanup_workspace().

Add local error cleanup for the partially built workspace and the
compiled XPath expression.  Also check xmlXPathNewContext() before
dereferencing the returned context.
---
 contrib/xml2/xpath.c | 51 +++++++++++++++++++++++++++-----------------
 1 file changed, 32 insertions(+), 19 deletions(-)

diff --git a/contrib/xml2/xpath.c b/contrib/xml2/xpath.c
index 9fe75cb5ff4..283bb51178d 100644
--- a/contrib/xml2/xpath.c
+++ b/contrib/xml2/xpath.c
@@ -497,36 +497,49 @@ static xpath_workspace *
 pgxml_xpath(text *document, xmlChar *xpath, PgXmlErrorContext *xmlerrcxt)
 {
 	int32		docsize = VARSIZE_ANY_EXHDR(document);
-	xmlXPathCompExprPtr comppath;
+	xmlXPathCompExprPtr volatile comppath = NULL;
 	xpath_workspace *workspace = palloc0_object(xpath_workspace);
 
 	workspace->doctree = NULL;
 	workspace->ctxt = NULL;
 	workspace->res = NULL;
 
-	workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
-									   docsize, NULL, NULL,
-									   XML_PARSE_NOENT);
-	if (workspace->doctree != NULL)
+	PG_TRY();
 	{
-		workspace->ctxt = xmlXPathNewContext(workspace->doctree);
-		workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
-
-		/* compile the path */
-		comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
-		if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+		workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
+										   docsize, NULL, NULL,
+										   XML_PARSE_NOENT);
+		if (workspace->doctree != NULL)
 		{
-			if (comppath != NULL)
-				xmlXPathFreeCompExpr(comppath);
-			xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
-						"XPath Syntax Error");
-		}
+			workspace->ctxt = xmlXPathNewContext(workspace->doctree);
+			if (workspace->ctxt == NULL)
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_OUT_OF_MEMORY,
+							"could not allocate XPath context");
 
-		/* Now evaluate the path expression. */
-		workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+			workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
+
+			/* compile the path */
+			comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
+			if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
+							"XPath Syntax Error");
+
+			/* Now evaluate the path expression. */
+			workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+
+			xmlXPathFreeCompExpr(comppath);
+			comppath = NULL;
+		}
+	}
+	PG_CATCH();
+	{
+		if (comppath != NULL)
+			xmlXPathFreeCompExpr(comppath);
+		cleanup_workspace(workspace);
 
-		xmlXPathFreeCompExpr(comppath);
+		PG_RE_THROW();
 	}
+	PG_END_TRY();
 
 	return workspace;
 }
-- 
2.54.0


--MP_/LMSk9=uMhuQ1QiIJDarDO8G--






^ permalink  raw  reply  [nested|flat] 611+ messages in thread

* [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths
@ 2026-06-01 22:41 Andrey Chernyy <andrey.cherny@tantorlabs.com>
  0 siblings, 0 replies; 611+ messages in thread

From: Andrey Chernyy @ 2026-06-01 22:41 UTC (permalink / raw)

pgxml_xpath() builds an xpath_workspace before returning it to
callers.  If an ERROR is thrown before the function returns, callers
have not received the workspace pointer yet and cannot run
cleanup_workspace().

Add local error cleanup for the partially built workspace and the
compiled XPath expression.  Also check xmlXPathNewContext() before
dereferencing the returned context.
---
 contrib/xml2/xpath.c | 51 +++++++++++++++++++++++++++-----------------
 1 file changed, 32 insertions(+), 19 deletions(-)

diff --git a/contrib/xml2/xpath.c b/contrib/xml2/xpath.c
index 9fe75cb5ff4..283bb51178d 100644
--- a/contrib/xml2/xpath.c
+++ b/contrib/xml2/xpath.c
@@ -497,36 +497,49 @@ static xpath_workspace *
 pgxml_xpath(text *document, xmlChar *xpath, PgXmlErrorContext *xmlerrcxt)
 {
 	int32		docsize = VARSIZE_ANY_EXHDR(document);
-	xmlXPathCompExprPtr comppath;
+	xmlXPathCompExprPtr volatile comppath = NULL;
 	xpath_workspace *workspace = palloc0_object(xpath_workspace);
 
 	workspace->doctree = NULL;
 	workspace->ctxt = NULL;
 	workspace->res = NULL;
 
-	workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
-									   docsize, NULL, NULL,
-									   XML_PARSE_NOENT);
-	if (workspace->doctree != NULL)
+	PG_TRY();
 	{
-		workspace->ctxt = xmlXPathNewContext(workspace->doctree);
-		workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
-
-		/* compile the path */
-		comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
-		if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+		workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
+										   docsize, NULL, NULL,
+										   XML_PARSE_NOENT);
+		if (workspace->doctree != NULL)
 		{
-			if (comppath != NULL)
-				xmlXPathFreeCompExpr(comppath);
-			xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
-						"XPath Syntax Error");
-		}
+			workspace->ctxt = xmlXPathNewContext(workspace->doctree);
+			if (workspace->ctxt == NULL)
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_OUT_OF_MEMORY,
+							"could not allocate XPath context");
 
-		/* Now evaluate the path expression. */
-		workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+			workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
+
+			/* compile the path */
+			comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
+			if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
+							"XPath Syntax Error");
+
+			/* Now evaluate the path expression. */
+			workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+
+			xmlXPathFreeCompExpr(comppath);
+			comppath = NULL;
+		}
+	}
+	PG_CATCH();
+	{
+		if (comppath != NULL)
+			xmlXPathFreeCompExpr(comppath);
+		cleanup_workspace(workspace);
 
-		xmlXPathFreeCompExpr(comppath);
+		PG_RE_THROW();
 	}
+	PG_END_TRY();
 
 	return workspace;
 }
-- 
2.54.0


--MP_/LMSk9=uMhuQ1QiIJDarDO8G--





^ permalink  raw  reply  [nested|flat] 611+ messages in thread

* [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths
@ 2026-06-01 22:41 Andrey Chernyy <andrey.cherny@tantorlabs.com>
  0 siblings, 0 replies; 611+ messages in thread

From: Andrey Chernyy @ 2026-06-01 22:41 UTC (permalink / raw)

pgxml_xpath() builds an xpath_workspace before returning it to
callers.  If an ERROR is thrown before the function returns, callers
have not received the workspace pointer yet and cannot run
cleanup_workspace().

Add local error cleanup for the partially built workspace and the
compiled XPath expression.  Also check xmlXPathNewContext() before
dereferencing the returned context.
---
 contrib/xml2/xpath.c | 51 +++++++++++++++++++++++++++-----------------
 1 file changed, 32 insertions(+), 19 deletions(-)

diff --git a/contrib/xml2/xpath.c b/contrib/xml2/xpath.c
index 9fe75cb5ff4..283bb51178d 100644
--- a/contrib/xml2/xpath.c
+++ b/contrib/xml2/xpath.c
@@ -497,36 +497,49 @@ static xpath_workspace *
 pgxml_xpath(text *document, xmlChar *xpath, PgXmlErrorContext *xmlerrcxt)
 {
 	int32		docsize = VARSIZE_ANY_EXHDR(document);
-	xmlXPathCompExprPtr comppath;
+	xmlXPathCompExprPtr volatile comppath = NULL;
 	xpath_workspace *workspace = palloc0_object(xpath_workspace);
 
 	workspace->doctree = NULL;
 	workspace->ctxt = NULL;
 	workspace->res = NULL;
 
-	workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
-									   docsize, NULL, NULL,
-									   XML_PARSE_NOENT);
-	if (workspace->doctree != NULL)
+	PG_TRY();
 	{
-		workspace->ctxt = xmlXPathNewContext(workspace->doctree);
-		workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
-
-		/* compile the path */
-		comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
-		if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+		workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
+										   docsize, NULL, NULL,
+										   XML_PARSE_NOENT);
+		if (workspace->doctree != NULL)
 		{
-			if (comppath != NULL)
-				xmlXPathFreeCompExpr(comppath);
-			xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
-						"XPath Syntax Error");
-		}
+			workspace->ctxt = xmlXPathNewContext(workspace->doctree);
+			if (workspace->ctxt == NULL)
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_OUT_OF_MEMORY,
+							"could not allocate XPath context");
 
-		/* Now evaluate the path expression. */
-		workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+			workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
+
+			/* compile the path */
+			comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
+			if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
+							"XPath Syntax Error");
+
+			/* Now evaluate the path expression. */
+			workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+
+			xmlXPathFreeCompExpr(comppath);
+			comppath = NULL;
+		}
+	}
+	PG_CATCH();
+	{
+		if (comppath != NULL)
+			xmlXPathFreeCompExpr(comppath);
+		cleanup_workspace(workspace);
 
-		xmlXPathFreeCompExpr(comppath);
+		PG_RE_THROW();
 	}
+	PG_END_TRY();
 
 	return workspace;
 }
-- 
2.54.0


--MP_/LMSk9=uMhuQ1QiIJDarDO8G--






^ permalink  raw  reply  [nested|flat] 611+ messages in thread

* [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths
@ 2026-06-01 22:41 Andrey Chernyy <andrey.cherny@tantorlabs.com>
  0 siblings, 0 replies; 611+ messages in thread

From: Andrey Chernyy @ 2026-06-01 22:41 UTC (permalink / raw)

pgxml_xpath() builds an xpath_workspace before returning it to
callers.  If an ERROR is thrown before the function returns, callers
have not received the workspace pointer yet and cannot run
cleanup_workspace().

Add local error cleanup for the partially built workspace and the
compiled XPath expression.  Also check xmlXPathNewContext() before
dereferencing the returned context.
---
 contrib/xml2/xpath.c | 51 +++++++++++++++++++++++++++-----------------
 1 file changed, 32 insertions(+), 19 deletions(-)

diff --git a/contrib/xml2/xpath.c b/contrib/xml2/xpath.c
index 9fe75cb5ff4..283bb51178d 100644
--- a/contrib/xml2/xpath.c
+++ b/contrib/xml2/xpath.c
@@ -497,36 +497,49 @@ static xpath_workspace *
 pgxml_xpath(text *document, xmlChar *xpath, PgXmlErrorContext *xmlerrcxt)
 {
 	int32		docsize = VARSIZE_ANY_EXHDR(document);
-	xmlXPathCompExprPtr comppath;
+	xmlXPathCompExprPtr volatile comppath = NULL;
 	xpath_workspace *workspace = palloc0_object(xpath_workspace);
 
 	workspace->doctree = NULL;
 	workspace->ctxt = NULL;
 	workspace->res = NULL;
 
-	workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
-									   docsize, NULL, NULL,
-									   XML_PARSE_NOENT);
-	if (workspace->doctree != NULL)
+	PG_TRY();
 	{
-		workspace->ctxt = xmlXPathNewContext(workspace->doctree);
-		workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
-
-		/* compile the path */
-		comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
-		if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+		workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
+										   docsize, NULL, NULL,
+										   XML_PARSE_NOENT);
+		if (workspace->doctree != NULL)
 		{
-			if (comppath != NULL)
-				xmlXPathFreeCompExpr(comppath);
-			xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
-						"XPath Syntax Error");
-		}
+			workspace->ctxt = xmlXPathNewContext(workspace->doctree);
+			if (workspace->ctxt == NULL)
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_OUT_OF_MEMORY,
+							"could not allocate XPath context");
 
-		/* Now evaluate the path expression. */
-		workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+			workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
+
+			/* compile the path */
+			comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
+			if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
+							"XPath Syntax Error");
+
+			/* Now evaluate the path expression. */
+			workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+
+			xmlXPathFreeCompExpr(comppath);
+			comppath = NULL;
+		}
+	}
+	PG_CATCH();
+	{
+		if (comppath != NULL)
+			xmlXPathFreeCompExpr(comppath);
+		cleanup_workspace(workspace);
 
-		xmlXPathFreeCompExpr(comppath);
+		PG_RE_THROW();
 	}
+	PG_END_TRY();
 
 	return workspace;
 }
-- 
2.54.0


--MP_/LMSk9=uMhuQ1QiIJDarDO8G--






^ permalink  raw  reply  [nested|flat] 611+ messages in thread

* [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths
@ 2026-06-01 22:41 Andrey Chernyy <andrey.cherny@tantorlabs.com>
  0 siblings, 0 replies; 611+ messages in thread

From: Andrey Chernyy @ 2026-06-01 22:41 UTC (permalink / raw)

pgxml_xpath() builds an xpath_workspace before returning it to
callers.  If an ERROR is thrown before the function returns, callers
have not received the workspace pointer yet and cannot run
cleanup_workspace().

Add local error cleanup for the partially built workspace and the
compiled XPath expression.  Also check xmlXPathNewContext() before
dereferencing the returned context.
---
 contrib/xml2/xpath.c | 51 +++++++++++++++++++++++++++-----------------
 1 file changed, 32 insertions(+), 19 deletions(-)

diff --git a/contrib/xml2/xpath.c b/contrib/xml2/xpath.c
index 9fe75cb5ff4..283bb51178d 100644
--- a/contrib/xml2/xpath.c
+++ b/contrib/xml2/xpath.c
@@ -497,36 +497,49 @@ static xpath_workspace *
 pgxml_xpath(text *document, xmlChar *xpath, PgXmlErrorContext *xmlerrcxt)
 {
 	int32		docsize = VARSIZE_ANY_EXHDR(document);
-	xmlXPathCompExprPtr comppath;
+	xmlXPathCompExprPtr volatile comppath = NULL;
 	xpath_workspace *workspace = palloc0_object(xpath_workspace);
 
 	workspace->doctree = NULL;
 	workspace->ctxt = NULL;
 	workspace->res = NULL;
 
-	workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
-									   docsize, NULL, NULL,
-									   XML_PARSE_NOENT);
-	if (workspace->doctree != NULL)
+	PG_TRY();
 	{
-		workspace->ctxt = xmlXPathNewContext(workspace->doctree);
-		workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
-
-		/* compile the path */
-		comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
-		if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+		workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
+										   docsize, NULL, NULL,
+										   XML_PARSE_NOENT);
+		if (workspace->doctree != NULL)
 		{
-			if (comppath != NULL)
-				xmlXPathFreeCompExpr(comppath);
-			xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
-						"XPath Syntax Error");
-		}
+			workspace->ctxt = xmlXPathNewContext(workspace->doctree);
+			if (workspace->ctxt == NULL)
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_OUT_OF_MEMORY,
+							"could not allocate XPath context");
 
-		/* Now evaluate the path expression. */
-		workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+			workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
+
+			/* compile the path */
+			comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
+			if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
+							"XPath Syntax Error");
+
+			/* Now evaluate the path expression. */
+			workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+
+			xmlXPathFreeCompExpr(comppath);
+			comppath = NULL;
+		}
+	}
+	PG_CATCH();
+	{
+		if (comppath != NULL)
+			xmlXPathFreeCompExpr(comppath);
+		cleanup_workspace(workspace);
 
-		xmlXPathFreeCompExpr(comppath);
+		PG_RE_THROW();
 	}
+	PG_END_TRY();
 
 	return workspace;
 }
-- 
2.54.0


--MP_/LMSk9=uMhuQ1QiIJDarDO8G--






^ permalink  raw  reply  [nested|flat] 611+ messages in thread

* [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths
@ 2026-06-01 22:41 Andrey Chernyy <andrey.cherny@tantorlabs.com>
  0 siblings, 0 replies; 611+ messages in thread

From: Andrey Chernyy @ 2026-06-01 22:41 UTC (permalink / raw)

pgxml_xpath() builds an xpath_workspace before returning it to
callers.  If an ERROR is thrown before the function returns, callers
have not received the workspace pointer yet and cannot run
cleanup_workspace().

Add local error cleanup for the partially built workspace and the
compiled XPath expression.  Also check xmlXPathNewContext() before
dereferencing the returned context.
---
 contrib/xml2/xpath.c | 51 +++++++++++++++++++++++++++-----------------
 1 file changed, 32 insertions(+), 19 deletions(-)

diff --git a/contrib/xml2/xpath.c b/contrib/xml2/xpath.c
index 9fe75cb5ff4..283bb51178d 100644
--- a/contrib/xml2/xpath.c
+++ b/contrib/xml2/xpath.c
@@ -497,36 +497,49 @@ static xpath_workspace *
 pgxml_xpath(text *document, xmlChar *xpath, PgXmlErrorContext *xmlerrcxt)
 {
 	int32		docsize = VARSIZE_ANY_EXHDR(document);
-	xmlXPathCompExprPtr comppath;
+	xmlXPathCompExprPtr volatile comppath = NULL;
 	xpath_workspace *workspace = palloc0_object(xpath_workspace);
 
 	workspace->doctree = NULL;
 	workspace->ctxt = NULL;
 	workspace->res = NULL;
 
-	workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
-									   docsize, NULL, NULL,
-									   XML_PARSE_NOENT);
-	if (workspace->doctree != NULL)
+	PG_TRY();
 	{
-		workspace->ctxt = xmlXPathNewContext(workspace->doctree);
-		workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
-
-		/* compile the path */
-		comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
-		if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+		workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
+										   docsize, NULL, NULL,
+										   XML_PARSE_NOENT);
+		if (workspace->doctree != NULL)
 		{
-			if (comppath != NULL)
-				xmlXPathFreeCompExpr(comppath);
-			xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
-						"XPath Syntax Error");
-		}
+			workspace->ctxt = xmlXPathNewContext(workspace->doctree);
+			if (workspace->ctxt == NULL)
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_OUT_OF_MEMORY,
+							"could not allocate XPath context");
 
-		/* Now evaluate the path expression. */
-		workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+			workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
+
+			/* compile the path */
+			comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
+			if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
+							"XPath Syntax Error");
+
+			/* Now evaluate the path expression. */
+			workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+
+			xmlXPathFreeCompExpr(comppath);
+			comppath = NULL;
+		}
+	}
+	PG_CATCH();
+	{
+		if (comppath != NULL)
+			xmlXPathFreeCompExpr(comppath);
+		cleanup_workspace(workspace);
 
-		xmlXPathFreeCompExpr(comppath);
+		PG_RE_THROW();
 	}
+	PG_END_TRY();
 
 	return workspace;
 }
-- 
2.54.0


--MP_/LMSk9=uMhuQ1QiIJDarDO8G--





^ permalink  raw  reply  [nested|flat] 611+ messages in thread

* [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths
@ 2026-06-01 22:41 Andrey Chernyy <andrey.cherny@tantorlabs.com>
  0 siblings, 0 replies; 611+ messages in thread

From: Andrey Chernyy @ 2026-06-01 22:41 UTC (permalink / raw)

pgxml_xpath() builds an xpath_workspace before returning it to
callers.  If an ERROR is thrown before the function returns, callers
have not received the workspace pointer yet and cannot run
cleanup_workspace().

Add local error cleanup for the partially built workspace and the
compiled XPath expression.  Also check xmlXPathNewContext() before
dereferencing the returned context.
---
 contrib/xml2/xpath.c | 51 +++++++++++++++++++++++++++-----------------
 1 file changed, 32 insertions(+), 19 deletions(-)

diff --git a/contrib/xml2/xpath.c b/contrib/xml2/xpath.c
index 9fe75cb5ff4..283bb51178d 100644
--- a/contrib/xml2/xpath.c
+++ b/contrib/xml2/xpath.c
@@ -497,36 +497,49 @@ static xpath_workspace *
 pgxml_xpath(text *document, xmlChar *xpath, PgXmlErrorContext *xmlerrcxt)
 {
 	int32		docsize = VARSIZE_ANY_EXHDR(document);
-	xmlXPathCompExprPtr comppath;
+	xmlXPathCompExprPtr volatile comppath = NULL;
 	xpath_workspace *workspace = palloc0_object(xpath_workspace);
 
 	workspace->doctree = NULL;
 	workspace->ctxt = NULL;
 	workspace->res = NULL;
 
-	workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
-									   docsize, NULL, NULL,
-									   XML_PARSE_NOENT);
-	if (workspace->doctree != NULL)
+	PG_TRY();
 	{
-		workspace->ctxt = xmlXPathNewContext(workspace->doctree);
-		workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
-
-		/* compile the path */
-		comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
-		if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+		workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
+										   docsize, NULL, NULL,
+										   XML_PARSE_NOENT);
+		if (workspace->doctree != NULL)
 		{
-			if (comppath != NULL)
-				xmlXPathFreeCompExpr(comppath);
-			xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
-						"XPath Syntax Error");
-		}
+			workspace->ctxt = xmlXPathNewContext(workspace->doctree);
+			if (workspace->ctxt == NULL)
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_OUT_OF_MEMORY,
+							"could not allocate XPath context");
 
-		/* Now evaluate the path expression. */
-		workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+			workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
+
+			/* compile the path */
+			comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
+			if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
+							"XPath Syntax Error");
+
+			/* Now evaluate the path expression. */
+			workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+
+			xmlXPathFreeCompExpr(comppath);
+			comppath = NULL;
+		}
+	}
+	PG_CATCH();
+	{
+		if (comppath != NULL)
+			xmlXPathFreeCompExpr(comppath);
+		cleanup_workspace(workspace);
 
-		xmlXPathFreeCompExpr(comppath);
+		PG_RE_THROW();
 	}
+	PG_END_TRY();
 
 	return workspace;
 }
-- 
2.54.0


--MP_/LMSk9=uMhuQ1QiIJDarDO8G--






^ permalink  raw  reply  [nested|flat] 611+ messages in thread

* [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths
@ 2026-06-01 22:41 Andrey Chernyy <andrey.cherny@tantorlabs.com>
  0 siblings, 0 replies; 611+ messages in thread

From: Andrey Chernyy @ 2026-06-01 22:41 UTC (permalink / raw)

pgxml_xpath() builds an xpath_workspace before returning it to
callers.  If an ERROR is thrown before the function returns, callers
have not received the workspace pointer yet and cannot run
cleanup_workspace().

Add local error cleanup for the partially built workspace and the
compiled XPath expression.  Also check xmlXPathNewContext() before
dereferencing the returned context.
---
 contrib/xml2/xpath.c | 51 +++++++++++++++++++++++++++-----------------
 1 file changed, 32 insertions(+), 19 deletions(-)

diff --git a/contrib/xml2/xpath.c b/contrib/xml2/xpath.c
index 9fe75cb5ff4..283bb51178d 100644
--- a/contrib/xml2/xpath.c
+++ b/contrib/xml2/xpath.c
@@ -497,36 +497,49 @@ static xpath_workspace *
 pgxml_xpath(text *document, xmlChar *xpath, PgXmlErrorContext *xmlerrcxt)
 {
 	int32		docsize = VARSIZE_ANY_EXHDR(document);
-	xmlXPathCompExprPtr comppath;
+	xmlXPathCompExprPtr volatile comppath = NULL;
 	xpath_workspace *workspace = palloc0_object(xpath_workspace);
 
 	workspace->doctree = NULL;
 	workspace->ctxt = NULL;
 	workspace->res = NULL;
 
-	workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
-									   docsize, NULL, NULL,
-									   XML_PARSE_NOENT);
-	if (workspace->doctree != NULL)
+	PG_TRY();
 	{
-		workspace->ctxt = xmlXPathNewContext(workspace->doctree);
-		workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
-
-		/* compile the path */
-		comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
-		if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+		workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
+										   docsize, NULL, NULL,
+										   XML_PARSE_NOENT);
+		if (workspace->doctree != NULL)
 		{
-			if (comppath != NULL)
-				xmlXPathFreeCompExpr(comppath);
-			xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
-						"XPath Syntax Error");
-		}
+			workspace->ctxt = xmlXPathNewContext(workspace->doctree);
+			if (workspace->ctxt == NULL)
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_OUT_OF_MEMORY,
+							"could not allocate XPath context");
 
-		/* Now evaluate the path expression. */
-		workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+			workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
+
+			/* compile the path */
+			comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
+			if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
+							"XPath Syntax Error");
+
+			/* Now evaluate the path expression. */
+			workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+
+			xmlXPathFreeCompExpr(comppath);
+			comppath = NULL;
+		}
+	}
+	PG_CATCH();
+	{
+		if (comppath != NULL)
+			xmlXPathFreeCompExpr(comppath);
+		cleanup_workspace(workspace);
 
-		xmlXPathFreeCompExpr(comppath);
+		PG_RE_THROW();
 	}
+	PG_END_TRY();
 
 	return workspace;
 }
-- 
2.54.0


--MP_/LMSk9=uMhuQ1QiIJDarDO8G--





^ permalink  raw  reply  [nested|flat] 611+ messages in thread

* [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths
@ 2026-06-01 22:41 Andrey Chernyy <andrey.cherny@tantorlabs.com>
  0 siblings, 0 replies; 611+ messages in thread

From: Andrey Chernyy @ 2026-06-01 22:41 UTC (permalink / raw)

pgxml_xpath() builds an xpath_workspace before returning it to
callers.  If an ERROR is thrown before the function returns, callers
have not received the workspace pointer yet and cannot run
cleanup_workspace().

Add local error cleanup for the partially built workspace and the
compiled XPath expression.  Also check xmlXPathNewContext() before
dereferencing the returned context.
---
 contrib/xml2/xpath.c | 51 +++++++++++++++++++++++++++-----------------
 1 file changed, 32 insertions(+), 19 deletions(-)

diff --git a/contrib/xml2/xpath.c b/contrib/xml2/xpath.c
index 9fe75cb5ff4..283bb51178d 100644
--- a/contrib/xml2/xpath.c
+++ b/contrib/xml2/xpath.c
@@ -497,36 +497,49 @@ static xpath_workspace *
 pgxml_xpath(text *document, xmlChar *xpath, PgXmlErrorContext *xmlerrcxt)
 {
 	int32		docsize = VARSIZE_ANY_EXHDR(document);
-	xmlXPathCompExprPtr comppath;
+	xmlXPathCompExprPtr volatile comppath = NULL;
 	xpath_workspace *workspace = palloc0_object(xpath_workspace);
 
 	workspace->doctree = NULL;
 	workspace->ctxt = NULL;
 	workspace->res = NULL;
 
-	workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
-									   docsize, NULL, NULL,
-									   XML_PARSE_NOENT);
-	if (workspace->doctree != NULL)
+	PG_TRY();
 	{
-		workspace->ctxt = xmlXPathNewContext(workspace->doctree);
-		workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
-
-		/* compile the path */
-		comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
-		if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+		workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
+										   docsize, NULL, NULL,
+										   XML_PARSE_NOENT);
+		if (workspace->doctree != NULL)
 		{
-			if (comppath != NULL)
-				xmlXPathFreeCompExpr(comppath);
-			xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
-						"XPath Syntax Error");
-		}
+			workspace->ctxt = xmlXPathNewContext(workspace->doctree);
+			if (workspace->ctxt == NULL)
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_OUT_OF_MEMORY,
+							"could not allocate XPath context");
 
-		/* Now evaluate the path expression. */
-		workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+			workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
+
+			/* compile the path */
+			comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
+			if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
+							"XPath Syntax Error");
+
+			/* Now evaluate the path expression. */
+			workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+
+			xmlXPathFreeCompExpr(comppath);
+			comppath = NULL;
+		}
+	}
+	PG_CATCH();
+	{
+		if (comppath != NULL)
+			xmlXPathFreeCompExpr(comppath);
+		cleanup_workspace(workspace);
 
-		xmlXPathFreeCompExpr(comppath);
+		PG_RE_THROW();
 	}
+	PG_END_TRY();
 
 	return workspace;
 }
-- 
2.54.0


--MP_/LMSk9=uMhuQ1QiIJDarDO8G--





^ permalink  raw  reply  [nested|flat] 611+ messages in thread

* [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths
@ 2026-06-01 22:41 Andrey Chernyy <andrey.cherny@tantorlabs.com>
  0 siblings, 0 replies; 611+ messages in thread

From: Andrey Chernyy @ 2026-06-01 22:41 UTC (permalink / raw)

pgxml_xpath() builds an xpath_workspace before returning it to
callers.  If an ERROR is thrown before the function returns, callers
have not received the workspace pointer yet and cannot run
cleanup_workspace().

Add local error cleanup for the partially built workspace and the
compiled XPath expression.  Also check xmlXPathNewContext() before
dereferencing the returned context.
---
 contrib/xml2/xpath.c | 51 +++++++++++++++++++++++++++-----------------
 1 file changed, 32 insertions(+), 19 deletions(-)

diff --git a/contrib/xml2/xpath.c b/contrib/xml2/xpath.c
index 9fe75cb5ff4..283bb51178d 100644
--- a/contrib/xml2/xpath.c
+++ b/contrib/xml2/xpath.c
@@ -497,36 +497,49 @@ static xpath_workspace *
 pgxml_xpath(text *document, xmlChar *xpath, PgXmlErrorContext *xmlerrcxt)
 {
 	int32		docsize = VARSIZE_ANY_EXHDR(document);
-	xmlXPathCompExprPtr comppath;
+	xmlXPathCompExprPtr volatile comppath = NULL;
 	xpath_workspace *workspace = palloc0_object(xpath_workspace);
 
 	workspace->doctree = NULL;
 	workspace->ctxt = NULL;
 	workspace->res = NULL;
 
-	workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
-									   docsize, NULL, NULL,
-									   XML_PARSE_NOENT);
-	if (workspace->doctree != NULL)
+	PG_TRY();
 	{
-		workspace->ctxt = xmlXPathNewContext(workspace->doctree);
-		workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
-
-		/* compile the path */
-		comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
-		if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+		workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
+										   docsize, NULL, NULL,
+										   XML_PARSE_NOENT);
+		if (workspace->doctree != NULL)
 		{
-			if (comppath != NULL)
-				xmlXPathFreeCompExpr(comppath);
-			xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
-						"XPath Syntax Error");
-		}
+			workspace->ctxt = xmlXPathNewContext(workspace->doctree);
+			if (workspace->ctxt == NULL)
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_OUT_OF_MEMORY,
+							"could not allocate XPath context");
 
-		/* Now evaluate the path expression. */
-		workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+			workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
+
+			/* compile the path */
+			comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
+			if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
+							"XPath Syntax Error");
+
+			/* Now evaluate the path expression. */
+			workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+
+			xmlXPathFreeCompExpr(comppath);
+			comppath = NULL;
+		}
+	}
+	PG_CATCH();
+	{
+		if (comppath != NULL)
+			xmlXPathFreeCompExpr(comppath);
+		cleanup_workspace(workspace);
 
-		xmlXPathFreeCompExpr(comppath);
+		PG_RE_THROW();
 	}
+	PG_END_TRY();
 
 	return workspace;
 }
-- 
2.54.0


--MP_/LMSk9=uMhuQ1QiIJDarDO8G--






^ permalink  raw  reply  [nested|flat] 611+ messages in thread

* [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths
@ 2026-06-01 22:41 Andrey Chernyy <andrey.cherny@tantorlabs.com>
  0 siblings, 0 replies; 611+ messages in thread

From: Andrey Chernyy @ 2026-06-01 22:41 UTC (permalink / raw)

pgxml_xpath() builds an xpath_workspace before returning it to
callers.  If an ERROR is thrown before the function returns, callers
have not received the workspace pointer yet and cannot run
cleanup_workspace().

Add local error cleanup for the partially built workspace and the
compiled XPath expression.  Also check xmlXPathNewContext() before
dereferencing the returned context.
---
 contrib/xml2/xpath.c | 51 +++++++++++++++++++++++++++-----------------
 1 file changed, 32 insertions(+), 19 deletions(-)

diff --git a/contrib/xml2/xpath.c b/contrib/xml2/xpath.c
index 9fe75cb5ff4..283bb51178d 100644
--- a/contrib/xml2/xpath.c
+++ b/contrib/xml2/xpath.c
@@ -497,36 +497,49 @@ static xpath_workspace *
 pgxml_xpath(text *document, xmlChar *xpath, PgXmlErrorContext *xmlerrcxt)
 {
 	int32		docsize = VARSIZE_ANY_EXHDR(document);
-	xmlXPathCompExprPtr comppath;
+	xmlXPathCompExprPtr volatile comppath = NULL;
 	xpath_workspace *workspace = palloc0_object(xpath_workspace);
 
 	workspace->doctree = NULL;
 	workspace->ctxt = NULL;
 	workspace->res = NULL;
 
-	workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
-									   docsize, NULL, NULL,
-									   XML_PARSE_NOENT);
-	if (workspace->doctree != NULL)
+	PG_TRY();
 	{
-		workspace->ctxt = xmlXPathNewContext(workspace->doctree);
-		workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
-
-		/* compile the path */
-		comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
-		if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+		workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
+										   docsize, NULL, NULL,
+										   XML_PARSE_NOENT);
+		if (workspace->doctree != NULL)
 		{
-			if (comppath != NULL)
-				xmlXPathFreeCompExpr(comppath);
-			xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
-						"XPath Syntax Error");
-		}
+			workspace->ctxt = xmlXPathNewContext(workspace->doctree);
+			if (workspace->ctxt == NULL)
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_OUT_OF_MEMORY,
+							"could not allocate XPath context");
 
-		/* Now evaluate the path expression. */
-		workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+			workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
+
+			/* compile the path */
+			comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
+			if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
+							"XPath Syntax Error");
+
+			/* Now evaluate the path expression. */
+			workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+
+			xmlXPathFreeCompExpr(comppath);
+			comppath = NULL;
+		}
+	}
+	PG_CATCH();
+	{
+		if (comppath != NULL)
+			xmlXPathFreeCompExpr(comppath);
+		cleanup_workspace(workspace);
 
-		xmlXPathFreeCompExpr(comppath);
+		PG_RE_THROW();
 	}
+	PG_END_TRY();
 
 	return workspace;
 }
-- 
2.54.0


--MP_/LMSk9=uMhuQ1QiIJDarDO8G--





^ permalink  raw  reply  [nested|flat] 611+ messages in thread

* [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths
@ 2026-06-01 22:41 Andrey Chernyy <andrey.cherny@tantorlabs.com>
  0 siblings, 0 replies; 611+ messages in thread

From: Andrey Chernyy @ 2026-06-01 22:41 UTC (permalink / raw)

pgxml_xpath() builds an xpath_workspace before returning it to
callers.  If an ERROR is thrown before the function returns, callers
have not received the workspace pointer yet and cannot run
cleanup_workspace().

Add local error cleanup for the partially built workspace and the
compiled XPath expression.  Also check xmlXPathNewContext() before
dereferencing the returned context.
---
 contrib/xml2/xpath.c | 51 +++++++++++++++++++++++++++-----------------
 1 file changed, 32 insertions(+), 19 deletions(-)

diff --git a/contrib/xml2/xpath.c b/contrib/xml2/xpath.c
index 9fe75cb5ff4..283bb51178d 100644
--- a/contrib/xml2/xpath.c
+++ b/contrib/xml2/xpath.c
@@ -497,36 +497,49 @@ static xpath_workspace *
 pgxml_xpath(text *document, xmlChar *xpath, PgXmlErrorContext *xmlerrcxt)
 {
 	int32		docsize = VARSIZE_ANY_EXHDR(document);
-	xmlXPathCompExprPtr comppath;
+	xmlXPathCompExprPtr volatile comppath = NULL;
 	xpath_workspace *workspace = palloc0_object(xpath_workspace);
 
 	workspace->doctree = NULL;
 	workspace->ctxt = NULL;
 	workspace->res = NULL;
 
-	workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
-									   docsize, NULL, NULL,
-									   XML_PARSE_NOENT);
-	if (workspace->doctree != NULL)
+	PG_TRY();
 	{
-		workspace->ctxt = xmlXPathNewContext(workspace->doctree);
-		workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
-
-		/* compile the path */
-		comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
-		if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+		workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
+										   docsize, NULL, NULL,
+										   XML_PARSE_NOENT);
+		if (workspace->doctree != NULL)
 		{
-			if (comppath != NULL)
-				xmlXPathFreeCompExpr(comppath);
-			xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
-						"XPath Syntax Error");
-		}
+			workspace->ctxt = xmlXPathNewContext(workspace->doctree);
+			if (workspace->ctxt == NULL)
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_OUT_OF_MEMORY,
+							"could not allocate XPath context");
 
-		/* Now evaluate the path expression. */
-		workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+			workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
+
+			/* compile the path */
+			comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
+			if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
+							"XPath Syntax Error");
+
+			/* Now evaluate the path expression. */
+			workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+
+			xmlXPathFreeCompExpr(comppath);
+			comppath = NULL;
+		}
+	}
+	PG_CATCH();
+	{
+		if (comppath != NULL)
+			xmlXPathFreeCompExpr(comppath);
+		cleanup_workspace(workspace);
 
-		xmlXPathFreeCompExpr(comppath);
+		PG_RE_THROW();
 	}
+	PG_END_TRY();
 
 	return workspace;
 }
-- 
2.54.0


--MP_/LMSk9=uMhuQ1QiIJDarDO8G--






^ permalink  raw  reply  [nested|flat] 611+ messages in thread

* [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths
@ 2026-06-01 22:41 Andrey Chernyy <andrey.cherny@tantorlabs.com>
  0 siblings, 0 replies; 611+ messages in thread

From: Andrey Chernyy @ 2026-06-01 22:41 UTC (permalink / raw)

pgxml_xpath() builds an xpath_workspace before returning it to
callers.  If an ERROR is thrown before the function returns, callers
have not received the workspace pointer yet and cannot run
cleanup_workspace().

Add local error cleanup for the partially built workspace and the
compiled XPath expression.  Also check xmlXPathNewContext() before
dereferencing the returned context.
---
 contrib/xml2/xpath.c | 51 +++++++++++++++++++++++++++-----------------
 1 file changed, 32 insertions(+), 19 deletions(-)

diff --git a/contrib/xml2/xpath.c b/contrib/xml2/xpath.c
index 9fe75cb5ff4..283bb51178d 100644
--- a/contrib/xml2/xpath.c
+++ b/contrib/xml2/xpath.c
@@ -497,36 +497,49 @@ static xpath_workspace *
 pgxml_xpath(text *document, xmlChar *xpath, PgXmlErrorContext *xmlerrcxt)
 {
 	int32		docsize = VARSIZE_ANY_EXHDR(document);
-	xmlXPathCompExprPtr comppath;
+	xmlXPathCompExprPtr volatile comppath = NULL;
 	xpath_workspace *workspace = palloc0_object(xpath_workspace);
 
 	workspace->doctree = NULL;
 	workspace->ctxt = NULL;
 	workspace->res = NULL;
 
-	workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
-									   docsize, NULL, NULL,
-									   XML_PARSE_NOENT);
-	if (workspace->doctree != NULL)
+	PG_TRY();
 	{
-		workspace->ctxt = xmlXPathNewContext(workspace->doctree);
-		workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
-
-		/* compile the path */
-		comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
-		if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+		workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
+										   docsize, NULL, NULL,
+										   XML_PARSE_NOENT);
+		if (workspace->doctree != NULL)
 		{
-			if (comppath != NULL)
-				xmlXPathFreeCompExpr(comppath);
-			xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
-						"XPath Syntax Error");
-		}
+			workspace->ctxt = xmlXPathNewContext(workspace->doctree);
+			if (workspace->ctxt == NULL)
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_OUT_OF_MEMORY,
+							"could not allocate XPath context");
 
-		/* Now evaluate the path expression. */
-		workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+			workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
+
+			/* compile the path */
+			comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
+			if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
+							"XPath Syntax Error");
+
+			/* Now evaluate the path expression. */
+			workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+
+			xmlXPathFreeCompExpr(comppath);
+			comppath = NULL;
+		}
+	}
+	PG_CATCH();
+	{
+		if (comppath != NULL)
+			xmlXPathFreeCompExpr(comppath);
+		cleanup_workspace(workspace);
 
-		xmlXPathFreeCompExpr(comppath);
+		PG_RE_THROW();
 	}
+	PG_END_TRY();
 
 	return workspace;
 }
-- 
2.54.0


--MP_/LMSk9=uMhuQ1QiIJDarDO8G--






^ permalink  raw  reply  [nested|flat] 611+ messages in thread

* [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths
@ 2026-06-01 22:41 Andrey Chernyy <andrey.cherny@tantorlabs.com>
  0 siblings, 0 replies; 611+ messages in thread

From: Andrey Chernyy @ 2026-06-01 22:41 UTC (permalink / raw)

pgxml_xpath() builds an xpath_workspace before returning it to
callers.  If an ERROR is thrown before the function returns, callers
have not received the workspace pointer yet and cannot run
cleanup_workspace().

Add local error cleanup for the partially built workspace and the
compiled XPath expression.  Also check xmlXPathNewContext() before
dereferencing the returned context.
---
 contrib/xml2/xpath.c | 51 +++++++++++++++++++++++++++-----------------
 1 file changed, 32 insertions(+), 19 deletions(-)

diff --git a/contrib/xml2/xpath.c b/contrib/xml2/xpath.c
index 9fe75cb5ff4..283bb51178d 100644
--- a/contrib/xml2/xpath.c
+++ b/contrib/xml2/xpath.c
@@ -497,36 +497,49 @@ static xpath_workspace *
 pgxml_xpath(text *document, xmlChar *xpath, PgXmlErrorContext *xmlerrcxt)
 {
 	int32		docsize = VARSIZE_ANY_EXHDR(document);
-	xmlXPathCompExprPtr comppath;
+	xmlXPathCompExprPtr volatile comppath = NULL;
 	xpath_workspace *workspace = palloc0_object(xpath_workspace);
 
 	workspace->doctree = NULL;
 	workspace->ctxt = NULL;
 	workspace->res = NULL;
 
-	workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
-									   docsize, NULL, NULL,
-									   XML_PARSE_NOENT);
-	if (workspace->doctree != NULL)
+	PG_TRY();
 	{
-		workspace->ctxt = xmlXPathNewContext(workspace->doctree);
-		workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
-
-		/* compile the path */
-		comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
-		if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+		workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
+										   docsize, NULL, NULL,
+										   XML_PARSE_NOENT);
+		if (workspace->doctree != NULL)
 		{
-			if (comppath != NULL)
-				xmlXPathFreeCompExpr(comppath);
-			xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
-						"XPath Syntax Error");
-		}
+			workspace->ctxt = xmlXPathNewContext(workspace->doctree);
+			if (workspace->ctxt == NULL)
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_OUT_OF_MEMORY,
+							"could not allocate XPath context");
 
-		/* Now evaluate the path expression. */
-		workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+			workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
+
+			/* compile the path */
+			comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
+			if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
+							"XPath Syntax Error");
+
+			/* Now evaluate the path expression. */
+			workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+
+			xmlXPathFreeCompExpr(comppath);
+			comppath = NULL;
+		}
+	}
+	PG_CATCH();
+	{
+		if (comppath != NULL)
+			xmlXPathFreeCompExpr(comppath);
+		cleanup_workspace(workspace);
 
-		xmlXPathFreeCompExpr(comppath);
+		PG_RE_THROW();
 	}
+	PG_END_TRY();
 
 	return workspace;
 }
-- 
2.54.0


--MP_/LMSk9=uMhuQ1QiIJDarDO8G--





^ permalink  raw  reply  [nested|flat] 611+ messages in thread

* [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths
@ 2026-06-01 22:41 Andrey Chernyy <andrey.cherny@tantorlabs.com>
  0 siblings, 0 replies; 611+ messages in thread

From: Andrey Chernyy @ 2026-06-01 22:41 UTC (permalink / raw)

pgxml_xpath() builds an xpath_workspace before returning it to
callers.  If an ERROR is thrown before the function returns, callers
have not received the workspace pointer yet and cannot run
cleanup_workspace().

Add local error cleanup for the partially built workspace and the
compiled XPath expression.  Also check xmlXPathNewContext() before
dereferencing the returned context.
---
 contrib/xml2/xpath.c | 51 +++++++++++++++++++++++++++-----------------
 1 file changed, 32 insertions(+), 19 deletions(-)

diff --git a/contrib/xml2/xpath.c b/contrib/xml2/xpath.c
index 9fe75cb5ff4..283bb51178d 100644
--- a/contrib/xml2/xpath.c
+++ b/contrib/xml2/xpath.c
@@ -497,36 +497,49 @@ static xpath_workspace *
 pgxml_xpath(text *document, xmlChar *xpath, PgXmlErrorContext *xmlerrcxt)
 {
 	int32		docsize = VARSIZE_ANY_EXHDR(document);
-	xmlXPathCompExprPtr comppath;
+	xmlXPathCompExprPtr volatile comppath = NULL;
 	xpath_workspace *workspace = palloc0_object(xpath_workspace);
 
 	workspace->doctree = NULL;
 	workspace->ctxt = NULL;
 	workspace->res = NULL;
 
-	workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
-									   docsize, NULL, NULL,
-									   XML_PARSE_NOENT);
-	if (workspace->doctree != NULL)
+	PG_TRY();
 	{
-		workspace->ctxt = xmlXPathNewContext(workspace->doctree);
-		workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
-
-		/* compile the path */
-		comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
-		if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+		workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
+										   docsize, NULL, NULL,
+										   XML_PARSE_NOENT);
+		if (workspace->doctree != NULL)
 		{
-			if (comppath != NULL)
-				xmlXPathFreeCompExpr(comppath);
-			xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
-						"XPath Syntax Error");
-		}
+			workspace->ctxt = xmlXPathNewContext(workspace->doctree);
+			if (workspace->ctxt == NULL)
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_OUT_OF_MEMORY,
+							"could not allocate XPath context");
 
-		/* Now evaluate the path expression. */
-		workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+			workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
+
+			/* compile the path */
+			comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
+			if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
+							"XPath Syntax Error");
+
+			/* Now evaluate the path expression. */
+			workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+
+			xmlXPathFreeCompExpr(comppath);
+			comppath = NULL;
+		}
+	}
+	PG_CATCH();
+	{
+		if (comppath != NULL)
+			xmlXPathFreeCompExpr(comppath);
+		cleanup_workspace(workspace);
 
-		xmlXPathFreeCompExpr(comppath);
+		PG_RE_THROW();
 	}
+	PG_END_TRY();
 
 	return workspace;
 }
-- 
2.54.0


--MP_/LMSk9=uMhuQ1QiIJDarDO8G--






^ permalink  raw  reply  [nested|flat] 611+ messages in thread

* [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths
@ 2026-06-01 22:41 Andrey Chernyy <andrey.cherny@tantorlabs.com>
  0 siblings, 0 replies; 611+ messages in thread

From: Andrey Chernyy @ 2026-06-01 22:41 UTC (permalink / raw)

pgxml_xpath() builds an xpath_workspace before returning it to
callers.  If an ERROR is thrown before the function returns, callers
have not received the workspace pointer yet and cannot run
cleanup_workspace().

Add local error cleanup for the partially built workspace and the
compiled XPath expression.  Also check xmlXPathNewContext() before
dereferencing the returned context.
---
 contrib/xml2/xpath.c | 51 +++++++++++++++++++++++++++-----------------
 1 file changed, 32 insertions(+), 19 deletions(-)

diff --git a/contrib/xml2/xpath.c b/contrib/xml2/xpath.c
index 9fe75cb5ff4..283bb51178d 100644
--- a/contrib/xml2/xpath.c
+++ b/contrib/xml2/xpath.c
@@ -497,36 +497,49 @@ static xpath_workspace *
 pgxml_xpath(text *document, xmlChar *xpath, PgXmlErrorContext *xmlerrcxt)
 {
 	int32		docsize = VARSIZE_ANY_EXHDR(document);
-	xmlXPathCompExprPtr comppath;
+	xmlXPathCompExprPtr volatile comppath = NULL;
 	xpath_workspace *workspace = palloc0_object(xpath_workspace);
 
 	workspace->doctree = NULL;
 	workspace->ctxt = NULL;
 	workspace->res = NULL;
 
-	workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
-									   docsize, NULL, NULL,
-									   XML_PARSE_NOENT);
-	if (workspace->doctree != NULL)
+	PG_TRY();
 	{
-		workspace->ctxt = xmlXPathNewContext(workspace->doctree);
-		workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
-
-		/* compile the path */
-		comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
-		if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+		workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
+										   docsize, NULL, NULL,
+										   XML_PARSE_NOENT);
+		if (workspace->doctree != NULL)
 		{
-			if (comppath != NULL)
-				xmlXPathFreeCompExpr(comppath);
-			xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
-						"XPath Syntax Error");
-		}
+			workspace->ctxt = xmlXPathNewContext(workspace->doctree);
+			if (workspace->ctxt == NULL)
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_OUT_OF_MEMORY,
+							"could not allocate XPath context");
 
-		/* Now evaluate the path expression. */
-		workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+			workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
+
+			/* compile the path */
+			comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
+			if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
+							"XPath Syntax Error");
+
+			/* Now evaluate the path expression. */
+			workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+
+			xmlXPathFreeCompExpr(comppath);
+			comppath = NULL;
+		}
+	}
+	PG_CATCH();
+	{
+		if (comppath != NULL)
+			xmlXPathFreeCompExpr(comppath);
+		cleanup_workspace(workspace);
 
-		xmlXPathFreeCompExpr(comppath);
+		PG_RE_THROW();
 	}
+	PG_END_TRY();
 
 	return workspace;
 }
-- 
2.54.0


--MP_/LMSk9=uMhuQ1QiIJDarDO8G--






^ permalink  raw  reply  [nested|flat] 611+ messages in thread

* [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths
@ 2026-06-01 22:41 Andrey Chernyy <andrey.cherny@tantorlabs.com>
  0 siblings, 0 replies; 611+ messages in thread

From: Andrey Chernyy @ 2026-06-01 22:41 UTC (permalink / raw)

pgxml_xpath() builds an xpath_workspace before returning it to
callers.  If an ERROR is thrown before the function returns, callers
have not received the workspace pointer yet and cannot run
cleanup_workspace().

Add local error cleanup for the partially built workspace and the
compiled XPath expression.  Also check xmlXPathNewContext() before
dereferencing the returned context.
---
 contrib/xml2/xpath.c | 51 +++++++++++++++++++++++++++-----------------
 1 file changed, 32 insertions(+), 19 deletions(-)

diff --git a/contrib/xml2/xpath.c b/contrib/xml2/xpath.c
index 9fe75cb5ff4..283bb51178d 100644
--- a/contrib/xml2/xpath.c
+++ b/contrib/xml2/xpath.c
@@ -497,36 +497,49 @@ static xpath_workspace *
 pgxml_xpath(text *document, xmlChar *xpath, PgXmlErrorContext *xmlerrcxt)
 {
 	int32		docsize = VARSIZE_ANY_EXHDR(document);
-	xmlXPathCompExprPtr comppath;
+	xmlXPathCompExprPtr volatile comppath = NULL;
 	xpath_workspace *workspace = palloc0_object(xpath_workspace);
 
 	workspace->doctree = NULL;
 	workspace->ctxt = NULL;
 	workspace->res = NULL;
 
-	workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
-									   docsize, NULL, NULL,
-									   XML_PARSE_NOENT);
-	if (workspace->doctree != NULL)
+	PG_TRY();
 	{
-		workspace->ctxt = xmlXPathNewContext(workspace->doctree);
-		workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
-
-		/* compile the path */
-		comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
-		if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+		workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
+										   docsize, NULL, NULL,
+										   XML_PARSE_NOENT);
+		if (workspace->doctree != NULL)
 		{
-			if (comppath != NULL)
-				xmlXPathFreeCompExpr(comppath);
-			xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
-						"XPath Syntax Error");
-		}
+			workspace->ctxt = xmlXPathNewContext(workspace->doctree);
+			if (workspace->ctxt == NULL)
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_OUT_OF_MEMORY,
+							"could not allocate XPath context");
 
-		/* Now evaluate the path expression. */
-		workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+			workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
+
+			/* compile the path */
+			comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
+			if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
+							"XPath Syntax Error");
+
+			/* Now evaluate the path expression. */
+			workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+
+			xmlXPathFreeCompExpr(comppath);
+			comppath = NULL;
+		}
+	}
+	PG_CATCH();
+	{
+		if (comppath != NULL)
+			xmlXPathFreeCompExpr(comppath);
+		cleanup_workspace(workspace);
 
-		xmlXPathFreeCompExpr(comppath);
+		PG_RE_THROW();
 	}
+	PG_END_TRY();
 
 	return workspace;
 }
-- 
2.54.0


--MP_/LMSk9=uMhuQ1QiIJDarDO8G--






^ permalink  raw  reply  [nested|flat] 611+ messages in thread

* [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths
@ 2026-06-01 22:41 Andrey Chernyy <andrey.cherny@tantorlabs.com>
  0 siblings, 0 replies; 611+ messages in thread

From: Andrey Chernyy @ 2026-06-01 22:41 UTC (permalink / raw)

pgxml_xpath() builds an xpath_workspace before returning it to
callers.  If an ERROR is thrown before the function returns, callers
have not received the workspace pointer yet and cannot run
cleanup_workspace().

Add local error cleanup for the partially built workspace and the
compiled XPath expression.  Also check xmlXPathNewContext() before
dereferencing the returned context.
---
 contrib/xml2/xpath.c | 51 +++++++++++++++++++++++++++-----------------
 1 file changed, 32 insertions(+), 19 deletions(-)

diff --git a/contrib/xml2/xpath.c b/contrib/xml2/xpath.c
index 9fe75cb5ff4..283bb51178d 100644
--- a/contrib/xml2/xpath.c
+++ b/contrib/xml2/xpath.c
@@ -497,36 +497,49 @@ static xpath_workspace *
 pgxml_xpath(text *document, xmlChar *xpath, PgXmlErrorContext *xmlerrcxt)
 {
 	int32		docsize = VARSIZE_ANY_EXHDR(document);
-	xmlXPathCompExprPtr comppath;
+	xmlXPathCompExprPtr volatile comppath = NULL;
 	xpath_workspace *workspace = palloc0_object(xpath_workspace);
 
 	workspace->doctree = NULL;
 	workspace->ctxt = NULL;
 	workspace->res = NULL;
 
-	workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
-									   docsize, NULL, NULL,
-									   XML_PARSE_NOENT);
-	if (workspace->doctree != NULL)
+	PG_TRY();
 	{
-		workspace->ctxt = xmlXPathNewContext(workspace->doctree);
-		workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
-
-		/* compile the path */
-		comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
-		if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+		workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
+										   docsize, NULL, NULL,
+										   XML_PARSE_NOENT);
+		if (workspace->doctree != NULL)
 		{
-			if (comppath != NULL)
-				xmlXPathFreeCompExpr(comppath);
-			xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
-						"XPath Syntax Error");
-		}
+			workspace->ctxt = xmlXPathNewContext(workspace->doctree);
+			if (workspace->ctxt == NULL)
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_OUT_OF_MEMORY,
+							"could not allocate XPath context");
 
-		/* Now evaluate the path expression. */
-		workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+			workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
+
+			/* compile the path */
+			comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
+			if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
+							"XPath Syntax Error");
+
+			/* Now evaluate the path expression. */
+			workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+
+			xmlXPathFreeCompExpr(comppath);
+			comppath = NULL;
+		}
+	}
+	PG_CATCH();
+	{
+		if (comppath != NULL)
+			xmlXPathFreeCompExpr(comppath);
+		cleanup_workspace(workspace);
 
-		xmlXPathFreeCompExpr(comppath);
+		PG_RE_THROW();
 	}
+	PG_END_TRY();
 
 	return workspace;
 }
-- 
2.54.0


--MP_/LMSk9=uMhuQ1QiIJDarDO8G--





^ permalink  raw  reply  [nested|flat] 611+ messages in thread

* [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths
@ 2026-06-01 22:41 Andrey Chernyy <andrey.cherny@tantorlabs.com>
  0 siblings, 0 replies; 611+ messages in thread

From: Andrey Chernyy @ 2026-06-01 22:41 UTC (permalink / raw)

pgxml_xpath() builds an xpath_workspace before returning it to
callers.  If an ERROR is thrown before the function returns, callers
have not received the workspace pointer yet and cannot run
cleanup_workspace().

Add local error cleanup for the partially built workspace and the
compiled XPath expression.  Also check xmlXPathNewContext() before
dereferencing the returned context.
---
 contrib/xml2/xpath.c | 51 +++++++++++++++++++++++++++-----------------
 1 file changed, 32 insertions(+), 19 deletions(-)

diff --git a/contrib/xml2/xpath.c b/contrib/xml2/xpath.c
index 9fe75cb5ff4..283bb51178d 100644
--- a/contrib/xml2/xpath.c
+++ b/contrib/xml2/xpath.c
@@ -497,36 +497,49 @@ static xpath_workspace *
 pgxml_xpath(text *document, xmlChar *xpath, PgXmlErrorContext *xmlerrcxt)
 {
 	int32		docsize = VARSIZE_ANY_EXHDR(document);
-	xmlXPathCompExprPtr comppath;
+	xmlXPathCompExprPtr volatile comppath = NULL;
 	xpath_workspace *workspace = palloc0_object(xpath_workspace);
 
 	workspace->doctree = NULL;
 	workspace->ctxt = NULL;
 	workspace->res = NULL;
 
-	workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
-									   docsize, NULL, NULL,
-									   XML_PARSE_NOENT);
-	if (workspace->doctree != NULL)
+	PG_TRY();
 	{
-		workspace->ctxt = xmlXPathNewContext(workspace->doctree);
-		workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
-
-		/* compile the path */
-		comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
-		if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+		workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
+										   docsize, NULL, NULL,
+										   XML_PARSE_NOENT);
+		if (workspace->doctree != NULL)
 		{
-			if (comppath != NULL)
-				xmlXPathFreeCompExpr(comppath);
-			xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
-						"XPath Syntax Error");
-		}
+			workspace->ctxt = xmlXPathNewContext(workspace->doctree);
+			if (workspace->ctxt == NULL)
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_OUT_OF_MEMORY,
+							"could not allocate XPath context");
 
-		/* Now evaluate the path expression. */
-		workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+			workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
+
+			/* compile the path */
+			comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
+			if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
+							"XPath Syntax Error");
+
+			/* Now evaluate the path expression. */
+			workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+
+			xmlXPathFreeCompExpr(comppath);
+			comppath = NULL;
+		}
+	}
+	PG_CATCH();
+	{
+		if (comppath != NULL)
+			xmlXPathFreeCompExpr(comppath);
+		cleanup_workspace(workspace);
 
-		xmlXPathFreeCompExpr(comppath);
+		PG_RE_THROW();
 	}
+	PG_END_TRY();
 
 	return workspace;
 }
-- 
2.54.0


--MP_/LMSk9=uMhuQ1QiIJDarDO8G--






^ permalink  raw  reply  [nested|flat] 611+ messages in thread

* [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths
@ 2026-06-01 22:41 Andrey Chernyy <andrey.cherny@tantorlabs.com>
  0 siblings, 0 replies; 611+ messages in thread

From: Andrey Chernyy @ 2026-06-01 22:41 UTC (permalink / raw)

pgxml_xpath() builds an xpath_workspace before returning it to
callers.  If an ERROR is thrown before the function returns, callers
have not received the workspace pointer yet and cannot run
cleanup_workspace().

Add local error cleanup for the partially built workspace and the
compiled XPath expression.  Also check xmlXPathNewContext() before
dereferencing the returned context.
---
 contrib/xml2/xpath.c | 51 +++++++++++++++++++++++++++-----------------
 1 file changed, 32 insertions(+), 19 deletions(-)

diff --git a/contrib/xml2/xpath.c b/contrib/xml2/xpath.c
index 9fe75cb5ff4..283bb51178d 100644
--- a/contrib/xml2/xpath.c
+++ b/contrib/xml2/xpath.c
@@ -497,36 +497,49 @@ static xpath_workspace *
 pgxml_xpath(text *document, xmlChar *xpath, PgXmlErrorContext *xmlerrcxt)
 {
 	int32		docsize = VARSIZE_ANY_EXHDR(document);
-	xmlXPathCompExprPtr comppath;
+	xmlXPathCompExprPtr volatile comppath = NULL;
 	xpath_workspace *workspace = palloc0_object(xpath_workspace);
 
 	workspace->doctree = NULL;
 	workspace->ctxt = NULL;
 	workspace->res = NULL;
 
-	workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
-									   docsize, NULL, NULL,
-									   XML_PARSE_NOENT);
-	if (workspace->doctree != NULL)
+	PG_TRY();
 	{
-		workspace->ctxt = xmlXPathNewContext(workspace->doctree);
-		workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
-
-		/* compile the path */
-		comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
-		if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+		workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
+										   docsize, NULL, NULL,
+										   XML_PARSE_NOENT);
+		if (workspace->doctree != NULL)
 		{
-			if (comppath != NULL)
-				xmlXPathFreeCompExpr(comppath);
-			xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
-						"XPath Syntax Error");
-		}
+			workspace->ctxt = xmlXPathNewContext(workspace->doctree);
+			if (workspace->ctxt == NULL)
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_OUT_OF_MEMORY,
+							"could not allocate XPath context");
 
-		/* Now evaluate the path expression. */
-		workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+			workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
+
+			/* compile the path */
+			comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
+			if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
+							"XPath Syntax Error");
+
+			/* Now evaluate the path expression. */
+			workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+
+			xmlXPathFreeCompExpr(comppath);
+			comppath = NULL;
+		}
+	}
+	PG_CATCH();
+	{
+		if (comppath != NULL)
+			xmlXPathFreeCompExpr(comppath);
+		cleanup_workspace(workspace);
 
-		xmlXPathFreeCompExpr(comppath);
+		PG_RE_THROW();
 	}
+	PG_END_TRY();
 
 	return workspace;
 }
-- 
2.54.0


--MP_/LMSk9=uMhuQ1QiIJDarDO8G--





^ permalink  raw  reply  [nested|flat] 611+ messages in thread

* [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths
@ 2026-06-01 22:41 Andrey Chernyy <andrey.cherny@tantorlabs.com>
  0 siblings, 0 replies; 611+ messages in thread

From: Andrey Chernyy @ 2026-06-01 22:41 UTC (permalink / raw)

pgxml_xpath() builds an xpath_workspace before returning it to
callers.  If an ERROR is thrown before the function returns, callers
have not received the workspace pointer yet and cannot run
cleanup_workspace().

Add local error cleanup for the partially built workspace and the
compiled XPath expression.  Also check xmlXPathNewContext() before
dereferencing the returned context.
---
 contrib/xml2/xpath.c | 51 +++++++++++++++++++++++++++-----------------
 1 file changed, 32 insertions(+), 19 deletions(-)

diff --git a/contrib/xml2/xpath.c b/contrib/xml2/xpath.c
index 9fe75cb5ff4..283bb51178d 100644
--- a/contrib/xml2/xpath.c
+++ b/contrib/xml2/xpath.c
@@ -497,36 +497,49 @@ static xpath_workspace *
 pgxml_xpath(text *document, xmlChar *xpath, PgXmlErrorContext *xmlerrcxt)
 {
 	int32		docsize = VARSIZE_ANY_EXHDR(document);
-	xmlXPathCompExprPtr comppath;
+	xmlXPathCompExprPtr volatile comppath = NULL;
 	xpath_workspace *workspace = palloc0_object(xpath_workspace);
 
 	workspace->doctree = NULL;
 	workspace->ctxt = NULL;
 	workspace->res = NULL;
 
-	workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
-									   docsize, NULL, NULL,
-									   XML_PARSE_NOENT);
-	if (workspace->doctree != NULL)
+	PG_TRY();
 	{
-		workspace->ctxt = xmlXPathNewContext(workspace->doctree);
-		workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
-
-		/* compile the path */
-		comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
-		if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+		workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
+										   docsize, NULL, NULL,
+										   XML_PARSE_NOENT);
+		if (workspace->doctree != NULL)
 		{
-			if (comppath != NULL)
-				xmlXPathFreeCompExpr(comppath);
-			xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
-						"XPath Syntax Error");
-		}
+			workspace->ctxt = xmlXPathNewContext(workspace->doctree);
+			if (workspace->ctxt == NULL)
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_OUT_OF_MEMORY,
+							"could not allocate XPath context");
 
-		/* Now evaluate the path expression. */
-		workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+			workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
+
+			/* compile the path */
+			comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
+			if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
+							"XPath Syntax Error");
+
+			/* Now evaluate the path expression. */
+			workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+
+			xmlXPathFreeCompExpr(comppath);
+			comppath = NULL;
+		}
+	}
+	PG_CATCH();
+	{
+		if (comppath != NULL)
+			xmlXPathFreeCompExpr(comppath);
+		cleanup_workspace(workspace);
 
-		xmlXPathFreeCompExpr(comppath);
+		PG_RE_THROW();
 	}
+	PG_END_TRY();
 
 	return workspace;
 }
-- 
2.54.0


--MP_/LMSk9=uMhuQ1QiIJDarDO8G--






^ permalink  raw  reply  [nested|flat] 611+ messages in thread

* [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths
@ 2026-06-01 22:41 Andrey Chernyy <andrey.cherny@tantorlabs.com>
  0 siblings, 0 replies; 611+ messages in thread

From: Andrey Chernyy @ 2026-06-01 22:41 UTC (permalink / raw)

pgxml_xpath() builds an xpath_workspace before returning it to
callers.  If an ERROR is thrown before the function returns, callers
have not received the workspace pointer yet and cannot run
cleanup_workspace().

Add local error cleanup for the partially built workspace and the
compiled XPath expression.  Also check xmlXPathNewContext() before
dereferencing the returned context.
---
 contrib/xml2/xpath.c | 51 +++++++++++++++++++++++++++-----------------
 1 file changed, 32 insertions(+), 19 deletions(-)

diff --git a/contrib/xml2/xpath.c b/contrib/xml2/xpath.c
index 9fe75cb5ff4..283bb51178d 100644
--- a/contrib/xml2/xpath.c
+++ b/contrib/xml2/xpath.c
@@ -497,36 +497,49 @@ static xpath_workspace *
 pgxml_xpath(text *document, xmlChar *xpath, PgXmlErrorContext *xmlerrcxt)
 {
 	int32		docsize = VARSIZE_ANY_EXHDR(document);
-	xmlXPathCompExprPtr comppath;
+	xmlXPathCompExprPtr volatile comppath = NULL;
 	xpath_workspace *workspace = palloc0_object(xpath_workspace);
 
 	workspace->doctree = NULL;
 	workspace->ctxt = NULL;
 	workspace->res = NULL;
 
-	workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
-									   docsize, NULL, NULL,
-									   XML_PARSE_NOENT);
-	if (workspace->doctree != NULL)
+	PG_TRY();
 	{
-		workspace->ctxt = xmlXPathNewContext(workspace->doctree);
-		workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
-
-		/* compile the path */
-		comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
-		if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+		workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
+										   docsize, NULL, NULL,
+										   XML_PARSE_NOENT);
+		if (workspace->doctree != NULL)
 		{
-			if (comppath != NULL)
-				xmlXPathFreeCompExpr(comppath);
-			xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
-						"XPath Syntax Error");
-		}
+			workspace->ctxt = xmlXPathNewContext(workspace->doctree);
+			if (workspace->ctxt == NULL)
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_OUT_OF_MEMORY,
+							"could not allocate XPath context");
 
-		/* Now evaluate the path expression. */
-		workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+			workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
+
+			/* compile the path */
+			comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
+			if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
+							"XPath Syntax Error");
+
+			/* Now evaluate the path expression. */
+			workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+
+			xmlXPathFreeCompExpr(comppath);
+			comppath = NULL;
+		}
+	}
+	PG_CATCH();
+	{
+		if (comppath != NULL)
+			xmlXPathFreeCompExpr(comppath);
+		cleanup_workspace(workspace);
 
-		xmlXPathFreeCompExpr(comppath);
+		PG_RE_THROW();
 	}
+	PG_END_TRY();
 
 	return workspace;
 }
-- 
2.54.0


--MP_/LMSk9=uMhuQ1QiIJDarDO8G--






^ permalink  raw  reply  [nested|flat] 611+ messages in thread

* [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths
@ 2026-06-01 22:41 Andrey Chernyy <andrey.cherny@tantorlabs.com>
  0 siblings, 0 replies; 611+ messages in thread

From: Andrey Chernyy @ 2026-06-01 22:41 UTC (permalink / raw)

pgxml_xpath() builds an xpath_workspace before returning it to
callers.  If an ERROR is thrown before the function returns, callers
have not received the workspace pointer yet and cannot run
cleanup_workspace().

Add local error cleanup for the partially built workspace and the
compiled XPath expression.  Also check xmlXPathNewContext() before
dereferencing the returned context.
---
 contrib/xml2/xpath.c | 51 +++++++++++++++++++++++++++-----------------
 1 file changed, 32 insertions(+), 19 deletions(-)

diff --git a/contrib/xml2/xpath.c b/contrib/xml2/xpath.c
index 9fe75cb5ff4..283bb51178d 100644
--- a/contrib/xml2/xpath.c
+++ b/contrib/xml2/xpath.c
@@ -497,36 +497,49 @@ static xpath_workspace *
 pgxml_xpath(text *document, xmlChar *xpath, PgXmlErrorContext *xmlerrcxt)
 {
 	int32		docsize = VARSIZE_ANY_EXHDR(document);
-	xmlXPathCompExprPtr comppath;
+	xmlXPathCompExprPtr volatile comppath = NULL;
 	xpath_workspace *workspace = palloc0_object(xpath_workspace);
 
 	workspace->doctree = NULL;
 	workspace->ctxt = NULL;
 	workspace->res = NULL;
 
-	workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
-									   docsize, NULL, NULL,
-									   XML_PARSE_NOENT);
-	if (workspace->doctree != NULL)
+	PG_TRY();
 	{
-		workspace->ctxt = xmlXPathNewContext(workspace->doctree);
-		workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
-
-		/* compile the path */
-		comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
-		if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+		workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
+										   docsize, NULL, NULL,
+										   XML_PARSE_NOENT);
+		if (workspace->doctree != NULL)
 		{
-			if (comppath != NULL)
-				xmlXPathFreeCompExpr(comppath);
-			xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
-						"XPath Syntax Error");
-		}
+			workspace->ctxt = xmlXPathNewContext(workspace->doctree);
+			if (workspace->ctxt == NULL)
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_OUT_OF_MEMORY,
+							"could not allocate XPath context");
 
-		/* Now evaluate the path expression. */
-		workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+			workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
+
+			/* compile the path */
+			comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
+			if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
+							"XPath Syntax Error");
+
+			/* Now evaluate the path expression. */
+			workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+
+			xmlXPathFreeCompExpr(comppath);
+			comppath = NULL;
+		}
+	}
+	PG_CATCH();
+	{
+		if (comppath != NULL)
+			xmlXPathFreeCompExpr(comppath);
+		cleanup_workspace(workspace);
 
-		xmlXPathFreeCompExpr(comppath);
+		PG_RE_THROW();
 	}
+	PG_END_TRY();
 
 	return workspace;
 }
-- 
2.54.0


--MP_/LMSk9=uMhuQ1QiIJDarDO8G--






^ permalink  raw  reply  [nested|flat] 611+ messages in thread

* [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths
@ 2026-06-01 22:41 Andrey Chernyy <andrey.cherny@tantorlabs.com>
  0 siblings, 0 replies; 611+ messages in thread

From: Andrey Chernyy @ 2026-06-01 22:41 UTC (permalink / raw)

pgxml_xpath() builds an xpath_workspace before returning it to
callers.  If an ERROR is thrown before the function returns, callers
have not received the workspace pointer yet and cannot run
cleanup_workspace().

Add local error cleanup for the partially built workspace and the
compiled XPath expression.  Also check xmlXPathNewContext() before
dereferencing the returned context.
---
 contrib/xml2/xpath.c | 51 +++++++++++++++++++++++++++-----------------
 1 file changed, 32 insertions(+), 19 deletions(-)

diff --git a/contrib/xml2/xpath.c b/contrib/xml2/xpath.c
index 9fe75cb5ff4..283bb51178d 100644
--- a/contrib/xml2/xpath.c
+++ b/contrib/xml2/xpath.c
@@ -497,36 +497,49 @@ static xpath_workspace *
 pgxml_xpath(text *document, xmlChar *xpath, PgXmlErrorContext *xmlerrcxt)
 {
 	int32		docsize = VARSIZE_ANY_EXHDR(document);
-	xmlXPathCompExprPtr comppath;
+	xmlXPathCompExprPtr volatile comppath = NULL;
 	xpath_workspace *workspace = palloc0_object(xpath_workspace);
 
 	workspace->doctree = NULL;
 	workspace->ctxt = NULL;
 	workspace->res = NULL;
 
-	workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
-									   docsize, NULL, NULL,
-									   XML_PARSE_NOENT);
-	if (workspace->doctree != NULL)
+	PG_TRY();
 	{
-		workspace->ctxt = xmlXPathNewContext(workspace->doctree);
-		workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
-
-		/* compile the path */
-		comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
-		if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+		workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
+										   docsize, NULL, NULL,
+										   XML_PARSE_NOENT);
+		if (workspace->doctree != NULL)
 		{
-			if (comppath != NULL)
-				xmlXPathFreeCompExpr(comppath);
-			xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
-						"XPath Syntax Error");
-		}
+			workspace->ctxt = xmlXPathNewContext(workspace->doctree);
+			if (workspace->ctxt == NULL)
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_OUT_OF_MEMORY,
+							"could not allocate XPath context");
 
-		/* Now evaluate the path expression. */
-		workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+			workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
+
+			/* compile the path */
+			comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
+			if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
+							"XPath Syntax Error");
+
+			/* Now evaluate the path expression. */
+			workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+
+			xmlXPathFreeCompExpr(comppath);
+			comppath = NULL;
+		}
+	}
+	PG_CATCH();
+	{
+		if (comppath != NULL)
+			xmlXPathFreeCompExpr(comppath);
+		cleanup_workspace(workspace);
 
-		xmlXPathFreeCompExpr(comppath);
+		PG_RE_THROW();
 	}
+	PG_END_TRY();
 
 	return workspace;
 }
-- 
2.54.0


--MP_/LMSk9=uMhuQ1QiIJDarDO8G--






^ permalink  raw  reply  [nested|flat] 611+ messages in thread

* [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths
@ 2026-06-01 22:41 Andrey Chernyy <andrey.cherny@tantorlabs.com>
  0 siblings, 0 replies; 611+ messages in thread

From: Andrey Chernyy @ 2026-06-01 22:41 UTC (permalink / raw)

pgxml_xpath() builds an xpath_workspace before returning it to
callers.  If an ERROR is thrown before the function returns, callers
have not received the workspace pointer yet and cannot run
cleanup_workspace().

Add local error cleanup for the partially built workspace and the
compiled XPath expression.  Also check xmlXPathNewContext() before
dereferencing the returned context.
---
 contrib/xml2/xpath.c | 51 +++++++++++++++++++++++++++-----------------
 1 file changed, 32 insertions(+), 19 deletions(-)

diff --git a/contrib/xml2/xpath.c b/contrib/xml2/xpath.c
index 9fe75cb5ff4..283bb51178d 100644
--- a/contrib/xml2/xpath.c
+++ b/contrib/xml2/xpath.c
@@ -497,36 +497,49 @@ static xpath_workspace *
 pgxml_xpath(text *document, xmlChar *xpath, PgXmlErrorContext *xmlerrcxt)
 {
 	int32		docsize = VARSIZE_ANY_EXHDR(document);
-	xmlXPathCompExprPtr comppath;
+	xmlXPathCompExprPtr volatile comppath = NULL;
 	xpath_workspace *workspace = palloc0_object(xpath_workspace);
 
 	workspace->doctree = NULL;
 	workspace->ctxt = NULL;
 	workspace->res = NULL;
 
-	workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
-									   docsize, NULL, NULL,
-									   XML_PARSE_NOENT);
-	if (workspace->doctree != NULL)
+	PG_TRY();
 	{
-		workspace->ctxt = xmlXPathNewContext(workspace->doctree);
-		workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
-
-		/* compile the path */
-		comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
-		if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+		workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
+										   docsize, NULL, NULL,
+										   XML_PARSE_NOENT);
+		if (workspace->doctree != NULL)
 		{
-			if (comppath != NULL)
-				xmlXPathFreeCompExpr(comppath);
-			xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
-						"XPath Syntax Error");
-		}
+			workspace->ctxt = xmlXPathNewContext(workspace->doctree);
+			if (workspace->ctxt == NULL)
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_OUT_OF_MEMORY,
+							"could not allocate XPath context");
 
-		/* Now evaluate the path expression. */
-		workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+			workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
+
+			/* compile the path */
+			comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
+			if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
+							"XPath Syntax Error");
+
+			/* Now evaluate the path expression. */
+			workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+
+			xmlXPathFreeCompExpr(comppath);
+			comppath = NULL;
+		}
+	}
+	PG_CATCH();
+	{
+		if (comppath != NULL)
+			xmlXPathFreeCompExpr(comppath);
+		cleanup_workspace(workspace);
 
-		xmlXPathFreeCompExpr(comppath);
+		PG_RE_THROW();
 	}
+	PG_END_TRY();
 
 	return workspace;
 }
-- 
2.54.0


--MP_/LMSk9=uMhuQ1QiIJDarDO8G--






^ permalink  raw  reply  [nested|flat] 611+ messages in thread

* [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths
@ 2026-06-01 22:41 Andrey Chernyy <andrey.cherny@tantorlabs.com>
  0 siblings, 0 replies; 611+ messages in thread

From: Andrey Chernyy @ 2026-06-01 22:41 UTC (permalink / raw)

pgxml_xpath() builds an xpath_workspace before returning it to
callers.  If an ERROR is thrown before the function returns, callers
have not received the workspace pointer yet and cannot run
cleanup_workspace().

Add local error cleanup for the partially built workspace and the
compiled XPath expression.  Also check xmlXPathNewContext() before
dereferencing the returned context.
---
 contrib/xml2/xpath.c | 51 +++++++++++++++++++++++++++-----------------
 1 file changed, 32 insertions(+), 19 deletions(-)

diff --git a/contrib/xml2/xpath.c b/contrib/xml2/xpath.c
index 9fe75cb5ff4..283bb51178d 100644
--- a/contrib/xml2/xpath.c
+++ b/contrib/xml2/xpath.c
@@ -497,36 +497,49 @@ static xpath_workspace *
 pgxml_xpath(text *document, xmlChar *xpath, PgXmlErrorContext *xmlerrcxt)
 {
 	int32		docsize = VARSIZE_ANY_EXHDR(document);
-	xmlXPathCompExprPtr comppath;
+	xmlXPathCompExprPtr volatile comppath = NULL;
 	xpath_workspace *workspace = palloc0_object(xpath_workspace);
 
 	workspace->doctree = NULL;
 	workspace->ctxt = NULL;
 	workspace->res = NULL;
 
-	workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
-									   docsize, NULL, NULL,
-									   XML_PARSE_NOENT);
-	if (workspace->doctree != NULL)
+	PG_TRY();
 	{
-		workspace->ctxt = xmlXPathNewContext(workspace->doctree);
-		workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
-
-		/* compile the path */
-		comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
-		if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+		workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
+										   docsize, NULL, NULL,
+										   XML_PARSE_NOENT);
+		if (workspace->doctree != NULL)
 		{
-			if (comppath != NULL)
-				xmlXPathFreeCompExpr(comppath);
-			xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
-						"XPath Syntax Error");
-		}
+			workspace->ctxt = xmlXPathNewContext(workspace->doctree);
+			if (workspace->ctxt == NULL)
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_OUT_OF_MEMORY,
+							"could not allocate XPath context");
 
-		/* Now evaluate the path expression. */
-		workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+			workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
+
+			/* compile the path */
+			comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
+			if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
+							"XPath Syntax Error");
+
+			/* Now evaluate the path expression. */
+			workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+
+			xmlXPathFreeCompExpr(comppath);
+			comppath = NULL;
+		}
+	}
+	PG_CATCH();
+	{
+		if (comppath != NULL)
+			xmlXPathFreeCompExpr(comppath);
+		cleanup_workspace(workspace);
 
-		xmlXPathFreeCompExpr(comppath);
+		PG_RE_THROW();
 	}
+	PG_END_TRY();
 
 	return workspace;
 }
-- 
2.54.0


--MP_/LMSk9=uMhuQ1QiIJDarDO8G--





^ permalink  raw  reply  [nested|flat] 611+ messages in thread

* [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths
@ 2026-06-01 22:41 Andrey Chernyy <andrey.cherny@tantorlabs.com>
  0 siblings, 0 replies; 611+ messages in thread

From: Andrey Chernyy @ 2026-06-01 22:41 UTC (permalink / raw)

pgxml_xpath() builds an xpath_workspace before returning it to
callers.  If an ERROR is thrown before the function returns, callers
have not received the workspace pointer yet and cannot run
cleanup_workspace().

Add local error cleanup for the partially built workspace and the
compiled XPath expression.  Also check xmlXPathNewContext() before
dereferencing the returned context.
---
 contrib/xml2/xpath.c | 51 +++++++++++++++++++++++++++-----------------
 1 file changed, 32 insertions(+), 19 deletions(-)

diff --git a/contrib/xml2/xpath.c b/contrib/xml2/xpath.c
index 9fe75cb5ff4..283bb51178d 100644
--- a/contrib/xml2/xpath.c
+++ b/contrib/xml2/xpath.c
@@ -497,36 +497,49 @@ static xpath_workspace *
 pgxml_xpath(text *document, xmlChar *xpath, PgXmlErrorContext *xmlerrcxt)
 {
 	int32		docsize = VARSIZE_ANY_EXHDR(document);
-	xmlXPathCompExprPtr comppath;
+	xmlXPathCompExprPtr volatile comppath = NULL;
 	xpath_workspace *workspace = palloc0_object(xpath_workspace);
 
 	workspace->doctree = NULL;
 	workspace->ctxt = NULL;
 	workspace->res = NULL;
 
-	workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
-									   docsize, NULL, NULL,
-									   XML_PARSE_NOENT);
-	if (workspace->doctree != NULL)
+	PG_TRY();
 	{
-		workspace->ctxt = xmlXPathNewContext(workspace->doctree);
-		workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
-
-		/* compile the path */
-		comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
-		if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+		workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
+										   docsize, NULL, NULL,
+										   XML_PARSE_NOENT);
+		if (workspace->doctree != NULL)
 		{
-			if (comppath != NULL)
-				xmlXPathFreeCompExpr(comppath);
-			xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
-						"XPath Syntax Error");
-		}
+			workspace->ctxt = xmlXPathNewContext(workspace->doctree);
+			if (workspace->ctxt == NULL)
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_OUT_OF_MEMORY,
+							"could not allocate XPath context");
 
-		/* Now evaluate the path expression. */
-		workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+			workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
+
+			/* compile the path */
+			comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
+			if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
+							"XPath Syntax Error");
+
+			/* Now evaluate the path expression. */
+			workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+
+			xmlXPathFreeCompExpr(comppath);
+			comppath = NULL;
+		}
+	}
+	PG_CATCH();
+	{
+		if (comppath != NULL)
+			xmlXPathFreeCompExpr(comppath);
+		cleanup_workspace(workspace);
 
-		xmlXPathFreeCompExpr(comppath);
+		PG_RE_THROW();
 	}
+	PG_END_TRY();
 
 	return workspace;
 }
-- 
2.54.0


--MP_/LMSk9=uMhuQ1QiIJDarDO8G--





^ permalink  raw  reply  [nested|flat] 611+ messages in thread

* [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths
@ 2026-06-01 22:41 Andrey Chernyy <andrey.cherny@tantorlabs.com>
  0 siblings, 0 replies; 611+ messages in thread

From: Andrey Chernyy @ 2026-06-01 22:41 UTC (permalink / raw)

pgxml_xpath() builds an xpath_workspace before returning it to
callers.  If an ERROR is thrown before the function returns, callers
have not received the workspace pointer yet and cannot run
cleanup_workspace().

Add local error cleanup for the partially built workspace and the
compiled XPath expression.  Also check xmlXPathNewContext() before
dereferencing the returned context.
---
 contrib/xml2/xpath.c | 51 +++++++++++++++++++++++++++-----------------
 1 file changed, 32 insertions(+), 19 deletions(-)

diff --git a/contrib/xml2/xpath.c b/contrib/xml2/xpath.c
index 9fe75cb5ff4..283bb51178d 100644
--- a/contrib/xml2/xpath.c
+++ b/contrib/xml2/xpath.c
@@ -497,36 +497,49 @@ static xpath_workspace *
 pgxml_xpath(text *document, xmlChar *xpath, PgXmlErrorContext *xmlerrcxt)
 {
 	int32		docsize = VARSIZE_ANY_EXHDR(document);
-	xmlXPathCompExprPtr comppath;
+	xmlXPathCompExprPtr volatile comppath = NULL;
 	xpath_workspace *workspace = palloc0_object(xpath_workspace);
 
 	workspace->doctree = NULL;
 	workspace->ctxt = NULL;
 	workspace->res = NULL;
 
-	workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
-									   docsize, NULL, NULL,
-									   XML_PARSE_NOENT);
-	if (workspace->doctree != NULL)
+	PG_TRY();
 	{
-		workspace->ctxt = xmlXPathNewContext(workspace->doctree);
-		workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
-
-		/* compile the path */
-		comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
-		if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+		workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
+										   docsize, NULL, NULL,
+										   XML_PARSE_NOENT);
+		if (workspace->doctree != NULL)
 		{
-			if (comppath != NULL)
-				xmlXPathFreeCompExpr(comppath);
-			xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
-						"XPath Syntax Error");
-		}
+			workspace->ctxt = xmlXPathNewContext(workspace->doctree);
+			if (workspace->ctxt == NULL)
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_OUT_OF_MEMORY,
+							"could not allocate XPath context");
 
-		/* Now evaluate the path expression. */
-		workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+			workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
+
+			/* compile the path */
+			comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
+			if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
+							"XPath Syntax Error");
+
+			/* Now evaluate the path expression. */
+			workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+
+			xmlXPathFreeCompExpr(comppath);
+			comppath = NULL;
+		}
+	}
+	PG_CATCH();
+	{
+		if (comppath != NULL)
+			xmlXPathFreeCompExpr(comppath);
+		cleanup_workspace(workspace);
 
-		xmlXPathFreeCompExpr(comppath);
+		PG_RE_THROW();
 	}
+	PG_END_TRY();
 
 	return workspace;
 }
-- 
2.54.0


--MP_/LMSk9=uMhuQ1QiIJDarDO8G--






^ permalink  raw  reply  [nested|flat] 611+ messages in thread

* [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths
@ 2026-06-01 22:41 Andrey Chernyy <andrey.cherny@tantorlabs.com>
  0 siblings, 0 replies; 611+ messages in thread

From: Andrey Chernyy @ 2026-06-01 22:41 UTC (permalink / raw)

pgxml_xpath() builds an xpath_workspace before returning it to
callers.  If an ERROR is thrown before the function returns, callers
have not received the workspace pointer yet and cannot run
cleanup_workspace().

Add local error cleanup for the partially built workspace and the
compiled XPath expression.  Also check xmlXPathNewContext() before
dereferencing the returned context.
---
 contrib/xml2/xpath.c | 51 +++++++++++++++++++++++++++-----------------
 1 file changed, 32 insertions(+), 19 deletions(-)

diff --git a/contrib/xml2/xpath.c b/contrib/xml2/xpath.c
index 9fe75cb5ff4..283bb51178d 100644
--- a/contrib/xml2/xpath.c
+++ b/contrib/xml2/xpath.c
@@ -497,36 +497,49 @@ static xpath_workspace *
 pgxml_xpath(text *document, xmlChar *xpath, PgXmlErrorContext *xmlerrcxt)
 {
 	int32		docsize = VARSIZE_ANY_EXHDR(document);
-	xmlXPathCompExprPtr comppath;
+	xmlXPathCompExprPtr volatile comppath = NULL;
 	xpath_workspace *workspace = palloc0_object(xpath_workspace);
 
 	workspace->doctree = NULL;
 	workspace->ctxt = NULL;
 	workspace->res = NULL;
 
-	workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
-									   docsize, NULL, NULL,
-									   XML_PARSE_NOENT);
-	if (workspace->doctree != NULL)
+	PG_TRY();
 	{
-		workspace->ctxt = xmlXPathNewContext(workspace->doctree);
-		workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
-
-		/* compile the path */
-		comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
-		if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+		workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
+										   docsize, NULL, NULL,
+										   XML_PARSE_NOENT);
+		if (workspace->doctree != NULL)
 		{
-			if (comppath != NULL)
-				xmlXPathFreeCompExpr(comppath);
-			xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
-						"XPath Syntax Error");
-		}
+			workspace->ctxt = xmlXPathNewContext(workspace->doctree);
+			if (workspace->ctxt == NULL)
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_OUT_OF_MEMORY,
+							"could not allocate XPath context");
 
-		/* Now evaluate the path expression. */
-		workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+			workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
+
+			/* compile the path */
+			comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
+			if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
+							"XPath Syntax Error");
+
+			/* Now evaluate the path expression. */
+			workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+
+			xmlXPathFreeCompExpr(comppath);
+			comppath = NULL;
+		}
+	}
+	PG_CATCH();
+	{
+		if (comppath != NULL)
+			xmlXPathFreeCompExpr(comppath);
+		cleanup_workspace(workspace);
 
-		xmlXPathFreeCompExpr(comppath);
+		PG_RE_THROW();
 	}
+	PG_END_TRY();
 
 	return workspace;
 }
-- 
2.54.0


--MP_/LMSk9=uMhuQ1QiIJDarDO8G--





^ permalink  raw  reply  [nested|flat] 611+ messages in thread

* [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths
@ 2026-06-01 22:41 Andrey Chernyy <andrey.cherny@tantorlabs.com>
  0 siblings, 0 replies; 611+ messages in thread

From: Andrey Chernyy @ 2026-06-01 22:41 UTC (permalink / raw)

pgxml_xpath() builds an xpath_workspace before returning it to
callers.  If an ERROR is thrown before the function returns, callers
have not received the workspace pointer yet and cannot run
cleanup_workspace().

Add local error cleanup for the partially built workspace and the
compiled XPath expression.  Also check xmlXPathNewContext() before
dereferencing the returned context.
---
 contrib/xml2/xpath.c | 51 +++++++++++++++++++++++++++-----------------
 1 file changed, 32 insertions(+), 19 deletions(-)

diff --git a/contrib/xml2/xpath.c b/contrib/xml2/xpath.c
index 9fe75cb5ff4..283bb51178d 100644
--- a/contrib/xml2/xpath.c
+++ b/contrib/xml2/xpath.c
@@ -497,36 +497,49 @@ static xpath_workspace *
 pgxml_xpath(text *document, xmlChar *xpath, PgXmlErrorContext *xmlerrcxt)
 {
 	int32		docsize = VARSIZE_ANY_EXHDR(document);
-	xmlXPathCompExprPtr comppath;
+	xmlXPathCompExprPtr volatile comppath = NULL;
 	xpath_workspace *workspace = palloc0_object(xpath_workspace);
 
 	workspace->doctree = NULL;
 	workspace->ctxt = NULL;
 	workspace->res = NULL;
 
-	workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
-									   docsize, NULL, NULL,
-									   XML_PARSE_NOENT);
-	if (workspace->doctree != NULL)
+	PG_TRY();
 	{
-		workspace->ctxt = xmlXPathNewContext(workspace->doctree);
-		workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
-
-		/* compile the path */
-		comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
-		if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+		workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
+										   docsize, NULL, NULL,
+										   XML_PARSE_NOENT);
+		if (workspace->doctree != NULL)
 		{
-			if (comppath != NULL)
-				xmlXPathFreeCompExpr(comppath);
-			xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
-						"XPath Syntax Error");
-		}
+			workspace->ctxt = xmlXPathNewContext(workspace->doctree);
+			if (workspace->ctxt == NULL)
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_OUT_OF_MEMORY,
+							"could not allocate XPath context");
 
-		/* Now evaluate the path expression. */
-		workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+			workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
+
+			/* compile the path */
+			comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
+			if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
+							"XPath Syntax Error");
+
+			/* Now evaluate the path expression. */
+			workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+
+			xmlXPathFreeCompExpr(comppath);
+			comppath = NULL;
+		}
+	}
+	PG_CATCH();
+	{
+		if (comppath != NULL)
+			xmlXPathFreeCompExpr(comppath);
+		cleanup_workspace(workspace);
 
-		xmlXPathFreeCompExpr(comppath);
+		PG_RE_THROW();
 	}
+	PG_END_TRY();
 
 	return workspace;
 }
-- 
2.54.0


--MP_/LMSk9=uMhuQ1QiIJDarDO8G--






^ permalink  raw  reply  [nested|flat] 611+ messages in thread

* [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths
@ 2026-06-01 22:41 Andrey Chernyy <andrey.cherny@tantorlabs.com>
  0 siblings, 0 replies; 611+ messages in thread

From: Andrey Chernyy @ 2026-06-01 22:41 UTC (permalink / raw)

pgxml_xpath() builds an xpath_workspace before returning it to
callers.  If an ERROR is thrown before the function returns, callers
have not received the workspace pointer yet and cannot run
cleanup_workspace().

Add local error cleanup for the partially built workspace and the
compiled XPath expression.  Also check xmlXPathNewContext() before
dereferencing the returned context.
---
 contrib/xml2/xpath.c | 51 +++++++++++++++++++++++++++-----------------
 1 file changed, 32 insertions(+), 19 deletions(-)

diff --git a/contrib/xml2/xpath.c b/contrib/xml2/xpath.c
index 9fe75cb5ff4..283bb51178d 100644
--- a/contrib/xml2/xpath.c
+++ b/contrib/xml2/xpath.c
@@ -497,36 +497,49 @@ static xpath_workspace *
 pgxml_xpath(text *document, xmlChar *xpath, PgXmlErrorContext *xmlerrcxt)
 {
 	int32		docsize = VARSIZE_ANY_EXHDR(document);
-	xmlXPathCompExprPtr comppath;
+	xmlXPathCompExprPtr volatile comppath = NULL;
 	xpath_workspace *workspace = palloc0_object(xpath_workspace);
 
 	workspace->doctree = NULL;
 	workspace->ctxt = NULL;
 	workspace->res = NULL;
 
-	workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
-									   docsize, NULL, NULL,
-									   XML_PARSE_NOENT);
-	if (workspace->doctree != NULL)
+	PG_TRY();
 	{
-		workspace->ctxt = xmlXPathNewContext(workspace->doctree);
-		workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
-
-		/* compile the path */
-		comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
-		if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+		workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
+										   docsize, NULL, NULL,
+										   XML_PARSE_NOENT);
+		if (workspace->doctree != NULL)
 		{
-			if (comppath != NULL)
-				xmlXPathFreeCompExpr(comppath);
-			xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
-						"XPath Syntax Error");
-		}
+			workspace->ctxt = xmlXPathNewContext(workspace->doctree);
+			if (workspace->ctxt == NULL)
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_OUT_OF_MEMORY,
+							"could not allocate XPath context");
 
-		/* Now evaluate the path expression. */
-		workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+			workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
+
+			/* compile the path */
+			comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
+			if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
+							"XPath Syntax Error");
+
+			/* Now evaluate the path expression. */
+			workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+
+			xmlXPathFreeCompExpr(comppath);
+			comppath = NULL;
+		}
+	}
+	PG_CATCH();
+	{
+		if (comppath != NULL)
+			xmlXPathFreeCompExpr(comppath);
+		cleanup_workspace(workspace);
 
-		xmlXPathFreeCompExpr(comppath);
+		PG_RE_THROW();
 	}
+	PG_END_TRY();
 
 	return workspace;
 }
-- 
2.54.0


--MP_/LMSk9=uMhuQ1QiIJDarDO8G--






^ permalink  raw  reply  [nested|flat] 611+ messages in thread

* [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths
@ 2026-06-01 22:41 Andrey Chernyy <andrey.cherny@tantorlabs.com>
  0 siblings, 0 replies; 611+ messages in thread

From: Andrey Chernyy @ 2026-06-01 22:41 UTC (permalink / raw)

pgxml_xpath() builds an xpath_workspace before returning it to
callers.  If an ERROR is thrown before the function returns, callers
have not received the workspace pointer yet and cannot run
cleanup_workspace().

Add local error cleanup for the partially built workspace and the
compiled XPath expression.  Also check xmlXPathNewContext() before
dereferencing the returned context.
---
 contrib/xml2/xpath.c | 51 +++++++++++++++++++++++++++-----------------
 1 file changed, 32 insertions(+), 19 deletions(-)

diff --git a/contrib/xml2/xpath.c b/contrib/xml2/xpath.c
index 9fe75cb5ff4..283bb51178d 100644
--- a/contrib/xml2/xpath.c
+++ b/contrib/xml2/xpath.c
@@ -497,36 +497,49 @@ static xpath_workspace *
 pgxml_xpath(text *document, xmlChar *xpath, PgXmlErrorContext *xmlerrcxt)
 {
 	int32		docsize = VARSIZE_ANY_EXHDR(document);
-	xmlXPathCompExprPtr comppath;
+	xmlXPathCompExprPtr volatile comppath = NULL;
 	xpath_workspace *workspace = palloc0_object(xpath_workspace);
 
 	workspace->doctree = NULL;
 	workspace->ctxt = NULL;
 	workspace->res = NULL;
 
-	workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
-									   docsize, NULL, NULL,
-									   XML_PARSE_NOENT);
-	if (workspace->doctree != NULL)
+	PG_TRY();
 	{
-		workspace->ctxt = xmlXPathNewContext(workspace->doctree);
-		workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
-
-		/* compile the path */
-		comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
-		if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+		workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
+										   docsize, NULL, NULL,
+										   XML_PARSE_NOENT);
+		if (workspace->doctree != NULL)
 		{
-			if (comppath != NULL)
-				xmlXPathFreeCompExpr(comppath);
-			xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
-						"XPath Syntax Error");
-		}
+			workspace->ctxt = xmlXPathNewContext(workspace->doctree);
+			if (workspace->ctxt == NULL)
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_OUT_OF_MEMORY,
+							"could not allocate XPath context");
 
-		/* Now evaluate the path expression. */
-		workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+			workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
+
+			/* compile the path */
+			comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
+			if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
+							"XPath Syntax Error");
+
+			/* Now evaluate the path expression. */
+			workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+
+			xmlXPathFreeCompExpr(comppath);
+			comppath = NULL;
+		}
+	}
+	PG_CATCH();
+	{
+		if (comppath != NULL)
+			xmlXPathFreeCompExpr(comppath);
+		cleanup_workspace(workspace);
 
-		xmlXPathFreeCompExpr(comppath);
+		PG_RE_THROW();
 	}
+	PG_END_TRY();
 
 	return workspace;
 }
-- 
2.54.0


--MP_/LMSk9=uMhuQ1QiIJDarDO8G--





^ permalink  raw  reply  [nested|flat] 611+ messages in thread

* [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths
@ 2026-06-01 22:41 Andrey Chernyy <andrey.cherny@tantorlabs.com>
  0 siblings, 0 replies; 611+ messages in thread

From: Andrey Chernyy @ 2026-06-01 22:41 UTC (permalink / raw)

pgxml_xpath() builds an xpath_workspace before returning it to
callers.  If an ERROR is thrown before the function returns, callers
have not received the workspace pointer yet and cannot run
cleanup_workspace().

Add local error cleanup for the partially built workspace and the
compiled XPath expression.  Also check xmlXPathNewContext() before
dereferencing the returned context.
---
 contrib/xml2/xpath.c | 51 +++++++++++++++++++++++++++-----------------
 1 file changed, 32 insertions(+), 19 deletions(-)

diff --git a/contrib/xml2/xpath.c b/contrib/xml2/xpath.c
index 9fe75cb5ff4..283bb51178d 100644
--- a/contrib/xml2/xpath.c
+++ b/contrib/xml2/xpath.c
@@ -497,36 +497,49 @@ static xpath_workspace *
 pgxml_xpath(text *document, xmlChar *xpath, PgXmlErrorContext *xmlerrcxt)
 {
 	int32		docsize = VARSIZE_ANY_EXHDR(document);
-	xmlXPathCompExprPtr comppath;
+	xmlXPathCompExprPtr volatile comppath = NULL;
 	xpath_workspace *workspace = palloc0_object(xpath_workspace);
 
 	workspace->doctree = NULL;
 	workspace->ctxt = NULL;
 	workspace->res = NULL;
 
-	workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
-									   docsize, NULL, NULL,
-									   XML_PARSE_NOENT);
-	if (workspace->doctree != NULL)
+	PG_TRY();
 	{
-		workspace->ctxt = xmlXPathNewContext(workspace->doctree);
-		workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
-
-		/* compile the path */
-		comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
-		if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+		workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
+										   docsize, NULL, NULL,
+										   XML_PARSE_NOENT);
+		if (workspace->doctree != NULL)
 		{
-			if (comppath != NULL)
-				xmlXPathFreeCompExpr(comppath);
-			xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
-						"XPath Syntax Error");
-		}
+			workspace->ctxt = xmlXPathNewContext(workspace->doctree);
+			if (workspace->ctxt == NULL)
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_OUT_OF_MEMORY,
+							"could not allocate XPath context");
 
-		/* Now evaluate the path expression. */
-		workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+			workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
+
+			/* compile the path */
+			comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
+			if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
+							"XPath Syntax Error");
+
+			/* Now evaluate the path expression. */
+			workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+
+			xmlXPathFreeCompExpr(comppath);
+			comppath = NULL;
+		}
+	}
+	PG_CATCH();
+	{
+		if (comppath != NULL)
+			xmlXPathFreeCompExpr(comppath);
+		cleanup_workspace(workspace);
 
-		xmlXPathFreeCompExpr(comppath);
+		PG_RE_THROW();
 	}
+	PG_END_TRY();
 
 	return workspace;
 }
-- 
2.54.0


--MP_/LMSk9=uMhuQ1QiIJDarDO8G--






^ permalink  raw  reply  [nested|flat] 611+ messages in thread

* [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths
@ 2026-06-01 22:41 Andrey Chernyy <andrey.cherny@tantorlabs.com>
  0 siblings, 0 replies; 611+ messages in thread

From: Andrey Chernyy @ 2026-06-01 22:41 UTC (permalink / raw)

pgxml_xpath() builds an xpath_workspace before returning it to
callers.  If an ERROR is thrown before the function returns, callers
have not received the workspace pointer yet and cannot run
cleanup_workspace().

Add local error cleanup for the partially built workspace and the
compiled XPath expression.  Also check xmlXPathNewContext() before
dereferencing the returned context.
---
 contrib/xml2/xpath.c | 51 +++++++++++++++++++++++++++-----------------
 1 file changed, 32 insertions(+), 19 deletions(-)

diff --git a/contrib/xml2/xpath.c b/contrib/xml2/xpath.c
index 9fe75cb5ff4..283bb51178d 100644
--- a/contrib/xml2/xpath.c
+++ b/contrib/xml2/xpath.c
@@ -497,36 +497,49 @@ static xpath_workspace *
 pgxml_xpath(text *document, xmlChar *xpath, PgXmlErrorContext *xmlerrcxt)
 {
 	int32		docsize = VARSIZE_ANY_EXHDR(document);
-	xmlXPathCompExprPtr comppath;
+	xmlXPathCompExprPtr volatile comppath = NULL;
 	xpath_workspace *workspace = palloc0_object(xpath_workspace);
 
 	workspace->doctree = NULL;
 	workspace->ctxt = NULL;
 	workspace->res = NULL;
 
-	workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
-									   docsize, NULL, NULL,
-									   XML_PARSE_NOENT);
-	if (workspace->doctree != NULL)
+	PG_TRY();
 	{
-		workspace->ctxt = xmlXPathNewContext(workspace->doctree);
-		workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
-
-		/* compile the path */
-		comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
-		if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+		workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
+										   docsize, NULL, NULL,
+										   XML_PARSE_NOENT);
+		if (workspace->doctree != NULL)
 		{
-			if (comppath != NULL)
-				xmlXPathFreeCompExpr(comppath);
-			xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
-						"XPath Syntax Error");
-		}
+			workspace->ctxt = xmlXPathNewContext(workspace->doctree);
+			if (workspace->ctxt == NULL)
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_OUT_OF_MEMORY,
+							"could not allocate XPath context");
 
-		/* Now evaluate the path expression. */
-		workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+			workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
+
+			/* compile the path */
+			comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
+			if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
+							"XPath Syntax Error");
+
+			/* Now evaluate the path expression. */
+			workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+
+			xmlXPathFreeCompExpr(comppath);
+			comppath = NULL;
+		}
+	}
+	PG_CATCH();
+	{
+		if (comppath != NULL)
+			xmlXPathFreeCompExpr(comppath);
+		cleanup_workspace(workspace);
 
-		xmlXPathFreeCompExpr(comppath);
+		PG_RE_THROW();
 	}
+	PG_END_TRY();
 
 	return workspace;
 }
-- 
2.54.0


--MP_/LMSk9=uMhuQ1QiIJDarDO8G--






^ permalink  raw  reply  [nested|flat] 611+ messages in thread

* [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths
@ 2026-06-01 22:41 Andrey Chernyy <andrey.cherny@tantorlabs.com>
  0 siblings, 0 replies; 611+ messages in thread

From: Andrey Chernyy @ 2026-06-01 22:41 UTC (permalink / raw)

pgxml_xpath() builds an xpath_workspace before returning it to
callers.  If an ERROR is thrown before the function returns, callers
have not received the workspace pointer yet and cannot run
cleanup_workspace().

Add local error cleanup for the partially built workspace and the
compiled XPath expression.  Also check xmlXPathNewContext() before
dereferencing the returned context.
---
 contrib/xml2/xpath.c | 51 +++++++++++++++++++++++++++-----------------
 1 file changed, 32 insertions(+), 19 deletions(-)

diff --git a/contrib/xml2/xpath.c b/contrib/xml2/xpath.c
index 9fe75cb5ff4..283bb51178d 100644
--- a/contrib/xml2/xpath.c
+++ b/contrib/xml2/xpath.c
@@ -497,36 +497,49 @@ static xpath_workspace *
 pgxml_xpath(text *document, xmlChar *xpath, PgXmlErrorContext *xmlerrcxt)
 {
 	int32		docsize = VARSIZE_ANY_EXHDR(document);
-	xmlXPathCompExprPtr comppath;
+	xmlXPathCompExprPtr volatile comppath = NULL;
 	xpath_workspace *workspace = palloc0_object(xpath_workspace);
 
 	workspace->doctree = NULL;
 	workspace->ctxt = NULL;
 	workspace->res = NULL;
 
-	workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
-									   docsize, NULL, NULL,
-									   XML_PARSE_NOENT);
-	if (workspace->doctree != NULL)
+	PG_TRY();
 	{
-		workspace->ctxt = xmlXPathNewContext(workspace->doctree);
-		workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
-
-		/* compile the path */
-		comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
-		if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+		workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
+										   docsize, NULL, NULL,
+										   XML_PARSE_NOENT);
+		if (workspace->doctree != NULL)
 		{
-			if (comppath != NULL)
-				xmlXPathFreeCompExpr(comppath);
-			xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
-						"XPath Syntax Error");
-		}
+			workspace->ctxt = xmlXPathNewContext(workspace->doctree);
+			if (workspace->ctxt == NULL)
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_OUT_OF_MEMORY,
+							"could not allocate XPath context");
 
-		/* Now evaluate the path expression. */
-		workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+			workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
+
+			/* compile the path */
+			comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
+			if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
+							"XPath Syntax Error");
+
+			/* Now evaluate the path expression. */
+			workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+
+			xmlXPathFreeCompExpr(comppath);
+			comppath = NULL;
+		}
+	}
+	PG_CATCH();
+	{
+		if (comppath != NULL)
+			xmlXPathFreeCompExpr(comppath);
+		cleanup_workspace(workspace);
 
-		xmlXPathFreeCompExpr(comppath);
+		PG_RE_THROW();
 	}
+	PG_END_TRY();
 
 	return workspace;
 }
-- 
2.54.0


--MP_/LMSk9=uMhuQ1QiIJDarDO8G--





^ permalink  raw  reply  [nested|flat] 611+ messages in thread

* [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths
@ 2026-06-01 22:41 Andrey Chernyy <andrey.cherny@tantorlabs.com>
  0 siblings, 0 replies; 611+ messages in thread

From: Andrey Chernyy @ 2026-06-01 22:41 UTC (permalink / raw)

pgxml_xpath() builds an xpath_workspace before returning it to
callers.  If an ERROR is thrown before the function returns, callers
have not received the workspace pointer yet and cannot run
cleanup_workspace().

Add local error cleanup for the partially built workspace and the
compiled XPath expression.  Also check xmlXPathNewContext() before
dereferencing the returned context.
---
 contrib/xml2/xpath.c | 51 +++++++++++++++++++++++++++-----------------
 1 file changed, 32 insertions(+), 19 deletions(-)

diff --git a/contrib/xml2/xpath.c b/contrib/xml2/xpath.c
index 9fe75cb5ff4..283bb51178d 100644
--- a/contrib/xml2/xpath.c
+++ b/contrib/xml2/xpath.c
@@ -497,36 +497,49 @@ static xpath_workspace *
 pgxml_xpath(text *document, xmlChar *xpath, PgXmlErrorContext *xmlerrcxt)
 {
 	int32		docsize = VARSIZE_ANY_EXHDR(document);
-	xmlXPathCompExprPtr comppath;
+	xmlXPathCompExprPtr volatile comppath = NULL;
 	xpath_workspace *workspace = palloc0_object(xpath_workspace);
 
 	workspace->doctree = NULL;
 	workspace->ctxt = NULL;
 	workspace->res = NULL;
 
-	workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
-									   docsize, NULL, NULL,
-									   XML_PARSE_NOENT);
-	if (workspace->doctree != NULL)
+	PG_TRY();
 	{
-		workspace->ctxt = xmlXPathNewContext(workspace->doctree);
-		workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
-
-		/* compile the path */
-		comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
-		if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+		workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
+										   docsize, NULL, NULL,
+										   XML_PARSE_NOENT);
+		if (workspace->doctree != NULL)
 		{
-			if (comppath != NULL)
-				xmlXPathFreeCompExpr(comppath);
-			xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
-						"XPath Syntax Error");
-		}
+			workspace->ctxt = xmlXPathNewContext(workspace->doctree);
+			if (workspace->ctxt == NULL)
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_OUT_OF_MEMORY,
+							"could not allocate XPath context");
 
-		/* Now evaluate the path expression. */
-		workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+			workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
+
+			/* compile the path */
+			comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
+			if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
+							"XPath Syntax Error");
+
+			/* Now evaluate the path expression. */
+			workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+
+			xmlXPathFreeCompExpr(comppath);
+			comppath = NULL;
+		}
+	}
+	PG_CATCH();
+	{
+		if (comppath != NULL)
+			xmlXPathFreeCompExpr(comppath);
+		cleanup_workspace(workspace);
 
-		xmlXPathFreeCompExpr(comppath);
+		PG_RE_THROW();
 	}
+	PG_END_TRY();
 
 	return workspace;
 }
-- 
2.54.0


--MP_/LMSk9=uMhuQ1QiIJDarDO8G--





^ permalink  raw  reply  [nested|flat] 611+ messages in thread

* [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths
@ 2026-06-01 22:41 Andrey Chernyy <andrey.cherny@tantorlabs.com>
  0 siblings, 0 replies; 611+ messages in thread

From: Andrey Chernyy @ 2026-06-01 22:41 UTC (permalink / raw)

pgxml_xpath() builds an xpath_workspace before returning it to
callers.  If an ERROR is thrown before the function returns, callers
have not received the workspace pointer yet and cannot run
cleanup_workspace().

Add local error cleanup for the partially built workspace and the
compiled XPath expression.  Also check xmlXPathNewContext() before
dereferencing the returned context.
---
 contrib/xml2/xpath.c | 51 +++++++++++++++++++++++++++-----------------
 1 file changed, 32 insertions(+), 19 deletions(-)

diff --git a/contrib/xml2/xpath.c b/contrib/xml2/xpath.c
index 9fe75cb5ff4..283bb51178d 100644
--- a/contrib/xml2/xpath.c
+++ b/contrib/xml2/xpath.c
@@ -497,36 +497,49 @@ static xpath_workspace *
 pgxml_xpath(text *document, xmlChar *xpath, PgXmlErrorContext *xmlerrcxt)
 {
 	int32		docsize = VARSIZE_ANY_EXHDR(document);
-	xmlXPathCompExprPtr comppath;
+	xmlXPathCompExprPtr volatile comppath = NULL;
 	xpath_workspace *workspace = palloc0_object(xpath_workspace);
 
 	workspace->doctree = NULL;
 	workspace->ctxt = NULL;
 	workspace->res = NULL;
 
-	workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
-									   docsize, NULL, NULL,
-									   XML_PARSE_NOENT);
-	if (workspace->doctree != NULL)
+	PG_TRY();
 	{
-		workspace->ctxt = xmlXPathNewContext(workspace->doctree);
-		workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
-
-		/* compile the path */
-		comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
-		if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+		workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
+										   docsize, NULL, NULL,
+										   XML_PARSE_NOENT);
+		if (workspace->doctree != NULL)
 		{
-			if (comppath != NULL)
-				xmlXPathFreeCompExpr(comppath);
-			xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
-						"XPath Syntax Error");
-		}
+			workspace->ctxt = xmlXPathNewContext(workspace->doctree);
+			if (workspace->ctxt == NULL)
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_OUT_OF_MEMORY,
+							"could not allocate XPath context");
 
-		/* Now evaluate the path expression. */
-		workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+			workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
+
+			/* compile the path */
+			comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
+			if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
+							"XPath Syntax Error");
+
+			/* Now evaluate the path expression. */
+			workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+
+			xmlXPathFreeCompExpr(comppath);
+			comppath = NULL;
+		}
+	}
+	PG_CATCH();
+	{
+		if (comppath != NULL)
+			xmlXPathFreeCompExpr(comppath);
+		cleanup_workspace(workspace);
 
-		xmlXPathFreeCompExpr(comppath);
+		PG_RE_THROW();
 	}
+	PG_END_TRY();
 
 	return workspace;
 }
-- 
2.54.0


--MP_/LMSk9=uMhuQ1QiIJDarDO8G--






^ permalink  raw  reply  [nested|flat] 611+ messages in thread

* [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths
@ 2026-06-01 22:41 Andrey Chernyy <andrey.cherny@tantorlabs.com>
  0 siblings, 0 replies; 611+ messages in thread

From: Andrey Chernyy @ 2026-06-01 22:41 UTC (permalink / raw)

pgxml_xpath() builds an xpath_workspace before returning it to
callers.  If an ERROR is thrown before the function returns, callers
have not received the workspace pointer yet and cannot run
cleanup_workspace().

Add local error cleanup for the partially built workspace and the
compiled XPath expression.  Also check xmlXPathNewContext() before
dereferencing the returned context.
---
 contrib/xml2/xpath.c | 51 +++++++++++++++++++++++++++-----------------
 1 file changed, 32 insertions(+), 19 deletions(-)

diff --git a/contrib/xml2/xpath.c b/contrib/xml2/xpath.c
index 9fe75cb5ff4..283bb51178d 100644
--- a/contrib/xml2/xpath.c
+++ b/contrib/xml2/xpath.c
@@ -497,36 +497,49 @@ static xpath_workspace *
 pgxml_xpath(text *document, xmlChar *xpath, PgXmlErrorContext *xmlerrcxt)
 {
 	int32		docsize = VARSIZE_ANY_EXHDR(document);
-	xmlXPathCompExprPtr comppath;
+	xmlXPathCompExprPtr volatile comppath = NULL;
 	xpath_workspace *workspace = palloc0_object(xpath_workspace);
 
 	workspace->doctree = NULL;
 	workspace->ctxt = NULL;
 	workspace->res = NULL;
 
-	workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
-									   docsize, NULL, NULL,
-									   XML_PARSE_NOENT);
-	if (workspace->doctree != NULL)
+	PG_TRY();
 	{
-		workspace->ctxt = xmlXPathNewContext(workspace->doctree);
-		workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
-
-		/* compile the path */
-		comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
-		if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+		workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
+										   docsize, NULL, NULL,
+										   XML_PARSE_NOENT);
+		if (workspace->doctree != NULL)
 		{
-			if (comppath != NULL)
-				xmlXPathFreeCompExpr(comppath);
-			xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
-						"XPath Syntax Error");
-		}
+			workspace->ctxt = xmlXPathNewContext(workspace->doctree);
+			if (workspace->ctxt == NULL)
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_OUT_OF_MEMORY,
+							"could not allocate XPath context");
 
-		/* Now evaluate the path expression. */
-		workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+			workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
+
+			/* compile the path */
+			comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
+			if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
+							"XPath Syntax Error");
+
+			/* Now evaluate the path expression. */
+			workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+
+			xmlXPathFreeCompExpr(comppath);
+			comppath = NULL;
+		}
+	}
+	PG_CATCH();
+	{
+		if (comppath != NULL)
+			xmlXPathFreeCompExpr(comppath);
+		cleanup_workspace(workspace);
 
-		xmlXPathFreeCompExpr(comppath);
+		PG_RE_THROW();
 	}
+	PG_END_TRY();
 
 	return workspace;
 }
-- 
2.54.0


--MP_/LMSk9=uMhuQ1QiIJDarDO8G--





^ permalink  raw  reply  [nested|flat] 611+ messages in thread

* [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths
@ 2026-06-01 22:41 Andrey Chernyy <andrey.cherny@tantorlabs.com>
  0 siblings, 0 replies; 611+ messages in thread

From: Andrey Chernyy @ 2026-06-01 22:41 UTC (permalink / raw)

pgxml_xpath() builds an xpath_workspace before returning it to
callers.  If an ERROR is thrown before the function returns, callers
have not received the workspace pointer yet and cannot run
cleanup_workspace().

Add local error cleanup for the partially built workspace and the
compiled XPath expression.  Also check xmlXPathNewContext() before
dereferencing the returned context.
---
 contrib/xml2/xpath.c | 51 +++++++++++++++++++++++++++-----------------
 1 file changed, 32 insertions(+), 19 deletions(-)

diff --git a/contrib/xml2/xpath.c b/contrib/xml2/xpath.c
index 9fe75cb5ff4..283bb51178d 100644
--- a/contrib/xml2/xpath.c
+++ b/contrib/xml2/xpath.c
@@ -497,36 +497,49 @@ static xpath_workspace *
 pgxml_xpath(text *document, xmlChar *xpath, PgXmlErrorContext *xmlerrcxt)
 {
 	int32		docsize = VARSIZE_ANY_EXHDR(document);
-	xmlXPathCompExprPtr comppath;
+	xmlXPathCompExprPtr volatile comppath = NULL;
 	xpath_workspace *workspace = palloc0_object(xpath_workspace);
 
 	workspace->doctree = NULL;
 	workspace->ctxt = NULL;
 	workspace->res = NULL;
 
-	workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
-									   docsize, NULL, NULL,
-									   XML_PARSE_NOENT);
-	if (workspace->doctree != NULL)
+	PG_TRY();
 	{
-		workspace->ctxt = xmlXPathNewContext(workspace->doctree);
-		workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
-
-		/* compile the path */
-		comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
-		if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+		workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
+										   docsize, NULL, NULL,
+										   XML_PARSE_NOENT);
+		if (workspace->doctree != NULL)
 		{
-			if (comppath != NULL)
-				xmlXPathFreeCompExpr(comppath);
-			xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
-						"XPath Syntax Error");
-		}
+			workspace->ctxt = xmlXPathNewContext(workspace->doctree);
+			if (workspace->ctxt == NULL)
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_OUT_OF_MEMORY,
+							"could not allocate XPath context");
 
-		/* Now evaluate the path expression. */
-		workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+			workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
+
+			/* compile the path */
+			comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
+			if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
+							"XPath Syntax Error");
+
+			/* Now evaluate the path expression. */
+			workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+
+			xmlXPathFreeCompExpr(comppath);
+			comppath = NULL;
+		}
+	}
+	PG_CATCH();
+	{
+		if (comppath != NULL)
+			xmlXPathFreeCompExpr(comppath);
+		cleanup_workspace(workspace);
 
-		xmlXPathFreeCompExpr(comppath);
+		PG_RE_THROW();
 	}
+	PG_END_TRY();
 
 	return workspace;
 }
-- 
2.54.0


--MP_/LMSk9=uMhuQ1QiIJDarDO8G--





^ permalink  raw  reply  [nested|flat] 611+ messages in thread

* [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths
@ 2026-06-01 22:41 Andrey Chernyy <andrey.cherny@tantorlabs.com>
  0 siblings, 0 replies; 611+ messages in thread

From: Andrey Chernyy @ 2026-06-01 22:41 UTC (permalink / raw)

pgxml_xpath() builds an xpath_workspace before returning it to
callers.  If an ERROR is thrown before the function returns, callers
have not received the workspace pointer yet and cannot run
cleanup_workspace().

Add local error cleanup for the partially built workspace and the
compiled XPath expression.  Also check xmlXPathNewContext() before
dereferencing the returned context.
---
 contrib/xml2/xpath.c | 51 +++++++++++++++++++++++++++-----------------
 1 file changed, 32 insertions(+), 19 deletions(-)

diff --git a/contrib/xml2/xpath.c b/contrib/xml2/xpath.c
index 9fe75cb5ff4..283bb51178d 100644
--- a/contrib/xml2/xpath.c
+++ b/contrib/xml2/xpath.c
@@ -497,36 +497,49 @@ static xpath_workspace *
 pgxml_xpath(text *document, xmlChar *xpath, PgXmlErrorContext *xmlerrcxt)
 {
 	int32		docsize = VARSIZE_ANY_EXHDR(document);
-	xmlXPathCompExprPtr comppath;
+	xmlXPathCompExprPtr volatile comppath = NULL;
 	xpath_workspace *workspace = palloc0_object(xpath_workspace);
 
 	workspace->doctree = NULL;
 	workspace->ctxt = NULL;
 	workspace->res = NULL;
 
-	workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
-									   docsize, NULL, NULL,
-									   XML_PARSE_NOENT);
-	if (workspace->doctree != NULL)
+	PG_TRY();
 	{
-		workspace->ctxt = xmlXPathNewContext(workspace->doctree);
-		workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
-
-		/* compile the path */
-		comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
-		if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+		workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
+										   docsize, NULL, NULL,
+										   XML_PARSE_NOENT);
+		if (workspace->doctree != NULL)
 		{
-			if (comppath != NULL)
-				xmlXPathFreeCompExpr(comppath);
-			xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
-						"XPath Syntax Error");
-		}
+			workspace->ctxt = xmlXPathNewContext(workspace->doctree);
+			if (workspace->ctxt == NULL)
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_OUT_OF_MEMORY,
+							"could not allocate XPath context");
 
-		/* Now evaluate the path expression. */
-		workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+			workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
+
+			/* compile the path */
+			comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
+			if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
+							"XPath Syntax Error");
+
+			/* Now evaluate the path expression. */
+			workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+
+			xmlXPathFreeCompExpr(comppath);
+			comppath = NULL;
+		}
+	}
+	PG_CATCH();
+	{
+		if (comppath != NULL)
+			xmlXPathFreeCompExpr(comppath);
+		cleanup_workspace(workspace);
 
-		xmlXPathFreeCompExpr(comppath);
+		PG_RE_THROW();
 	}
+	PG_END_TRY();
 
 	return workspace;
 }
-- 
2.54.0


--MP_/LMSk9=uMhuQ1QiIJDarDO8G--





^ permalink  raw  reply  [nested|flat] 611+ messages in thread

* [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths
@ 2026-06-01 22:41 Andrey Chernyy <andrey.cherny@tantorlabs.com>
  0 siblings, 0 replies; 611+ messages in thread

From: Andrey Chernyy @ 2026-06-01 22:41 UTC (permalink / raw)

pgxml_xpath() builds an xpath_workspace before returning it to
callers.  If an ERROR is thrown before the function returns, callers
have not received the workspace pointer yet and cannot run
cleanup_workspace().

Add local error cleanup for the partially built workspace and the
compiled XPath expression.  Also check xmlXPathNewContext() before
dereferencing the returned context.
---
 contrib/xml2/xpath.c | 51 +++++++++++++++++++++++++++-----------------
 1 file changed, 32 insertions(+), 19 deletions(-)

diff --git a/contrib/xml2/xpath.c b/contrib/xml2/xpath.c
index 9fe75cb5ff4..283bb51178d 100644
--- a/contrib/xml2/xpath.c
+++ b/contrib/xml2/xpath.c
@@ -497,36 +497,49 @@ static xpath_workspace *
 pgxml_xpath(text *document, xmlChar *xpath, PgXmlErrorContext *xmlerrcxt)
 {
 	int32		docsize = VARSIZE_ANY_EXHDR(document);
-	xmlXPathCompExprPtr comppath;
+	xmlXPathCompExprPtr volatile comppath = NULL;
 	xpath_workspace *workspace = palloc0_object(xpath_workspace);
 
 	workspace->doctree = NULL;
 	workspace->ctxt = NULL;
 	workspace->res = NULL;
 
-	workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
-									   docsize, NULL, NULL,
-									   XML_PARSE_NOENT);
-	if (workspace->doctree != NULL)
+	PG_TRY();
 	{
-		workspace->ctxt = xmlXPathNewContext(workspace->doctree);
-		workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
-
-		/* compile the path */
-		comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
-		if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+		workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
+										   docsize, NULL, NULL,
+										   XML_PARSE_NOENT);
+		if (workspace->doctree != NULL)
 		{
-			if (comppath != NULL)
-				xmlXPathFreeCompExpr(comppath);
-			xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
-						"XPath Syntax Error");
-		}
+			workspace->ctxt = xmlXPathNewContext(workspace->doctree);
+			if (workspace->ctxt == NULL)
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_OUT_OF_MEMORY,
+							"could not allocate XPath context");
 
-		/* Now evaluate the path expression. */
-		workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+			workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
+
+			/* compile the path */
+			comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
+			if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
+							"XPath Syntax Error");
+
+			/* Now evaluate the path expression. */
+			workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+
+			xmlXPathFreeCompExpr(comppath);
+			comppath = NULL;
+		}
+	}
+	PG_CATCH();
+	{
+		if (comppath != NULL)
+			xmlXPathFreeCompExpr(comppath);
+		cleanup_workspace(workspace);
 
-		xmlXPathFreeCompExpr(comppath);
+		PG_RE_THROW();
 	}
+	PG_END_TRY();
 
 	return workspace;
 }
-- 
2.54.0


--MP_/LMSk9=uMhuQ1QiIJDarDO8G--






^ permalink  raw  reply  [nested|flat] 611+ messages in thread

* [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths
@ 2026-06-01 22:41 Andrey Chernyy <andrey.cherny@tantorlabs.com>
  0 siblings, 0 replies; 611+ messages in thread

From: Andrey Chernyy @ 2026-06-01 22:41 UTC (permalink / raw)

pgxml_xpath() builds an xpath_workspace before returning it to
callers.  If an ERROR is thrown before the function returns, callers
have not received the workspace pointer yet and cannot run
cleanup_workspace().

Add local error cleanup for the partially built workspace and the
compiled XPath expression.  Also check xmlXPathNewContext() before
dereferencing the returned context.
---
 contrib/xml2/xpath.c | 51 +++++++++++++++++++++++++++-----------------
 1 file changed, 32 insertions(+), 19 deletions(-)

diff --git a/contrib/xml2/xpath.c b/contrib/xml2/xpath.c
index 9fe75cb5ff4..283bb51178d 100644
--- a/contrib/xml2/xpath.c
+++ b/contrib/xml2/xpath.c
@@ -497,36 +497,49 @@ static xpath_workspace *
 pgxml_xpath(text *document, xmlChar *xpath, PgXmlErrorContext *xmlerrcxt)
 {
 	int32		docsize = VARSIZE_ANY_EXHDR(document);
-	xmlXPathCompExprPtr comppath;
+	xmlXPathCompExprPtr volatile comppath = NULL;
 	xpath_workspace *workspace = palloc0_object(xpath_workspace);
 
 	workspace->doctree = NULL;
 	workspace->ctxt = NULL;
 	workspace->res = NULL;
 
-	workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
-									   docsize, NULL, NULL,
-									   XML_PARSE_NOENT);
-	if (workspace->doctree != NULL)
+	PG_TRY();
 	{
-		workspace->ctxt = xmlXPathNewContext(workspace->doctree);
-		workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
-
-		/* compile the path */
-		comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
-		if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+		workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
+										   docsize, NULL, NULL,
+										   XML_PARSE_NOENT);
+		if (workspace->doctree != NULL)
 		{
-			if (comppath != NULL)
-				xmlXPathFreeCompExpr(comppath);
-			xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
-						"XPath Syntax Error");
-		}
+			workspace->ctxt = xmlXPathNewContext(workspace->doctree);
+			if (workspace->ctxt == NULL)
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_OUT_OF_MEMORY,
+							"could not allocate XPath context");
 
-		/* Now evaluate the path expression. */
-		workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+			workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
+
+			/* compile the path */
+			comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
+			if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
+							"XPath Syntax Error");
+
+			/* Now evaluate the path expression. */
+			workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+
+			xmlXPathFreeCompExpr(comppath);
+			comppath = NULL;
+		}
+	}
+	PG_CATCH();
+	{
+		if (comppath != NULL)
+			xmlXPathFreeCompExpr(comppath);
+		cleanup_workspace(workspace);
 
-		xmlXPathFreeCompExpr(comppath);
+		PG_RE_THROW();
 	}
+	PG_END_TRY();
 
 	return workspace;
 }
-- 
2.54.0


--MP_/LMSk9=uMhuQ1QiIJDarDO8G--






^ permalink  raw  reply  [nested|flat] 611+ messages in thread

* [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths
@ 2026-06-01 22:41 Andrey Chernyy <andrey.cherny@tantorlabs.com>
  0 siblings, 0 replies; 611+ messages in thread

From: Andrey Chernyy @ 2026-06-01 22:41 UTC (permalink / raw)

pgxml_xpath() builds an xpath_workspace before returning it to
callers.  If an ERROR is thrown before the function returns, callers
have not received the workspace pointer yet and cannot run
cleanup_workspace().

Add local error cleanup for the partially built workspace and the
compiled XPath expression.  Also check xmlXPathNewContext() before
dereferencing the returned context.
---
 contrib/xml2/xpath.c | 51 +++++++++++++++++++++++++++-----------------
 1 file changed, 32 insertions(+), 19 deletions(-)

diff --git a/contrib/xml2/xpath.c b/contrib/xml2/xpath.c
index 9fe75cb5ff4..283bb51178d 100644
--- a/contrib/xml2/xpath.c
+++ b/contrib/xml2/xpath.c
@@ -497,36 +497,49 @@ static xpath_workspace *
 pgxml_xpath(text *document, xmlChar *xpath, PgXmlErrorContext *xmlerrcxt)
 {
 	int32		docsize = VARSIZE_ANY_EXHDR(document);
-	xmlXPathCompExprPtr comppath;
+	xmlXPathCompExprPtr volatile comppath = NULL;
 	xpath_workspace *workspace = palloc0_object(xpath_workspace);
 
 	workspace->doctree = NULL;
 	workspace->ctxt = NULL;
 	workspace->res = NULL;
 
-	workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
-									   docsize, NULL, NULL,
-									   XML_PARSE_NOENT);
-	if (workspace->doctree != NULL)
+	PG_TRY();
 	{
-		workspace->ctxt = xmlXPathNewContext(workspace->doctree);
-		workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
-
-		/* compile the path */
-		comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
-		if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+		workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
+										   docsize, NULL, NULL,
+										   XML_PARSE_NOENT);
+		if (workspace->doctree != NULL)
 		{
-			if (comppath != NULL)
-				xmlXPathFreeCompExpr(comppath);
-			xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
-						"XPath Syntax Error");
-		}
+			workspace->ctxt = xmlXPathNewContext(workspace->doctree);
+			if (workspace->ctxt == NULL)
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_OUT_OF_MEMORY,
+							"could not allocate XPath context");
 
-		/* Now evaluate the path expression. */
-		workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+			workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
+
+			/* compile the path */
+			comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
+			if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
+							"XPath Syntax Error");
+
+			/* Now evaluate the path expression. */
+			workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+
+			xmlXPathFreeCompExpr(comppath);
+			comppath = NULL;
+		}
+	}
+	PG_CATCH();
+	{
+		if (comppath != NULL)
+			xmlXPathFreeCompExpr(comppath);
+		cleanup_workspace(workspace);
 
-		xmlXPathFreeCompExpr(comppath);
+		PG_RE_THROW();
 	}
+	PG_END_TRY();
 
 	return workspace;
 }
-- 
2.54.0


--MP_/LMSk9=uMhuQ1QiIJDarDO8G--






^ permalink  raw  reply  [nested|flat] 611+ messages in thread

* [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths
@ 2026-06-01 22:41 Andrey Chernyy <andrey.cherny@tantorlabs.com>
  0 siblings, 0 replies; 611+ messages in thread

From: Andrey Chernyy @ 2026-06-01 22:41 UTC (permalink / raw)

pgxml_xpath() builds an xpath_workspace before returning it to
callers.  If an ERROR is thrown before the function returns, callers
have not received the workspace pointer yet and cannot run
cleanup_workspace().

Add local error cleanup for the partially built workspace and the
compiled XPath expression.  Also check xmlXPathNewContext() before
dereferencing the returned context.
---
 contrib/xml2/xpath.c | 51 +++++++++++++++++++++++++++-----------------
 1 file changed, 32 insertions(+), 19 deletions(-)

diff --git a/contrib/xml2/xpath.c b/contrib/xml2/xpath.c
index 9fe75cb5ff4..283bb51178d 100644
--- a/contrib/xml2/xpath.c
+++ b/contrib/xml2/xpath.c
@@ -497,36 +497,49 @@ static xpath_workspace *
 pgxml_xpath(text *document, xmlChar *xpath, PgXmlErrorContext *xmlerrcxt)
 {
 	int32		docsize = VARSIZE_ANY_EXHDR(document);
-	xmlXPathCompExprPtr comppath;
+	xmlXPathCompExprPtr volatile comppath = NULL;
 	xpath_workspace *workspace = palloc0_object(xpath_workspace);
 
 	workspace->doctree = NULL;
 	workspace->ctxt = NULL;
 	workspace->res = NULL;
 
-	workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
-									   docsize, NULL, NULL,
-									   XML_PARSE_NOENT);
-	if (workspace->doctree != NULL)
+	PG_TRY();
 	{
-		workspace->ctxt = xmlXPathNewContext(workspace->doctree);
-		workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
-
-		/* compile the path */
-		comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
-		if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+		workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
+										   docsize, NULL, NULL,
+										   XML_PARSE_NOENT);
+		if (workspace->doctree != NULL)
 		{
-			if (comppath != NULL)
-				xmlXPathFreeCompExpr(comppath);
-			xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
-						"XPath Syntax Error");
-		}
+			workspace->ctxt = xmlXPathNewContext(workspace->doctree);
+			if (workspace->ctxt == NULL)
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_OUT_OF_MEMORY,
+							"could not allocate XPath context");
 
-		/* Now evaluate the path expression. */
-		workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+			workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
+
+			/* compile the path */
+			comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
+			if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
+							"XPath Syntax Error");
+
+			/* Now evaluate the path expression. */
+			workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+
+			xmlXPathFreeCompExpr(comppath);
+			comppath = NULL;
+		}
+	}
+	PG_CATCH();
+	{
+		if (comppath != NULL)
+			xmlXPathFreeCompExpr(comppath);
+		cleanup_workspace(workspace);
 
-		xmlXPathFreeCompExpr(comppath);
+		PG_RE_THROW();
 	}
+	PG_END_TRY();
 
 	return workspace;
 }
-- 
2.54.0


--MP_/LMSk9=uMhuQ1QiIJDarDO8G--





^ permalink  raw  reply  [nested|flat] 611+ messages in thread

* [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths
@ 2026-06-01 22:41 Andrey Chernyy <andrey.cherny@tantorlabs.com>
  0 siblings, 0 replies; 611+ messages in thread

From: Andrey Chernyy @ 2026-06-01 22:41 UTC (permalink / raw)

pgxml_xpath() builds an xpath_workspace before returning it to
callers.  If an ERROR is thrown before the function returns, callers
have not received the workspace pointer yet and cannot run
cleanup_workspace().

Add local error cleanup for the partially built workspace and the
compiled XPath expression.  Also check xmlXPathNewContext() before
dereferencing the returned context.
---
 contrib/xml2/xpath.c | 51 +++++++++++++++++++++++++++-----------------
 1 file changed, 32 insertions(+), 19 deletions(-)

diff --git a/contrib/xml2/xpath.c b/contrib/xml2/xpath.c
index 9fe75cb5ff4..283bb51178d 100644
--- a/contrib/xml2/xpath.c
+++ b/contrib/xml2/xpath.c
@@ -497,36 +497,49 @@ static xpath_workspace *
 pgxml_xpath(text *document, xmlChar *xpath, PgXmlErrorContext *xmlerrcxt)
 {
 	int32		docsize = VARSIZE_ANY_EXHDR(document);
-	xmlXPathCompExprPtr comppath;
+	xmlXPathCompExprPtr volatile comppath = NULL;
 	xpath_workspace *workspace = palloc0_object(xpath_workspace);
 
 	workspace->doctree = NULL;
 	workspace->ctxt = NULL;
 	workspace->res = NULL;
 
-	workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
-									   docsize, NULL, NULL,
-									   XML_PARSE_NOENT);
-	if (workspace->doctree != NULL)
+	PG_TRY();
 	{
-		workspace->ctxt = xmlXPathNewContext(workspace->doctree);
-		workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
-
-		/* compile the path */
-		comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
-		if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+		workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
+										   docsize, NULL, NULL,
+										   XML_PARSE_NOENT);
+		if (workspace->doctree != NULL)
 		{
-			if (comppath != NULL)
-				xmlXPathFreeCompExpr(comppath);
-			xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
-						"XPath Syntax Error");
-		}
+			workspace->ctxt = xmlXPathNewContext(workspace->doctree);
+			if (workspace->ctxt == NULL)
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_OUT_OF_MEMORY,
+							"could not allocate XPath context");
 
-		/* Now evaluate the path expression. */
-		workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+			workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
+
+			/* compile the path */
+			comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
+			if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
+							"XPath Syntax Error");
+
+			/* Now evaluate the path expression. */
+			workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+
+			xmlXPathFreeCompExpr(comppath);
+			comppath = NULL;
+		}
+	}
+	PG_CATCH();
+	{
+		if (comppath != NULL)
+			xmlXPathFreeCompExpr(comppath);
+		cleanup_workspace(workspace);
 
-		xmlXPathFreeCompExpr(comppath);
+		PG_RE_THROW();
 	}
+	PG_END_TRY();
 
 	return workspace;
 }
-- 
2.54.0


--MP_/LMSk9=uMhuQ1QiIJDarDO8G--






^ permalink  raw  reply  [nested|flat] 611+ messages in thread

* [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths
@ 2026-06-01 22:41 Andrey Chernyy <andrey.cherny@tantorlabs.com>
  0 siblings, 0 replies; 611+ messages in thread

From: Andrey Chernyy @ 2026-06-01 22:41 UTC (permalink / raw)

pgxml_xpath() builds an xpath_workspace before returning it to
callers.  If an ERROR is thrown before the function returns, callers
have not received the workspace pointer yet and cannot run
cleanup_workspace().

Add local error cleanup for the partially built workspace and the
compiled XPath expression.  Also check xmlXPathNewContext() before
dereferencing the returned context.
---
 contrib/xml2/xpath.c | 51 +++++++++++++++++++++++++++-----------------
 1 file changed, 32 insertions(+), 19 deletions(-)

diff --git a/contrib/xml2/xpath.c b/contrib/xml2/xpath.c
index 9fe75cb5ff4..283bb51178d 100644
--- a/contrib/xml2/xpath.c
+++ b/contrib/xml2/xpath.c
@@ -497,36 +497,49 @@ static xpath_workspace *
 pgxml_xpath(text *document, xmlChar *xpath, PgXmlErrorContext *xmlerrcxt)
 {
 	int32		docsize = VARSIZE_ANY_EXHDR(document);
-	xmlXPathCompExprPtr comppath;
+	xmlXPathCompExprPtr volatile comppath = NULL;
 	xpath_workspace *workspace = palloc0_object(xpath_workspace);
 
 	workspace->doctree = NULL;
 	workspace->ctxt = NULL;
 	workspace->res = NULL;
 
-	workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
-									   docsize, NULL, NULL,
-									   XML_PARSE_NOENT);
-	if (workspace->doctree != NULL)
+	PG_TRY();
 	{
-		workspace->ctxt = xmlXPathNewContext(workspace->doctree);
-		workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
-
-		/* compile the path */
-		comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
-		if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+		workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
+										   docsize, NULL, NULL,
+										   XML_PARSE_NOENT);
+		if (workspace->doctree != NULL)
 		{
-			if (comppath != NULL)
-				xmlXPathFreeCompExpr(comppath);
-			xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
-						"XPath Syntax Error");
-		}
+			workspace->ctxt = xmlXPathNewContext(workspace->doctree);
+			if (workspace->ctxt == NULL)
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_OUT_OF_MEMORY,
+							"could not allocate XPath context");
 
-		/* Now evaluate the path expression. */
-		workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+			workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
+
+			/* compile the path */
+			comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
+			if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
+							"XPath Syntax Error");
+
+			/* Now evaluate the path expression. */
+			workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+
+			xmlXPathFreeCompExpr(comppath);
+			comppath = NULL;
+		}
+	}
+	PG_CATCH();
+	{
+		if (comppath != NULL)
+			xmlXPathFreeCompExpr(comppath);
+		cleanup_workspace(workspace);
 
-		xmlXPathFreeCompExpr(comppath);
+		PG_RE_THROW();
 	}
+	PG_END_TRY();
 
 	return workspace;
 }
-- 
2.54.0


--MP_/LMSk9=uMhuQ1QiIJDarDO8G--






^ permalink  raw  reply  [nested|flat] 611+ messages in thread

* [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths
@ 2026-06-01 22:41 Andrey Chernyy <andrey.cherny@tantorlabs.com>
  0 siblings, 0 replies; 611+ messages in thread

From: Andrey Chernyy @ 2026-06-01 22:41 UTC (permalink / raw)

pgxml_xpath() builds an xpath_workspace before returning it to
callers.  If an ERROR is thrown before the function returns, callers
have not received the workspace pointer yet and cannot run
cleanup_workspace().

Add local error cleanup for the partially built workspace and the
compiled XPath expression.  Also check xmlXPathNewContext() before
dereferencing the returned context.
---
 contrib/xml2/xpath.c | 51 +++++++++++++++++++++++++++-----------------
 1 file changed, 32 insertions(+), 19 deletions(-)

diff --git a/contrib/xml2/xpath.c b/contrib/xml2/xpath.c
index 9fe75cb5ff4..283bb51178d 100644
--- a/contrib/xml2/xpath.c
+++ b/contrib/xml2/xpath.c
@@ -497,36 +497,49 @@ static xpath_workspace *
 pgxml_xpath(text *document, xmlChar *xpath, PgXmlErrorContext *xmlerrcxt)
 {
 	int32		docsize = VARSIZE_ANY_EXHDR(document);
-	xmlXPathCompExprPtr comppath;
+	xmlXPathCompExprPtr volatile comppath = NULL;
 	xpath_workspace *workspace = palloc0_object(xpath_workspace);
 
 	workspace->doctree = NULL;
 	workspace->ctxt = NULL;
 	workspace->res = NULL;
 
-	workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
-									   docsize, NULL, NULL,
-									   XML_PARSE_NOENT);
-	if (workspace->doctree != NULL)
+	PG_TRY();
 	{
-		workspace->ctxt = xmlXPathNewContext(workspace->doctree);
-		workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
-
-		/* compile the path */
-		comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
-		if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+		workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
+										   docsize, NULL, NULL,
+										   XML_PARSE_NOENT);
+		if (workspace->doctree != NULL)
 		{
-			if (comppath != NULL)
-				xmlXPathFreeCompExpr(comppath);
-			xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
-						"XPath Syntax Error");
-		}
+			workspace->ctxt = xmlXPathNewContext(workspace->doctree);
+			if (workspace->ctxt == NULL)
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_OUT_OF_MEMORY,
+							"could not allocate XPath context");
 
-		/* Now evaluate the path expression. */
-		workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+			workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
+
+			/* compile the path */
+			comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
+			if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
+							"XPath Syntax Error");
+
+			/* Now evaluate the path expression. */
+			workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+
+			xmlXPathFreeCompExpr(comppath);
+			comppath = NULL;
+		}
+	}
+	PG_CATCH();
+	{
+		if (comppath != NULL)
+			xmlXPathFreeCompExpr(comppath);
+		cleanup_workspace(workspace);
 
-		xmlXPathFreeCompExpr(comppath);
+		PG_RE_THROW();
 	}
+	PG_END_TRY();
 
 	return workspace;
 }
-- 
2.54.0


--MP_/LMSk9=uMhuQ1QiIJDarDO8G--






^ permalink  raw  reply  [nested|flat] 611+ messages in thread

* [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths
@ 2026-06-01 22:41 Andrey Chernyy <andrey.cherny@tantorlabs.com>
  0 siblings, 0 replies; 611+ messages in thread

From: Andrey Chernyy @ 2026-06-01 22:41 UTC (permalink / raw)

pgxml_xpath() builds an xpath_workspace before returning it to
callers.  If an ERROR is thrown before the function returns, callers
have not received the workspace pointer yet and cannot run
cleanup_workspace().

Add local error cleanup for the partially built workspace and the
compiled XPath expression.  Also check xmlXPathNewContext() before
dereferencing the returned context.
---
 contrib/xml2/xpath.c | 51 +++++++++++++++++++++++++++-----------------
 1 file changed, 32 insertions(+), 19 deletions(-)

diff --git a/contrib/xml2/xpath.c b/contrib/xml2/xpath.c
index 9fe75cb5ff4..283bb51178d 100644
--- a/contrib/xml2/xpath.c
+++ b/contrib/xml2/xpath.c
@@ -497,36 +497,49 @@ static xpath_workspace *
 pgxml_xpath(text *document, xmlChar *xpath, PgXmlErrorContext *xmlerrcxt)
 {
 	int32		docsize = VARSIZE_ANY_EXHDR(document);
-	xmlXPathCompExprPtr comppath;
+	xmlXPathCompExprPtr volatile comppath = NULL;
 	xpath_workspace *workspace = palloc0_object(xpath_workspace);
 
 	workspace->doctree = NULL;
 	workspace->ctxt = NULL;
 	workspace->res = NULL;
 
-	workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
-									   docsize, NULL, NULL,
-									   XML_PARSE_NOENT);
-	if (workspace->doctree != NULL)
+	PG_TRY();
 	{
-		workspace->ctxt = xmlXPathNewContext(workspace->doctree);
-		workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
-
-		/* compile the path */
-		comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
-		if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+		workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
+										   docsize, NULL, NULL,
+										   XML_PARSE_NOENT);
+		if (workspace->doctree != NULL)
 		{
-			if (comppath != NULL)
-				xmlXPathFreeCompExpr(comppath);
-			xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
-						"XPath Syntax Error");
-		}
+			workspace->ctxt = xmlXPathNewContext(workspace->doctree);
+			if (workspace->ctxt == NULL)
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_OUT_OF_MEMORY,
+							"could not allocate XPath context");
 
-		/* Now evaluate the path expression. */
-		workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+			workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
+
+			/* compile the path */
+			comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
+			if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
+							"XPath Syntax Error");
+
+			/* Now evaluate the path expression. */
+			workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+
+			xmlXPathFreeCompExpr(comppath);
+			comppath = NULL;
+		}
+	}
+	PG_CATCH();
+	{
+		if (comppath != NULL)
+			xmlXPathFreeCompExpr(comppath);
+		cleanup_workspace(workspace);
 
-		xmlXPathFreeCompExpr(comppath);
+		PG_RE_THROW();
 	}
+	PG_END_TRY();
 
 	return workspace;
 }
-- 
2.54.0


--MP_/LMSk9=uMhuQ1QiIJDarDO8G--






^ permalink  raw  reply  [nested|flat] 611+ messages in thread

* [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths
@ 2026-06-01 22:41 Andrey Chernyy <andrey.cherny@tantorlabs.com>
  0 siblings, 0 replies; 611+ messages in thread

From: Andrey Chernyy @ 2026-06-01 22:41 UTC (permalink / raw)

pgxml_xpath() builds an xpath_workspace before returning it to
callers.  If an ERROR is thrown before the function returns, callers
have not received the workspace pointer yet and cannot run
cleanup_workspace().

Add local error cleanup for the partially built workspace and the
compiled XPath expression.  Also check xmlXPathNewContext() before
dereferencing the returned context.
---
 contrib/xml2/xpath.c | 51 +++++++++++++++++++++++++++-----------------
 1 file changed, 32 insertions(+), 19 deletions(-)

diff --git a/contrib/xml2/xpath.c b/contrib/xml2/xpath.c
index 9fe75cb5ff4..283bb51178d 100644
--- a/contrib/xml2/xpath.c
+++ b/contrib/xml2/xpath.c
@@ -497,36 +497,49 @@ static xpath_workspace *
 pgxml_xpath(text *document, xmlChar *xpath, PgXmlErrorContext *xmlerrcxt)
 {
 	int32		docsize = VARSIZE_ANY_EXHDR(document);
-	xmlXPathCompExprPtr comppath;
+	xmlXPathCompExprPtr volatile comppath = NULL;
 	xpath_workspace *workspace = palloc0_object(xpath_workspace);
 
 	workspace->doctree = NULL;
 	workspace->ctxt = NULL;
 	workspace->res = NULL;
 
-	workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
-									   docsize, NULL, NULL,
-									   XML_PARSE_NOENT);
-	if (workspace->doctree != NULL)
+	PG_TRY();
 	{
-		workspace->ctxt = xmlXPathNewContext(workspace->doctree);
-		workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
-
-		/* compile the path */
-		comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
-		if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+		workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
+										   docsize, NULL, NULL,
+										   XML_PARSE_NOENT);
+		if (workspace->doctree != NULL)
 		{
-			if (comppath != NULL)
-				xmlXPathFreeCompExpr(comppath);
-			xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
-						"XPath Syntax Error");
-		}
+			workspace->ctxt = xmlXPathNewContext(workspace->doctree);
+			if (workspace->ctxt == NULL)
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_OUT_OF_MEMORY,
+							"could not allocate XPath context");
 
-		/* Now evaluate the path expression. */
-		workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+			workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
+
+			/* compile the path */
+			comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
+			if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
+							"XPath Syntax Error");
+
+			/* Now evaluate the path expression. */
+			workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+
+			xmlXPathFreeCompExpr(comppath);
+			comppath = NULL;
+		}
+	}
+	PG_CATCH();
+	{
+		if (comppath != NULL)
+			xmlXPathFreeCompExpr(comppath);
+		cleanup_workspace(workspace);
 
-		xmlXPathFreeCompExpr(comppath);
+		PG_RE_THROW();
 	}
+	PG_END_TRY();
 
 	return workspace;
 }
-- 
2.54.0


--MP_/LMSk9=uMhuQ1QiIJDarDO8G--





^ permalink  raw  reply  [nested|flat] 611+ messages in thread

* [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths
@ 2026-06-01 22:41 Andrey Chernyy <andrey.cherny@tantorlabs.com>
  0 siblings, 0 replies; 611+ messages in thread

From: Andrey Chernyy @ 2026-06-01 22:41 UTC (permalink / raw)

pgxml_xpath() builds an xpath_workspace before returning it to
callers.  If an ERROR is thrown before the function returns, callers
have not received the workspace pointer yet and cannot run
cleanup_workspace().

Add local error cleanup for the partially built workspace and the
compiled XPath expression.  Also check xmlXPathNewContext() before
dereferencing the returned context.
---
 contrib/xml2/xpath.c | 51 +++++++++++++++++++++++++++-----------------
 1 file changed, 32 insertions(+), 19 deletions(-)

diff --git a/contrib/xml2/xpath.c b/contrib/xml2/xpath.c
index 9fe75cb5ff4..283bb51178d 100644
--- a/contrib/xml2/xpath.c
+++ b/contrib/xml2/xpath.c
@@ -497,36 +497,49 @@ static xpath_workspace *
 pgxml_xpath(text *document, xmlChar *xpath, PgXmlErrorContext *xmlerrcxt)
 {
 	int32		docsize = VARSIZE_ANY_EXHDR(document);
-	xmlXPathCompExprPtr comppath;
+	xmlXPathCompExprPtr volatile comppath = NULL;
 	xpath_workspace *workspace = palloc0_object(xpath_workspace);
 
 	workspace->doctree = NULL;
 	workspace->ctxt = NULL;
 	workspace->res = NULL;
 
-	workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
-									   docsize, NULL, NULL,
-									   XML_PARSE_NOENT);
-	if (workspace->doctree != NULL)
+	PG_TRY();
 	{
-		workspace->ctxt = xmlXPathNewContext(workspace->doctree);
-		workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
-
-		/* compile the path */
-		comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
-		if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+		workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
+										   docsize, NULL, NULL,
+										   XML_PARSE_NOENT);
+		if (workspace->doctree != NULL)
 		{
-			if (comppath != NULL)
-				xmlXPathFreeCompExpr(comppath);
-			xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
-						"XPath Syntax Error");
-		}
+			workspace->ctxt = xmlXPathNewContext(workspace->doctree);
+			if (workspace->ctxt == NULL)
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_OUT_OF_MEMORY,
+							"could not allocate XPath context");
 
-		/* Now evaluate the path expression. */
-		workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+			workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
+
+			/* compile the path */
+			comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
+			if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
+							"XPath Syntax Error");
+
+			/* Now evaluate the path expression. */
+			workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+
+			xmlXPathFreeCompExpr(comppath);
+			comppath = NULL;
+		}
+	}
+	PG_CATCH();
+	{
+		if (comppath != NULL)
+			xmlXPathFreeCompExpr(comppath);
+		cleanup_workspace(workspace);
 
-		xmlXPathFreeCompExpr(comppath);
+		PG_RE_THROW();
 	}
+	PG_END_TRY();
 
 	return workspace;
 }
-- 
2.54.0


--MP_/LMSk9=uMhuQ1QiIJDarDO8G--





^ permalink  raw  reply  [nested|flat] 611+ messages in thread

* [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths
@ 2026-06-01 22:41 Andrey Chernyy <andrey.cherny@tantorlabs.com>
  0 siblings, 0 replies; 611+ messages in thread

From: Andrey Chernyy @ 2026-06-01 22:41 UTC (permalink / raw)

pgxml_xpath() builds an xpath_workspace before returning it to
callers.  If an ERROR is thrown before the function returns, callers
have not received the workspace pointer yet and cannot run
cleanup_workspace().

Add local error cleanup for the partially built workspace and the
compiled XPath expression.  Also check xmlXPathNewContext() before
dereferencing the returned context.
---
 contrib/xml2/xpath.c | 51 +++++++++++++++++++++++++++-----------------
 1 file changed, 32 insertions(+), 19 deletions(-)

diff --git a/contrib/xml2/xpath.c b/contrib/xml2/xpath.c
index 9fe75cb5ff4..283bb51178d 100644
--- a/contrib/xml2/xpath.c
+++ b/contrib/xml2/xpath.c
@@ -497,36 +497,49 @@ static xpath_workspace *
 pgxml_xpath(text *document, xmlChar *xpath, PgXmlErrorContext *xmlerrcxt)
 {
 	int32		docsize = VARSIZE_ANY_EXHDR(document);
-	xmlXPathCompExprPtr comppath;
+	xmlXPathCompExprPtr volatile comppath = NULL;
 	xpath_workspace *workspace = palloc0_object(xpath_workspace);
 
 	workspace->doctree = NULL;
 	workspace->ctxt = NULL;
 	workspace->res = NULL;
 
-	workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
-									   docsize, NULL, NULL,
-									   XML_PARSE_NOENT);
-	if (workspace->doctree != NULL)
+	PG_TRY();
 	{
-		workspace->ctxt = xmlXPathNewContext(workspace->doctree);
-		workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
-
-		/* compile the path */
-		comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
-		if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+		workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
+										   docsize, NULL, NULL,
+										   XML_PARSE_NOENT);
+		if (workspace->doctree != NULL)
 		{
-			if (comppath != NULL)
-				xmlXPathFreeCompExpr(comppath);
-			xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
-						"XPath Syntax Error");
-		}
+			workspace->ctxt = xmlXPathNewContext(workspace->doctree);
+			if (workspace->ctxt == NULL)
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_OUT_OF_MEMORY,
+							"could not allocate XPath context");
 
-		/* Now evaluate the path expression. */
-		workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+			workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
+
+			/* compile the path */
+			comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
+			if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
+							"XPath Syntax Error");
+
+			/* Now evaluate the path expression. */
+			workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+
+			xmlXPathFreeCompExpr(comppath);
+			comppath = NULL;
+		}
+	}
+	PG_CATCH();
+	{
+		if (comppath != NULL)
+			xmlXPathFreeCompExpr(comppath);
+		cleanup_workspace(workspace);
 
-		xmlXPathFreeCompExpr(comppath);
+		PG_RE_THROW();
 	}
+	PG_END_TRY();
 
 	return workspace;
 }
-- 
2.54.0


--MP_/LMSk9=uMhuQ1QiIJDarDO8G--





^ permalink  raw  reply  [nested|flat] 611+ messages in thread

* [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths
@ 2026-06-01 22:41 Andrey Chernyy <andrey.cherny@tantorlabs.com>
  0 siblings, 0 replies; 611+ messages in thread

From: Andrey Chernyy @ 2026-06-01 22:41 UTC (permalink / raw)

pgxml_xpath() builds an xpath_workspace before returning it to
callers.  If an ERROR is thrown before the function returns, callers
have not received the workspace pointer yet and cannot run
cleanup_workspace().

Add local error cleanup for the partially built workspace and the
compiled XPath expression.  Also check xmlXPathNewContext() before
dereferencing the returned context.
---
 contrib/xml2/xpath.c | 51 +++++++++++++++++++++++++++-----------------
 1 file changed, 32 insertions(+), 19 deletions(-)

diff --git a/contrib/xml2/xpath.c b/contrib/xml2/xpath.c
index 9fe75cb5ff4..283bb51178d 100644
--- a/contrib/xml2/xpath.c
+++ b/contrib/xml2/xpath.c
@@ -497,36 +497,49 @@ static xpath_workspace *
 pgxml_xpath(text *document, xmlChar *xpath, PgXmlErrorContext *xmlerrcxt)
 {
 	int32		docsize = VARSIZE_ANY_EXHDR(document);
-	xmlXPathCompExprPtr comppath;
+	xmlXPathCompExprPtr volatile comppath = NULL;
 	xpath_workspace *workspace = palloc0_object(xpath_workspace);
 
 	workspace->doctree = NULL;
 	workspace->ctxt = NULL;
 	workspace->res = NULL;
 
-	workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
-									   docsize, NULL, NULL,
-									   XML_PARSE_NOENT);
-	if (workspace->doctree != NULL)
+	PG_TRY();
 	{
-		workspace->ctxt = xmlXPathNewContext(workspace->doctree);
-		workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
-
-		/* compile the path */
-		comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
-		if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+		workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
+										   docsize, NULL, NULL,
+										   XML_PARSE_NOENT);
+		if (workspace->doctree != NULL)
 		{
-			if (comppath != NULL)
-				xmlXPathFreeCompExpr(comppath);
-			xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
-						"XPath Syntax Error");
-		}
+			workspace->ctxt = xmlXPathNewContext(workspace->doctree);
+			if (workspace->ctxt == NULL)
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_OUT_OF_MEMORY,
+							"could not allocate XPath context");
 
-		/* Now evaluate the path expression. */
-		workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+			workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
+
+			/* compile the path */
+			comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
+			if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
+							"XPath Syntax Error");
+
+			/* Now evaluate the path expression. */
+			workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+
+			xmlXPathFreeCompExpr(comppath);
+			comppath = NULL;
+		}
+	}
+	PG_CATCH();
+	{
+		if (comppath != NULL)
+			xmlXPathFreeCompExpr(comppath);
+		cleanup_workspace(workspace);
 
-		xmlXPathFreeCompExpr(comppath);
+		PG_RE_THROW();
 	}
+	PG_END_TRY();
 
 	return workspace;
 }
-- 
2.54.0


--MP_/LMSk9=uMhuQ1QiIJDarDO8G--





^ permalink  raw  reply  [nested|flat] 611+ messages in thread

* [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths
@ 2026-06-01 22:41 Andrey Chernyy <andrey.cherny@tantorlabs.com>
  0 siblings, 0 replies; 611+ messages in thread

From: Andrey Chernyy @ 2026-06-01 22:41 UTC (permalink / raw)

pgxml_xpath() builds an xpath_workspace before returning it to
callers.  If an ERROR is thrown before the function returns, callers
have not received the workspace pointer yet and cannot run
cleanup_workspace().

Add local error cleanup for the partially built workspace and the
compiled XPath expression.  Also check xmlXPathNewContext() before
dereferencing the returned context.
---
 contrib/xml2/xpath.c | 51 +++++++++++++++++++++++++++-----------------
 1 file changed, 32 insertions(+), 19 deletions(-)

diff --git a/contrib/xml2/xpath.c b/contrib/xml2/xpath.c
index 9fe75cb5ff4..283bb51178d 100644
--- a/contrib/xml2/xpath.c
+++ b/contrib/xml2/xpath.c
@@ -497,36 +497,49 @@ static xpath_workspace *
 pgxml_xpath(text *document, xmlChar *xpath, PgXmlErrorContext *xmlerrcxt)
 {
 	int32		docsize = VARSIZE_ANY_EXHDR(document);
-	xmlXPathCompExprPtr comppath;
+	xmlXPathCompExprPtr volatile comppath = NULL;
 	xpath_workspace *workspace = palloc0_object(xpath_workspace);
 
 	workspace->doctree = NULL;
 	workspace->ctxt = NULL;
 	workspace->res = NULL;
 
-	workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
-									   docsize, NULL, NULL,
-									   XML_PARSE_NOENT);
-	if (workspace->doctree != NULL)
+	PG_TRY();
 	{
-		workspace->ctxt = xmlXPathNewContext(workspace->doctree);
-		workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
-
-		/* compile the path */
-		comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
-		if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+		workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
+										   docsize, NULL, NULL,
+										   XML_PARSE_NOENT);
+		if (workspace->doctree != NULL)
 		{
-			if (comppath != NULL)
-				xmlXPathFreeCompExpr(comppath);
-			xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
-						"XPath Syntax Error");
-		}
+			workspace->ctxt = xmlXPathNewContext(workspace->doctree);
+			if (workspace->ctxt == NULL)
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_OUT_OF_MEMORY,
+							"could not allocate XPath context");
 
-		/* Now evaluate the path expression. */
-		workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+			workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
+
+			/* compile the path */
+			comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
+			if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
+							"XPath Syntax Error");
+
+			/* Now evaluate the path expression. */
+			workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+
+			xmlXPathFreeCompExpr(comppath);
+			comppath = NULL;
+		}
+	}
+	PG_CATCH();
+	{
+		if (comppath != NULL)
+			xmlXPathFreeCompExpr(comppath);
+		cleanup_workspace(workspace);
 
-		xmlXPathFreeCompExpr(comppath);
+		PG_RE_THROW();
 	}
+	PG_END_TRY();
 
 	return workspace;
 }
-- 
2.54.0


--MP_/LMSk9=uMhuQ1QiIJDarDO8G--






^ permalink  raw  reply  [nested|flat] 611+ messages in thread

* [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths
@ 2026-06-01 22:41 Andrey Chernyy <andrey.cherny@tantorlabs.com>
  0 siblings, 0 replies; 611+ messages in thread

From: Andrey Chernyy @ 2026-06-01 22:41 UTC (permalink / raw)

pgxml_xpath() builds an xpath_workspace before returning it to
callers.  If an ERROR is thrown before the function returns, callers
have not received the workspace pointer yet and cannot run
cleanup_workspace().

Add local error cleanup for the partially built workspace and the
compiled XPath expression.  Also check xmlXPathNewContext() before
dereferencing the returned context.
---
 contrib/xml2/xpath.c | 51 +++++++++++++++++++++++++++-----------------
 1 file changed, 32 insertions(+), 19 deletions(-)

diff --git a/contrib/xml2/xpath.c b/contrib/xml2/xpath.c
index 9fe75cb5ff4..283bb51178d 100644
--- a/contrib/xml2/xpath.c
+++ b/contrib/xml2/xpath.c
@@ -497,36 +497,49 @@ static xpath_workspace *
 pgxml_xpath(text *document, xmlChar *xpath, PgXmlErrorContext *xmlerrcxt)
 {
 	int32		docsize = VARSIZE_ANY_EXHDR(document);
-	xmlXPathCompExprPtr comppath;
+	xmlXPathCompExprPtr volatile comppath = NULL;
 	xpath_workspace *workspace = palloc0_object(xpath_workspace);
 
 	workspace->doctree = NULL;
 	workspace->ctxt = NULL;
 	workspace->res = NULL;
 
-	workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
-									   docsize, NULL, NULL,
-									   XML_PARSE_NOENT);
-	if (workspace->doctree != NULL)
+	PG_TRY();
 	{
-		workspace->ctxt = xmlXPathNewContext(workspace->doctree);
-		workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
-
-		/* compile the path */
-		comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
-		if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+		workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
+										   docsize, NULL, NULL,
+										   XML_PARSE_NOENT);
+		if (workspace->doctree != NULL)
 		{
-			if (comppath != NULL)
-				xmlXPathFreeCompExpr(comppath);
-			xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
-						"XPath Syntax Error");
-		}
+			workspace->ctxt = xmlXPathNewContext(workspace->doctree);
+			if (workspace->ctxt == NULL)
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_OUT_OF_MEMORY,
+							"could not allocate XPath context");
 
-		/* Now evaluate the path expression. */
-		workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+			workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
+
+			/* compile the path */
+			comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
+			if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
+							"XPath Syntax Error");
+
+			/* Now evaluate the path expression. */
+			workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+
+			xmlXPathFreeCompExpr(comppath);
+			comppath = NULL;
+		}
+	}
+	PG_CATCH();
+	{
+		if (comppath != NULL)
+			xmlXPathFreeCompExpr(comppath);
+		cleanup_workspace(workspace);
 
-		xmlXPathFreeCompExpr(comppath);
+		PG_RE_THROW();
 	}
+	PG_END_TRY();
 
 	return workspace;
 }
-- 
2.54.0


--MP_/LMSk9=uMhuQ1QiIJDarDO8G--





^ permalink  raw  reply  [nested|flat] 611+ messages in thread

* [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths
@ 2026-06-01 22:41 Andrey Chernyy <andrey.cherny@tantorlabs.com>
  0 siblings, 0 replies; 611+ messages in thread

From: Andrey Chernyy @ 2026-06-01 22:41 UTC (permalink / raw)

pgxml_xpath() builds an xpath_workspace before returning it to
callers.  If an ERROR is thrown before the function returns, callers
have not received the workspace pointer yet and cannot run
cleanup_workspace().

Add local error cleanup for the partially built workspace and the
compiled XPath expression.  Also check xmlXPathNewContext() before
dereferencing the returned context.
---
 contrib/xml2/xpath.c | 51 +++++++++++++++++++++++++++-----------------
 1 file changed, 32 insertions(+), 19 deletions(-)

diff --git a/contrib/xml2/xpath.c b/contrib/xml2/xpath.c
index 9fe75cb5ff4..283bb51178d 100644
--- a/contrib/xml2/xpath.c
+++ b/contrib/xml2/xpath.c
@@ -497,36 +497,49 @@ static xpath_workspace *
 pgxml_xpath(text *document, xmlChar *xpath, PgXmlErrorContext *xmlerrcxt)
 {
 	int32		docsize = VARSIZE_ANY_EXHDR(document);
-	xmlXPathCompExprPtr comppath;
+	xmlXPathCompExprPtr volatile comppath = NULL;
 	xpath_workspace *workspace = palloc0_object(xpath_workspace);
 
 	workspace->doctree = NULL;
 	workspace->ctxt = NULL;
 	workspace->res = NULL;
 
-	workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
-									   docsize, NULL, NULL,
-									   XML_PARSE_NOENT);
-	if (workspace->doctree != NULL)
+	PG_TRY();
 	{
-		workspace->ctxt = xmlXPathNewContext(workspace->doctree);
-		workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
-
-		/* compile the path */
-		comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
-		if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+		workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
+										   docsize, NULL, NULL,
+										   XML_PARSE_NOENT);
+		if (workspace->doctree != NULL)
 		{
-			if (comppath != NULL)
-				xmlXPathFreeCompExpr(comppath);
-			xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
-						"XPath Syntax Error");
-		}
+			workspace->ctxt = xmlXPathNewContext(workspace->doctree);
+			if (workspace->ctxt == NULL)
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_OUT_OF_MEMORY,
+							"could not allocate XPath context");
 
-		/* Now evaluate the path expression. */
-		workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+			workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
+
+			/* compile the path */
+			comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
+			if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
+							"XPath Syntax Error");
+
+			/* Now evaluate the path expression. */
+			workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+
+			xmlXPathFreeCompExpr(comppath);
+			comppath = NULL;
+		}
+	}
+	PG_CATCH();
+	{
+		if (comppath != NULL)
+			xmlXPathFreeCompExpr(comppath);
+		cleanup_workspace(workspace);
 
-		xmlXPathFreeCompExpr(comppath);
+		PG_RE_THROW();
 	}
+	PG_END_TRY();
 
 	return workspace;
 }
-- 
2.54.0


--MP_/LMSk9=uMhuQ1QiIJDarDO8G--






^ permalink  raw  reply  [nested|flat] 611+ messages in thread

* [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths
@ 2026-06-01 22:41 Andrey Chernyy <andrey.cherny@tantorlabs.com>
  0 siblings, 0 replies; 611+ messages in thread

From: Andrey Chernyy @ 2026-06-01 22:41 UTC (permalink / raw)

pgxml_xpath() builds an xpath_workspace before returning it to
callers.  If an ERROR is thrown before the function returns, callers
have not received the workspace pointer yet and cannot run
cleanup_workspace().

Add local error cleanup for the partially built workspace and the
compiled XPath expression.  Also check xmlXPathNewContext() before
dereferencing the returned context.
---
 contrib/xml2/xpath.c | 51 +++++++++++++++++++++++++++-----------------
 1 file changed, 32 insertions(+), 19 deletions(-)

diff --git a/contrib/xml2/xpath.c b/contrib/xml2/xpath.c
index 9fe75cb5ff4..283bb51178d 100644
--- a/contrib/xml2/xpath.c
+++ b/contrib/xml2/xpath.c
@@ -497,36 +497,49 @@ static xpath_workspace *
 pgxml_xpath(text *document, xmlChar *xpath, PgXmlErrorContext *xmlerrcxt)
 {
 	int32		docsize = VARSIZE_ANY_EXHDR(document);
-	xmlXPathCompExprPtr comppath;
+	xmlXPathCompExprPtr volatile comppath = NULL;
 	xpath_workspace *workspace = palloc0_object(xpath_workspace);
 
 	workspace->doctree = NULL;
 	workspace->ctxt = NULL;
 	workspace->res = NULL;
 
-	workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
-									   docsize, NULL, NULL,
-									   XML_PARSE_NOENT);
-	if (workspace->doctree != NULL)
+	PG_TRY();
 	{
-		workspace->ctxt = xmlXPathNewContext(workspace->doctree);
-		workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
-
-		/* compile the path */
-		comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
-		if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+		workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
+										   docsize, NULL, NULL,
+										   XML_PARSE_NOENT);
+		if (workspace->doctree != NULL)
 		{
-			if (comppath != NULL)
-				xmlXPathFreeCompExpr(comppath);
-			xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
-						"XPath Syntax Error");
-		}
+			workspace->ctxt = xmlXPathNewContext(workspace->doctree);
+			if (workspace->ctxt == NULL)
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_OUT_OF_MEMORY,
+							"could not allocate XPath context");
 
-		/* Now evaluate the path expression. */
-		workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+			workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
+
+			/* compile the path */
+			comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
+			if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
+							"XPath Syntax Error");
+
+			/* Now evaluate the path expression. */
+			workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+
+			xmlXPathFreeCompExpr(comppath);
+			comppath = NULL;
+		}
+	}
+	PG_CATCH();
+	{
+		if (comppath != NULL)
+			xmlXPathFreeCompExpr(comppath);
+		cleanup_workspace(workspace);
 
-		xmlXPathFreeCompExpr(comppath);
+		PG_RE_THROW();
 	}
+	PG_END_TRY();
 
 	return workspace;
 }
-- 
2.54.0


--MP_/LMSk9=uMhuQ1QiIJDarDO8G--





^ permalink  raw  reply  [nested|flat] 611+ messages in thread

* [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths
@ 2026-06-01 22:41 Andrey Chernyy <andrey.cherny@tantorlabs.com>
  0 siblings, 0 replies; 611+ messages in thread

From: Andrey Chernyy @ 2026-06-01 22:41 UTC (permalink / raw)

pgxml_xpath() builds an xpath_workspace before returning it to
callers.  If an ERROR is thrown before the function returns, callers
have not received the workspace pointer yet and cannot run
cleanup_workspace().

Add local error cleanup for the partially built workspace and the
compiled XPath expression.  Also check xmlXPathNewContext() before
dereferencing the returned context.
---
 contrib/xml2/xpath.c | 51 +++++++++++++++++++++++++++-----------------
 1 file changed, 32 insertions(+), 19 deletions(-)

diff --git a/contrib/xml2/xpath.c b/contrib/xml2/xpath.c
index 9fe75cb5ff4..283bb51178d 100644
--- a/contrib/xml2/xpath.c
+++ b/contrib/xml2/xpath.c
@@ -497,36 +497,49 @@ static xpath_workspace *
 pgxml_xpath(text *document, xmlChar *xpath, PgXmlErrorContext *xmlerrcxt)
 {
 	int32		docsize = VARSIZE_ANY_EXHDR(document);
-	xmlXPathCompExprPtr comppath;
+	xmlXPathCompExprPtr volatile comppath = NULL;
 	xpath_workspace *workspace = palloc0_object(xpath_workspace);
 
 	workspace->doctree = NULL;
 	workspace->ctxt = NULL;
 	workspace->res = NULL;
 
-	workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
-									   docsize, NULL, NULL,
-									   XML_PARSE_NOENT);
-	if (workspace->doctree != NULL)
+	PG_TRY();
 	{
-		workspace->ctxt = xmlXPathNewContext(workspace->doctree);
-		workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
-
-		/* compile the path */
-		comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
-		if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+		workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
+										   docsize, NULL, NULL,
+										   XML_PARSE_NOENT);
+		if (workspace->doctree != NULL)
 		{
-			if (comppath != NULL)
-				xmlXPathFreeCompExpr(comppath);
-			xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
-						"XPath Syntax Error");
-		}
+			workspace->ctxt = xmlXPathNewContext(workspace->doctree);
+			if (workspace->ctxt == NULL)
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_OUT_OF_MEMORY,
+							"could not allocate XPath context");
 
-		/* Now evaluate the path expression. */
-		workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+			workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
+
+			/* compile the path */
+			comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
+			if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
+							"XPath Syntax Error");
+
+			/* Now evaluate the path expression. */
+			workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+
+			xmlXPathFreeCompExpr(comppath);
+			comppath = NULL;
+		}
+	}
+	PG_CATCH();
+	{
+		if (comppath != NULL)
+			xmlXPathFreeCompExpr(comppath);
+		cleanup_workspace(workspace);
 
-		xmlXPathFreeCompExpr(comppath);
+		PG_RE_THROW();
 	}
+	PG_END_TRY();
 
 	return workspace;
 }
-- 
2.54.0


--MP_/LMSk9=uMhuQ1QiIJDarDO8G--






^ permalink  raw  reply  [nested|flat] 611+ messages in thread

* [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths
@ 2026-06-01 22:41 Andrey Chernyy <andrey.cherny@tantorlabs.com>
  0 siblings, 0 replies; 611+ messages in thread

From: Andrey Chernyy @ 2026-06-01 22:41 UTC (permalink / raw)

pgxml_xpath() builds an xpath_workspace before returning it to
callers.  If an ERROR is thrown before the function returns, callers
have not received the workspace pointer yet and cannot run
cleanup_workspace().

Add local error cleanup for the partially built workspace and the
compiled XPath expression.  Also check xmlXPathNewContext() before
dereferencing the returned context.
---
 contrib/xml2/xpath.c | 51 +++++++++++++++++++++++++++-----------------
 1 file changed, 32 insertions(+), 19 deletions(-)

diff --git a/contrib/xml2/xpath.c b/contrib/xml2/xpath.c
index 9fe75cb5ff4..283bb51178d 100644
--- a/contrib/xml2/xpath.c
+++ b/contrib/xml2/xpath.c
@@ -497,36 +497,49 @@ static xpath_workspace *
 pgxml_xpath(text *document, xmlChar *xpath, PgXmlErrorContext *xmlerrcxt)
 {
 	int32		docsize = VARSIZE_ANY_EXHDR(document);
-	xmlXPathCompExprPtr comppath;
+	xmlXPathCompExprPtr volatile comppath = NULL;
 	xpath_workspace *workspace = palloc0_object(xpath_workspace);
 
 	workspace->doctree = NULL;
 	workspace->ctxt = NULL;
 	workspace->res = NULL;
 
-	workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
-									   docsize, NULL, NULL,
-									   XML_PARSE_NOENT);
-	if (workspace->doctree != NULL)
+	PG_TRY();
 	{
-		workspace->ctxt = xmlXPathNewContext(workspace->doctree);
-		workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
-
-		/* compile the path */
-		comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
-		if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+		workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
+										   docsize, NULL, NULL,
+										   XML_PARSE_NOENT);
+		if (workspace->doctree != NULL)
 		{
-			if (comppath != NULL)
-				xmlXPathFreeCompExpr(comppath);
-			xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
-						"XPath Syntax Error");
-		}
+			workspace->ctxt = xmlXPathNewContext(workspace->doctree);
+			if (workspace->ctxt == NULL)
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_OUT_OF_MEMORY,
+							"could not allocate XPath context");
 
-		/* Now evaluate the path expression. */
-		workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+			workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
+
+			/* compile the path */
+			comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
+			if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
+							"XPath Syntax Error");
+
+			/* Now evaluate the path expression. */
+			workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+
+			xmlXPathFreeCompExpr(comppath);
+			comppath = NULL;
+		}
+	}
+	PG_CATCH();
+	{
+		if (comppath != NULL)
+			xmlXPathFreeCompExpr(comppath);
+		cleanup_workspace(workspace);
 
-		xmlXPathFreeCompExpr(comppath);
+		PG_RE_THROW();
 	}
+	PG_END_TRY();
 
 	return workspace;
 }
-- 
2.54.0


--MP_/LMSk9=uMhuQ1QiIJDarDO8G--






^ permalink  raw  reply  [nested|flat] 611+ messages in thread

* [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths
@ 2026-06-01 22:41 Andrey Chernyy <andrey.cherny@tantorlabs.com>
  0 siblings, 0 replies; 611+ messages in thread

From: Andrey Chernyy @ 2026-06-01 22:41 UTC (permalink / raw)

pgxml_xpath() builds an xpath_workspace before returning it to
callers.  If an ERROR is thrown before the function returns, callers
have not received the workspace pointer yet and cannot run
cleanup_workspace().

Add local error cleanup for the partially built workspace and the
compiled XPath expression.  Also check xmlXPathNewContext() before
dereferencing the returned context.
---
 contrib/xml2/xpath.c | 51 +++++++++++++++++++++++++++-----------------
 1 file changed, 32 insertions(+), 19 deletions(-)

diff --git a/contrib/xml2/xpath.c b/contrib/xml2/xpath.c
index 9fe75cb5ff4..283bb51178d 100644
--- a/contrib/xml2/xpath.c
+++ b/contrib/xml2/xpath.c
@@ -497,36 +497,49 @@ static xpath_workspace *
 pgxml_xpath(text *document, xmlChar *xpath, PgXmlErrorContext *xmlerrcxt)
 {
 	int32		docsize = VARSIZE_ANY_EXHDR(document);
-	xmlXPathCompExprPtr comppath;
+	xmlXPathCompExprPtr volatile comppath = NULL;
 	xpath_workspace *workspace = palloc0_object(xpath_workspace);
 
 	workspace->doctree = NULL;
 	workspace->ctxt = NULL;
 	workspace->res = NULL;
 
-	workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
-									   docsize, NULL, NULL,
-									   XML_PARSE_NOENT);
-	if (workspace->doctree != NULL)
+	PG_TRY();
 	{
-		workspace->ctxt = xmlXPathNewContext(workspace->doctree);
-		workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
-
-		/* compile the path */
-		comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
-		if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+		workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
+										   docsize, NULL, NULL,
+										   XML_PARSE_NOENT);
+		if (workspace->doctree != NULL)
 		{
-			if (comppath != NULL)
-				xmlXPathFreeCompExpr(comppath);
-			xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
-						"XPath Syntax Error");
-		}
+			workspace->ctxt = xmlXPathNewContext(workspace->doctree);
+			if (workspace->ctxt == NULL)
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_OUT_OF_MEMORY,
+							"could not allocate XPath context");
 
-		/* Now evaluate the path expression. */
-		workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+			workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
+
+			/* compile the path */
+			comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
+			if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
+							"XPath Syntax Error");
+
+			/* Now evaluate the path expression. */
+			workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+
+			xmlXPathFreeCompExpr(comppath);
+			comppath = NULL;
+		}
+	}
+	PG_CATCH();
+	{
+		if (comppath != NULL)
+			xmlXPathFreeCompExpr(comppath);
+		cleanup_workspace(workspace);
 
-		xmlXPathFreeCompExpr(comppath);
+		PG_RE_THROW();
 	}
+	PG_END_TRY();
 
 	return workspace;
 }
-- 
2.54.0


--MP_/LMSk9=uMhuQ1QiIJDarDO8G--






^ permalink  raw  reply  [nested|flat] 611+ messages in thread

* [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths
@ 2026-06-01 22:41 Andrey Chernyy <andrey.cherny@tantorlabs.com>
  0 siblings, 0 replies; 611+ messages in thread

From: Andrey Chernyy @ 2026-06-01 22:41 UTC (permalink / raw)

pgxml_xpath() builds an xpath_workspace before returning it to
callers.  If an ERROR is thrown before the function returns, callers
have not received the workspace pointer yet and cannot run
cleanup_workspace().

Add local error cleanup for the partially built workspace and the
compiled XPath expression.  Also check xmlXPathNewContext() before
dereferencing the returned context.
---
 contrib/xml2/xpath.c | 51 +++++++++++++++++++++++++++-----------------
 1 file changed, 32 insertions(+), 19 deletions(-)

diff --git a/contrib/xml2/xpath.c b/contrib/xml2/xpath.c
index 9fe75cb5ff4..283bb51178d 100644
--- a/contrib/xml2/xpath.c
+++ b/contrib/xml2/xpath.c
@@ -497,36 +497,49 @@ static xpath_workspace *
 pgxml_xpath(text *document, xmlChar *xpath, PgXmlErrorContext *xmlerrcxt)
 {
 	int32		docsize = VARSIZE_ANY_EXHDR(document);
-	xmlXPathCompExprPtr comppath;
+	xmlXPathCompExprPtr volatile comppath = NULL;
 	xpath_workspace *workspace = palloc0_object(xpath_workspace);
 
 	workspace->doctree = NULL;
 	workspace->ctxt = NULL;
 	workspace->res = NULL;
 
-	workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
-									   docsize, NULL, NULL,
-									   XML_PARSE_NOENT);
-	if (workspace->doctree != NULL)
+	PG_TRY();
 	{
-		workspace->ctxt = xmlXPathNewContext(workspace->doctree);
-		workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
-
-		/* compile the path */
-		comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
-		if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+		workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
+										   docsize, NULL, NULL,
+										   XML_PARSE_NOENT);
+		if (workspace->doctree != NULL)
 		{
-			if (comppath != NULL)
-				xmlXPathFreeCompExpr(comppath);
-			xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
-						"XPath Syntax Error");
-		}
+			workspace->ctxt = xmlXPathNewContext(workspace->doctree);
+			if (workspace->ctxt == NULL)
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_OUT_OF_MEMORY,
+							"could not allocate XPath context");
 
-		/* Now evaluate the path expression. */
-		workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+			workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
+
+			/* compile the path */
+			comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
+			if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
+							"XPath Syntax Error");
+
+			/* Now evaluate the path expression. */
+			workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+
+			xmlXPathFreeCompExpr(comppath);
+			comppath = NULL;
+		}
+	}
+	PG_CATCH();
+	{
+		if (comppath != NULL)
+			xmlXPathFreeCompExpr(comppath);
+		cleanup_workspace(workspace);
 
-		xmlXPathFreeCompExpr(comppath);
+		PG_RE_THROW();
 	}
+	PG_END_TRY();
 
 	return workspace;
 }
-- 
2.54.0


--MP_/LMSk9=uMhuQ1QiIJDarDO8G--






^ permalink  raw  reply  [nested|flat] 611+ messages in thread

* [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths
@ 2026-06-01 22:41 Andrey Chernyy <andrey.cherny@tantorlabs.com>
  0 siblings, 0 replies; 611+ messages in thread

From: Andrey Chernyy @ 2026-06-01 22:41 UTC (permalink / raw)

pgxml_xpath() builds an xpath_workspace before returning it to
callers.  If an ERROR is thrown before the function returns, callers
have not received the workspace pointer yet and cannot run
cleanup_workspace().

Add local error cleanup for the partially built workspace and the
compiled XPath expression.  Also check xmlXPathNewContext() before
dereferencing the returned context.
---
 contrib/xml2/xpath.c | 51 +++++++++++++++++++++++++++-----------------
 1 file changed, 32 insertions(+), 19 deletions(-)

diff --git a/contrib/xml2/xpath.c b/contrib/xml2/xpath.c
index 9fe75cb5ff4..283bb51178d 100644
--- a/contrib/xml2/xpath.c
+++ b/contrib/xml2/xpath.c
@@ -497,36 +497,49 @@ static xpath_workspace *
 pgxml_xpath(text *document, xmlChar *xpath, PgXmlErrorContext *xmlerrcxt)
 {
 	int32		docsize = VARSIZE_ANY_EXHDR(document);
-	xmlXPathCompExprPtr comppath;
+	xmlXPathCompExprPtr volatile comppath = NULL;
 	xpath_workspace *workspace = palloc0_object(xpath_workspace);
 
 	workspace->doctree = NULL;
 	workspace->ctxt = NULL;
 	workspace->res = NULL;
 
-	workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
-									   docsize, NULL, NULL,
-									   XML_PARSE_NOENT);
-	if (workspace->doctree != NULL)
+	PG_TRY();
 	{
-		workspace->ctxt = xmlXPathNewContext(workspace->doctree);
-		workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
-
-		/* compile the path */
-		comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
-		if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+		workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
+										   docsize, NULL, NULL,
+										   XML_PARSE_NOENT);
+		if (workspace->doctree != NULL)
 		{
-			if (comppath != NULL)
-				xmlXPathFreeCompExpr(comppath);
-			xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
-						"XPath Syntax Error");
-		}
+			workspace->ctxt = xmlXPathNewContext(workspace->doctree);
+			if (workspace->ctxt == NULL)
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_OUT_OF_MEMORY,
+							"could not allocate XPath context");
 
-		/* Now evaluate the path expression. */
-		workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+			workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
+
+			/* compile the path */
+			comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
+			if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
+							"XPath Syntax Error");
+
+			/* Now evaluate the path expression. */
+			workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+
+			xmlXPathFreeCompExpr(comppath);
+			comppath = NULL;
+		}
+	}
+	PG_CATCH();
+	{
+		if (comppath != NULL)
+			xmlXPathFreeCompExpr(comppath);
+		cleanup_workspace(workspace);
 
-		xmlXPathFreeCompExpr(comppath);
+		PG_RE_THROW();
 	}
+	PG_END_TRY();
 
 	return workspace;
 }
-- 
2.54.0


--MP_/LMSk9=uMhuQ1QiIJDarDO8G--





^ permalink  raw  reply  [nested|flat] 611+ messages in thread

* [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths
@ 2026-06-01 22:41 Andrey Chernyy <andrey.cherny@tantorlabs.com>
  0 siblings, 0 replies; 611+ messages in thread

From: Andrey Chernyy @ 2026-06-01 22:41 UTC (permalink / raw)

pgxml_xpath() builds an xpath_workspace before returning it to
callers.  If an ERROR is thrown before the function returns, callers
have not received the workspace pointer yet and cannot run
cleanup_workspace().

Add local error cleanup for the partially built workspace and the
compiled XPath expression.  Also check xmlXPathNewContext() before
dereferencing the returned context.
---
 contrib/xml2/xpath.c | 51 +++++++++++++++++++++++++++-----------------
 1 file changed, 32 insertions(+), 19 deletions(-)

diff --git a/contrib/xml2/xpath.c b/contrib/xml2/xpath.c
index 9fe75cb5ff4..283bb51178d 100644
--- a/contrib/xml2/xpath.c
+++ b/contrib/xml2/xpath.c
@@ -497,36 +497,49 @@ static xpath_workspace *
 pgxml_xpath(text *document, xmlChar *xpath, PgXmlErrorContext *xmlerrcxt)
 {
 	int32		docsize = VARSIZE_ANY_EXHDR(document);
-	xmlXPathCompExprPtr comppath;
+	xmlXPathCompExprPtr volatile comppath = NULL;
 	xpath_workspace *workspace = palloc0_object(xpath_workspace);
 
 	workspace->doctree = NULL;
 	workspace->ctxt = NULL;
 	workspace->res = NULL;
 
-	workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
-									   docsize, NULL, NULL,
-									   XML_PARSE_NOENT);
-	if (workspace->doctree != NULL)
+	PG_TRY();
 	{
-		workspace->ctxt = xmlXPathNewContext(workspace->doctree);
-		workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
-
-		/* compile the path */
-		comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
-		if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+		workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
+										   docsize, NULL, NULL,
+										   XML_PARSE_NOENT);
+		if (workspace->doctree != NULL)
 		{
-			if (comppath != NULL)
-				xmlXPathFreeCompExpr(comppath);
-			xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
-						"XPath Syntax Error");
-		}
+			workspace->ctxt = xmlXPathNewContext(workspace->doctree);
+			if (workspace->ctxt == NULL)
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_OUT_OF_MEMORY,
+							"could not allocate XPath context");
 
-		/* Now evaluate the path expression. */
-		workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+			workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
+
+			/* compile the path */
+			comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
+			if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
+							"XPath Syntax Error");
+
+			/* Now evaluate the path expression. */
+			workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+
+			xmlXPathFreeCompExpr(comppath);
+			comppath = NULL;
+		}
+	}
+	PG_CATCH();
+	{
+		if (comppath != NULL)
+			xmlXPathFreeCompExpr(comppath);
+		cleanup_workspace(workspace);
 
-		xmlXPathFreeCompExpr(comppath);
+		PG_RE_THROW();
 	}
+	PG_END_TRY();
 
 	return workspace;
 }
-- 
2.54.0


--MP_/LMSk9=uMhuQ1QiIJDarDO8G--





^ permalink  raw  reply  [nested|flat] 611+ messages in thread

* [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths
@ 2026-06-01 22:41 Andrey Chernyy <andrey.cherny@tantorlabs.com>
  0 siblings, 0 replies; 611+ messages in thread

From: Andrey Chernyy @ 2026-06-01 22:41 UTC (permalink / raw)

pgxml_xpath() builds an xpath_workspace before returning it to
callers.  If an ERROR is thrown before the function returns, callers
have not received the workspace pointer yet and cannot run
cleanup_workspace().

Add local error cleanup for the partially built workspace and the
compiled XPath expression.  Also check xmlXPathNewContext() before
dereferencing the returned context.
---
 contrib/xml2/xpath.c | 51 +++++++++++++++++++++++++++-----------------
 1 file changed, 32 insertions(+), 19 deletions(-)

diff --git a/contrib/xml2/xpath.c b/contrib/xml2/xpath.c
index 9fe75cb5ff4..283bb51178d 100644
--- a/contrib/xml2/xpath.c
+++ b/contrib/xml2/xpath.c
@@ -497,36 +497,49 @@ static xpath_workspace *
 pgxml_xpath(text *document, xmlChar *xpath, PgXmlErrorContext *xmlerrcxt)
 {
 	int32		docsize = VARSIZE_ANY_EXHDR(document);
-	xmlXPathCompExprPtr comppath;
+	xmlXPathCompExprPtr volatile comppath = NULL;
 	xpath_workspace *workspace = palloc0_object(xpath_workspace);
 
 	workspace->doctree = NULL;
 	workspace->ctxt = NULL;
 	workspace->res = NULL;
 
-	workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
-									   docsize, NULL, NULL,
-									   XML_PARSE_NOENT);
-	if (workspace->doctree != NULL)
+	PG_TRY();
 	{
-		workspace->ctxt = xmlXPathNewContext(workspace->doctree);
-		workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
-
-		/* compile the path */
-		comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
-		if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+		workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
+										   docsize, NULL, NULL,
+										   XML_PARSE_NOENT);
+		if (workspace->doctree != NULL)
 		{
-			if (comppath != NULL)
-				xmlXPathFreeCompExpr(comppath);
-			xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
-						"XPath Syntax Error");
-		}
+			workspace->ctxt = xmlXPathNewContext(workspace->doctree);
+			if (workspace->ctxt == NULL)
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_OUT_OF_MEMORY,
+							"could not allocate XPath context");
 
-		/* Now evaluate the path expression. */
-		workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+			workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
+
+			/* compile the path */
+			comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
+			if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
+							"XPath Syntax Error");
+
+			/* Now evaluate the path expression. */
+			workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+
+			xmlXPathFreeCompExpr(comppath);
+			comppath = NULL;
+		}
+	}
+	PG_CATCH();
+	{
+		if (comppath != NULL)
+			xmlXPathFreeCompExpr(comppath);
+		cleanup_workspace(workspace);
 
-		xmlXPathFreeCompExpr(comppath);
+		PG_RE_THROW();
 	}
+	PG_END_TRY();
 
 	return workspace;
 }
-- 
2.54.0


--MP_/LMSk9=uMhuQ1QiIJDarDO8G--






^ permalink  raw  reply  [nested|flat] 611+ messages in thread

* [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths
@ 2026-06-01 22:41 Andrey Chernyy <andrey.cherny@tantorlabs.com>
  0 siblings, 0 replies; 611+ messages in thread

From: Andrey Chernyy @ 2026-06-01 22:41 UTC (permalink / raw)

pgxml_xpath() builds an xpath_workspace before returning it to
callers.  If an ERROR is thrown before the function returns, callers
have not received the workspace pointer yet and cannot run
cleanup_workspace().

Add local error cleanup for the partially built workspace and the
compiled XPath expression.  Also check xmlXPathNewContext() before
dereferencing the returned context.
---
 contrib/xml2/xpath.c | 51 +++++++++++++++++++++++++++-----------------
 1 file changed, 32 insertions(+), 19 deletions(-)

diff --git a/contrib/xml2/xpath.c b/contrib/xml2/xpath.c
index 9fe75cb5ff4..283bb51178d 100644
--- a/contrib/xml2/xpath.c
+++ b/contrib/xml2/xpath.c
@@ -497,36 +497,49 @@ static xpath_workspace *
 pgxml_xpath(text *document, xmlChar *xpath, PgXmlErrorContext *xmlerrcxt)
 {
 	int32		docsize = VARSIZE_ANY_EXHDR(document);
-	xmlXPathCompExprPtr comppath;
+	xmlXPathCompExprPtr volatile comppath = NULL;
 	xpath_workspace *workspace = palloc0_object(xpath_workspace);
 
 	workspace->doctree = NULL;
 	workspace->ctxt = NULL;
 	workspace->res = NULL;
 
-	workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
-									   docsize, NULL, NULL,
-									   XML_PARSE_NOENT);
-	if (workspace->doctree != NULL)
+	PG_TRY();
 	{
-		workspace->ctxt = xmlXPathNewContext(workspace->doctree);
-		workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
-
-		/* compile the path */
-		comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
-		if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+		workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
+										   docsize, NULL, NULL,
+										   XML_PARSE_NOENT);
+		if (workspace->doctree != NULL)
 		{
-			if (comppath != NULL)
-				xmlXPathFreeCompExpr(comppath);
-			xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
-						"XPath Syntax Error");
-		}
+			workspace->ctxt = xmlXPathNewContext(workspace->doctree);
+			if (workspace->ctxt == NULL)
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_OUT_OF_MEMORY,
+							"could not allocate XPath context");
 
-		/* Now evaluate the path expression. */
-		workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+			workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
+
+			/* compile the path */
+			comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
+			if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
+							"XPath Syntax Error");
+
+			/* Now evaluate the path expression. */
+			workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+
+			xmlXPathFreeCompExpr(comppath);
+			comppath = NULL;
+		}
+	}
+	PG_CATCH();
+	{
+		if (comppath != NULL)
+			xmlXPathFreeCompExpr(comppath);
+		cleanup_workspace(workspace);
 
-		xmlXPathFreeCompExpr(comppath);
+		PG_RE_THROW();
 	}
+	PG_END_TRY();
 
 	return workspace;
 }
-- 
2.54.0


--MP_/LMSk9=uMhuQ1QiIJDarDO8G--





^ permalink  raw  reply  [nested|flat] 611+ messages in thread

* [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths
@ 2026-06-01 22:41 Andrey Chernyy <andrey.cherny@tantorlabs.com>
  0 siblings, 0 replies; 611+ messages in thread

From: Andrey Chernyy @ 2026-06-01 22:41 UTC (permalink / raw)

pgxml_xpath() builds an xpath_workspace before returning it to
callers.  If an ERROR is thrown before the function returns, callers
have not received the workspace pointer yet and cannot run
cleanup_workspace().

Add local error cleanup for the partially built workspace and the
compiled XPath expression.  Also check xmlXPathNewContext() before
dereferencing the returned context.
---
 contrib/xml2/xpath.c | 51 +++++++++++++++++++++++++++-----------------
 1 file changed, 32 insertions(+), 19 deletions(-)

diff --git a/contrib/xml2/xpath.c b/contrib/xml2/xpath.c
index 9fe75cb5ff4..283bb51178d 100644
--- a/contrib/xml2/xpath.c
+++ b/contrib/xml2/xpath.c
@@ -497,36 +497,49 @@ static xpath_workspace *
 pgxml_xpath(text *document, xmlChar *xpath, PgXmlErrorContext *xmlerrcxt)
 {
 	int32		docsize = VARSIZE_ANY_EXHDR(document);
-	xmlXPathCompExprPtr comppath;
+	xmlXPathCompExprPtr volatile comppath = NULL;
 	xpath_workspace *workspace = palloc0_object(xpath_workspace);
 
 	workspace->doctree = NULL;
 	workspace->ctxt = NULL;
 	workspace->res = NULL;
 
-	workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
-									   docsize, NULL, NULL,
-									   XML_PARSE_NOENT);
-	if (workspace->doctree != NULL)
+	PG_TRY();
 	{
-		workspace->ctxt = xmlXPathNewContext(workspace->doctree);
-		workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
-
-		/* compile the path */
-		comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
-		if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+		workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
+										   docsize, NULL, NULL,
+										   XML_PARSE_NOENT);
+		if (workspace->doctree != NULL)
 		{
-			if (comppath != NULL)
-				xmlXPathFreeCompExpr(comppath);
-			xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
-						"XPath Syntax Error");
-		}
+			workspace->ctxt = xmlXPathNewContext(workspace->doctree);
+			if (workspace->ctxt == NULL)
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_OUT_OF_MEMORY,
+							"could not allocate XPath context");
 
-		/* Now evaluate the path expression. */
-		workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+			workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
+
+			/* compile the path */
+			comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
+			if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
+							"XPath Syntax Error");
+
+			/* Now evaluate the path expression. */
+			workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+
+			xmlXPathFreeCompExpr(comppath);
+			comppath = NULL;
+		}
+	}
+	PG_CATCH();
+	{
+		if (comppath != NULL)
+			xmlXPathFreeCompExpr(comppath);
+		cleanup_workspace(workspace);
 
-		xmlXPathFreeCompExpr(comppath);
+		PG_RE_THROW();
 	}
+	PG_END_TRY();
 
 	return workspace;
 }
-- 
2.54.0


--MP_/LMSk9=uMhuQ1QiIJDarDO8G--





^ permalink  raw  reply  [nested|flat] 611+ messages in thread

* [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths
@ 2026-06-01 22:41 Andrey Chernyy <andrey.cherny@tantorlabs.com>
  0 siblings, 0 replies; 611+ messages in thread

From: Andrey Chernyy @ 2026-06-01 22:41 UTC (permalink / raw)

pgxml_xpath() builds an xpath_workspace before returning it to
callers.  If an ERROR is thrown before the function returns, callers
have not received the workspace pointer yet and cannot run
cleanup_workspace().

Add local error cleanup for the partially built workspace and the
compiled XPath expression.  Also check xmlXPathNewContext() before
dereferencing the returned context.
---
 contrib/xml2/xpath.c | 51 +++++++++++++++++++++++++++-----------------
 1 file changed, 32 insertions(+), 19 deletions(-)

diff --git a/contrib/xml2/xpath.c b/contrib/xml2/xpath.c
index 9fe75cb5ff4..283bb51178d 100644
--- a/contrib/xml2/xpath.c
+++ b/contrib/xml2/xpath.c
@@ -497,36 +497,49 @@ static xpath_workspace *
 pgxml_xpath(text *document, xmlChar *xpath, PgXmlErrorContext *xmlerrcxt)
 {
 	int32		docsize = VARSIZE_ANY_EXHDR(document);
-	xmlXPathCompExprPtr comppath;
+	xmlXPathCompExprPtr volatile comppath = NULL;
 	xpath_workspace *workspace = palloc0_object(xpath_workspace);
 
 	workspace->doctree = NULL;
 	workspace->ctxt = NULL;
 	workspace->res = NULL;
 
-	workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
-									   docsize, NULL, NULL,
-									   XML_PARSE_NOENT);
-	if (workspace->doctree != NULL)
+	PG_TRY();
 	{
-		workspace->ctxt = xmlXPathNewContext(workspace->doctree);
-		workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
-
-		/* compile the path */
-		comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
-		if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+		workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
+										   docsize, NULL, NULL,
+										   XML_PARSE_NOENT);
+		if (workspace->doctree != NULL)
 		{
-			if (comppath != NULL)
-				xmlXPathFreeCompExpr(comppath);
-			xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
-						"XPath Syntax Error");
-		}
+			workspace->ctxt = xmlXPathNewContext(workspace->doctree);
+			if (workspace->ctxt == NULL)
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_OUT_OF_MEMORY,
+							"could not allocate XPath context");
 
-		/* Now evaluate the path expression. */
-		workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+			workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
+
+			/* compile the path */
+			comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
+			if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
+							"XPath Syntax Error");
+
+			/* Now evaluate the path expression. */
+			workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+
+			xmlXPathFreeCompExpr(comppath);
+			comppath = NULL;
+		}
+	}
+	PG_CATCH();
+	{
+		if (comppath != NULL)
+			xmlXPathFreeCompExpr(comppath);
+		cleanup_workspace(workspace);
 
-		xmlXPathFreeCompExpr(comppath);
+		PG_RE_THROW();
 	}
+	PG_END_TRY();
 
 	return workspace;
 }
-- 
2.54.0


--MP_/LMSk9=uMhuQ1QiIJDarDO8G--





^ permalink  raw  reply  [nested|flat] 611+ messages in thread

* [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths
@ 2026-06-01 22:41 Andrey Chernyy <andrey.cherny@tantorlabs.com>
  0 siblings, 0 replies; 611+ messages in thread

From: Andrey Chernyy @ 2026-06-01 22:41 UTC (permalink / raw)

pgxml_xpath() builds an xpath_workspace before returning it to
callers.  If an ERROR is thrown before the function returns, callers
have not received the workspace pointer yet and cannot run
cleanup_workspace().

Add local error cleanup for the partially built workspace and the
compiled XPath expression.  Also check xmlXPathNewContext() before
dereferencing the returned context.
---
 contrib/xml2/xpath.c | 51 +++++++++++++++++++++++++++-----------------
 1 file changed, 32 insertions(+), 19 deletions(-)

diff --git a/contrib/xml2/xpath.c b/contrib/xml2/xpath.c
index 9fe75cb5ff4..283bb51178d 100644
--- a/contrib/xml2/xpath.c
+++ b/contrib/xml2/xpath.c
@@ -497,36 +497,49 @@ static xpath_workspace *
 pgxml_xpath(text *document, xmlChar *xpath, PgXmlErrorContext *xmlerrcxt)
 {
 	int32		docsize = VARSIZE_ANY_EXHDR(document);
-	xmlXPathCompExprPtr comppath;
+	xmlXPathCompExprPtr volatile comppath = NULL;
 	xpath_workspace *workspace = palloc0_object(xpath_workspace);
 
 	workspace->doctree = NULL;
 	workspace->ctxt = NULL;
 	workspace->res = NULL;
 
-	workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
-									   docsize, NULL, NULL,
-									   XML_PARSE_NOENT);
-	if (workspace->doctree != NULL)
+	PG_TRY();
 	{
-		workspace->ctxt = xmlXPathNewContext(workspace->doctree);
-		workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
-
-		/* compile the path */
-		comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
-		if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+		workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
+										   docsize, NULL, NULL,
+										   XML_PARSE_NOENT);
+		if (workspace->doctree != NULL)
 		{
-			if (comppath != NULL)
-				xmlXPathFreeCompExpr(comppath);
-			xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
-						"XPath Syntax Error");
-		}
+			workspace->ctxt = xmlXPathNewContext(workspace->doctree);
+			if (workspace->ctxt == NULL)
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_OUT_OF_MEMORY,
+							"could not allocate XPath context");
 
-		/* Now evaluate the path expression. */
-		workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+			workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
+
+			/* compile the path */
+			comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
+			if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
+							"XPath Syntax Error");
+
+			/* Now evaluate the path expression. */
+			workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+
+			xmlXPathFreeCompExpr(comppath);
+			comppath = NULL;
+		}
+	}
+	PG_CATCH();
+	{
+		if (comppath != NULL)
+			xmlXPathFreeCompExpr(comppath);
+		cleanup_workspace(workspace);
 
-		xmlXPathFreeCompExpr(comppath);
+		PG_RE_THROW();
 	}
+	PG_END_TRY();
 
 	return workspace;
 }
-- 
2.54.0


--MP_/LMSk9=uMhuQ1QiIJDarDO8G--






^ permalink  raw  reply  [nested|flat] 611+ messages in thread

* [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths
@ 2026-06-01 22:41 Andrey Chernyy <andrey.cherny@tantorlabs.com>
  0 siblings, 0 replies; 611+ messages in thread

From: Andrey Chernyy @ 2026-06-01 22:41 UTC (permalink / raw)

pgxml_xpath() builds an xpath_workspace before returning it to
callers.  If an ERROR is thrown before the function returns, callers
have not received the workspace pointer yet and cannot run
cleanup_workspace().

Add local error cleanup for the partially built workspace and the
compiled XPath expression.  Also check xmlXPathNewContext() before
dereferencing the returned context.
---
 contrib/xml2/xpath.c | 51 +++++++++++++++++++++++++++-----------------
 1 file changed, 32 insertions(+), 19 deletions(-)

diff --git a/contrib/xml2/xpath.c b/contrib/xml2/xpath.c
index 9fe75cb5ff4..283bb51178d 100644
--- a/contrib/xml2/xpath.c
+++ b/contrib/xml2/xpath.c
@@ -497,36 +497,49 @@ static xpath_workspace *
 pgxml_xpath(text *document, xmlChar *xpath, PgXmlErrorContext *xmlerrcxt)
 {
 	int32		docsize = VARSIZE_ANY_EXHDR(document);
-	xmlXPathCompExprPtr comppath;
+	xmlXPathCompExprPtr volatile comppath = NULL;
 	xpath_workspace *workspace = palloc0_object(xpath_workspace);
 
 	workspace->doctree = NULL;
 	workspace->ctxt = NULL;
 	workspace->res = NULL;
 
-	workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
-									   docsize, NULL, NULL,
-									   XML_PARSE_NOENT);
-	if (workspace->doctree != NULL)
+	PG_TRY();
 	{
-		workspace->ctxt = xmlXPathNewContext(workspace->doctree);
-		workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
-
-		/* compile the path */
-		comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
-		if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+		workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
+										   docsize, NULL, NULL,
+										   XML_PARSE_NOENT);
+		if (workspace->doctree != NULL)
 		{
-			if (comppath != NULL)
-				xmlXPathFreeCompExpr(comppath);
-			xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
-						"XPath Syntax Error");
-		}
+			workspace->ctxt = xmlXPathNewContext(workspace->doctree);
+			if (workspace->ctxt == NULL)
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_OUT_OF_MEMORY,
+							"could not allocate XPath context");
 
-		/* Now evaluate the path expression. */
-		workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+			workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
+
+			/* compile the path */
+			comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
+			if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
+							"XPath Syntax Error");
+
+			/* Now evaluate the path expression. */
+			workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+
+			xmlXPathFreeCompExpr(comppath);
+			comppath = NULL;
+		}
+	}
+	PG_CATCH();
+	{
+		if (comppath != NULL)
+			xmlXPathFreeCompExpr(comppath);
+		cleanup_workspace(workspace);
 
-		xmlXPathFreeCompExpr(comppath);
+		PG_RE_THROW();
 	}
+	PG_END_TRY();
 
 	return workspace;
 }
-- 
2.54.0


--MP_/LMSk9=uMhuQ1QiIJDarDO8G--






^ permalink  raw  reply  [nested|flat] 611+ messages in thread

* [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths
@ 2026-06-01 22:41 Andrey Chernyy <andrey.cherny@tantorlabs.com>
  0 siblings, 0 replies; 611+ messages in thread

From: Andrey Chernyy @ 2026-06-01 22:41 UTC (permalink / raw)

pgxml_xpath() builds an xpath_workspace before returning it to
callers.  If an ERROR is thrown before the function returns, callers
have not received the workspace pointer yet and cannot run
cleanup_workspace().

Add local error cleanup for the partially built workspace and the
compiled XPath expression.  Also check xmlXPathNewContext() before
dereferencing the returned context.
---
 contrib/xml2/xpath.c | 51 +++++++++++++++++++++++++++-----------------
 1 file changed, 32 insertions(+), 19 deletions(-)

diff --git a/contrib/xml2/xpath.c b/contrib/xml2/xpath.c
index 9fe75cb5ff4..283bb51178d 100644
--- a/contrib/xml2/xpath.c
+++ b/contrib/xml2/xpath.c
@@ -497,36 +497,49 @@ static xpath_workspace *
 pgxml_xpath(text *document, xmlChar *xpath, PgXmlErrorContext *xmlerrcxt)
 {
 	int32		docsize = VARSIZE_ANY_EXHDR(document);
-	xmlXPathCompExprPtr comppath;
+	xmlXPathCompExprPtr volatile comppath = NULL;
 	xpath_workspace *workspace = palloc0_object(xpath_workspace);
 
 	workspace->doctree = NULL;
 	workspace->ctxt = NULL;
 	workspace->res = NULL;
 
-	workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
-									   docsize, NULL, NULL,
-									   XML_PARSE_NOENT);
-	if (workspace->doctree != NULL)
+	PG_TRY();
 	{
-		workspace->ctxt = xmlXPathNewContext(workspace->doctree);
-		workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
-
-		/* compile the path */
-		comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
-		if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+		workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
+										   docsize, NULL, NULL,
+										   XML_PARSE_NOENT);
+		if (workspace->doctree != NULL)
 		{
-			if (comppath != NULL)
-				xmlXPathFreeCompExpr(comppath);
-			xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
-						"XPath Syntax Error");
-		}
+			workspace->ctxt = xmlXPathNewContext(workspace->doctree);
+			if (workspace->ctxt == NULL)
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_OUT_OF_MEMORY,
+							"could not allocate XPath context");
 
-		/* Now evaluate the path expression. */
-		workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+			workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
+
+			/* compile the path */
+			comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
+			if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
+							"XPath Syntax Error");
+
+			/* Now evaluate the path expression. */
+			workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+
+			xmlXPathFreeCompExpr(comppath);
+			comppath = NULL;
+		}
+	}
+	PG_CATCH();
+	{
+		if (comppath != NULL)
+			xmlXPathFreeCompExpr(comppath);
+		cleanup_workspace(workspace);
 
-		xmlXPathFreeCompExpr(comppath);
+		PG_RE_THROW();
 	}
+	PG_END_TRY();
 
 	return workspace;
 }
-- 
2.54.0


--MP_/LMSk9=uMhuQ1QiIJDarDO8G--






^ permalink  raw  reply  [nested|flat] 611+ messages in thread

* [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths
@ 2026-06-01 22:41 Andrey Chernyy <andrey.cherny@tantorlabs.com>
  0 siblings, 0 replies; 611+ messages in thread

From: Andrey Chernyy @ 2026-06-01 22:41 UTC (permalink / raw)

pgxml_xpath() builds an xpath_workspace before returning it to
callers.  If an ERROR is thrown before the function returns, callers
have not received the workspace pointer yet and cannot run
cleanup_workspace().

Add local error cleanup for the partially built workspace and the
compiled XPath expression.  Also check xmlXPathNewContext() before
dereferencing the returned context.
---
 contrib/xml2/xpath.c | 51 +++++++++++++++++++++++++++-----------------
 1 file changed, 32 insertions(+), 19 deletions(-)

diff --git a/contrib/xml2/xpath.c b/contrib/xml2/xpath.c
index 9fe75cb5ff4..283bb51178d 100644
--- a/contrib/xml2/xpath.c
+++ b/contrib/xml2/xpath.c
@@ -497,36 +497,49 @@ static xpath_workspace *
 pgxml_xpath(text *document, xmlChar *xpath, PgXmlErrorContext *xmlerrcxt)
 {
 	int32		docsize = VARSIZE_ANY_EXHDR(document);
-	xmlXPathCompExprPtr comppath;
+	xmlXPathCompExprPtr volatile comppath = NULL;
 	xpath_workspace *workspace = palloc0_object(xpath_workspace);
 
 	workspace->doctree = NULL;
 	workspace->ctxt = NULL;
 	workspace->res = NULL;
 
-	workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
-									   docsize, NULL, NULL,
-									   XML_PARSE_NOENT);
-	if (workspace->doctree != NULL)
+	PG_TRY();
 	{
-		workspace->ctxt = xmlXPathNewContext(workspace->doctree);
-		workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
-
-		/* compile the path */
-		comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
-		if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+		workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
+										   docsize, NULL, NULL,
+										   XML_PARSE_NOENT);
+		if (workspace->doctree != NULL)
 		{
-			if (comppath != NULL)
-				xmlXPathFreeCompExpr(comppath);
-			xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
-						"XPath Syntax Error");
-		}
+			workspace->ctxt = xmlXPathNewContext(workspace->doctree);
+			if (workspace->ctxt == NULL)
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_OUT_OF_MEMORY,
+							"could not allocate XPath context");
 
-		/* Now evaluate the path expression. */
-		workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+			workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
+
+			/* compile the path */
+			comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
+			if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
+							"XPath Syntax Error");
+
+			/* Now evaluate the path expression. */
+			workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+
+			xmlXPathFreeCompExpr(comppath);
+			comppath = NULL;
+		}
+	}
+	PG_CATCH();
+	{
+		if (comppath != NULL)
+			xmlXPathFreeCompExpr(comppath);
+		cleanup_workspace(workspace);
 
-		xmlXPathFreeCompExpr(comppath);
+		PG_RE_THROW();
 	}
+	PG_END_TRY();
 
 	return workspace;
 }
-- 
2.54.0


--MP_/LMSk9=uMhuQ1QiIJDarDO8G--






^ permalink  raw  reply  [nested|flat] 611+ messages in thread

* [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths
@ 2026-06-01 22:41 Andrey Chernyy <andrey.cherny@tantorlabs.com>
  0 siblings, 0 replies; 611+ messages in thread

From: Andrey Chernyy @ 2026-06-01 22:41 UTC (permalink / raw)

pgxml_xpath() builds an xpath_workspace before returning it to
callers.  If an ERROR is thrown before the function returns, callers
have not received the workspace pointer yet and cannot run
cleanup_workspace().

Add local error cleanup for the partially built workspace and the
compiled XPath expression.  Also check xmlXPathNewContext() before
dereferencing the returned context.
---
 contrib/xml2/xpath.c | 51 +++++++++++++++++++++++++++-----------------
 1 file changed, 32 insertions(+), 19 deletions(-)

diff --git a/contrib/xml2/xpath.c b/contrib/xml2/xpath.c
index 9fe75cb5ff4..283bb51178d 100644
--- a/contrib/xml2/xpath.c
+++ b/contrib/xml2/xpath.c
@@ -497,36 +497,49 @@ static xpath_workspace *
 pgxml_xpath(text *document, xmlChar *xpath, PgXmlErrorContext *xmlerrcxt)
 {
 	int32		docsize = VARSIZE_ANY_EXHDR(document);
-	xmlXPathCompExprPtr comppath;
+	xmlXPathCompExprPtr volatile comppath = NULL;
 	xpath_workspace *workspace = palloc0_object(xpath_workspace);
 
 	workspace->doctree = NULL;
 	workspace->ctxt = NULL;
 	workspace->res = NULL;
 
-	workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
-									   docsize, NULL, NULL,
-									   XML_PARSE_NOENT);
-	if (workspace->doctree != NULL)
+	PG_TRY();
 	{
-		workspace->ctxt = xmlXPathNewContext(workspace->doctree);
-		workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
-
-		/* compile the path */
-		comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
-		if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+		workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
+										   docsize, NULL, NULL,
+										   XML_PARSE_NOENT);
+		if (workspace->doctree != NULL)
 		{
-			if (comppath != NULL)
-				xmlXPathFreeCompExpr(comppath);
-			xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
-						"XPath Syntax Error");
-		}
+			workspace->ctxt = xmlXPathNewContext(workspace->doctree);
+			if (workspace->ctxt == NULL)
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_OUT_OF_MEMORY,
+							"could not allocate XPath context");
 
-		/* Now evaluate the path expression. */
-		workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+			workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
+
+			/* compile the path */
+			comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
+			if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
+							"XPath Syntax Error");
+
+			/* Now evaluate the path expression. */
+			workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+
+			xmlXPathFreeCompExpr(comppath);
+			comppath = NULL;
+		}
+	}
+	PG_CATCH();
+	{
+		if (comppath != NULL)
+			xmlXPathFreeCompExpr(comppath);
+		cleanup_workspace(workspace);
 
-		xmlXPathFreeCompExpr(comppath);
+		PG_RE_THROW();
 	}
+	PG_END_TRY();
 
 	return workspace;
 }
-- 
2.54.0


--MP_/LMSk9=uMhuQ1QiIJDarDO8G--





^ permalink  raw  reply  [nested|flat] 611+ messages in thread

* [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths
@ 2026-06-01 22:41 Andrey Chernyy <andrey.cherny@tantorlabs.com>
  0 siblings, 0 replies; 611+ messages in thread

From: Andrey Chernyy @ 2026-06-01 22:41 UTC (permalink / raw)

pgxml_xpath() builds an xpath_workspace before returning it to
callers.  If an ERROR is thrown before the function returns, callers
have not received the workspace pointer yet and cannot run
cleanup_workspace().

Add local error cleanup for the partially built workspace and the
compiled XPath expression.  Also check xmlXPathNewContext() before
dereferencing the returned context.
---
 contrib/xml2/xpath.c | 51 +++++++++++++++++++++++++++-----------------
 1 file changed, 32 insertions(+), 19 deletions(-)

diff --git a/contrib/xml2/xpath.c b/contrib/xml2/xpath.c
index 9fe75cb5ff4..283bb51178d 100644
--- a/contrib/xml2/xpath.c
+++ b/contrib/xml2/xpath.c
@@ -497,36 +497,49 @@ static xpath_workspace *
 pgxml_xpath(text *document, xmlChar *xpath, PgXmlErrorContext *xmlerrcxt)
 {
 	int32		docsize = VARSIZE_ANY_EXHDR(document);
-	xmlXPathCompExprPtr comppath;
+	xmlXPathCompExprPtr volatile comppath = NULL;
 	xpath_workspace *workspace = palloc0_object(xpath_workspace);
 
 	workspace->doctree = NULL;
 	workspace->ctxt = NULL;
 	workspace->res = NULL;
 
-	workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
-									   docsize, NULL, NULL,
-									   XML_PARSE_NOENT);
-	if (workspace->doctree != NULL)
+	PG_TRY();
 	{
-		workspace->ctxt = xmlXPathNewContext(workspace->doctree);
-		workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
-
-		/* compile the path */
-		comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
-		if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+		workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
+										   docsize, NULL, NULL,
+										   XML_PARSE_NOENT);
+		if (workspace->doctree != NULL)
 		{
-			if (comppath != NULL)
-				xmlXPathFreeCompExpr(comppath);
-			xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
-						"XPath Syntax Error");
-		}
+			workspace->ctxt = xmlXPathNewContext(workspace->doctree);
+			if (workspace->ctxt == NULL)
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_OUT_OF_MEMORY,
+							"could not allocate XPath context");
 
-		/* Now evaluate the path expression. */
-		workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+			workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
+
+			/* compile the path */
+			comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
+			if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
+							"XPath Syntax Error");
+
+			/* Now evaluate the path expression. */
+			workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+
+			xmlXPathFreeCompExpr(comppath);
+			comppath = NULL;
+		}
+	}
+	PG_CATCH();
+	{
+		if (comppath != NULL)
+			xmlXPathFreeCompExpr(comppath);
+		cleanup_workspace(workspace);
 
-		xmlXPathFreeCompExpr(comppath);
+		PG_RE_THROW();
 	}
+	PG_END_TRY();
 
 	return workspace;
 }
-- 
2.54.0


--MP_/LMSk9=uMhuQ1QiIJDarDO8G--





^ permalink  raw  reply  [nested|flat] 611+ messages in thread

* [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths
@ 2026-06-01 22:41 Andrey Chernyy <andrey.cherny@tantorlabs.com>
  0 siblings, 0 replies; 611+ messages in thread

From: Andrey Chernyy @ 2026-06-01 22:41 UTC (permalink / raw)

pgxml_xpath() builds an xpath_workspace before returning it to
callers.  If an ERROR is thrown before the function returns, callers
have not received the workspace pointer yet and cannot run
cleanup_workspace().

Add local error cleanup for the partially built workspace and the
compiled XPath expression.  Also check xmlXPathNewContext() before
dereferencing the returned context.
---
 contrib/xml2/xpath.c | 51 +++++++++++++++++++++++++++-----------------
 1 file changed, 32 insertions(+), 19 deletions(-)

diff --git a/contrib/xml2/xpath.c b/contrib/xml2/xpath.c
index 9fe75cb5ff4..283bb51178d 100644
--- a/contrib/xml2/xpath.c
+++ b/contrib/xml2/xpath.c
@@ -497,36 +497,49 @@ static xpath_workspace *
 pgxml_xpath(text *document, xmlChar *xpath, PgXmlErrorContext *xmlerrcxt)
 {
 	int32		docsize = VARSIZE_ANY_EXHDR(document);
-	xmlXPathCompExprPtr comppath;
+	xmlXPathCompExprPtr volatile comppath = NULL;
 	xpath_workspace *workspace = palloc0_object(xpath_workspace);
 
 	workspace->doctree = NULL;
 	workspace->ctxt = NULL;
 	workspace->res = NULL;
 
-	workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
-									   docsize, NULL, NULL,
-									   XML_PARSE_NOENT);
-	if (workspace->doctree != NULL)
+	PG_TRY();
 	{
-		workspace->ctxt = xmlXPathNewContext(workspace->doctree);
-		workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
-
-		/* compile the path */
-		comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
-		if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+		workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
+										   docsize, NULL, NULL,
+										   XML_PARSE_NOENT);
+		if (workspace->doctree != NULL)
 		{
-			if (comppath != NULL)
-				xmlXPathFreeCompExpr(comppath);
-			xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
-						"XPath Syntax Error");
-		}
+			workspace->ctxt = xmlXPathNewContext(workspace->doctree);
+			if (workspace->ctxt == NULL)
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_OUT_OF_MEMORY,
+							"could not allocate XPath context");
 
-		/* Now evaluate the path expression. */
-		workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+			workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
+
+			/* compile the path */
+			comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
+			if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
+							"XPath Syntax Error");
+
+			/* Now evaluate the path expression. */
+			workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+
+			xmlXPathFreeCompExpr(comppath);
+			comppath = NULL;
+		}
+	}
+	PG_CATCH();
+	{
+		if (comppath != NULL)
+			xmlXPathFreeCompExpr(comppath);
+		cleanup_workspace(workspace);
 
-		xmlXPathFreeCompExpr(comppath);
+		PG_RE_THROW();
 	}
+	PG_END_TRY();
 
 	return workspace;
 }
-- 
2.54.0


--MP_/LMSk9=uMhuQ1QiIJDarDO8G--





^ permalink  raw  reply  [nested|flat] 611+ messages in thread

* [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths
@ 2026-06-01 22:41 Andrey Chernyy <andrey.cherny@tantorlabs.com>
  0 siblings, 0 replies; 611+ messages in thread

From: Andrey Chernyy @ 2026-06-01 22:41 UTC (permalink / raw)

pgxml_xpath() builds an xpath_workspace before returning it to
callers.  If an ERROR is thrown before the function returns, callers
have not received the workspace pointer yet and cannot run
cleanup_workspace().

Add local error cleanup for the partially built workspace and the
compiled XPath expression.  Also check xmlXPathNewContext() before
dereferencing the returned context.
---
 contrib/xml2/xpath.c | 51 +++++++++++++++++++++++++++-----------------
 1 file changed, 32 insertions(+), 19 deletions(-)

diff --git a/contrib/xml2/xpath.c b/contrib/xml2/xpath.c
index 9fe75cb5ff4..283bb51178d 100644
--- a/contrib/xml2/xpath.c
+++ b/contrib/xml2/xpath.c
@@ -497,36 +497,49 @@ static xpath_workspace *
 pgxml_xpath(text *document, xmlChar *xpath, PgXmlErrorContext *xmlerrcxt)
 {
 	int32		docsize = VARSIZE_ANY_EXHDR(document);
-	xmlXPathCompExprPtr comppath;
+	xmlXPathCompExprPtr volatile comppath = NULL;
 	xpath_workspace *workspace = palloc0_object(xpath_workspace);
 
 	workspace->doctree = NULL;
 	workspace->ctxt = NULL;
 	workspace->res = NULL;
 
-	workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
-									   docsize, NULL, NULL,
-									   XML_PARSE_NOENT);
-	if (workspace->doctree != NULL)
+	PG_TRY();
 	{
-		workspace->ctxt = xmlXPathNewContext(workspace->doctree);
-		workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
-
-		/* compile the path */
-		comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
-		if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+		workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
+										   docsize, NULL, NULL,
+										   XML_PARSE_NOENT);
+		if (workspace->doctree != NULL)
 		{
-			if (comppath != NULL)
-				xmlXPathFreeCompExpr(comppath);
-			xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
-						"XPath Syntax Error");
-		}
+			workspace->ctxt = xmlXPathNewContext(workspace->doctree);
+			if (workspace->ctxt == NULL)
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_OUT_OF_MEMORY,
+							"could not allocate XPath context");
 
-		/* Now evaluate the path expression. */
-		workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+			workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
+
+			/* compile the path */
+			comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
+			if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
+							"XPath Syntax Error");
+
+			/* Now evaluate the path expression. */
+			workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+
+			xmlXPathFreeCompExpr(comppath);
+			comppath = NULL;
+		}
+	}
+	PG_CATCH();
+	{
+		if (comppath != NULL)
+			xmlXPathFreeCompExpr(comppath);
+		cleanup_workspace(workspace);
 
-		xmlXPathFreeCompExpr(comppath);
+		PG_RE_THROW();
 	}
+	PG_END_TRY();
 
 	return workspace;
 }
-- 
2.54.0


--MP_/LMSk9=uMhuQ1QiIJDarDO8G--






^ permalink  raw  reply  [nested|flat] 611+ messages in thread

* [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths
@ 2026-06-01 22:41 Andrey Chernyy <andrey.cherny@tantorlabs.com>
  0 siblings, 0 replies; 611+ messages in thread

From: Andrey Chernyy @ 2026-06-01 22:41 UTC (permalink / raw)

pgxml_xpath() builds an xpath_workspace before returning it to
callers.  If an ERROR is thrown before the function returns, callers
have not received the workspace pointer yet and cannot run
cleanup_workspace().

Add local error cleanup for the partially built workspace and the
compiled XPath expression.  Also check xmlXPathNewContext() before
dereferencing the returned context.
---
 contrib/xml2/xpath.c | 51 +++++++++++++++++++++++++++-----------------
 1 file changed, 32 insertions(+), 19 deletions(-)

diff --git a/contrib/xml2/xpath.c b/contrib/xml2/xpath.c
index 9fe75cb5ff4..283bb51178d 100644
--- a/contrib/xml2/xpath.c
+++ b/contrib/xml2/xpath.c
@@ -497,36 +497,49 @@ static xpath_workspace *
 pgxml_xpath(text *document, xmlChar *xpath, PgXmlErrorContext *xmlerrcxt)
 {
 	int32		docsize = VARSIZE_ANY_EXHDR(document);
-	xmlXPathCompExprPtr comppath;
+	xmlXPathCompExprPtr volatile comppath = NULL;
 	xpath_workspace *workspace = palloc0_object(xpath_workspace);
 
 	workspace->doctree = NULL;
 	workspace->ctxt = NULL;
 	workspace->res = NULL;
 
-	workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
-									   docsize, NULL, NULL,
-									   XML_PARSE_NOENT);
-	if (workspace->doctree != NULL)
+	PG_TRY();
 	{
-		workspace->ctxt = xmlXPathNewContext(workspace->doctree);
-		workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
-
-		/* compile the path */
-		comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
-		if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+		workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
+										   docsize, NULL, NULL,
+										   XML_PARSE_NOENT);
+		if (workspace->doctree != NULL)
 		{
-			if (comppath != NULL)
-				xmlXPathFreeCompExpr(comppath);
-			xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
-						"XPath Syntax Error");
-		}
+			workspace->ctxt = xmlXPathNewContext(workspace->doctree);
+			if (workspace->ctxt == NULL)
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_OUT_OF_MEMORY,
+							"could not allocate XPath context");
 
-		/* Now evaluate the path expression. */
-		workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+			workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
+
+			/* compile the path */
+			comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
+			if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
+							"XPath Syntax Error");
+
+			/* Now evaluate the path expression. */
+			workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+
+			xmlXPathFreeCompExpr(comppath);
+			comppath = NULL;
+		}
+	}
+	PG_CATCH();
+	{
+		if (comppath != NULL)
+			xmlXPathFreeCompExpr(comppath);
+		cleanup_workspace(workspace);
 
-		xmlXPathFreeCompExpr(comppath);
+		PG_RE_THROW();
 	}
+	PG_END_TRY();
 
 	return workspace;
 }
-- 
2.54.0


--MP_/LMSk9=uMhuQ1QiIJDarDO8G--





^ permalink  raw  reply  [nested|flat] 611+ messages in thread

* [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths
@ 2026-06-01 22:41 Andrey Chernyy <andrey.cherny@tantorlabs.com>
  0 siblings, 0 replies; 611+ messages in thread

From: Andrey Chernyy @ 2026-06-01 22:41 UTC (permalink / raw)

pgxml_xpath() builds an xpath_workspace before returning it to
callers.  If an ERROR is thrown before the function returns, callers
have not received the workspace pointer yet and cannot run
cleanup_workspace().

Add local error cleanup for the partially built workspace and the
compiled XPath expression.  Also check xmlXPathNewContext() before
dereferencing the returned context.
---
 contrib/xml2/xpath.c | 51 +++++++++++++++++++++++++++-----------------
 1 file changed, 32 insertions(+), 19 deletions(-)

diff --git a/contrib/xml2/xpath.c b/contrib/xml2/xpath.c
index 9fe75cb5ff4..283bb51178d 100644
--- a/contrib/xml2/xpath.c
+++ b/contrib/xml2/xpath.c
@@ -497,36 +497,49 @@ static xpath_workspace *
 pgxml_xpath(text *document, xmlChar *xpath, PgXmlErrorContext *xmlerrcxt)
 {
 	int32		docsize = VARSIZE_ANY_EXHDR(document);
-	xmlXPathCompExprPtr comppath;
+	xmlXPathCompExprPtr volatile comppath = NULL;
 	xpath_workspace *workspace = palloc0_object(xpath_workspace);
 
 	workspace->doctree = NULL;
 	workspace->ctxt = NULL;
 	workspace->res = NULL;
 
-	workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
-									   docsize, NULL, NULL,
-									   XML_PARSE_NOENT);
-	if (workspace->doctree != NULL)
+	PG_TRY();
 	{
-		workspace->ctxt = xmlXPathNewContext(workspace->doctree);
-		workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
-
-		/* compile the path */
-		comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
-		if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+		workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
+										   docsize, NULL, NULL,
+										   XML_PARSE_NOENT);
+		if (workspace->doctree != NULL)
 		{
-			if (comppath != NULL)
-				xmlXPathFreeCompExpr(comppath);
-			xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
-						"XPath Syntax Error");
-		}
+			workspace->ctxt = xmlXPathNewContext(workspace->doctree);
+			if (workspace->ctxt == NULL)
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_OUT_OF_MEMORY,
+							"could not allocate XPath context");
 
-		/* Now evaluate the path expression. */
-		workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+			workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
+
+			/* compile the path */
+			comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
+			if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
+							"XPath Syntax Error");
+
+			/* Now evaluate the path expression. */
+			workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+
+			xmlXPathFreeCompExpr(comppath);
+			comppath = NULL;
+		}
+	}
+	PG_CATCH();
+	{
+		if (comppath != NULL)
+			xmlXPathFreeCompExpr(comppath);
+		cleanup_workspace(workspace);
 
-		xmlXPathFreeCompExpr(comppath);
+		PG_RE_THROW();
 	}
+	PG_END_TRY();
 
 	return workspace;
 }
-- 
2.54.0


--MP_/LMSk9=uMhuQ1QiIJDarDO8G--






^ permalink  raw  reply  [nested|flat] 611+ messages in thread

* [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths
@ 2026-06-01 22:41 Andrey Chernyy <andrey.cherny@tantorlabs.com>
  0 siblings, 0 replies; 611+ messages in thread

From: Andrey Chernyy @ 2026-06-01 22:41 UTC (permalink / raw)

pgxml_xpath() builds an xpath_workspace before returning it to
callers.  If an ERROR is thrown before the function returns, callers
have not received the workspace pointer yet and cannot run
cleanup_workspace().

Add local error cleanup for the partially built workspace and the
compiled XPath expression.  Also check xmlXPathNewContext() before
dereferencing the returned context.
---
 contrib/xml2/xpath.c | 51 +++++++++++++++++++++++++++-----------------
 1 file changed, 32 insertions(+), 19 deletions(-)

diff --git a/contrib/xml2/xpath.c b/contrib/xml2/xpath.c
index 9fe75cb5ff4..283bb51178d 100644
--- a/contrib/xml2/xpath.c
+++ b/contrib/xml2/xpath.c
@@ -497,36 +497,49 @@ static xpath_workspace *
 pgxml_xpath(text *document, xmlChar *xpath, PgXmlErrorContext *xmlerrcxt)
 {
 	int32		docsize = VARSIZE_ANY_EXHDR(document);
-	xmlXPathCompExprPtr comppath;
+	xmlXPathCompExprPtr volatile comppath = NULL;
 	xpath_workspace *workspace = palloc0_object(xpath_workspace);
 
 	workspace->doctree = NULL;
 	workspace->ctxt = NULL;
 	workspace->res = NULL;
 
-	workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
-									   docsize, NULL, NULL,
-									   XML_PARSE_NOENT);
-	if (workspace->doctree != NULL)
+	PG_TRY();
 	{
-		workspace->ctxt = xmlXPathNewContext(workspace->doctree);
-		workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
-
-		/* compile the path */
-		comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
-		if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+		workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
+										   docsize, NULL, NULL,
+										   XML_PARSE_NOENT);
+		if (workspace->doctree != NULL)
 		{
-			if (comppath != NULL)
-				xmlXPathFreeCompExpr(comppath);
-			xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
-						"XPath Syntax Error");
-		}
+			workspace->ctxt = xmlXPathNewContext(workspace->doctree);
+			if (workspace->ctxt == NULL)
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_OUT_OF_MEMORY,
+							"could not allocate XPath context");
 
-		/* Now evaluate the path expression. */
-		workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+			workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
+
+			/* compile the path */
+			comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
+			if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
+							"XPath Syntax Error");
+
+			/* Now evaluate the path expression. */
+			workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+
+			xmlXPathFreeCompExpr(comppath);
+			comppath = NULL;
+		}
+	}
+	PG_CATCH();
+	{
+		if (comppath != NULL)
+			xmlXPathFreeCompExpr(comppath);
+		cleanup_workspace(workspace);
 
-		xmlXPathFreeCompExpr(comppath);
+		PG_RE_THROW();
 	}
+	PG_END_TRY();
 
 	return workspace;
 }
-- 
2.54.0


--MP_/LMSk9=uMhuQ1QiIJDarDO8G--






^ permalink  raw  reply  [nested|flat] 611+ messages in thread

* [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths
@ 2026-06-01 22:41 Andrey Chernyy <andrey.cherny@tantorlabs.com>
  0 siblings, 0 replies; 611+ messages in thread

From: Andrey Chernyy @ 2026-06-01 22:41 UTC (permalink / raw)

pgxml_xpath() builds an xpath_workspace before returning it to
callers.  If an ERROR is thrown before the function returns, callers
have not received the workspace pointer yet and cannot run
cleanup_workspace().

Add local error cleanup for the partially built workspace and the
compiled XPath expression.  Also check xmlXPathNewContext() before
dereferencing the returned context.
---
 contrib/xml2/xpath.c | 51 +++++++++++++++++++++++++++-----------------
 1 file changed, 32 insertions(+), 19 deletions(-)

diff --git a/contrib/xml2/xpath.c b/contrib/xml2/xpath.c
index 9fe75cb5ff4..283bb51178d 100644
--- a/contrib/xml2/xpath.c
+++ b/contrib/xml2/xpath.c
@@ -497,36 +497,49 @@ static xpath_workspace *
 pgxml_xpath(text *document, xmlChar *xpath, PgXmlErrorContext *xmlerrcxt)
 {
 	int32		docsize = VARSIZE_ANY_EXHDR(document);
-	xmlXPathCompExprPtr comppath;
+	xmlXPathCompExprPtr volatile comppath = NULL;
 	xpath_workspace *workspace = palloc0_object(xpath_workspace);
 
 	workspace->doctree = NULL;
 	workspace->ctxt = NULL;
 	workspace->res = NULL;
 
-	workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
-									   docsize, NULL, NULL,
-									   XML_PARSE_NOENT);
-	if (workspace->doctree != NULL)
+	PG_TRY();
 	{
-		workspace->ctxt = xmlXPathNewContext(workspace->doctree);
-		workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
-
-		/* compile the path */
-		comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
-		if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+		workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
+										   docsize, NULL, NULL,
+										   XML_PARSE_NOENT);
+		if (workspace->doctree != NULL)
 		{
-			if (comppath != NULL)
-				xmlXPathFreeCompExpr(comppath);
-			xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
-						"XPath Syntax Error");
-		}
+			workspace->ctxt = xmlXPathNewContext(workspace->doctree);
+			if (workspace->ctxt == NULL)
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_OUT_OF_MEMORY,
+							"could not allocate XPath context");
 
-		/* Now evaluate the path expression. */
-		workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+			workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
+
+			/* compile the path */
+			comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
+			if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
+							"XPath Syntax Error");
+
+			/* Now evaluate the path expression. */
+			workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+
+			xmlXPathFreeCompExpr(comppath);
+			comppath = NULL;
+		}
+	}
+	PG_CATCH();
+	{
+		if (comppath != NULL)
+			xmlXPathFreeCompExpr(comppath);
+		cleanup_workspace(workspace);
 
-		xmlXPathFreeCompExpr(comppath);
+		PG_RE_THROW();
 	}
+	PG_END_TRY();
 
 	return workspace;
 }
-- 
2.54.0


--MP_/LMSk9=uMhuQ1QiIJDarDO8G--





^ permalink  raw  reply  [nested|flat] 611+ messages in thread

* [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths
@ 2026-06-01 22:41 Andrey Chernyy <andrey.cherny@tantorlabs.com>
  0 siblings, 0 replies; 611+ messages in thread

From: Andrey Chernyy @ 2026-06-01 22:41 UTC (permalink / raw)

pgxml_xpath() builds an xpath_workspace before returning it to
callers.  If an ERROR is thrown before the function returns, callers
have not received the workspace pointer yet and cannot run
cleanup_workspace().

Add local error cleanup for the partially built workspace and the
compiled XPath expression.  Also check xmlXPathNewContext() before
dereferencing the returned context.
---
 contrib/xml2/xpath.c | 51 +++++++++++++++++++++++++++-----------------
 1 file changed, 32 insertions(+), 19 deletions(-)

diff --git a/contrib/xml2/xpath.c b/contrib/xml2/xpath.c
index 9fe75cb5ff4..283bb51178d 100644
--- a/contrib/xml2/xpath.c
+++ b/contrib/xml2/xpath.c
@@ -497,36 +497,49 @@ static xpath_workspace *
 pgxml_xpath(text *document, xmlChar *xpath, PgXmlErrorContext *xmlerrcxt)
 {
 	int32		docsize = VARSIZE_ANY_EXHDR(document);
-	xmlXPathCompExprPtr comppath;
+	xmlXPathCompExprPtr volatile comppath = NULL;
 	xpath_workspace *workspace = palloc0_object(xpath_workspace);
 
 	workspace->doctree = NULL;
 	workspace->ctxt = NULL;
 	workspace->res = NULL;
 
-	workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
-									   docsize, NULL, NULL,
-									   XML_PARSE_NOENT);
-	if (workspace->doctree != NULL)
+	PG_TRY();
 	{
-		workspace->ctxt = xmlXPathNewContext(workspace->doctree);
-		workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
-
-		/* compile the path */
-		comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
-		if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+		workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
+										   docsize, NULL, NULL,
+										   XML_PARSE_NOENT);
+		if (workspace->doctree != NULL)
 		{
-			if (comppath != NULL)
-				xmlXPathFreeCompExpr(comppath);
-			xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
-						"XPath Syntax Error");
-		}
+			workspace->ctxt = xmlXPathNewContext(workspace->doctree);
+			if (workspace->ctxt == NULL)
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_OUT_OF_MEMORY,
+							"could not allocate XPath context");
 
-		/* Now evaluate the path expression. */
-		workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+			workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
+
+			/* compile the path */
+			comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
+			if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
+							"XPath Syntax Error");
+
+			/* Now evaluate the path expression. */
+			workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+
+			xmlXPathFreeCompExpr(comppath);
+			comppath = NULL;
+		}
+	}
+	PG_CATCH();
+	{
+		if (comppath != NULL)
+			xmlXPathFreeCompExpr(comppath);
+		cleanup_workspace(workspace);
 
-		xmlXPathFreeCompExpr(comppath);
+		PG_RE_THROW();
 	}
+	PG_END_TRY();
 
 	return workspace;
 }
-- 
2.54.0


--MP_/LMSk9=uMhuQ1QiIJDarDO8G--






^ permalink  raw  reply  [nested|flat] 611+ messages in thread

* [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths
@ 2026-06-01 22:41 Andrey Chernyy <andrey.cherny@tantorlabs.com>
  0 siblings, 0 replies; 611+ messages in thread

From: Andrey Chernyy @ 2026-06-01 22:41 UTC (permalink / raw)

pgxml_xpath() builds an xpath_workspace before returning it to
callers.  If an ERROR is thrown before the function returns, callers
have not received the workspace pointer yet and cannot run
cleanup_workspace().

Add local error cleanup for the partially built workspace and the
compiled XPath expression.  Also check xmlXPathNewContext() before
dereferencing the returned context.
---
 contrib/xml2/xpath.c | 51 +++++++++++++++++++++++++++-----------------
 1 file changed, 32 insertions(+), 19 deletions(-)

diff --git a/contrib/xml2/xpath.c b/contrib/xml2/xpath.c
index 9fe75cb5ff4..283bb51178d 100644
--- a/contrib/xml2/xpath.c
+++ b/contrib/xml2/xpath.c
@@ -497,36 +497,49 @@ static xpath_workspace *
 pgxml_xpath(text *document, xmlChar *xpath, PgXmlErrorContext *xmlerrcxt)
 {
 	int32		docsize = VARSIZE_ANY_EXHDR(document);
-	xmlXPathCompExprPtr comppath;
+	xmlXPathCompExprPtr volatile comppath = NULL;
 	xpath_workspace *workspace = palloc0_object(xpath_workspace);
 
 	workspace->doctree = NULL;
 	workspace->ctxt = NULL;
 	workspace->res = NULL;
 
-	workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
-									   docsize, NULL, NULL,
-									   XML_PARSE_NOENT);
-	if (workspace->doctree != NULL)
+	PG_TRY();
 	{
-		workspace->ctxt = xmlXPathNewContext(workspace->doctree);
-		workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
-
-		/* compile the path */
-		comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
-		if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+		workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
+										   docsize, NULL, NULL,
+										   XML_PARSE_NOENT);
+		if (workspace->doctree != NULL)
 		{
-			if (comppath != NULL)
-				xmlXPathFreeCompExpr(comppath);
-			xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
-						"XPath Syntax Error");
-		}
+			workspace->ctxt = xmlXPathNewContext(workspace->doctree);
+			if (workspace->ctxt == NULL)
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_OUT_OF_MEMORY,
+							"could not allocate XPath context");
 
-		/* Now evaluate the path expression. */
-		workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+			workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
+
+			/* compile the path */
+			comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
+			if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
+							"XPath Syntax Error");
+
+			/* Now evaluate the path expression. */
+			workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+
+			xmlXPathFreeCompExpr(comppath);
+			comppath = NULL;
+		}
+	}
+	PG_CATCH();
+	{
+		if (comppath != NULL)
+			xmlXPathFreeCompExpr(comppath);
+		cleanup_workspace(workspace);
 
-		xmlXPathFreeCompExpr(comppath);
+		PG_RE_THROW();
 	}
+	PG_END_TRY();
 
 	return workspace;
 }
-- 
2.54.0


--MP_/LMSk9=uMhuQ1QiIJDarDO8G--






^ permalink  raw  reply  [nested|flat] 611+ messages in thread

* [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths
@ 2026-06-01 22:41 Andrey Chernyy <andrey.cherny@tantorlabs.com>
  0 siblings, 0 replies; 611+ messages in thread

From: Andrey Chernyy @ 2026-06-01 22:41 UTC (permalink / raw)

pgxml_xpath() builds an xpath_workspace before returning it to
callers.  If an ERROR is thrown before the function returns, callers
have not received the workspace pointer yet and cannot run
cleanup_workspace().

Add local error cleanup for the partially built workspace and the
compiled XPath expression.  Also check xmlXPathNewContext() before
dereferencing the returned context.
---
 contrib/xml2/xpath.c | 51 +++++++++++++++++++++++++++-----------------
 1 file changed, 32 insertions(+), 19 deletions(-)

diff --git a/contrib/xml2/xpath.c b/contrib/xml2/xpath.c
index 9fe75cb5ff4..283bb51178d 100644
--- a/contrib/xml2/xpath.c
+++ b/contrib/xml2/xpath.c
@@ -497,36 +497,49 @@ static xpath_workspace *
 pgxml_xpath(text *document, xmlChar *xpath, PgXmlErrorContext *xmlerrcxt)
 {
 	int32		docsize = VARSIZE_ANY_EXHDR(document);
-	xmlXPathCompExprPtr comppath;
+	xmlXPathCompExprPtr volatile comppath = NULL;
 	xpath_workspace *workspace = palloc0_object(xpath_workspace);
 
 	workspace->doctree = NULL;
 	workspace->ctxt = NULL;
 	workspace->res = NULL;
 
-	workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
-									   docsize, NULL, NULL,
-									   XML_PARSE_NOENT);
-	if (workspace->doctree != NULL)
+	PG_TRY();
 	{
-		workspace->ctxt = xmlXPathNewContext(workspace->doctree);
-		workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
-
-		/* compile the path */
-		comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
-		if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+		workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
+										   docsize, NULL, NULL,
+										   XML_PARSE_NOENT);
+		if (workspace->doctree != NULL)
 		{
-			if (comppath != NULL)
-				xmlXPathFreeCompExpr(comppath);
-			xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
-						"XPath Syntax Error");
-		}
+			workspace->ctxt = xmlXPathNewContext(workspace->doctree);
+			if (workspace->ctxt == NULL)
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_OUT_OF_MEMORY,
+							"could not allocate XPath context");
 
-		/* Now evaluate the path expression. */
-		workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+			workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
+
+			/* compile the path */
+			comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
+			if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
+							"XPath Syntax Error");
+
+			/* Now evaluate the path expression. */
+			workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+
+			xmlXPathFreeCompExpr(comppath);
+			comppath = NULL;
+		}
+	}
+	PG_CATCH();
+	{
+		if (comppath != NULL)
+			xmlXPathFreeCompExpr(comppath);
+		cleanup_workspace(workspace);
 
-		xmlXPathFreeCompExpr(comppath);
+		PG_RE_THROW();
 	}
+	PG_END_TRY();
 
 	return workspace;
 }
-- 
2.54.0


--MP_/LMSk9=uMhuQ1QiIJDarDO8G--






^ permalink  raw  reply  [nested|flat] 611+ messages in thread

* [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths
@ 2026-06-01 22:41 Andrey Chernyy <andrey.cherny@tantorlabs.com>
  0 siblings, 0 replies; 611+ messages in thread

From: Andrey Chernyy @ 2026-06-01 22:41 UTC (permalink / raw)

pgxml_xpath() builds an xpath_workspace before returning it to
callers.  If an ERROR is thrown before the function returns, callers
have not received the workspace pointer yet and cannot run
cleanup_workspace().

Add local error cleanup for the partially built workspace and the
compiled XPath expression.  Also check xmlXPathNewContext() before
dereferencing the returned context.
---
 contrib/xml2/xpath.c | 51 +++++++++++++++++++++++++++-----------------
 1 file changed, 32 insertions(+), 19 deletions(-)

diff --git a/contrib/xml2/xpath.c b/contrib/xml2/xpath.c
index 9fe75cb5ff4..283bb51178d 100644
--- a/contrib/xml2/xpath.c
+++ b/contrib/xml2/xpath.c
@@ -497,36 +497,49 @@ static xpath_workspace *
 pgxml_xpath(text *document, xmlChar *xpath, PgXmlErrorContext *xmlerrcxt)
 {
 	int32		docsize = VARSIZE_ANY_EXHDR(document);
-	xmlXPathCompExprPtr comppath;
+	xmlXPathCompExprPtr volatile comppath = NULL;
 	xpath_workspace *workspace = palloc0_object(xpath_workspace);
 
 	workspace->doctree = NULL;
 	workspace->ctxt = NULL;
 	workspace->res = NULL;
 
-	workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
-									   docsize, NULL, NULL,
-									   XML_PARSE_NOENT);
-	if (workspace->doctree != NULL)
+	PG_TRY();
 	{
-		workspace->ctxt = xmlXPathNewContext(workspace->doctree);
-		workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
-
-		/* compile the path */
-		comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
-		if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+		workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
+										   docsize, NULL, NULL,
+										   XML_PARSE_NOENT);
+		if (workspace->doctree != NULL)
 		{
-			if (comppath != NULL)
-				xmlXPathFreeCompExpr(comppath);
-			xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
-						"XPath Syntax Error");
-		}
+			workspace->ctxt = xmlXPathNewContext(workspace->doctree);
+			if (workspace->ctxt == NULL)
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_OUT_OF_MEMORY,
+							"could not allocate XPath context");
 
-		/* Now evaluate the path expression. */
-		workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+			workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
+
+			/* compile the path */
+			comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
+			if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
+							"XPath Syntax Error");
+
+			/* Now evaluate the path expression. */
+			workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+
+			xmlXPathFreeCompExpr(comppath);
+			comppath = NULL;
+		}
+	}
+	PG_CATCH();
+	{
+		if (comppath != NULL)
+			xmlXPathFreeCompExpr(comppath);
+		cleanup_workspace(workspace);
 
-		xmlXPathFreeCompExpr(comppath);
+		PG_RE_THROW();
 	}
+	PG_END_TRY();
 
 	return workspace;
 }
-- 
2.54.0


--MP_/LMSk9=uMhuQ1QiIJDarDO8G--





^ permalink  raw  reply  [nested|flat] 611+ messages in thread

* [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths
@ 2026-06-01 22:41 Andrey Chernyy <andrey.cherny@tantorlabs.com>
  0 siblings, 0 replies; 611+ messages in thread

From: Andrey Chernyy @ 2026-06-01 22:41 UTC (permalink / raw)

pgxml_xpath() builds an xpath_workspace before returning it to
callers.  If an ERROR is thrown before the function returns, callers
have not received the workspace pointer yet and cannot run
cleanup_workspace().

Add local error cleanup for the partially built workspace and the
compiled XPath expression.  Also check xmlXPathNewContext() before
dereferencing the returned context.
---
 contrib/xml2/xpath.c | 51 +++++++++++++++++++++++++++-----------------
 1 file changed, 32 insertions(+), 19 deletions(-)

diff --git a/contrib/xml2/xpath.c b/contrib/xml2/xpath.c
index 9fe75cb5ff4..283bb51178d 100644
--- a/contrib/xml2/xpath.c
+++ b/contrib/xml2/xpath.c
@@ -497,36 +497,49 @@ static xpath_workspace *
 pgxml_xpath(text *document, xmlChar *xpath, PgXmlErrorContext *xmlerrcxt)
 {
 	int32		docsize = VARSIZE_ANY_EXHDR(document);
-	xmlXPathCompExprPtr comppath;
+	xmlXPathCompExprPtr volatile comppath = NULL;
 	xpath_workspace *workspace = palloc0_object(xpath_workspace);
 
 	workspace->doctree = NULL;
 	workspace->ctxt = NULL;
 	workspace->res = NULL;
 
-	workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
-									   docsize, NULL, NULL,
-									   XML_PARSE_NOENT);
-	if (workspace->doctree != NULL)
+	PG_TRY();
 	{
-		workspace->ctxt = xmlXPathNewContext(workspace->doctree);
-		workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
-
-		/* compile the path */
-		comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
-		if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+		workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
+										   docsize, NULL, NULL,
+										   XML_PARSE_NOENT);
+		if (workspace->doctree != NULL)
 		{
-			if (comppath != NULL)
-				xmlXPathFreeCompExpr(comppath);
-			xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
-						"XPath Syntax Error");
-		}
+			workspace->ctxt = xmlXPathNewContext(workspace->doctree);
+			if (workspace->ctxt == NULL)
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_OUT_OF_MEMORY,
+							"could not allocate XPath context");
 
-		/* Now evaluate the path expression. */
-		workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+			workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
+
+			/* compile the path */
+			comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
+			if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
+							"XPath Syntax Error");
+
+			/* Now evaluate the path expression. */
+			workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+
+			xmlXPathFreeCompExpr(comppath);
+			comppath = NULL;
+		}
+	}
+	PG_CATCH();
+	{
+		if (comppath != NULL)
+			xmlXPathFreeCompExpr(comppath);
+		cleanup_workspace(workspace);
 
-		xmlXPathFreeCompExpr(comppath);
+		PG_RE_THROW();
 	}
+	PG_END_TRY();
 
 	return workspace;
 }
-- 
2.54.0


--MP_/LMSk9=uMhuQ1QiIJDarDO8G--






^ permalink  raw  reply  [nested|flat] 611+ messages in thread

* [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths
@ 2026-06-01 22:41 Andrey Chernyy <andrey.cherny@tantorlabs.com>
  0 siblings, 0 replies; 611+ messages in thread

From: Andrey Chernyy @ 2026-06-01 22:41 UTC (permalink / raw)

pgxml_xpath() builds an xpath_workspace before returning it to
callers.  If an ERROR is thrown before the function returns, callers
have not received the workspace pointer yet and cannot run
cleanup_workspace().

Add local error cleanup for the partially built workspace and the
compiled XPath expression.  Also check xmlXPathNewContext() before
dereferencing the returned context.
---
 contrib/xml2/xpath.c | 51 +++++++++++++++++++++++++++-----------------
 1 file changed, 32 insertions(+), 19 deletions(-)

diff --git a/contrib/xml2/xpath.c b/contrib/xml2/xpath.c
index 9fe75cb5ff4..283bb51178d 100644
--- a/contrib/xml2/xpath.c
+++ b/contrib/xml2/xpath.c
@@ -497,36 +497,49 @@ static xpath_workspace *
 pgxml_xpath(text *document, xmlChar *xpath, PgXmlErrorContext *xmlerrcxt)
 {
 	int32		docsize = VARSIZE_ANY_EXHDR(document);
-	xmlXPathCompExprPtr comppath;
+	xmlXPathCompExprPtr volatile comppath = NULL;
 	xpath_workspace *workspace = palloc0_object(xpath_workspace);
 
 	workspace->doctree = NULL;
 	workspace->ctxt = NULL;
 	workspace->res = NULL;
 
-	workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
-									   docsize, NULL, NULL,
-									   XML_PARSE_NOENT);
-	if (workspace->doctree != NULL)
+	PG_TRY();
 	{
-		workspace->ctxt = xmlXPathNewContext(workspace->doctree);
-		workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
-
-		/* compile the path */
-		comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
-		if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+		workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
+										   docsize, NULL, NULL,
+										   XML_PARSE_NOENT);
+		if (workspace->doctree != NULL)
 		{
-			if (comppath != NULL)
-				xmlXPathFreeCompExpr(comppath);
-			xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
-						"XPath Syntax Error");
-		}
+			workspace->ctxt = xmlXPathNewContext(workspace->doctree);
+			if (workspace->ctxt == NULL)
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_OUT_OF_MEMORY,
+							"could not allocate XPath context");
 
-		/* Now evaluate the path expression. */
-		workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+			workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
+
+			/* compile the path */
+			comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
+			if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
+							"XPath Syntax Error");
+
+			/* Now evaluate the path expression. */
+			workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+
+			xmlXPathFreeCompExpr(comppath);
+			comppath = NULL;
+		}
+	}
+	PG_CATCH();
+	{
+		if (comppath != NULL)
+			xmlXPathFreeCompExpr(comppath);
+		cleanup_workspace(workspace);
 
-		xmlXPathFreeCompExpr(comppath);
+		PG_RE_THROW();
 	}
+	PG_END_TRY();
 
 	return workspace;
 }
-- 
2.54.0


--MP_/LMSk9=uMhuQ1QiIJDarDO8G--





^ permalink  raw  reply  [nested|flat] 611+ messages in thread

* [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths
@ 2026-06-01 22:41 Andrey Chernyy <andrey.cherny@tantorlabs.com>
  0 siblings, 0 replies; 611+ messages in thread

From: Andrey Chernyy @ 2026-06-01 22:41 UTC (permalink / raw)

pgxml_xpath() builds an xpath_workspace before returning it to
callers.  If an ERROR is thrown before the function returns, callers
have not received the workspace pointer yet and cannot run
cleanup_workspace().

Add local error cleanup for the partially built workspace and the
compiled XPath expression.  Also check xmlXPathNewContext() before
dereferencing the returned context.
---
 contrib/xml2/xpath.c | 51 +++++++++++++++++++++++++++-----------------
 1 file changed, 32 insertions(+), 19 deletions(-)

diff --git a/contrib/xml2/xpath.c b/contrib/xml2/xpath.c
index 9fe75cb5ff4..283bb51178d 100644
--- a/contrib/xml2/xpath.c
+++ b/contrib/xml2/xpath.c
@@ -497,36 +497,49 @@ static xpath_workspace *
 pgxml_xpath(text *document, xmlChar *xpath, PgXmlErrorContext *xmlerrcxt)
 {
 	int32		docsize = VARSIZE_ANY_EXHDR(document);
-	xmlXPathCompExprPtr comppath;
+	xmlXPathCompExprPtr volatile comppath = NULL;
 	xpath_workspace *workspace = palloc0_object(xpath_workspace);
 
 	workspace->doctree = NULL;
 	workspace->ctxt = NULL;
 	workspace->res = NULL;
 
-	workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
-									   docsize, NULL, NULL,
-									   XML_PARSE_NOENT);
-	if (workspace->doctree != NULL)
+	PG_TRY();
 	{
-		workspace->ctxt = xmlXPathNewContext(workspace->doctree);
-		workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
-
-		/* compile the path */
-		comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
-		if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+		workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
+										   docsize, NULL, NULL,
+										   XML_PARSE_NOENT);
+		if (workspace->doctree != NULL)
 		{
-			if (comppath != NULL)
-				xmlXPathFreeCompExpr(comppath);
-			xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
-						"XPath Syntax Error");
-		}
+			workspace->ctxt = xmlXPathNewContext(workspace->doctree);
+			if (workspace->ctxt == NULL)
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_OUT_OF_MEMORY,
+							"could not allocate XPath context");
 
-		/* Now evaluate the path expression. */
-		workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+			workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
+
+			/* compile the path */
+			comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
+			if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
+							"XPath Syntax Error");
+
+			/* Now evaluate the path expression. */
+			workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+
+			xmlXPathFreeCompExpr(comppath);
+			comppath = NULL;
+		}
+	}
+	PG_CATCH();
+	{
+		if (comppath != NULL)
+			xmlXPathFreeCompExpr(comppath);
+		cleanup_workspace(workspace);
 
-		xmlXPathFreeCompExpr(comppath);
+		PG_RE_THROW();
 	}
+	PG_END_TRY();
 
 	return workspace;
 }
-- 
2.54.0


--MP_/LMSk9=uMhuQ1QiIJDarDO8G--






^ permalink  raw  reply  [nested|flat] 611+ messages in thread

* [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths
@ 2026-06-01 22:41 Andrey Chernyy <andrey.cherny@tantorlabs.com>
  0 siblings, 0 replies; 611+ messages in thread

From: Andrey Chernyy @ 2026-06-01 22:41 UTC (permalink / raw)

pgxml_xpath() builds an xpath_workspace before returning it to
callers.  If an ERROR is thrown before the function returns, callers
have not received the workspace pointer yet and cannot run
cleanup_workspace().

Add local error cleanup for the partially built workspace and the
compiled XPath expression.  Also check xmlXPathNewContext() before
dereferencing the returned context.
---
 contrib/xml2/xpath.c | 51 +++++++++++++++++++++++++++-----------------
 1 file changed, 32 insertions(+), 19 deletions(-)

diff --git a/contrib/xml2/xpath.c b/contrib/xml2/xpath.c
index 9fe75cb5ff4..283bb51178d 100644
--- a/contrib/xml2/xpath.c
+++ b/contrib/xml2/xpath.c
@@ -497,36 +497,49 @@ static xpath_workspace *
 pgxml_xpath(text *document, xmlChar *xpath, PgXmlErrorContext *xmlerrcxt)
 {
 	int32		docsize = VARSIZE_ANY_EXHDR(document);
-	xmlXPathCompExprPtr comppath;
+	xmlXPathCompExprPtr volatile comppath = NULL;
 	xpath_workspace *workspace = palloc0_object(xpath_workspace);
 
 	workspace->doctree = NULL;
 	workspace->ctxt = NULL;
 	workspace->res = NULL;
 
-	workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
-									   docsize, NULL, NULL,
-									   XML_PARSE_NOENT);
-	if (workspace->doctree != NULL)
+	PG_TRY();
 	{
-		workspace->ctxt = xmlXPathNewContext(workspace->doctree);
-		workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
-
-		/* compile the path */
-		comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
-		if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+		workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
+										   docsize, NULL, NULL,
+										   XML_PARSE_NOENT);
+		if (workspace->doctree != NULL)
 		{
-			if (comppath != NULL)
-				xmlXPathFreeCompExpr(comppath);
-			xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
-						"XPath Syntax Error");
-		}
+			workspace->ctxt = xmlXPathNewContext(workspace->doctree);
+			if (workspace->ctxt == NULL)
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_OUT_OF_MEMORY,
+							"could not allocate XPath context");
 
-		/* Now evaluate the path expression. */
-		workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+			workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
+
+			/* compile the path */
+			comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
+			if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
+							"XPath Syntax Error");
+
+			/* Now evaluate the path expression. */
+			workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+
+			xmlXPathFreeCompExpr(comppath);
+			comppath = NULL;
+		}
+	}
+	PG_CATCH();
+	{
+		if (comppath != NULL)
+			xmlXPathFreeCompExpr(comppath);
+		cleanup_workspace(workspace);
 
-		xmlXPathFreeCompExpr(comppath);
+		PG_RE_THROW();
 	}
+	PG_END_TRY();
 
 	return workspace;
 }
-- 
2.54.0


--MP_/LMSk9=uMhuQ1QiIJDarDO8G--





^ permalink  raw  reply  [nested|flat] 611+ messages in thread

* [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths
@ 2026-06-01 22:41 Andrey Chernyy <andrey.cherny@tantorlabs.com>
  0 siblings, 0 replies; 611+ messages in thread

From: Andrey Chernyy @ 2026-06-01 22:41 UTC (permalink / raw)

pgxml_xpath() builds an xpath_workspace before returning it to
callers.  If an ERROR is thrown before the function returns, callers
have not received the workspace pointer yet and cannot run
cleanup_workspace().

Add local error cleanup for the partially built workspace and the
compiled XPath expression.  Also check xmlXPathNewContext() before
dereferencing the returned context.
---
 contrib/xml2/xpath.c | 51 +++++++++++++++++++++++++++-----------------
 1 file changed, 32 insertions(+), 19 deletions(-)

diff --git a/contrib/xml2/xpath.c b/contrib/xml2/xpath.c
index 9fe75cb5ff4..283bb51178d 100644
--- a/contrib/xml2/xpath.c
+++ b/contrib/xml2/xpath.c
@@ -497,36 +497,49 @@ static xpath_workspace *
 pgxml_xpath(text *document, xmlChar *xpath, PgXmlErrorContext *xmlerrcxt)
 {
 	int32		docsize = VARSIZE_ANY_EXHDR(document);
-	xmlXPathCompExprPtr comppath;
+	xmlXPathCompExprPtr volatile comppath = NULL;
 	xpath_workspace *workspace = palloc0_object(xpath_workspace);
 
 	workspace->doctree = NULL;
 	workspace->ctxt = NULL;
 	workspace->res = NULL;
 
-	workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
-									   docsize, NULL, NULL,
-									   XML_PARSE_NOENT);
-	if (workspace->doctree != NULL)
+	PG_TRY();
 	{
-		workspace->ctxt = xmlXPathNewContext(workspace->doctree);
-		workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
-
-		/* compile the path */
-		comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
-		if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+		workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
+										   docsize, NULL, NULL,
+										   XML_PARSE_NOENT);
+		if (workspace->doctree != NULL)
 		{
-			if (comppath != NULL)
-				xmlXPathFreeCompExpr(comppath);
-			xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
-						"XPath Syntax Error");
-		}
+			workspace->ctxt = xmlXPathNewContext(workspace->doctree);
+			if (workspace->ctxt == NULL)
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_OUT_OF_MEMORY,
+							"could not allocate XPath context");
 
-		/* Now evaluate the path expression. */
-		workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+			workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
+
+			/* compile the path */
+			comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
+			if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
+							"XPath Syntax Error");
+
+			/* Now evaluate the path expression. */
+			workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+
+			xmlXPathFreeCompExpr(comppath);
+			comppath = NULL;
+		}
+	}
+	PG_CATCH();
+	{
+		if (comppath != NULL)
+			xmlXPathFreeCompExpr(comppath);
+		cleanup_workspace(workspace);
 
-		xmlXPathFreeCompExpr(comppath);
+		PG_RE_THROW();
 	}
+	PG_END_TRY();
 
 	return workspace;
 }
-- 
2.54.0


--MP_/LMSk9=uMhuQ1QiIJDarDO8G--






^ permalink  raw  reply  [nested|flat] 611+ messages in thread

* [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths
@ 2026-06-01 22:41 Andrey Chernyy <andrey.cherny@tantorlabs.com>
  0 siblings, 0 replies; 611+ messages in thread

From: Andrey Chernyy @ 2026-06-01 22:41 UTC (permalink / raw)

pgxml_xpath() builds an xpath_workspace before returning it to
callers.  If an ERROR is thrown before the function returns, callers
have not received the workspace pointer yet and cannot run
cleanup_workspace().

Add local error cleanup for the partially built workspace and the
compiled XPath expression.  Also check xmlXPathNewContext() before
dereferencing the returned context.
---
 contrib/xml2/xpath.c | 51 +++++++++++++++++++++++++++-----------------
 1 file changed, 32 insertions(+), 19 deletions(-)

diff --git a/contrib/xml2/xpath.c b/contrib/xml2/xpath.c
index 9fe75cb5ff4..283bb51178d 100644
--- a/contrib/xml2/xpath.c
+++ b/contrib/xml2/xpath.c
@@ -497,36 +497,49 @@ static xpath_workspace *
 pgxml_xpath(text *document, xmlChar *xpath, PgXmlErrorContext *xmlerrcxt)
 {
 	int32		docsize = VARSIZE_ANY_EXHDR(document);
-	xmlXPathCompExprPtr comppath;
+	xmlXPathCompExprPtr volatile comppath = NULL;
 	xpath_workspace *workspace = palloc0_object(xpath_workspace);
 
 	workspace->doctree = NULL;
 	workspace->ctxt = NULL;
 	workspace->res = NULL;
 
-	workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
-									   docsize, NULL, NULL,
-									   XML_PARSE_NOENT);
-	if (workspace->doctree != NULL)
+	PG_TRY();
 	{
-		workspace->ctxt = xmlXPathNewContext(workspace->doctree);
-		workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
-
-		/* compile the path */
-		comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
-		if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+		workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
+										   docsize, NULL, NULL,
+										   XML_PARSE_NOENT);
+		if (workspace->doctree != NULL)
 		{
-			if (comppath != NULL)
-				xmlXPathFreeCompExpr(comppath);
-			xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
-						"XPath Syntax Error");
-		}
+			workspace->ctxt = xmlXPathNewContext(workspace->doctree);
+			if (workspace->ctxt == NULL)
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_OUT_OF_MEMORY,
+							"could not allocate XPath context");
 
-		/* Now evaluate the path expression. */
-		workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+			workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
+
+			/* compile the path */
+			comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
+			if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
+							"XPath Syntax Error");
+
+			/* Now evaluate the path expression. */
+			workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+
+			xmlXPathFreeCompExpr(comppath);
+			comppath = NULL;
+		}
+	}
+	PG_CATCH();
+	{
+		if (comppath != NULL)
+			xmlXPathFreeCompExpr(comppath);
+		cleanup_workspace(workspace);
 
-		xmlXPathFreeCompExpr(comppath);
+		PG_RE_THROW();
 	}
+	PG_END_TRY();
 
 	return workspace;
 }
-- 
2.54.0


--MP_/LMSk9=uMhuQ1QiIJDarDO8G--





^ permalink  raw  reply  [nested|flat] 611+ messages in thread

* [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths
@ 2026-06-01 22:41 Andrey Chernyy <andrey.cherny@tantorlabs.com>
  0 siblings, 0 replies; 611+ messages in thread

From: Andrey Chernyy @ 2026-06-01 22:41 UTC (permalink / raw)

pgxml_xpath() builds an xpath_workspace before returning it to
callers.  If an ERROR is thrown before the function returns, callers
have not received the workspace pointer yet and cannot run
cleanup_workspace().

Add local error cleanup for the partially built workspace and the
compiled XPath expression.  Also check xmlXPathNewContext() before
dereferencing the returned context.
---
 contrib/xml2/xpath.c | 51 +++++++++++++++++++++++++++-----------------
 1 file changed, 32 insertions(+), 19 deletions(-)

diff --git a/contrib/xml2/xpath.c b/contrib/xml2/xpath.c
index 9fe75cb5ff4..283bb51178d 100644
--- a/contrib/xml2/xpath.c
+++ b/contrib/xml2/xpath.c
@@ -497,36 +497,49 @@ static xpath_workspace *
 pgxml_xpath(text *document, xmlChar *xpath, PgXmlErrorContext *xmlerrcxt)
 {
 	int32		docsize = VARSIZE_ANY_EXHDR(document);
-	xmlXPathCompExprPtr comppath;
+	xmlXPathCompExprPtr volatile comppath = NULL;
 	xpath_workspace *workspace = palloc0_object(xpath_workspace);
 
 	workspace->doctree = NULL;
 	workspace->ctxt = NULL;
 	workspace->res = NULL;
 
-	workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
-									   docsize, NULL, NULL,
-									   XML_PARSE_NOENT);
-	if (workspace->doctree != NULL)
+	PG_TRY();
 	{
-		workspace->ctxt = xmlXPathNewContext(workspace->doctree);
-		workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
-
-		/* compile the path */
-		comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
-		if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+		workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
+										   docsize, NULL, NULL,
+										   XML_PARSE_NOENT);
+		if (workspace->doctree != NULL)
 		{
-			if (comppath != NULL)
-				xmlXPathFreeCompExpr(comppath);
-			xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
-						"XPath Syntax Error");
-		}
+			workspace->ctxt = xmlXPathNewContext(workspace->doctree);
+			if (workspace->ctxt == NULL)
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_OUT_OF_MEMORY,
+							"could not allocate XPath context");
 
-		/* Now evaluate the path expression. */
-		workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+			workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
+
+			/* compile the path */
+			comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
+			if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
+							"XPath Syntax Error");
+
+			/* Now evaluate the path expression. */
+			workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+
+			xmlXPathFreeCompExpr(comppath);
+			comppath = NULL;
+		}
+	}
+	PG_CATCH();
+	{
+		if (comppath != NULL)
+			xmlXPathFreeCompExpr(comppath);
+		cleanup_workspace(workspace);
 
-		xmlXPathFreeCompExpr(comppath);
+		PG_RE_THROW();
 	}
+	PG_END_TRY();
 
 	return workspace;
 }
-- 
2.54.0


--MP_/LMSk9=uMhuQ1QiIJDarDO8G--






^ permalink  raw  reply  [nested|flat] 611+ messages in thread

* [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths
@ 2026-06-01 22:41 Andrey Chernyy <andrey.cherny@tantorlabs.com>
  0 siblings, 0 replies; 611+ messages in thread

From: Andrey Chernyy @ 2026-06-01 22:41 UTC (permalink / raw)

pgxml_xpath() builds an xpath_workspace before returning it to
callers.  If an ERROR is thrown before the function returns, callers
have not received the workspace pointer yet and cannot run
cleanup_workspace().

Add local error cleanup for the partially built workspace and the
compiled XPath expression.  Also check xmlXPathNewContext() before
dereferencing the returned context.
---
 contrib/xml2/xpath.c | 51 +++++++++++++++++++++++++++-----------------
 1 file changed, 32 insertions(+), 19 deletions(-)

diff --git a/contrib/xml2/xpath.c b/contrib/xml2/xpath.c
index 9fe75cb5ff4..283bb51178d 100644
--- a/contrib/xml2/xpath.c
+++ b/contrib/xml2/xpath.c
@@ -497,36 +497,49 @@ static xpath_workspace *
 pgxml_xpath(text *document, xmlChar *xpath, PgXmlErrorContext *xmlerrcxt)
 {
 	int32		docsize = VARSIZE_ANY_EXHDR(document);
-	xmlXPathCompExprPtr comppath;
+	xmlXPathCompExprPtr volatile comppath = NULL;
 	xpath_workspace *workspace = palloc0_object(xpath_workspace);
 
 	workspace->doctree = NULL;
 	workspace->ctxt = NULL;
 	workspace->res = NULL;
 
-	workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
-									   docsize, NULL, NULL,
-									   XML_PARSE_NOENT);
-	if (workspace->doctree != NULL)
+	PG_TRY();
 	{
-		workspace->ctxt = xmlXPathNewContext(workspace->doctree);
-		workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
-
-		/* compile the path */
-		comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
-		if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+		workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
+										   docsize, NULL, NULL,
+										   XML_PARSE_NOENT);
+		if (workspace->doctree != NULL)
 		{
-			if (comppath != NULL)
-				xmlXPathFreeCompExpr(comppath);
-			xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
-						"XPath Syntax Error");
-		}
+			workspace->ctxt = xmlXPathNewContext(workspace->doctree);
+			if (workspace->ctxt == NULL)
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_OUT_OF_MEMORY,
+							"could not allocate XPath context");
 
-		/* Now evaluate the path expression. */
-		workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+			workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
+
+			/* compile the path */
+			comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
+			if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
+							"XPath Syntax Error");
+
+			/* Now evaluate the path expression. */
+			workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+
+			xmlXPathFreeCompExpr(comppath);
+			comppath = NULL;
+		}
+	}
+	PG_CATCH();
+	{
+		if (comppath != NULL)
+			xmlXPathFreeCompExpr(comppath);
+		cleanup_workspace(workspace);
 
-		xmlXPathFreeCompExpr(comppath);
+		PG_RE_THROW();
 	}
+	PG_END_TRY();
 
 	return workspace;
 }
-- 
2.54.0


--MP_/LMSk9=uMhuQ1QiIJDarDO8G--





^ permalink  raw  reply  [nested|flat] 611+ messages in thread

* [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths
@ 2026-06-01 22:41 Andrey Chernyy <andrey.cherny@tantorlabs.com>
  0 siblings, 0 replies; 611+ messages in thread

From: Andrey Chernyy @ 2026-06-01 22:41 UTC (permalink / raw)

pgxml_xpath() builds an xpath_workspace before returning it to
callers.  If an ERROR is thrown before the function returns, callers
have not received the workspace pointer yet and cannot run
cleanup_workspace().

Add local error cleanup for the partially built workspace and the
compiled XPath expression.  Also check xmlXPathNewContext() before
dereferencing the returned context.
---
 contrib/xml2/xpath.c | 51 +++++++++++++++++++++++++++-----------------
 1 file changed, 32 insertions(+), 19 deletions(-)

diff --git a/contrib/xml2/xpath.c b/contrib/xml2/xpath.c
index 9fe75cb5ff4..283bb51178d 100644
--- a/contrib/xml2/xpath.c
+++ b/contrib/xml2/xpath.c
@@ -497,36 +497,49 @@ static xpath_workspace *
 pgxml_xpath(text *document, xmlChar *xpath, PgXmlErrorContext *xmlerrcxt)
 {
 	int32		docsize = VARSIZE_ANY_EXHDR(document);
-	xmlXPathCompExprPtr comppath;
+	xmlXPathCompExprPtr volatile comppath = NULL;
 	xpath_workspace *workspace = palloc0_object(xpath_workspace);
 
 	workspace->doctree = NULL;
 	workspace->ctxt = NULL;
 	workspace->res = NULL;
 
-	workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
-									   docsize, NULL, NULL,
-									   XML_PARSE_NOENT);
-	if (workspace->doctree != NULL)
+	PG_TRY();
 	{
-		workspace->ctxt = xmlXPathNewContext(workspace->doctree);
-		workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
-
-		/* compile the path */
-		comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
-		if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+		workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
+										   docsize, NULL, NULL,
+										   XML_PARSE_NOENT);
+		if (workspace->doctree != NULL)
 		{
-			if (comppath != NULL)
-				xmlXPathFreeCompExpr(comppath);
-			xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
-						"XPath Syntax Error");
-		}
+			workspace->ctxt = xmlXPathNewContext(workspace->doctree);
+			if (workspace->ctxt == NULL)
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_OUT_OF_MEMORY,
+							"could not allocate XPath context");
 
-		/* Now evaluate the path expression. */
-		workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+			workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
+
+			/* compile the path */
+			comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
+			if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
+							"XPath Syntax Error");
+
+			/* Now evaluate the path expression. */
+			workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+
+			xmlXPathFreeCompExpr(comppath);
+			comppath = NULL;
+		}
+	}
+	PG_CATCH();
+	{
+		if (comppath != NULL)
+			xmlXPathFreeCompExpr(comppath);
+		cleanup_workspace(workspace);
 
-		xmlXPathFreeCompExpr(comppath);
+		PG_RE_THROW();
 	}
+	PG_END_TRY();
 
 	return workspace;
 }
-- 
2.54.0


--MP_/LMSk9=uMhuQ1QiIJDarDO8G--





^ permalink  raw  reply  [nested|flat] 611+ messages in thread

* [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths
@ 2026-06-01 22:41 Andrey Chernyy <andrey.cherny@tantorlabs.com>
  0 siblings, 0 replies; 611+ messages in thread

From: Andrey Chernyy @ 2026-06-01 22:41 UTC (permalink / raw)

pgxml_xpath() builds an xpath_workspace before returning it to
callers.  If an ERROR is thrown before the function returns, callers
have not received the workspace pointer yet and cannot run
cleanup_workspace().

Add local error cleanup for the partially built workspace and the
compiled XPath expression.  Also check xmlXPathNewContext() before
dereferencing the returned context.
---
 contrib/xml2/xpath.c | 51 +++++++++++++++++++++++++++-----------------
 1 file changed, 32 insertions(+), 19 deletions(-)

diff --git a/contrib/xml2/xpath.c b/contrib/xml2/xpath.c
index 9fe75cb5ff4..283bb51178d 100644
--- a/contrib/xml2/xpath.c
+++ b/contrib/xml2/xpath.c
@@ -497,36 +497,49 @@ static xpath_workspace *
 pgxml_xpath(text *document, xmlChar *xpath, PgXmlErrorContext *xmlerrcxt)
 {
 	int32		docsize = VARSIZE_ANY_EXHDR(document);
-	xmlXPathCompExprPtr comppath;
+	xmlXPathCompExprPtr volatile comppath = NULL;
 	xpath_workspace *workspace = palloc0_object(xpath_workspace);
 
 	workspace->doctree = NULL;
 	workspace->ctxt = NULL;
 	workspace->res = NULL;
 
-	workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
-									   docsize, NULL, NULL,
-									   XML_PARSE_NOENT);
-	if (workspace->doctree != NULL)
+	PG_TRY();
 	{
-		workspace->ctxt = xmlXPathNewContext(workspace->doctree);
-		workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
-
-		/* compile the path */
-		comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
-		if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+		workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
+										   docsize, NULL, NULL,
+										   XML_PARSE_NOENT);
+		if (workspace->doctree != NULL)
 		{
-			if (comppath != NULL)
-				xmlXPathFreeCompExpr(comppath);
-			xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
-						"XPath Syntax Error");
-		}
+			workspace->ctxt = xmlXPathNewContext(workspace->doctree);
+			if (workspace->ctxt == NULL)
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_OUT_OF_MEMORY,
+							"could not allocate XPath context");
 
-		/* Now evaluate the path expression. */
-		workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+			workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
+
+			/* compile the path */
+			comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
+			if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
+							"XPath Syntax Error");
+
+			/* Now evaluate the path expression. */
+			workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+
+			xmlXPathFreeCompExpr(comppath);
+			comppath = NULL;
+		}
+	}
+	PG_CATCH();
+	{
+		if (comppath != NULL)
+			xmlXPathFreeCompExpr(comppath);
+		cleanup_workspace(workspace);
 
-		xmlXPathFreeCompExpr(comppath);
+		PG_RE_THROW();
 	}
+	PG_END_TRY();
 
 	return workspace;
 }
-- 
2.54.0


--MP_/LMSk9=uMhuQ1QiIJDarDO8G--






^ permalink  raw  reply  [nested|flat] 611+ messages in thread

* [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths
@ 2026-06-01 22:41 Andrey Chernyy <andrey.cherny@tantorlabs.com>
  0 siblings, 0 replies; 611+ messages in thread

From: Andrey Chernyy @ 2026-06-01 22:41 UTC (permalink / raw)

pgxml_xpath() builds an xpath_workspace before returning it to
callers.  If an ERROR is thrown before the function returns, callers
have not received the workspace pointer yet and cannot run
cleanup_workspace().

Add local error cleanup for the partially built workspace and the
compiled XPath expression.  Also check xmlXPathNewContext() before
dereferencing the returned context.
---
 contrib/xml2/xpath.c | 51 +++++++++++++++++++++++++++-----------------
 1 file changed, 32 insertions(+), 19 deletions(-)

diff --git a/contrib/xml2/xpath.c b/contrib/xml2/xpath.c
index 9fe75cb5ff4..283bb51178d 100644
--- a/contrib/xml2/xpath.c
+++ b/contrib/xml2/xpath.c
@@ -497,36 +497,49 @@ static xpath_workspace *
 pgxml_xpath(text *document, xmlChar *xpath, PgXmlErrorContext *xmlerrcxt)
 {
 	int32		docsize = VARSIZE_ANY_EXHDR(document);
-	xmlXPathCompExprPtr comppath;
+	xmlXPathCompExprPtr volatile comppath = NULL;
 	xpath_workspace *workspace = palloc0_object(xpath_workspace);
 
 	workspace->doctree = NULL;
 	workspace->ctxt = NULL;
 	workspace->res = NULL;
 
-	workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
-									   docsize, NULL, NULL,
-									   XML_PARSE_NOENT);
-	if (workspace->doctree != NULL)
+	PG_TRY();
 	{
-		workspace->ctxt = xmlXPathNewContext(workspace->doctree);
-		workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
-
-		/* compile the path */
-		comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
-		if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+		workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
+										   docsize, NULL, NULL,
+										   XML_PARSE_NOENT);
+		if (workspace->doctree != NULL)
 		{
-			if (comppath != NULL)
-				xmlXPathFreeCompExpr(comppath);
-			xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
-						"XPath Syntax Error");
-		}
+			workspace->ctxt = xmlXPathNewContext(workspace->doctree);
+			if (workspace->ctxt == NULL)
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_OUT_OF_MEMORY,
+							"could not allocate XPath context");
 
-		/* Now evaluate the path expression. */
-		workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+			workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
+
+			/* compile the path */
+			comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
+			if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
+							"XPath Syntax Error");
+
+			/* Now evaluate the path expression. */
+			workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+
+			xmlXPathFreeCompExpr(comppath);
+			comppath = NULL;
+		}
+	}
+	PG_CATCH();
+	{
+		if (comppath != NULL)
+			xmlXPathFreeCompExpr(comppath);
+		cleanup_workspace(workspace);
 
-		xmlXPathFreeCompExpr(comppath);
+		PG_RE_THROW();
 	}
+	PG_END_TRY();
 
 	return workspace;
 }
-- 
2.54.0


--MP_/LMSk9=uMhuQ1QiIJDarDO8G--






^ permalink  raw  reply  [nested|flat] 611+ messages in thread

* [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths
@ 2026-06-01 22:41 Andrey Chernyy <andrey.cherny@tantorlabs.com>
  0 siblings, 0 replies; 611+ messages in thread

From: Andrey Chernyy @ 2026-06-01 22:41 UTC (permalink / raw)

pgxml_xpath() builds an xpath_workspace before returning it to
callers.  If an ERROR is thrown before the function returns, callers
have not received the workspace pointer yet and cannot run
cleanup_workspace().

Add local error cleanup for the partially built workspace and the
compiled XPath expression.  Also check xmlXPathNewContext() before
dereferencing the returned context.
---
 contrib/xml2/xpath.c | 51 +++++++++++++++++++++++++++-----------------
 1 file changed, 32 insertions(+), 19 deletions(-)

diff --git a/contrib/xml2/xpath.c b/contrib/xml2/xpath.c
index 9fe75cb5ff4..283bb51178d 100644
--- a/contrib/xml2/xpath.c
+++ b/contrib/xml2/xpath.c
@@ -497,36 +497,49 @@ static xpath_workspace *
 pgxml_xpath(text *document, xmlChar *xpath, PgXmlErrorContext *xmlerrcxt)
 {
 	int32		docsize = VARSIZE_ANY_EXHDR(document);
-	xmlXPathCompExprPtr comppath;
+	xmlXPathCompExprPtr volatile comppath = NULL;
 	xpath_workspace *workspace = palloc0_object(xpath_workspace);
 
 	workspace->doctree = NULL;
 	workspace->ctxt = NULL;
 	workspace->res = NULL;
 
-	workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
-									   docsize, NULL, NULL,
-									   XML_PARSE_NOENT);
-	if (workspace->doctree != NULL)
+	PG_TRY();
 	{
-		workspace->ctxt = xmlXPathNewContext(workspace->doctree);
-		workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
-
-		/* compile the path */
-		comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
-		if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+		workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
+										   docsize, NULL, NULL,
+										   XML_PARSE_NOENT);
+		if (workspace->doctree != NULL)
 		{
-			if (comppath != NULL)
-				xmlXPathFreeCompExpr(comppath);
-			xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
-						"XPath Syntax Error");
-		}
+			workspace->ctxt = xmlXPathNewContext(workspace->doctree);
+			if (workspace->ctxt == NULL)
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_OUT_OF_MEMORY,
+							"could not allocate XPath context");
 
-		/* Now evaluate the path expression. */
-		workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+			workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
+
+			/* compile the path */
+			comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
+			if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
+							"XPath Syntax Error");
+
+			/* Now evaluate the path expression. */
+			workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+
+			xmlXPathFreeCompExpr(comppath);
+			comppath = NULL;
+		}
+	}
+	PG_CATCH();
+	{
+		if (comppath != NULL)
+			xmlXPathFreeCompExpr(comppath);
+		cleanup_workspace(workspace);
 
-		xmlXPathFreeCompExpr(comppath);
+		PG_RE_THROW();
 	}
+	PG_END_TRY();
 
 	return workspace;
 }
-- 
2.54.0


--MP_/LMSk9=uMhuQ1QiIJDarDO8G--





^ permalink  raw  reply  [nested|flat] 611+ messages in thread

* [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths
@ 2026-06-01 22:41 Andrey Chernyy <andrey.cherny@tantorlabs.com>
  0 siblings, 0 replies; 611+ messages in thread

From: Andrey Chernyy @ 2026-06-01 22:41 UTC (permalink / raw)

pgxml_xpath() builds an xpath_workspace before returning it to
callers.  If an ERROR is thrown before the function returns, callers
have not received the workspace pointer yet and cannot run
cleanup_workspace().

Add local error cleanup for the partially built workspace and the
compiled XPath expression.  Also check xmlXPathNewContext() before
dereferencing the returned context.
---
 contrib/xml2/xpath.c | 51 +++++++++++++++++++++++++++-----------------
 1 file changed, 32 insertions(+), 19 deletions(-)

diff --git a/contrib/xml2/xpath.c b/contrib/xml2/xpath.c
index 9fe75cb5ff4..283bb51178d 100644
--- a/contrib/xml2/xpath.c
+++ b/contrib/xml2/xpath.c
@@ -497,36 +497,49 @@ static xpath_workspace *
 pgxml_xpath(text *document, xmlChar *xpath, PgXmlErrorContext *xmlerrcxt)
 {
 	int32		docsize = VARSIZE_ANY_EXHDR(document);
-	xmlXPathCompExprPtr comppath;
+	xmlXPathCompExprPtr volatile comppath = NULL;
 	xpath_workspace *workspace = palloc0_object(xpath_workspace);
 
 	workspace->doctree = NULL;
 	workspace->ctxt = NULL;
 	workspace->res = NULL;
 
-	workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
-									   docsize, NULL, NULL,
-									   XML_PARSE_NOENT);
-	if (workspace->doctree != NULL)
+	PG_TRY();
 	{
-		workspace->ctxt = xmlXPathNewContext(workspace->doctree);
-		workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
-
-		/* compile the path */
-		comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
-		if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+		workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
+										   docsize, NULL, NULL,
+										   XML_PARSE_NOENT);
+		if (workspace->doctree != NULL)
 		{
-			if (comppath != NULL)
-				xmlXPathFreeCompExpr(comppath);
-			xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
-						"XPath Syntax Error");
-		}
+			workspace->ctxt = xmlXPathNewContext(workspace->doctree);
+			if (workspace->ctxt == NULL)
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_OUT_OF_MEMORY,
+							"could not allocate XPath context");
 
-		/* Now evaluate the path expression. */
-		workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+			workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
+
+			/* compile the path */
+			comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
+			if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
+							"XPath Syntax Error");
+
+			/* Now evaluate the path expression. */
+			workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+
+			xmlXPathFreeCompExpr(comppath);
+			comppath = NULL;
+		}
+	}
+	PG_CATCH();
+	{
+		if (comppath != NULL)
+			xmlXPathFreeCompExpr(comppath);
+		cleanup_workspace(workspace);
 
-		xmlXPathFreeCompExpr(comppath);
+		PG_RE_THROW();
 	}
+	PG_END_TRY();
 
 	return workspace;
 }
-- 
2.54.0


--MP_/LMSk9=uMhuQ1QiIJDarDO8G--





^ permalink  raw  reply  [nested|flat] 611+ messages in thread

* [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths
@ 2026-06-01 22:41 Andrey Chernyy <andrey.cherny@tantorlabs.com>
  0 siblings, 0 replies; 611+ messages in thread

From: Andrey Chernyy @ 2026-06-01 22:41 UTC (permalink / raw)

pgxml_xpath() builds an xpath_workspace before returning it to
callers.  If an ERROR is thrown before the function returns, callers
have not received the workspace pointer yet and cannot run
cleanup_workspace().

Add local error cleanup for the partially built workspace and the
compiled XPath expression.  Also check xmlXPathNewContext() before
dereferencing the returned context.
---
 contrib/xml2/xpath.c | 51 +++++++++++++++++++++++++++-----------------
 1 file changed, 32 insertions(+), 19 deletions(-)

diff --git a/contrib/xml2/xpath.c b/contrib/xml2/xpath.c
index 9fe75cb5ff4..283bb51178d 100644
--- a/contrib/xml2/xpath.c
+++ b/contrib/xml2/xpath.c
@@ -497,36 +497,49 @@ static xpath_workspace *
 pgxml_xpath(text *document, xmlChar *xpath, PgXmlErrorContext *xmlerrcxt)
 {
 	int32		docsize = VARSIZE_ANY_EXHDR(document);
-	xmlXPathCompExprPtr comppath;
+	xmlXPathCompExprPtr volatile comppath = NULL;
 	xpath_workspace *workspace = palloc0_object(xpath_workspace);
 
 	workspace->doctree = NULL;
 	workspace->ctxt = NULL;
 	workspace->res = NULL;
 
-	workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
-									   docsize, NULL, NULL,
-									   XML_PARSE_NOENT);
-	if (workspace->doctree != NULL)
+	PG_TRY();
 	{
-		workspace->ctxt = xmlXPathNewContext(workspace->doctree);
-		workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
-
-		/* compile the path */
-		comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
-		if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+		workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
+										   docsize, NULL, NULL,
+										   XML_PARSE_NOENT);
+		if (workspace->doctree != NULL)
 		{
-			if (comppath != NULL)
-				xmlXPathFreeCompExpr(comppath);
-			xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
-						"XPath Syntax Error");
-		}
+			workspace->ctxt = xmlXPathNewContext(workspace->doctree);
+			if (workspace->ctxt == NULL)
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_OUT_OF_MEMORY,
+							"could not allocate XPath context");
 
-		/* Now evaluate the path expression. */
-		workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+			workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
+
+			/* compile the path */
+			comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
+			if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
+							"XPath Syntax Error");
+
+			/* Now evaluate the path expression. */
+			workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+
+			xmlXPathFreeCompExpr(comppath);
+			comppath = NULL;
+		}
+	}
+	PG_CATCH();
+	{
+		if (comppath != NULL)
+			xmlXPathFreeCompExpr(comppath);
+		cleanup_workspace(workspace);
 
-		xmlXPathFreeCompExpr(comppath);
+		PG_RE_THROW();
 	}
+	PG_END_TRY();
 
 	return workspace;
 }
-- 
2.54.0


--MP_/LMSk9=uMhuQ1QiIJDarDO8G--






^ permalink  raw  reply  [nested|flat] 611+ messages in thread

* [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths
@ 2026-06-01 22:41 Andrey Chernyy <andrey.cherny@tantorlabs.com>
  0 siblings, 0 replies; 611+ messages in thread

From: Andrey Chernyy @ 2026-06-01 22:41 UTC (permalink / raw)

pgxml_xpath() builds an xpath_workspace before returning it to
callers.  If an ERROR is thrown before the function returns, callers
have not received the workspace pointer yet and cannot run
cleanup_workspace().

Add local error cleanup for the partially built workspace and the
compiled XPath expression.  Also check xmlXPathNewContext() before
dereferencing the returned context.
---
 contrib/xml2/xpath.c | 51 +++++++++++++++++++++++++++-----------------
 1 file changed, 32 insertions(+), 19 deletions(-)

diff --git a/contrib/xml2/xpath.c b/contrib/xml2/xpath.c
index 9fe75cb5ff4..283bb51178d 100644
--- a/contrib/xml2/xpath.c
+++ b/contrib/xml2/xpath.c
@@ -497,36 +497,49 @@ static xpath_workspace *
 pgxml_xpath(text *document, xmlChar *xpath, PgXmlErrorContext *xmlerrcxt)
 {
 	int32		docsize = VARSIZE_ANY_EXHDR(document);
-	xmlXPathCompExprPtr comppath;
+	xmlXPathCompExprPtr volatile comppath = NULL;
 	xpath_workspace *workspace = palloc0_object(xpath_workspace);
 
 	workspace->doctree = NULL;
 	workspace->ctxt = NULL;
 	workspace->res = NULL;
 
-	workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
-									   docsize, NULL, NULL,
-									   XML_PARSE_NOENT);
-	if (workspace->doctree != NULL)
+	PG_TRY();
 	{
-		workspace->ctxt = xmlXPathNewContext(workspace->doctree);
-		workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
-
-		/* compile the path */
-		comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
-		if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+		workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
+										   docsize, NULL, NULL,
+										   XML_PARSE_NOENT);
+		if (workspace->doctree != NULL)
 		{
-			if (comppath != NULL)
-				xmlXPathFreeCompExpr(comppath);
-			xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
-						"XPath Syntax Error");
-		}
+			workspace->ctxt = xmlXPathNewContext(workspace->doctree);
+			if (workspace->ctxt == NULL)
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_OUT_OF_MEMORY,
+							"could not allocate XPath context");
 
-		/* Now evaluate the path expression. */
-		workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+			workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
+
+			/* compile the path */
+			comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
+			if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
+							"XPath Syntax Error");
+
+			/* Now evaluate the path expression. */
+			workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+
+			xmlXPathFreeCompExpr(comppath);
+			comppath = NULL;
+		}
+	}
+	PG_CATCH();
+	{
+		if (comppath != NULL)
+			xmlXPathFreeCompExpr(comppath);
+		cleanup_workspace(workspace);
 
-		xmlXPathFreeCompExpr(comppath);
+		PG_RE_THROW();
 	}
+	PG_END_TRY();
 
 	return workspace;
 }
-- 
2.54.0


--MP_/LMSk9=uMhuQ1QiIJDarDO8G--





^ permalink  raw  reply  [nested|flat] 611+ messages in thread

* [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths
@ 2026-06-01 22:41 Andrey Chernyy <andrey.cherny@tantorlabs.com>
  0 siblings, 0 replies; 611+ messages in thread

From: Andrey Chernyy @ 2026-06-01 22:41 UTC (permalink / raw)

pgxml_xpath() builds an xpath_workspace before returning it to
callers.  If an ERROR is thrown before the function returns, callers
have not received the workspace pointer yet and cannot run
cleanup_workspace().

Add local error cleanup for the partially built workspace and the
compiled XPath expression.  Also check xmlXPathNewContext() before
dereferencing the returned context.
---
 contrib/xml2/xpath.c | 51 +++++++++++++++++++++++++++-----------------
 1 file changed, 32 insertions(+), 19 deletions(-)

diff --git a/contrib/xml2/xpath.c b/contrib/xml2/xpath.c
index 9fe75cb5ff4..283bb51178d 100644
--- a/contrib/xml2/xpath.c
+++ b/contrib/xml2/xpath.c
@@ -497,36 +497,49 @@ static xpath_workspace *
 pgxml_xpath(text *document, xmlChar *xpath, PgXmlErrorContext *xmlerrcxt)
 {
 	int32		docsize = VARSIZE_ANY_EXHDR(document);
-	xmlXPathCompExprPtr comppath;
+	xmlXPathCompExprPtr volatile comppath = NULL;
 	xpath_workspace *workspace = palloc0_object(xpath_workspace);
 
 	workspace->doctree = NULL;
 	workspace->ctxt = NULL;
 	workspace->res = NULL;
 
-	workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
-									   docsize, NULL, NULL,
-									   XML_PARSE_NOENT);
-	if (workspace->doctree != NULL)
+	PG_TRY();
 	{
-		workspace->ctxt = xmlXPathNewContext(workspace->doctree);
-		workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
-
-		/* compile the path */
-		comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
-		if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+		workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
+										   docsize, NULL, NULL,
+										   XML_PARSE_NOENT);
+		if (workspace->doctree != NULL)
 		{
-			if (comppath != NULL)
-				xmlXPathFreeCompExpr(comppath);
-			xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
-						"XPath Syntax Error");
-		}
+			workspace->ctxt = xmlXPathNewContext(workspace->doctree);
+			if (workspace->ctxt == NULL)
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_OUT_OF_MEMORY,
+							"could not allocate XPath context");
 
-		/* Now evaluate the path expression. */
-		workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+			workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
+
+			/* compile the path */
+			comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
+			if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
+							"XPath Syntax Error");
+
+			/* Now evaluate the path expression. */
+			workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+
+			xmlXPathFreeCompExpr(comppath);
+			comppath = NULL;
+		}
+	}
+	PG_CATCH();
+	{
+		if (comppath != NULL)
+			xmlXPathFreeCompExpr(comppath);
+		cleanup_workspace(workspace);
 
-		xmlXPathFreeCompExpr(comppath);
+		PG_RE_THROW();
 	}
+	PG_END_TRY();
 
 	return workspace;
 }
-- 
2.54.0


--MP_/LMSk9=uMhuQ1QiIJDarDO8G--






^ permalink  raw  reply  [nested|flat] 611+ messages in thread

* [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths
@ 2026-06-01 22:41 Andrey Chernyy <andrey.cherny@tantorlabs.com>
  0 siblings, 0 replies; 611+ messages in thread

From: Andrey Chernyy @ 2026-06-01 22:41 UTC (permalink / raw)

pgxml_xpath() builds an xpath_workspace before returning it to
callers.  If an ERROR is thrown before the function returns, callers
have not received the workspace pointer yet and cannot run
cleanup_workspace().

Add local error cleanup for the partially built workspace and the
compiled XPath expression.  Also check xmlXPathNewContext() before
dereferencing the returned context.
---
 contrib/xml2/xpath.c | 51 +++++++++++++++++++++++++++-----------------
 1 file changed, 32 insertions(+), 19 deletions(-)

diff --git a/contrib/xml2/xpath.c b/contrib/xml2/xpath.c
index 9fe75cb5ff4..283bb51178d 100644
--- a/contrib/xml2/xpath.c
+++ b/contrib/xml2/xpath.c
@@ -497,36 +497,49 @@ static xpath_workspace *
 pgxml_xpath(text *document, xmlChar *xpath, PgXmlErrorContext *xmlerrcxt)
 {
 	int32		docsize = VARSIZE_ANY_EXHDR(document);
-	xmlXPathCompExprPtr comppath;
+	xmlXPathCompExprPtr volatile comppath = NULL;
 	xpath_workspace *workspace = palloc0_object(xpath_workspace);
 
 	workspace->doctree = NULL;
 	workspace->ctxt = NULL;
 	workspace->res = NULL;
 
-	workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
-									   docsize, NULL, NULL,
-									   XML_PARSE_NOENT);
-	if (workspace->doctree != NULL)
+	PG_TRY();
 	{
-		workspace->ctxt = xmlXPathNewContext(workspace->doctree);
-		workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
-
-		/* compile the path */
-		comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
-		if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+		workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
+										   docsize, NULL, NULL,
+										   XML_PARSE_NOENT);
+		if (workspace->doctree != NULL)
 		{
-			if (comppath != NULL)
-				xmlXPathFreeCompExpr(comppath);
-			xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
-						"XPath Syntax Error");
-		}
+			workspace->ctxt = xmlXPathNewContext(workspace->doctree);
+			if (workspace->ctxt == NULL)
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_OUT_OF_MEMORY,
+							"could not allocate XPath context");
 
-		/* Now evaluate the path expression. */
-		workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+			workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
+
+			/* compile the path */
+			comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
+			if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
+							"XPath Syntax Error");
+
+			/* Now evaluate the path expression. */
+			workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+
+			xmlXPathFreeCompExpr(comppath);
+			comppath = NULL;
+		}
+	}
+	PG_CATCH();
+	{
+		if (comppath != NULL)
+			xmlXPathFreeCompExpr(comppath);
+		cleanup_workspace(workspace);
 
-		xmlXPathFreeCompExpr(comppath);
+		PG_RE_THROW();
 	}
+	PG_END_TRY();
 
 	return workspace;
 }
-- 
2.54.0


--MP_/LMSk9=uMhuQ1QiIJDarDO8G--






^ permalink  raw  reply  [nested|flat] 611+ messages in thread

* [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths
@ 2026-06-01 22:41 Andrey Chernyy <andrey.cherny@tantorlabs.com>
  0 siblings, 0 replies; 611+ messages in thread

From: Andrey Chernyy @ 2026-06-01 22:41 UTC (permalink / raw)

pgxml_xpath() builds an xpath_workspace before returning it to
callers.  If an ERROR is thrown before the function returns, callers
have not received the workspace pointer yet and cannot run
cleanup_workspace().

Add local error cleanup for the partially built workspace and the
compiled XPath expression.  Also check xmlXPathNewContext() before
dereferencing the returned context.
---
 contrib/xml2/xpath.c | 51 +++++++++++++++++++++++++++-----------------
 1 file changed, 32 insertions(+), 19 deletions(-)

diff --git a/contrib/xml2/xpath.c b/contrib/xml2/xpath.c
index 9fe75cb5ff4..283bb51178d 100644
--- a/contrib/xml2/xpath.c
+++ b/contrib/xml2/xpath.c
@@ -497,36 +497,49 @@ static xpath_workspace *
 pgxml_xpath(text *document, xmlChar *xpath, PgXmlErrorContext *xmlerrcxt)
 {
 	int32		docsize = VARSIZE_ANY_EXHDR(document);
-	xmlXPathCompExprPtr comppath;
+	xmlXPathCompExprPtr volatile comppath = NULL;
 	xpath_workspace *workspace = palloc0_object(xpath_workspace);
 
 	workspace->doctree = NULL;
 	workspace->ctxt = NULL;
 	workspace->res = NULL;
 
-	workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
-									   docsize, NULL, NULL,
-									   XML_PARSE_NOENT);
-	if (workspace->doctree != NULL)
+	PG_TRY();
 	{
-		workspace->ctxt = xmlXPathNewContext(workspace->doctree);
-		workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
-
-		/* compile the path */
-		comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
-		if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+		workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
+										   docsize, NULL, NULL,
+										   XML_PARSE_NOENT);
+		if (workspace->doctree != NULL)
 		{
-			if (comppath != NULL)
-				xmlXPathFreeCompExpr(comppath);
-			xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
-						"XPath Syntax Error");
-		}
+			workspace->ctxt = xmlXPathNewContext(workspace->doctree);
+			if (workspace->ctxt == NULL)
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_OUT_OF_MEMORY,
+							"could not allocate XPath context");
 
-		/* Now evaluate the path expression. */
-		workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+			workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
+
+			/* compile the path */
+			comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
+			if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
+							"XPath Syntax Error");
+
+			/* Now evaluate the path expression. */
+			workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+
+			xmlXPathFreeCompExpr(comppath);
+			comppath = NULL;
+		}
+	}
+	PG_CATCH();
+	{
+		if (comppath != NULL)
+			xmlXPathFreeCompExpr(comppath);
+		cleanup_workspace(workspace);
 
-		xmlXPathFreeCompExpr(comppath);
+		PG_RE_THROW();
 	}
+	PG_END_TRY();
 
 	return workspace;
 }
-- 
2.54.0


--MP_/LMSk9=uMhuQ1QiIJDarDO8G--





^ permalink  raw  reply  [nested|flat] 611+ messages in thread

* [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths
@ 2026-06-01 22:41 Andrey Chernyy <andrey.cherny@tantorlabs.com>
  0 siblings, 0 replies; 611+ messages in thread

From: Andrey Chernyy @ 2026-06-01 22:41 UTC (permalink / raw)

pgxml_xpath() builds an xpath_workspace before returning it to
callers.  If an ERROR is thrown before the function returns, callers
have not received the workspace pointer yet and cannot run
cleanup_workspace().

Add local error cleanup for the partially built workspace and the
compiled XPath expression.  Also check xmlXPathNewContext() before
dereferencing the returned context.
---
 contrib/xml2/xpath.c | 51 +++++++++++++++++++++++++++-----------------
 1 file changed, 32 insertions(+), 19 deletions(-)

diff --git a/contrib/xml2/xpath.c b/contrib/xml2/xpath.c
index 9fe75cb5ff4..283bb51178d 100644
--- a/contrib/xml2/xpath.c
+++ b/contrib/xml2/xpath.c
@@ -497,36 +497,49 @@ static xpath_workspace *
 pgxml_xpath(text *document, xmlChar *xpath, PgXmlErrorContext *xmlerrcxt)
 {
 	int32		docsize = VARSIZE_ANY_EXHDR(document);
-	xmlXPathCompExprPtr comppath;
+	xmlXPathCompExprPtr volatile comppath = NULL;
 	xpath_workspace *workspace = palloc0_object(xpath_workspace);
 
 	workspace->doctree = NULL;
 	workspace->ctxt = NULL;
 	workspace->res = NULL;
 
-	workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
-									   docsize, NULL, NULL,
-									   XML_PARSE_NOENT);
-	if (workspace->doctree != NULL)
+	PG_TRY();
 	{
-		workspace->ctxt = xmlXPathNewContext(workspace->doctree);
-		workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
-
-		/* compile the path */
-		comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
-		if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+		workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
+										   docsize, NULL, NULL,
+										   XML_PARSE_NOENT);
+		if (workspace->doctree != NULL)
 		{
-			if (comppath != NULL)
-				xmlXPathFreeCompExpr(comppath);
-			xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
-						"XPath Syntax Error");
-		}
+			workspace->ctxt = xmlXPathNewContext(workspace->doctree);
+			if (workspace->ctxt == NULL)
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_OUT_OF_MEMORY,
+							"could not allocate XPath context");
 
-		/* Now evaluate the path expression. */
-		workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+			workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
+
+			/* compile the path */
+			comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
+			if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
+							"XPath Syntax Error");
+
+			/* Now evaluate the path expression. */
+			workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+
+			xmlXPathFreeCompExpr(comppath);
+			comppath = NULL;
+		}
+	}
+	PG_CATCH();
+	{
+		if (comppath != NULL)
+			xmlXPathFreeCompExpr(comppath);
+		cleanup_workspace(workspace);
 
-		xmlXPathFreeCompExpr(comppath);
+		PG_RE_THROW();
 	}
+	PG_END_TRY();
 
 	return workspace;
 }
-- 
2.54.0


--MP_/LMSk9=uMhuQ1QiIJDarDO8G--





^ permalink  raw  reply  [nested|flat] 611+ messages in thread

* [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths
@ 2026-06-01 22:41 Andrey Chernyy <andrey.cherny@tantorlabs.com>
  0 siblings, 0 replies; 611+ messages in thread

From: Andrey Chernyy @ 2026-06-01 22:41 UTC (permalink / raw)

pgxml_xpath() builds an xpath_workspace before returning it to
callers.  If an ERROR is thrown before the function returns, callers
have not received the workspace pointer yet and cannot run
cleanup_workspace().

Add local error cleanup for the partially built workspace and the
compiled XPath expression.  Also check xmlXPathNewContext() before
dereferencing the returned context.
---
 contrib/xml2/xpath.c | 51 +++++++++++++++++++++++++++-----------------
 1 file changed, 32 insertions(+), 19 deletions(-)

diff --git a/contrib/xml2/xpath.c b/contrib/xml2/xpath.c
index 9fe75cb5ff4..283bb51178d 100644
--- a/contrib/xml2/xpath.c
+++ b/contrib/xml2/xpath.c
@@ -497,36 +497,49 @@ static xpath_workspace *
 pgxml_xpath(text *document, xmlChar *xpath, PgXmlErrorContext *xmlerrcxt)
 {
 	int32		docsize = VARSIZE_ANY_EXHDR(document);
-	xmlXPathCompExprPtr comppath;
+	xmlXPathCompExprPtr volatile comppath = NULL;
 	xpath_workspace *workspace = palloc0_object(xpath_workspace);
 
 	workspace->doctree = NULL;
 	workspace->ctxt = NULL;
 	workspace->res = NULL;
 
-	workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
-									   docsize, NULL, NULL,
-									   XML_PARSE_NOENT);
-	if (workspace->doctree != NULL)
+	PG_TRY();
 	{
-		workspace->ctxt = xmlXPathNewContext(workspace->doctree);
-		workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
-
-		/* compile the path */
-		comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
-		if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+		workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
+										   docsize, NULL, NULL,
+										   XML_PARSE_NOENT);
+		if (workspace->doctree != NULL)
 		{
-			if (comppath != NULL)
-				xmlXPathFreeCompExpr(comppath);
-			xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
-						"XPath Syntax Error");
-		}
+			workspace->ctxt = xmlXPathNewContext(workspace->doctree);
+			if (workspace->ctxt == NULL)
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_OUT_OF_MEMORY,
+							"could not allocate XPath context");
 
-		/* Now evaluate the path expression. */
-		workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+			workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
+
+			/* compile the path */
+			comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
+			if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
+							"XPath Syntax Error");
+
+			/* Now evaluate the path expression. */
+			workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+
+			xmlXPathFreeCompExpr(comppath);
+			comppath = NULL;
+		}
+	}
+	PG_CATCH();
+	{
+		if (comppath != NULL)
+			xmlXPathFreeCompExpr(comppath);
+		cleanup_workspace(workspace);
 
-		xmlXPathFreeCompExpr(comppath);
+		PG_RE_THROW();
 	}
+	PG_END_TRY();
 
 	return workspace;
 }
-- 
2.54.0


--MP_/LMSk9=uMhuQ1QiIJDarDO8G--





^ permalink  raw  reply  [nested|flat] 611+ messages in thread

* [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths
@ 2026-06-01 22:41 Andrey Chernyy <andrey.cherny@tantorlabs.com>
  0 siblings, 0 replies; 611+ messages in thread

From: Andrey Chernyy @ 2026-06-01 22:41 UTC (permalink / raw)

pgxml_xpath() builds an xpath_workspace before returning it to
callers.  If an ERROR is thrown before the function returns, callers
have not received the workspace pointer yet and cannot run
cleanup_workspace().

Add local error cleanup for the partially built workspace and the
compiled XPath expression.  Also check xmlXPathNewContext() before
dereferencing the returned context.
---
 contrib/xml2/xpath.c | 51 +++++++++++++++++++++++++++-----------------
 1 file changed, 32 insertions(+), 19 deletions(-)

diff --git a/contrib/xml2/xpath.c b/contrib/xml2/xpath.c
index 9fe75cb5ff4..283bb51178d 100644
--- a/contrib/xml2/xpath.c
+++ b/contrib/xml2/xpath.c
@@ -497,36 +497,49 @@ static xpath_workspace *
 pgxml_xpath(text *document, xmlChar *xpath, PgXmlErrorContext *xmlerrcxt)
 {
 	int32		docsize = VARSIZE_ANY_EXHDR(document);
-	xmlXPathCompExprPtr comppath;
+	xmlXPathCompExprPtr volatile comppath = NULL;
 	xpath_workspace *workspace = palloc0_object(xpath_workspace);
 
 	workspace->doctree = NULL;
 	workspace->ctxt = NULL;
 	workspace->res = NULL;
 
-	workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
-									   docsize, NULL, NULL,
-									   XML_PARSE_NOENT);
-	if (workspace->doctree != NULL)
+	PG_TRY();
 	{
-		workspace->ctxt = xmlXPathNewContext(workspace->doctree);
-		workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
-
-		/* compile the path */
-		comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
-		if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+		workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
+										   docsize, NULL, NULL,
+										   XML_PARSE_NOENT);
+		if (workspace->doctree != NULL)
 		{
-			if (comppath != NULL)
-				xmlXPathFreeCompExpr(comppath);
-			xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
-						"XPath Syntax Error");
-		}
+			workspace->ctxt = xmlXPathNewContext(workspace->doctree);
+			if (workspace->ctxt == NULL)
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_OUT_OF_MEMORY,
+							"could not allocate XPath context");
 
-		/* Now evaluate the path expression. */
-		workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+			workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
+
+			/* compile the path */
+			comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
+			if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
+							"XPath Syntax Error");
+
+			/* Now evaluate the path expression. */
+			workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+
+			xmlXPathFreeCompExpr(comppath);
+			comppath = NULL;
+		}
+	}
+	PG_CATCH();
+	{
+		if (comppath != NULL)
+			xmlXPathFreeCompExpr(comppath);
+		cleanup_workspace(workspace);
 
-		xmlXPathFreeCompExpr(comppath);
+		PG_RE_THROW();
 	}
+	PG_END_TRY();
 
 	return workspace;
 }
-- 
2.54.0


--MP_/LMSk9=uMhuQ1QiIJDarDO8G--






^ permalink  raw  reply  [nested|flat] 611+ messages in thread

* [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths
@ 2026-06-01 22:41 Andrey Chernyy <andrey.cherny@tantorlabs.com>
  0 siblings, 0 replies; 611+ messages in thread

From: Andrey Chernyy @ 2026-06-01 22:41 UTC (permalink / raw)

pgxml_xpath() builds an xpath_workspace before returning it to
callers.  If an ERROR is thrown before the function returns, callers
have not received the workspace pointer yet and cannot run
cleanup_workspace().

Add local error cleanup for the partially built workspace and the
compiled XPath expression.  Also check xmlXPathNewContext() before
dereferencing the returned context.
---
 contrib/xml2/xpath.c | 51 +++++++++++++++++++++++++++-----------------
 1 file changed, 32 insertions(+), 19 deletions(-)

diff --git a/contrib/xml2/xpath.c b/contrib/xml2/xpath.c
index 9fe75cb5ff4..283bb51178d 100644
--- a/contrib/xml2/xpath.c
+++ b/contrib/xml2/xpath.c
@@ -497,36 +497,49 @@ static xpath_workspace *
 pgxml_xpath(text *document, xmlChar *xpath, PgXmlErrorContext *xmlerrcxt)
 {
 	int32		docsize = VARSIZE_ANY_EXHDR(document);
-	xmlXPathCompExprPtr comppath;
+	xmlXPathCompExprPtr volatile comppath = NULL;
 	xpath_workspace *workspace = palloc0_object(xpath_workspace);
 
 	workspace->doctree = NULL;
 	workspace->ctxt = NULL;
 	workspace->res = NULL;
 
-	workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
-									   docsize, NULL, NULL,
-									   XML_PARSE_NOENT);
-	if (workspace->doctree != NULL)
+	PG_TRY();
 	{
-		workspace->ctxt = xmlXPathNewContext(workspace->doctree);
-		workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
-
-		/* compile the path */
-		comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
-		if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+		workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
+										   docsize, NULL, NULL,
+										   XML_PARSE_NOENT);
+		if (workspace->doctree != NULL)
 		{
-			if (comppath != NULL)
-				xmlXPathFreeCompExpr(comppath);
-			xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
-						"XPath Syntax Error");
-		}
+			workspace->ctxt = xmlXPathNewContext(workspace->doctree);
+			if (workspace->ctxt == NULL)
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_OUT_OF_MEMORY,
+							"could not allocate XPath context");
 
-		/* Now evaluate the path expression. */
-		workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+			workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
+
+			/* compile the path */
+			comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
+			if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
+							"XPath Syntax Error");
+
+			/* Now evaluate the path expression. */
+			workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+
+			xmlXPathFreeCompExpr(comppath);
+			comppath = NULL;
+		}
+	}
+	PG_CATCH();
+	{
+		if (comppath != NULL)
+			xmlXPathFreeCompExpr(comppath);
+		cleanup_workspace(workspace);
 
-		xmlXPathFreeCompExpr(comppath);
+		PG_RE_THROW();
 	}
+	PG_END_TRY();
 
 	return workspace;
 }
-- 
2.54.0


--MP_/LMSk9=uMhuQ1QiIJDarDO8G--






^ permalink  raw  reply  [nested|flat] 611+ messages in thread

* [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths
@ 2026-06-01 22:41 Andrey Chernyy <andrey.cherny@tantorlabs.com>
  0 siblings, 0 replies; 611+ messages in thread

From: Andrey Chernyy @ 2026-06-01 22:41 UTC (permalink / raw)

pgxml_xpath() builds an xpath_workspace before returning it to
callers.  If an ERROR is thrown before the function returns, callers
have not received the workspace pointer yet and cannot run
cleanup_workspace().

Add local error cleanup for the partially built workspace and the
compiled XPath expression.  Also check xmlXPathNewContext() before
dereferencing the returned context.
---
 contrib/xml2/xpath.c | 51 +++++++++++++++++++++++++++-----------------
 1 file changed, 32 insertions(+), 19 deletions(-)

diff --git a/contrib/xml2/xpath.c b/contrib/xml2/xpath.c
index 9fe75cb5ff4..283bb51178d 100644
--- a/contrib/xml2/xpath.c
+++ b/contrib/xml2/xpath.c
@@ -497,36 +497,49 @@ static xpath_workspace *
 pgxml_xpath(text *document, xmlChar *xpath, PgXmlErrorContext *xmlerrcxt)
 {
 	int32		docsize = VARSIZE_ANY_EXHDR(document);
-	xmlXPathCompExprPtr comppath;
+	xmlXPathCompExprPtr volatile comppath = NULL;
 	xpath_workspace *workspace = palloc0_object(xpath_workspace);
 
 	workspace->doctree = NULL;
 	workspace->ctxt = NULL;
 	workspace->res = NULL;
 
-	workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
-									   docsize, NULL, NULL,
-									   XML_PARSE_NOENT);
-	if (workspace->doctree != NULL)
+	PG_TRY();
 	{
-		workspace->ctxt = xmlXPathNewContext(workspace->doctree);
-		workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
-
-		/* compile the path */
-		comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
-		if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+		workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
+										   docsize, NULL, NULL,
+										   XML_PARSE_NOENT);
+		if (workspace->doctree != NULL)
 		{
-			if (comppath != NULL)
-				xmlXPathFreeCompExpr(comppath);
-			xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
-						"XPath Syntax Error");
-		}
+			workspace->ctxt = xmlXPathNewContext(workspace->doctree);
+			if (workspace->ctxt == NULL)
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_OUT_OF_MEMORY,
+							"could not allocate XPath context");
 
-		/* Now evaluate the path expression. */
-		workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+			workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
+
+			/* compile the path */
+			comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
+			if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
+							"XPath Syntax Error");
+
+			/* Now evaluate the path expression. */
+			workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+
+			xmlXPathFreeCompExpr(comppath);
+			comppath = NULL;
+		}
+	}
+	PG_CATCH();
+	{
+		if (comppath != NULL)
+			xmlXPathFreeCompExpr(comppath);
+		cleanup_workspace(workspace);
 
-		xmlXPathFreeCompExpr(comppath);
+		PG_RE_THROW();
 	}
+	PG_END_TRY();
 
 	return workspace;
 }
-- 
2.54.0


--MP_/LMSk9=uMhuQ1QiIJDarDO8G--






^ permalink  raw  reply  [nested|flat] 611+ messages in thread

* [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths
@ 2026-06-01 22:41 Andrey Chernyy <andrey.cherny@tantorlabs.com>
  0 siblings, 0 replies; 611+ messages in thread

From: Andrey Chernyy @ 2026-06-01 22:41 UTC (permalink / raw)

pgxml_xpath() builds an xpath_workspace before returning it to
callers.  If an ERROR is thrown before the function returns, callers
have not received the workspace pointer yet and cannot run
cleanup_workspace().

Add local error cleanup for the partially built workspace and the
compiled XPath expression.  Also check xmlXPathNewContext() before
dereferencing the returned context.
---
 contrib/xml2/xpath.c | 51 +++++++++++++++++++++++++++-----------------
 1 file changed, 32 insertions(+), 19 deletions(-)

diff --git a/contrib/xml2/xpath.c b/contrib/xml2/xpath.c
index 9fe75cb5ff4..283bb51178d 100644
--- a/contrib/xml2/xpath.c
+++ b/contrib/xml2/xpath.c
@@ -497,36 +497,49 @@ static xpath_workspace *
 pgxml_xpath(text *document, xmlChar *xpath, PgXmlErrorContext *xmlerrcxt)
 {
 	int32		docsize = VARSIZE_ANY_EXHDR(document);
-	xmlXPathCompExprPtr comppath;
+	xmlXPathCompExprPtr volatile comppath = NULL;
 	xpath_workspace *workspace = palloc0_object(xpath_workspace);
 
 	workspace->doctree = NULL;
 	workspace->ctxt = NULL;
 	workspace->res = NULL;
 
-	workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
-									   docsize, NULL, NULL,
-									   XML_PARSE_NOENT);
-	if (workspace->doctree != NULL)
+	PG_TRY();
 	{
-		workspace->ctxt = xmlXPathNewContext(workspace->doctree);
-		workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
-
-		/* compile the path */
-		comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
-		if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+		workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
+										   docsize, NULL, NULL,
+										   XML_PARSE_NOENT);
+		if (workspace->doctree != NULL)
 		{
-			if (comppath != NULL)
-				xmlXPathFreeCompExpr(comppath);
-			xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
-						"XPath Syntax Error");
-		}
+			workspace->ctxt = xmlXPathNewContext(workspace->doctree);
+			if (workspace->ctxt == NULL)
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_OUT_OF_MEMORY,
+							"could not allocate XPath context");
 
-		/* Now evaluate the path expression. */
-		workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+			workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
+
+			/* compile the path */
+			comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
+			if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
+							"XPath Syntax Error");
+
+			/* Now evaluate the path expression. */
+			workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+
+			xmlXPathFreeCompExpr(comppath);
+			comppath = NULL;
+		}
+	}
+	PG_CATCH();
+	{
+		if (comppath != NULL)
+			xmlXPathFreeCompExpr(comppath);
+		cleanup_workspace(workspace);
 
-		xmlXPathFreeCompExpr(comppath);
+		PG_RE_THROW();
 	}
+	PG_END_TRY();
 
 	return workspace;
 }
-- 
2.54.0


--MP_/LMSk9=uMhuQ1QiIJDarDO8G--






^ permalink  raw  reply  [nested|flat] 611+ messages in thread

* [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths
@ 2026-06-01 22:41 Andrey Chernyy <andrey.cherny@tantorlabs.com>
  0 siblings, 0 replies; 611+ messages in thread

From: Andrey Chernyy @ 2026-06-01 22:41 UTC (permalink / raw)

pgxml_xpath() builds an xpath_workspace before returning it to
callers.  If an ERROR is thrown before the function returns, callers
have not received the workspace pointer yet and cannot run
cleanup_workspace().

Add local error cleanup for the partially built workspace and the
compiled XPath expression.  Also check xmlXPathNewContext() before
dereferencing the returned context.
---
 contrib/xml2/xpath.c | 51 +++++++++++++++++++++++++++-----------------
 1 file changed, 32 insertions(+), 19 deletions(-)

diff --git a/contrib/xml2/xpath.c b/contrib/xml2/xpath.c
index 9fe75cb5ff4..283bb51178d 100644
--- a/contrib/xml2/xpath.c
+++ b/contrib/xml2/xpath.c
@@ -497,36 +497,49 @@ static xpath_workspace *
 pgxml_xpath(text *document, xmlChar *xpath, PgXmlErrorContext *xmlerrcxt)
 {
 	int32		docsize = VARSIZE_ANY_EXHDR(document);
-	xmlXPathCompExprPtr comppath;
+	xmlXPathCompExprPtr volatile comppath = NULL;
 	xpath_workspace *workspace = palloc0_object(xpath_workspace);
 
 	workspace->doctree = NULL;
 	workspace->ctxt = NULL;
 	workspace->res = NULL;
 
-	workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
-									   docsize, NULL, NULL,
-									   XML_PARSE_NOENT);
-	if (workspace->doctree != NULL)
+	PG_TRY();
 	{
-		workspace->ctxt = xmlXPathNewContext(workspace->doctree);
-		workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
-
-		/* compile the path */
-		comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
-		if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+		workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
+										   docsize, NULL, NULL,
+										   XML_PARSE_NOENT);
+		if (workspace->doctree != NULL)
 		{
-			if (comppath != NULL)
-				xmlXPathFreeCompExpr(comppath);
-			xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
-						"XPath Syntax Error");
-		}
+			workspace->ctxt = xmlXPathNewContext(workspace->doctree);
+			if (workspace->ctxt == NULL)
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_OUT_OF_MEMORY,
+							"could not allocate XPath context");
 
-		/* Now evaluate the path expression. */
-		workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+			workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
+
+			/* compile the path */
+			comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
+			if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
+							"XPath Syntax Error");
+
+			/* Now evaluate the path expression. */
+			workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+
+			xmlXPathFreeCompExpr(comppath);
+			comppath = NULL;
+		}
+	}
+	PG_CATCH();
+	{
+		if (comppath != NULL)
+			xmlXPathFreeCompExpr(comppath);
+		cleanup_workspace(workspace);
 
-		xmlXPathFreeCompExpr(comppath);
+		PG_RE_THROW();
 	}
+	PG_END_TRY();
 
 	return workspace;
 }
-- 
2.54.0


--MP_/LMSk9=uMhuQ1QiIJDarDO8G--





^ permalink  raw  reply  [nested|flat] 611+ messages in thread

* [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths
@ 2026-06-01 22:41 Andrey Chernyy <andrey.cherny@tantorlabs.com>
  0 siblings, 0 replies; 611+ messages in thread

From: Andrey Chernyy @ 2026-06-01 22:41 UTC (permalink / raw)

pgxml_xpath() builds an xpath_workspace before returning it to
callers.  If an ERROR is thrown before the function returns, callers
have not received the workspace pointer yet and cannot run
cleanup_workspace().

Add local error cleanup for the partially built workspace and the
compiled XPath expression.  Also check xmlXPathNewContext() before
dereferencing the returned context.
---
 contrib/xml2/xpath.c | 51 +++++++++++++++++++++++++++-----------------
 1 file changed, 32 insertions(+), 19 deletions(-)

diff --git a/contrib/xml2/xpath.c b/contrib/xml2/xpath.c
index 9fe75cb5ff4..283bb51178d 100644
--- a/contrib/xml2/xpath.c
+++ b/contrib/xml2/xpath.c
@@ -497,36 +497,49 @@ static xpath_workspace *
 pgxml_xpath(text *document, xmlChar *xpath, PgXmlErrorContext *xmlerrcxt)
 {
 	int32		docsize = VARSIZE_ANY_EXHDR(document);
-	xmlXPathCompExprPtr comppath;
+	xmlXPathCompExprPtr volatile comppath = NULL;
 	xpath_workspace *workspace = palloc0_object(xpath_workspace);
 
 	workspace->doctree = NULL;
 	workspace->ctxt = NULL;
 	workspace->res = NULL;
 
-	workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
-									   docsize, NULL, NULL,
-									   XML_PARSE_NOENT);
-	if (workspace->doctree != NULL)
+	PG_TRY();
 	{
-		workspace->ctxt = xmlXPathNewContext(workspace->doctree);
-		workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
-
-		/* compile the path */
-		comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
-		if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+		workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
+										   docsize, NULL, NULL,
+										   XML_PARSE_NOENT);
+		if (workspace->doctree != NULL)
 		{
-			if (comppath != NULL)
-				xmlXPathFreeCompExpr(comppath);
-			xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
-						"XPath Syntax Error");
-		}
+			workspace->ctxt = xmlXPathNewContext(workspace->doctree);
+			if (workspace->ctxt == NULL)
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_OUT_OF_MEMORY,
+							"could not allocate XPath context");
 
-		/* Now evaluate the path expression. */
-		workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+			workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
+
+			/* compile the path */
+			comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
+			if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
+							"XPath Syntax Error");
+
+			/* Now evaluate the path expression. */
+			workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+
+			xmlXPathFreeCompExpr(comppath);
+			comppath = NULL;
+		}
+	}
+	PG_CATCH();
+	{
+		if (comppath != NULL)
+			xmlXPathFreeCompExpr(comppath);
+		cleanup_workspace(workspace);
 
-		xmlXPathFreeCompExpr(comppath);
+		PG_RE_THROW();
 	}
+	PG_END_TRY();
 
 	return workspace;
 }
-- 
2.54.0


--MP_/LMSk9=uMhuQ1QiIJDarDO8G--






^ permalink  raw  reply  [nested|flat] 611+ messages in thread

* [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths
@ 2026-06-01 22:41 Andrey Chernyy <andrey.cherny@tantorlabs.com>
  0 siblings, 0 replies; 611+ messages in thread

From: Andrey Chernyy @ 2026-06-01 22:41 UTC (permalink / raw)

pgxml_xpath() builds an xpath_workspace before returning it to
callers.  If an ERROR is thrown before the function returns, callers
have not received the workspace pointer yet and cannot run
cleanup_workspace().

Add local error cleanup for the partially built workspace and the
compiled XPath expression.  Also check xmlXPathNewContext() before
dereferencing the returned context.
---
 contrib/xml2/xpath.c | 51 +++++++++++++++++++++++++++-----------------
 1 file changed, 32 insertions(+), 19 deletions(-)

diff --git a/contrib/xml2/xpath.c b/contrib/xml2/xpath.c
index 9fe75cb5ff4..283bb51178d 100644
--- a/contrib/xml2/xpath.c
+++ b/contrib/xml2/xpath.c
@@ -497,36 +497,49 @@ static xpath_workspace *
 pgxml_xpath(text *document, xmlChar *xpath, PgXmlErrorContext *xmlerrcxt)
 {
 	int32		docsize = VARSIZE_ANY_EXHDR(document);
-	xmlXPathCompExprPtr comppath;
+	xmlXPathCompExprPtr volatile comppath = NULL;
 	xpath_workspace *workspace = palloc0_object(xpath_workspace);
 
 	workspace->doctree = NULL;
 	workspace->ctxt = NULL;
 	workspace->res = NULL;
 
-	workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
-									   docsize, NULL, NULL,
-									   XML_PARSE_NOENT);
-	if (workspace->doctree != NULL)
+	PG_TRY();
 	{
-		workspace->ctxt = xmlXPathNewContext(workspace->doctree);
-		workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
-
-		/* compile the path */
-		comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
-		if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+		workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
+										   docsize, NULL, NULL,
+										   XML_PARSE_NOENT);
+		if (workspace->doctree != NULL)
 		{
-			if (comppath != NULL)
-				xmlXPathFreeCompExpr(comppath);
-			xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
-						"XPath Syntax Error");
-		}
+			workspace->ctxt = xmlXPathNewContext(workspace->doctree);
+			if (workspace->ctxt == NULL)
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_OUT_OF_MEMORY,
+							"could not allocate XPath context");
 
-		/* Now evaluate the path expression. */
-		workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+			workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
+
+			/* compile the path */
+			comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
+			if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
+							"XPath Syntax Error");
+
+			/* Now evaluate the path expression. */
+			workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+
+			xmlXPathFreeCompExpr(comppath);
+			comppath = NULL;
+		}
+	}
+	PG_CATCH();
+	{
+		if (comppath != NULL)
+			xmlXPathFreeCompExpr(comppath);
+		cleanup_workspace(workspace);
 
-		xmlXPathFreeCompExpr(comppath);
+		PG_RE_THROW();
 	}
+	PG_END_TRY();
 
 	return workspace;
 }
-- 
2.54.0


--MP_/LMSk9=uMhuQ1QiIJDarDO8G--






^ permalink  raw  reply  [nested|flat] 611+ messages in thread

* [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths
@ 2026-06-01 22:41 Andrey Chernyy <andrey.cherny@tantorlabs.com>
  0 siblings, 0 replies; 611+ messages in thread

From: Andrey Chernyy @ 2026-06-01 22:41 UTC (permalink / raw)

pgxml_xpath() builds an xpath_workspace before returning it to
callers.  If an ERROR is thrown before the function returns, callers
have not received the workspace pointer yet and cannot run
cleanup_workspace().

Add local error cleanup for the partially built workspace and the
compiled XPath expression.  Also check xmlXPathNewContext() before
dereferencing the returned context.
---
 contrib/xml2/xpath.c | 51 +++++++++++++++++++++++++++-----------------
 1 file changed, 32 insertions(+), 19 deletions(-)

diff --git a/contrib/xml2/xpath.c b/contrib/xml2/xpath.c
index 9fe75cb5ff4..283bb51178d 100644
--- a/contrib/xml2/xpath.c
+++ b/contrib/xml2/xpath.c
@@ -497,36 +497,49 @@ static xpath_workspace *
 pgxml_xpath(text *document, xmlChar *xpath, PgXmlErrorContext *xmlerrcxt)
 {
 	int32		docsize = VARSIZE_ANY_EXHDR(document);
-	xmlXPathCompExprPtr comppath;
+	xmlXPathCompExprPtr volatile comppath = NULL;
 	xpath_workspace *workspace = palloc0_object(xpath_workspace);
 
 	workspace->doctree = NULL;
 	workspace->ctxt = NULL;
 	workspace->res = NULL;
 
-	workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
-									   docsize, NULL, NULL,
-									   XML_PARSE_NOENT);
-	if (workspace->doctree != NULL)
+	PG_TRY();
 	{
-		workspace->ctxt = xmlXPathNewContext(workspace->doctree);
-		workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
-
-		/* compile the path */
-		comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
-		if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+		workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
+										   docsize, NULL, NULL,
+										   XML_PARSE_NOENT);
+		if (workspace->doctree != NULL)
 		{
-			if (comppath != NULL)
-				xmlXPathFreeCompExpr(comppath);
-			xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
-						"XPath Syntax Error");
-		}
+			workspace->ctxt = xmlXPathNewContext(workspace->doctree);
+			if (workspace->ctxt == NULL)
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_OUT_OF_MEMORY,
+							"could not allocate XPath context");
 
-		/* Now evaluate the path expression. */
-		workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+			workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
+
+			/* compile the path */
+			comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
+			if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
+							"XPath Syntax Error");
+
+			/* Now evaluate the path expression. */
+			workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+
+			xmlXPathFreeCompExpr(comppath);
+			comppath = NULL;
+		}
+	}
+	PG_CATCH();
+	{
+		if (comppath != NULL)
+			xmlXPathFreeCompExpr(comppath);
+		cleanup_workspace(workspace);
 
-		xmlXPathFreeCompExpr(comppath);
+		PG_RE_THROW();
 	}
+	PG_END_TRY();
 
 	return workspace;
 }
-- 
2.54.0


--MP_/LMSk9=uMhuQ1QiIJDarDO8G--





^ permalink  raw  reply  [nested|flat] 611+ messages in thread

* [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths
@ 2026-06-01 22:41 Andrey Chernyy <andrey.cherny@tantorlabs.com>
  0 siblings, 0 replies; 611+ messages in thread

From: Andrey Chernyy @ 2026-06-01 22:41 UTC (permalink / raw)

pgxml_xpath() builds an xpath_workspace before returning it to
callers.  If an ERROR is thrown before the function returns, callers
have not received the workspace pointer yet and cannot run
cleanup_workspace().

Add local error cleanup for the partially built workspace and the
compiled XPath expression.  Also check xmlXPathNewContext() before
dereferencing the returned context.
---
 contrib/xml2/xpath.c | 51 +++++++++++++++++++++++++++-----------------
 1 file changed, 32 insertions(+), 19 deletions(-)

diff --git a/contrib/xml2/xpath.c b/contrib/xml2/xpath.c
index 9fe75cb5ff4..283bb51178d 100644
--- a/contrib/xml2/xpath.c
+++ b/contrib/xml2/xpath.c
@@ -497,36 +497,49 @@ static xpath_workspace *
 pgxml_xpath(text *document, xmlChar *xpath, PgXmlErrorContext *xmlerrcxt)
 {
 	int32		docsize = VARSIZE_ANY_EXHDR(document);
-	xmlXPathCompExprPtr comppath;
+	xmlXPathCompExprPtr volatile comppath = NULL;
 	xpath_workspace *workspace = palloc0_object(xpath_workspace);
 
 	workspace->doctree = NULL;
 	workspace->ctxt = NULL;
 	workspace->res = NULL;
 
-	workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
-									   docsize, NULL, NULL,
-									   XML_PARSE_NOENT);
-	if (workspace->doctree != NULL)
+	PG_TRY();
 	{
-		workspace->ctxt = xmlXPathNewContext(workspace->doctree);
-		workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
-
-		/* compile the path */
-		comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
-		if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+		workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
+										   docsize, NULL, NULL,
+										   XML_PARSE_NOENT);
+		if (workspace->doctree != NULL)
 		{
-			if (comppath != NULL)
-				xmlXPathFreeCompExpr(comppath);
-			xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
-						"XPath Syntax Error");
-		}
+			workspace->ctxt = xmlXPathNewContext(workspace->doctree);
+			if (workspace->ctxt == NULL)
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_OUT_OF_MEMORY,
+							"could not allocate XPath context");
 
-		/* Now evaluate the path expression. */
-		workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+			workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
+
+			/* compile the path */
+			comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
+			if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
+							"XPath Syntax Error");
+
+			/* Now evaluate the path expression. */
+			workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+
+			xmlXPathFreeCompExpr(comppath);
+			comppath = NULL;
+		}
+	}
+	PG_CATCH();
+	{
+		if (comppath != NULL)
+			xmlXPathFreeCompExpr(comppath);
+		cleanup_workspace(workspace);
 
-		xmlXPathFreeCompExpr(comppath);
+		PG_RE_THROW();
 	}
+	PG_END_TRY();
 
 	return workspace;
 }
-- 
2.54.0


--MP_/LMSk9=uMhuQ1QiIJDarDO8G--





^ permalink  raw  reply  [nested|flat] 611+ messages in thread

* [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths
@ 2026-06-01 22:41 Andrey Chernyy <andrey.cherny@tantorlabs.com>
  0 siblings, 0 replies; 611+ messages in thread

From: Andrey Chernyy @ 2026-06-01 22:41 UTC (permalink / raw)

pgxml_xpath() builds an xpath_workspace before returning it to
callers.  If an ERROR is thrown before the function returns, callers
have not received the workspace pointer yet and cannot run
cleanup_workspace().

Add local error cleanup for the partially built workspace and the
compiled XPath expression.  Also check xmlXPathNewContext() before
dereferencing the returned context.
---
 contrib/xml2/xpath.c | 51 +++++++++++++++++++++++++++-----------------
 1 file changed, 32 insertions(+), 19 deletions(-)

diff --git a/contrib/xml2/xpath.c b/contrib/xml2/xpath.c
index 9fe75cb5ff4..283bb51178d 100644
--- a/contrib/xml2/xpath.c
+++ b/contrib/xml2/xpath.c
@@ -497,36 +497,49 @@ static xpath_workspace *
 pgxml_xpath(text *document, xmlChar *xpath, PgXmlErrorContext *xmlerrcxt)
 {
 	int32		docsize = VARSIZE_ANY_EXHDR(document);
-	xmlXPathCompExprPtr comppath;
+	xmlXPathCompExprPtr volatile comppath = NULL;
 	xpath_workspace *workspace = palloc0_object(xpath_workspace);
 
 	workspace->doctree = NULL;
 	workspace->ctxt = NULL;
 	workspace->res = NULL;
 
-	workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
-									   docsize, NULL, NULL,
-									   XML_PARSE_NOENT);
-	if (workspace->doctree != NULL)
+	PG_TRY();
 	{
-		workspace->ctxt = xmlXPathNewContext(workspace->doctree);
-		workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
-
-		/* compile the path */
-		comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
-		if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+		workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
+										   docsize, NULL, NULL,
+										   XML_PARSE_NOENT);
+		if (workspace->doctree != NULL)
 		{
-			if (comppath != NULL)
-				xmlXPathFreeCompExpr(comppath);
-			xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
-						"XPath Syntax Error");
-		}
+			workspace->ctxt = xmlXPathNewContext(workspace->doctree);
+			if (workspace->ctxt == NULL)
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_OUT_OF_MEMORY,
+							"could not allocate XPath context");
 
-		/* Now evaluate the path expression. */
-		workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+			workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
+
+			/* compile the path */
+			comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
+			if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
+							"XPath Syntax Error");
+
+			/* Now evaluate the path expression. */
+			workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+
+			xmlXPathFreeCompExpr(comppath);
+			comppath = NULL;
+		}
+	}
+	PG_CATCH();
+	{
+		if (comppath != NULL)
+			xmlXPathFreeCompExpr(comppath);
+		cleanup_workspace(workspace);
 
-		xmlXPathFreeCompExpr(comppath);
+		PG_RE_THROW();
 	}
+	PG_END_TRY();
 
 	return workspace;
 }
-- 
2.54.0


--MP_/LMSk9=uMhuQ1QiIJDarDO8G--






^ permalink  raw  reply  [nested|flat] 611+ messages in thread

* [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths
@ 2026-06-01 22:41 Andrey Chernyy <andrey.cherny@tantorlabs.com>
  0 siblings, 0 replies; 611+ messages in thread

From: Andrey Chernyy @ 2026-06-01 22:41 UTC (permalink / raw)

pgxml_xpath() builds an xpath_workspace before returning it to
callers.  If an ERROR is thrown before the function returns, callers
have not received the workspace pointer yet and cannot run
cleanup_workspace().

Add local error cleanup for the partially built workspace and the
compiled XPath expression.  Also check xmlXPathNewContext() before
dereferencing the returned context.
---
 contrib/xml2/xpath.c | 51 +++++++++++++++++++++++++++-----------------
 1 file changed, 32 insertions(+), 19 deletions(-)

diff --git a/contrib/xml2/xpath.c b/contrib/xml2/xpath.c
index 9fe75cb5ff4..283bb51178d 100644
--- a/contrib/xml2/xpath.c
+++ b/contrib/xml2/xpath.c
@@ -497,36 +497,49 @@ static xpath_workspace *
 pgxml_xpath(text *document, xmlChar *xpath, PgXmlErrorContext *xmlerrcxt)
 {
 	int32		docsize = VARSIZE_ANY_EXHDR(document);
-	xmlXPathCompExprPtr comppath;
+	xmlXPathCompExprPtr volatile comppath = NULL;
 	xpath_workspace *workspace = palloc0_object(xpath_workspace);
 
 	workspace->doctree = NULL;
 	workspace->ctxt = NULL;
 	workspace->res = NULL;
 
-	workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
-									   docsize, NULL, NULL,
-									   XML_PARSE_NOENT);
-	if (workspace->doctree != NULL)
+	PG_TRY();
 	{
-		workspace->ctxt = xmlXPathNewContext(workspace->doctree);
-		workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
-
-		/* compile the path */
-		comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
-		if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+		workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document),
+										   docsize, NULL, NULL,
+										   XML_PARSE_NOENT);
+		if (workspace->doctree != NULL)
 		{
-			if (comppath != NULL)
-				xmlXPathFreeCompExpr(comppath);
-			xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
-						"XPath Syntax Error");
-		}
+			workspace->ctxt = xmlXPathNewContext(workspace->doctree);
+			if (workspace->ctxt == NULL)
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_OUT_OF_MEMORY,
+							"could not allocate XPath context");
 
-		/* Now evaluate the path expression. */
-		workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+			workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
+
+			/* compile the path */
+			comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);
+			if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt))
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
+							"XPath Syntax Error");
+
+			/* Now evaluate the path expression. */
+			workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+
+			xmlXPathFreeCompExpr(comppath);
+			comppath = NULL;
+		}
+	}
+	PG_CATCH();
+	{
+		if (comppath != NULL)
+			xmlXPathFreeCompExpr(comppath);
+		cleanup_workspace(workspace);
 
-		xmlXPathFreeCompExpr(comppath);
+		PG_RE_THROW();
 	}
+	PG_END_TRY();
 
 	return workspace;
 }
-- 
2.54.0


--MP_/LMSk9=uMhuQ1QiIJDarDO8G--





^ permalink  raw  reply  [nested|flat] 611+ messages in thread


end of thread, other threads:[~2026-06-01 22:41 UTC | newest]

Thread overview: 611+ messages (download: mbox mbox.gz follow: Atom feed)
-- links below jump to the message on this page --
2014-08-06 17:39 posix_fadvise() and pg_receivexlog Fujii Masao <masao.fujii@gmail.com>
2014-08-06 18:56 ` Robert Haas <robertmhaas@gmail.com>
2014-08-06 18:59 ` Heikki Linnakangas <hlinnakangas@vmware.com>
2014-08-07 04:47   ` Fujii Masao <masao.fujii@gmail.com>
2014-08-07 07:10     ` Mitsumasa KONDO <kondo.mitsumasa@gmail.com>
2014-08-07 08:02       ` Heikki Linnakangas <hlinnakangas@vmware.com>
2014-08-07 10:54         ` Fujii Masao <masao.fujii@gmail.com>
2014-09-09 12:07         ` didier <did447@gmail.com>
2014-09-09 13:48           ` Fujii Masao <masao.fujii@gmail.com>
2014-09-09 18:19           ` Robert Haas <robertmhaas@gmail.com>
2026-06-01 22:41 [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths Andrey Chernyy <andrey.cherny@tantorlabs.com>
2026-06-01 22:41 [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths Andrey Chernyy <andrey.cherny@tantorlabs.com>
2026-06-01 22:41 [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths Andrey Chernyy <andrey.cherny@tantorlabs.com>
2026-06-01 22:41 [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths Andrey Chernyy <andrey.cherny@tantorlabs.com>
2026-06-01 22:41 [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths Andrey Chernyy <andrey.cherny@tantorlabs.com>
2026-06-01 22:41 [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths Andrey Chernyy <andrey.cherny@tantorlabs.com>
2026-06-01 22:41 [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths Andrey Chernyy <andrey.cherny@tantorlabs.com>
2026-06-01 22:41 [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths Andrey Chernyy <andrey.cherny@tantorlabs.com>
2026-06-01 22:41 [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths Andrey Chernyy <andrey.cherny@tantorlabs.com>
2026-06-01 22:41 [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths Andrey Chernyy <andrey.cherny@tantorlabs.com>
2026-06-01 22:41 [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths Andrey Chernyy <andrey.cherny@tantorlabs.com>
2026-06-01 22:41 [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths Andrey Chernyy <andrey.cherny@tantorlabs.com>
2026-06-01 22:41 [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths Andrey Chernyy <andrey.cherny@tantorlabs.com>
2026-06-01 22:41 [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths Andrey Chernyy <andrey.cherny@tantorlabs.com>
2026-06-01 22:41 [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths Andrey Chernyy <andrey.cherny@tantorlabs.com>
2026-06-01 22:41 [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths Andrey Chernyy <andrey.cherny@tantorlabs.com>
2026-06-01 22:41 [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths Andrey Chernyy <andrey.cherny@tantorlabs.com>
2026-06-01 22:41 [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths Andrey Chernyy <andrey.cherny@tantorlabs.com>
2026-06-01 22:41 [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths Andrey Chernyy <andrey.cherny@tantorlabs.com>
2026-06-01 22:41 [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths Andrey Chernyy <andrey.cherny@tantorlabs.com>
2026-06-01 22:41 [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths Andrey Chernyy <andrey.cherny@tantorlabs.com>
2026-06-01 22:41 [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths Andrey Chernyy <andrey.cherny@tantorlabs.com>
2026-06-01 22:41 [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths Andrey Chernyy <andrey.cherny@tantorlabs.com>
2026-06-01 22:41 [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths Andrey Chernyy <andrey.cherny@tantorlabs.com>
2026-06-01 22:41 [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths Andrey Chernyy <andrey.cherny@tantorlabs.com>
2026-06-01 22:41 [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths Andrey Chernyy <andrey.cherny@tantorlabs.com>
2026-06-01 22:41 [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths Andrey Chernyy <andrey.cherny@tantorlabs.com>
2026-06-01 22:41 [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths Andrey Chernyy <andrey.cherny@tantorlabs.com>
2026-06-01 22:41 [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths Andrey Chernyy <andrey.cherny@tantorlabs.com>
2026-06-01 22:41 [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths Andrey Chernyy <andrey.cherny@tantorlabs.com>
2026-06-01 22:41 [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths Andrey Chernyy <andrey.cherny@tantorlabs.com>
2026-06-01 22:41 [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths Andrey Chernyy <andrey.cherny@tantorlabs.com>
2026-06-01 22:41 [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths Andrey Chernyy <andrey.cherny@tantorlabs.com>
2026-06-01 22:41 [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths Andrey Chernyy <andrey.cherny@tantorlabs.com>
2026-06-01 22:41 [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths Andrey Chernyy <andrey.cherny@tantorlabs.com>
2026-06-01 22:41 [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths Andrey Chernyy <andrey.cherny@tantorlabs.com>
2026-06-01 22:41 [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths Andrey Chernyy <andrey.cherny@tantorlabs.com>
2026-06-01 22:41 [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths Andrey Chernyy <andrey.cherny@tantorlabs.com>
2026-06-01 22:41 [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths Andrey Chernyy <andrey.cherny@tantorlabs.com>
2026-06-01 22:41 [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths Andrey Chernyy <andrey.cherny@tantorlabs.com>
2026-06-01 22:41 [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths Andrey Chernyy <andrey.cherny@tantorlabs.com>
2026-06-01 22:41 [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths Andrey Chernyy <andrey.cherny@tantorlabs.com>
2026-06-01 22:41 [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths Andrey Chernyy <andrey.cherny@tantorlabs.com>
2026-06-01 22:41 [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths Andrey Chernyy <andrey.cherny@tantorlabs.com>
2026-06-01 22:41 [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths Andrey Chernyy <andrey.cherny@tantorlabs.com>
2026-06-01 22:41 [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths Andrey Chernyy <andrey.cherny@tantorlabs.com>
2026-06-01 22:41 [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths Andrey Chernyy <andrey.cherny@tantorlabs.com>
2026-06-01 22:41 [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths Andrey Chernyy <andrey.cherny@tantorlabs.com>
2026-06-01 22:41 [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths Andrey Chernyy <andrey.cherny@tantorlabs.com>
2026-06-01 22:41 [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths Andrey Chernyy <andrey.cherny@tantorlabs.com>
2026-06-01 22:41 [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths Andrey Chernyy <andrey.cherny@tantorlabs.com>
2026-06-01 22:41 [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths Andrey Chernyy <andrey.cherny@tantorlabs.com>
2026-06-01 22:41 [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths Andrey Chernyy <andrey.cherny@tantorlabs.com>
2026-06-01 22:41 [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths Andrey Chernyy <andrey.cherny@tantorlabs.com>
2026-06-01 22:41 [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths Andrey Chernyy <andrey.cherny@tantorlabs.com>
2026-06-01 22:41 [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths Andrey Chernyy <andrey.cherny@tantorlabs.com>
2026-06-01 22:41 [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths Andrey Chernyy <andrey.cherny@tantorlabs.com>
2026-06-01 22:41 [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths Andrey Chernyy <andrey.cherny@tantorlabs.com>
2026-06-01 22:41 [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths Andrey Chernyy <andrey.cherny@tantorlabs.com>
2026-06-01 22:41 [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths Andrey Chernyy <andrey.cherny@tantorlabs.com>
2026-06-01 22:41 [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths Andrey Chernyy <andrey.cherny@tantorlabs.com>
2026-06-01 22:41 [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths Andrey Chernyy <andrey.cherny@tantorlabs.com>
2026-06-01 22:41 [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths Andrey Chernyy <andrey.cherny@tantorlabs.com>
2026-06-01 22:41 [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths Andrey Chernyy <andrey.cherny@tantorlabs.com>
2026-06-01 22:41 [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths Andrey Chernyy <andrey.cherny@tantorlabs.com>
2026-06-01 22:41 [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths Andrey Chernyy <andrey.cherny@tantorlabs.com>
2026-06-01 22:41 [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths Andrey Chernyy <andrey.cherny@tantorlabs.com>
2026-06-01 22:41 [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths Andrey Chernyy <andrey.cherny@tantorlabs.com>
2026-06-01 22:41 [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths Andrey Chernyy <andrey.cherny@tantorlabs.com>
2026-06-01 22:41 [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths Andrey Chernyy <andrey.cherny@tantorlabs.com>
2026-06-01 22:41 [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths Andrey Chernyy <andrey.cherny@tantorlabs.com>
2026-06-01 22:41 [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths Andrey Chernyy <andrey.cherny@tantorlabs.com>
2026-06-01 22:41 [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths Andrey Chernyy <andrey.cherny@tantorlabs.com>
2026-06-01 22:41 [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths Andrey Chernyy <andrey.cherny@tantorlabs.com>
2026-06-01 22:41 [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths Andrey Chernyy <andrey.cherny@tantorlabs.com>
2026-06-01 22:41 [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths Andrey Chernyy <andrey.cherny@tantorlabs.com>
2026-06-01 22:41 [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths Andrey Chernyy <andrey.cherny@tantorlabs.com>
2026-06-01 22:41 [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths Andrey Chernyy <andrey.cherny@tantorlabs.com>
2026-06-01 22:41 [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths Andrey Chernyy <andrey.cherny@tantorlabs.com>
2026-06-01 22:41 [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths Andrey Chernyy <andrey.cherny@tantorlabs.com>
2026-06-01 22:41 [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths Andrey Chernyy <andrey.cherny@tantorlabs.com>
2026-06-01 22:41 [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths Andrey Chernyy <andrey.cherny@tantorlabs.com>
2026-06-01 22:41 [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths Andrey Chernyy <andrey.cherny@tantorlabs.com>
2026-06-01 22:41 [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths Andrey Chernyy <andrey.cherny@tantorlabs.com>
2026-06-01 22:41 [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths Andrey Chernyy <andrey.cherny@tantorlabs.com>
2026-06-01 22:41 [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths Andrey Chernyy <andrey.cherny@tantorlabs.com>
2026-06-01 22:41 [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths Andrey Chernyy <andrey.cherny@tantorlabs.com>
2026-06-01 22:41 [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths Andrey Chernyy <andrey.cherny@tantorlabs.com>
2026-06-01 22:41 [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths Andrey Chernyy <andrey.cherny@tantorlabs.com>
2026-06-01 22:41 [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths Andrey Chernyy <andrey.cherny@tantorlabs.com>
2026-06-01 22:41 [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths Andrey Chernyy <andrey.cherny@tantorlabs.com>
2026-06-01 22:41 [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths Andrey Chernyy <andrey.cherny@tantorlabs.com>
2026-06-01 22:41 [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths Andrey Chernyy <andrey.cherny@tantorlabs.com>
2026-06-01 22:41 [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths Andrey Chernyy <andrey.cherny@tantorlabs.com>
2026-06-01 22:41 [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths Andrey Chernyy <andrey.cherny@tantorlabs.com>
2026-06-01 22:41 [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths Andrey Chernyy <andrey.cherny@tantorlabs.com>
2026-06-01 22:41 [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths Andrey Chernyy <andrey.cherny@tantorlabs.com>
2026-06-01 22:41 [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths Andrey Chernyy <andrey.cherny@tantorlabs.com>
2026-06-01 22:41 [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths Andrey Chernyy <andrey.cherny@tantorlabs.com>
2026-06-01 22:41 [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths Andrey Chernyy <andrey.cherny@tantorlabs.com>
2026-06-01 22:41 [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths Andrey Chernyy <andrey.cherny@tantorlabs.com>
2026-06-01 22:41 [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths Andrey Chernyy <andrey.cherny@tantorlabs.com>
2026-06-01 22:41 [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths Andrey Chernyy <andrey.cherny@tantorlabs.com>
2026-06-01 22:41 [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths Andrey Chernyy <andrey.cherny@tantorlabs.com>
2026-06-01 22:41 [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths Andrey Chernyy <andrey.cherny@tantorlabs.com>
2026-06-01 22:41 [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths Andrey Chernyy <andrey.cherny@tantorlabs.com>
2026-06-01 22:41 [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths Andrey Chernyy <andrey.cherny@tantorlabs.com>
2026-06-01 22:41 [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths Andrey Chernyy <andrey.cherny@tantorlabs.com>
2026-06-01 22:41 [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths Andrey Chernyy <andrey.cherny@tantorlabs.com>
2026-06-01 22:41 [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths Andrey Chernyy <andrey.cherny@tantorlabs.com>
2026-06-01 22:41 [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths Andrey Chernyy <andrey.cherny@tantorlabs.com>
2026-06-01 22:41 [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths Andrey Chernyy <andrey.cherny@tantorlabs.com>
2026-06-01 22:41 [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths Andrey Chernyy <andrey.cherny@tantorlabs.com>
2026-06-01 22:41 [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths Andrey Chernyy <andrey.cherny@tantorlabs.com>
2026-06-01 22:41 [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths Andrey Chernyy <andrey.cherny@tantorlabs.com>
2026-06-01 22:41 [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths Andrey Chernyy <andrey.cherny@tantorlabs.com>
2026-06-01 22:41 [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths Andrey Chernyy <andrey.cherny@tantorlabs.com>
2026-06-01 22:41 [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths Andrey Chernyy <andrey.cherny@tantorlabs.com>
2026-06-01 22:41 [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths Andrey Chernyy <andrey.cherny@tantorlabs.com>
2026-06-01 22:41 [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths Andrey Chernyy <andrey.cherny@tantorlabs.com>
2026-06-01 22:41 [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths Andrey Chernyy <andrey.cherny@tantorlabs.com>
2026-06-01 22:41 [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths Andrey Chernyy <andrey.cherny@tantorlabs.com>
2026-06-01 22:41 [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths Andrey Chernyy <andrey.cherny@tantorlabs.com>
2026-06-01 22:41 [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths Andrey Chernyy <andrey.cherny@tantorlabs.com>
2026-06-01 22:41 [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths Andrey Chernyy <andrey.cherny@tantorlabs.com>
2026-06-01 22:41 [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths Andrey Chernyy <andrey.cherny@tantorlabs.com>
2026-06-01 22:41 [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths Andrey Chernyy <andrey.cherny@tantorlabs.com>
2026-06-01 22:41 [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths Andrey Chernyy <andrey.cherny@tantorlabs.com>
2026-06-01 22:41 [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths Andrey Chernyy <andrey.cherny@tantorlabs.com>
2026-06-01 22:41 [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths Andrey Chernyy <andrey.cherny@tantorlabs.com>
2026-06-01 22:41 [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths Andrey Chernyy <andrey.cherny@tantorlabs.com>
2026-06-01 22:41 [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths Andrey Chernyy <andrey.cherny@tantorlabs.com>
2026-06-01 22:41 [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths Andrey Chernyy <andrey.cherny@tantorlabs.com>
2026-06-01 22:41 [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths Andrey Chernyy <andrey.cherny@tantorlabs.com>
2026-06-01 22:41 [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths Andrey Chernyy <andrey.cherny@tantorlabs.com>
2026-06-01 22:41 [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths Andrey Chernyy <andrey.cherny@tantorlabs.com>
2026-06-01 22:41 [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths Andrey Chernyy <andrey.cherny@tantorlabs.com>
2026-06-01 22:41 [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths Andrey Chernyy <andrey.cherny@tantorlabs.com>
2026-06-01 22:41 [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths Andrey Chernyy <andrey.cherny@tantorlabs.com>
2026-06-01 22:41 [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths Andrey Chernyy <andrey.cherny@tantorlabs.com>
2026-06-01 22:41 [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths Andrey Chernyy <andrey.cherny@tantorlabs.com>
2026-06-01 22:41 [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths Andrey Chernyy <andrey.cherny@tantorlabs.com>
2026-06-01 22:41 [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths Andrey Chernyy <andrey.cherny@tantorlabs.com>
2026-06-01 22:41 [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths Andrey Chernyy <andrey.cherny@tantorlabs.com>
2026-06-01 22:41 [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths Andrey Chernyy <andrey.cherny@tantorlabs.com>
2026-06-01 22:41 [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths Andrey Chernyy <andrey.cherny@tantorlabs.com>
2026-06-01 22:41 [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths Andrey Chernyy <andrey.cherny@tantorlabs.com>
2026-06-01 22:41 [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths Andrey Chernyy <andrey.cherny@tantorlabs.com>
2026-06-01 22:41 [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths Andrey Chernyy <andrey.cherny@tantorlabs.com>
2026-06-01 22:41 [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths Andrey Chernyy <andrey.cherny@tantorlabs.com>
2026-06-01 22:41 [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths Andrey Chernyy <andrey.cherny@tantorlabs.com>
2026-06-01 22:41 [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths Andrey Chernyy <andrey.cherny@tantorlabs.com>
2026-06-01 22:41 [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths Andrey Chernyy <andrey.cherny@tantorlabs.com>
2026-06-01 22:41 [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths Andrey Chernyy <andrey.cherny@tantorlabs.com>
2026-06-01 22:41 [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths Andrey Chernyy <andrey.cherny@tantorlabs.com>
2026-06-01 22:41 [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths Andrey Chernyy <andrey.cherny@tantorlabs.com>
2026-06-01 22:41 [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths Andrey Chernyy <andrey.cherny@tantorlabs.com>
2026-06-01 22:41 [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths Andrey Chernyy <andrey.cherny@tantorlabs.com>
2026-06-01 22:41 [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths Andrey Chernyy <andrey.cherny@tantorlabs.com>
2026-06-01 22:41 [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths Andrey Chernyy <andrey.cherny@tantorlabs.com>
2026-06-01 22:41 [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths Andrey Chernyy <andrey.cherny@tantorlabs.com>
2026-06-01 22:41 [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths Andrey Chernyy <andrey.cherny@tantorlabs.com>
2026-06-01 22:41 [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths Andrey Chernyy <andrey.cherny@tantorlabs.com>
2026-06-01 22:41 [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths Andrey Chernyy <andrey.cherny@tantorlabs.com>
2026-06-01 22:41 [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths Andrey Chernyy <andrey.cherny@tantorlabs.com>
2026-06-01 22:41 [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths Andrey Chernyy <andrey.cherny@tantorlabs.com>
2026-06-01 22:41 [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths Andrey Chernyy <andrey.cherny@tantorlabs.com>
2026-06-01 22:41 [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths Andrey Chernyy <andrey.cherny@tantorlabs.com>
2026-06-01 22:41 [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths Andrey Chernyy <andrey.cherny@tantorlabs.com>
2026-06-01 22:41 [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths Andrey Chernyy <andrey.cherny@tantorlabs.com>
2026-06-01 22:41 [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths Andrey Chernyy <andrey.cherny@tantorlabs.com>
2026-06-01 22:41 [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths Andrey Chernyy <andrey.cherny@tantorlabs.com>
2026-06-01 22:41 [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths Andrey Chernyy <andrey.cherny@tantorlabs.com>
2026-06-01 22:41 [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths Andrey Chernyy <andrey.cherny@tantorlabs.com>
2026-06-01 22:41 [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths Andrey Chernyy <andrey.cherny@tantorlabs.com>
2026-06-01 22:41 [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths Andrey Chernyy <andrey.cherny@tantorlabs.com>
2026-06-01 22:41 [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths Andrey Chernyy <andrey.cherny@tantorlabs.com>
2026-06-01 22:41 [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths Andrey Chernyy <andrey.cherny@tantorlabs.com>
2026-06-01 22:41 [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths Andrey Chernyy <andrey.cherny@tantorlabs.com>
2026-06-01 22:41 [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths Andrey Chernyy <andrey.cherny@tantorlabs.com>
2026-06-01 22:41 [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths Andrey Chernyy <andrey.cherny@tantorlabs.com>
2026-06-01 22:41 [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths Andrey Chernyy <andrey.cherny@tantorlabs.com>
2026-06-01 22:41 [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths Andrey Chernyy <andrey.cherny@tantorlabs.com>
2026-06-01 22:41 [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths Andrey Chernyy <andrey.cherny@tantorlabs.com>
2026-06-01 22:41 [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths Andrey Chernyy <andrey.cherny@tantorlabs.com>
2026-06-01 22:41 [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths Andrey Chernyy <andrey.cherny@tantorlabs.com>
2026-06-01 22:41 [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths Andrey Chernyy <andrey.cherny@tantorlabs.com>
2026-06-01 22:41 [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths Andrey Chernyy <andrey.cherny@tantorlabs.com>
2026-06-01 22:41 [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths Andrey Chernyy <andrey.cherny@tantorlabs.com>
2026-06-01 22:41 [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths Andrey Chernyy <andrey.cherny@tantorlabs.com>
2026-06-01 22:41 [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths Andrey Chernyy <andrey.cherny@tantorlabs.com>
2026-06-01 22:41 [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths Andrey Chernyy <andrey.cherny@tantorlabs.com>
2026-06-01 22:41 [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths Andrey Chernyy <andrey.cherny@tantorlabs.com>
2026-06-01 22:41 [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths Andrey Chernyy <andrey.cherny@tantorlabs.com>
2026-06-01 22:41 [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths Andrey Chernyy <andrey.cherny@tantorlabs.com>
2026-06-01 22:41 [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths Andrey Chernyy <andrey.cherny@tantorlabs.com>
2026-06-01 22:41 [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths Andrey Chernyy <andrey.cherny@tantorlabs.com>
2026-06-01 22:41 [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths Andrey Chernyy <andrey.cherny@tantorlabs.com>
2026-06-01 22:41 [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths Andrey Chernyy <andrey.cherny@tantorlabs.com>
2026-06-01 22:41 [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths Andrey Chernyy <andrey.cherny@tantorlabs.com>
2026-06-01 22:41 [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths Andrey Chernyy <andrey.cherny@tantorlabs.com>
2026-06-01 22:41 [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths Andrey Chernyy <andrey.cherny@tantorlabs.com>
2026-06-01 22:41 [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths Andrey Chernyy <andrey.cherny@tantorlabs.com>
2026-06-01 22:41 [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths Andrey Chernyy <andrey.cherny@tantorlabs.com>
2026-06-01 22:41 [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths Andrey Chernyy <andrey.cherny@tantorlabs.com>
2026-06-01 22:41 [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths Andrey Chernyy <andrey.cherny@tantorlabs.com>
2026-06-01 22:41 [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths Andrey Chernyy <andrey.cherny@tantorlabs.com>
2026-06-01 22:41 [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths Andrey Chernyy <andrey.cherny@tantorlabs.com>
2026-06-01 22:41 [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths Andrey Chernyy <andrey.cherny@tantorlabs.com>
2026-06-01 22:41 [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths Andrey Chernyy <andrey.cherny@tantorlabs.com>
2026-06-01 22:41 [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths Andrey Chernyy <andrey.cherny@tantorlabs.com>
2026-06-01 22:41 [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths Andrey Chernyy <andrey.cherny@tantorlabs.com>
2026-06-01 22:41 [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths Andrey Chernyy <andrey.cherny@tantorlabs.com>
2026-06-01 22:41 [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths Andrey Chernyy <andrey.cherny@tantorlabs.com>
2026-06-01 22:41 [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths Andrey Chernyy <andrey.cherny@tantorlabs.com>
2026-06-01 22:41 [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths Andrey Chernyy <andrey.cherny@tantorlabs.com>
2026-06-01 22:41 [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths Andrey Chernyy <andrey.cherny@tantorlabs.com>
2026-06-01 22:41 [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths Andrey Chernyy <andrey.cherny@tantorlabs.com>
2026-06-01 22:41 [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths Andrey Chernyy <andrey.cherny@tantorlabs.com>
2026-06-01 22:41 [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths Andrey Chernyy <andrey.cherny@tantorlabs.com>
2026-06-01 22:41 [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths Andrey Chernyy <andrey.cherny@tantorlabs.com>
2026-06-01 22:41 [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths Andrey Chernyy <andrey.cherny@tantorlabs.com>
2026-06-01 22:41 [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths Andrey Chernyy <andrey.cherny@tantorlabs.com>
2026-06-01 22:41 [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths Andrey Chernyy <andrey.cherny@tantorlabs.com>
2026-06-01 22:41 [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths Andrey Chernyy <andrey.cherny@tantorlabs.com>
2026-06-01 22:41 [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths Andrey Chernyy <andrey.cherny@tantorlabs.com>
2026-06-01 22:41 [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths Andrey Chernyy <andrey.cherny@tantorlabs.com>
2026-06-01 22:41 [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths Andrey Chernyy <andrey.cherny@tantorlabs.com>
2026-06-01 22:41 [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths Andrey Chernyy <andrey.cherny@tantorlabs.com>
2026-06-01 22:41 [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths Andrey Chernyy <andrey.cherny@tantorlabs.com>
2026-06-01 22:41 [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths Andrey Chernyy <andrey.cherny@tantorlabs.com>
2026-06-01 22:41 [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths Andrey Chernyy <andrey.cherny@tantorlabs.com>
2026-06-01 22:41 [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths Andrey Chernyy <andrey.cherny@tantorlabs.com>
2026-06-01 22:41 [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths Andrey Chernyy <andrey.cherny@tantorlabs.com>
2026-06-01 22:41 [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths Andrey Chernyy <andrey.cherny@tantorlabs.com>
2026-06-01 22:41 [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths Andrey Chernyy <andrey.cherny@tantorlabs.com>
2026-06-01 22:41 [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths Andrey Chernyy <andrey.cherny@tantorlabs.com>
2026-06-01 22:41 [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths Andrey Chernyy <andrey.cherny@tantorlabs.com>
2026-06-01 22:41 [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths Andrey Chernyy <andrey.cherny@tantorlabs.com>
2026-06-01 22:41 [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths Andrey Chernyy <andrey.cherny@tantorlabs.com>
2026-06-01 22:41 [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths Andrey Chernyy <andrey.cherny@tantorlabs.com>
2026-06-01 22:41 [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths Andrey Chernyy <andrey.cherny@tantorlabs.com>
2026-06-01 22:41 [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths Andrey Chernyy <andrey.cherny@tantorlabs.com>
2026-06-01 22:41 [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths Andrey Chernyy <andrey.cherny@tantorlabs.com>
2026-06-01 22:41 [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths Andrey Chernyy <andrey.cherny@tantorlabs.com>
2026-06-01 22:41 [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths Andrey Chernyy <andrey.cherny@tantorlabs.com>
2026-06-01 22:41 [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths Andrey Chernyy <andrey.cherny@tantorlabs.com>
2026-06-01 22:41 [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths Andrey Chernyy <andrey.cherny@tantorlabs.com>
2026-06-01 22:41 [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths Andrey Chernyy <andrey.cherny@tantorlabs.com>
2026-06-01 22:41 [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths Andrey Chernyy <andrey.cherny@tantorlabs.com>
2026-06-01 22:41 [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths Andrey Chernyy <andrey.cherny@tantorlabs.com>
2026-06-01 22:41 [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths Andrey Chernyy <andrey.cherny@tantorlabs.com>
2026-06-01 22:41 [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths Andrey Chernyy <andrey.cherny@tantorlabs.com>
2026-06-01 22:41 [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths Andrey Chernyy <andrey.cherny@tantorlabs.com>
2026-06-01 22:41 [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths Andrey Chernyy <andrey.cherny@tantorlabs.com>
2026-06-01 22:41 [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths Andrey Chernyy <andrey.cherny@tantorlabs.com>
2026-06-01 22:41 [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths Andrey Chernyy <andrey.cherny@tantorlabs.com>
2026-06-01 22:41 [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths Andrey Chernyy <andrey.cherny@tantorlabs.com>
2026-06-01 22:41 [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths Andrey Chernyy <andrey.cherny@tantorlabs.com>
2026-06-01 22:41 [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths Andrey Chernyy <andrey.cherny@tantorlabs.com>
2026-06-01 22:41 [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths Andrey Chernyy <andrey.cherny@tantorlabs.com>
2026-06-01 22:41 [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths Andrey Chernyy <andrey.cherny@tantorlabs.com>
2026-06-01 22:41 [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths Andrey Chernyy <andrey.cherny@tantorlabs.com>
2026-06-01 22:41 [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths Andrey Chernyy <andrey.cherny@tantorlabs.com>
2026-06-01 22:41 [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths Andrey Chernyy <andrey.cherny@tantorlabs.com>
2026-06-01 22:41 [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths Andrey Chernyy <andrey.cherny@tantorlabs.com>
2026-06-01 22:41 [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths Andrey Chernyy <andrey.cherny@tantorlabs.com>
2026-06-01 22:41 [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths Andrey Chernyy <andrey.cherny@tantorlabs.com>
2026-06-01 22:41 [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths Andrey Chernyy <andrey.cherny@tantorlabs.com>
2026-06-01 22:41 [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths Andrey Chernyy <andrey.cherny@tantorlabs.com>
2026-06-01 22:41 [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths Andrey Chernyy <andrey.cherny@tantorlabs.com>
2026-06-01 22:41 [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths Andrey Chernyy <andrey.cherny@tantorlabs.com>
2026-06-01 22:41 [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths Andrey Chernyy <andrey.cherny@tantorlabs.com>
2026-06-01 22:41 [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths Andrey Chernyy <andrey.cherny@tantorlabs.com>
2026-06-01 22:41 [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths Andrey Chernyy <andrey.cherny@tantorlabs.com>
2026-06-01 22:41 [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths Andrey Chernyy <andrey.cherny@tantorlabs.com>
2026-06-01 22:41 [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths Andrey Chernyy <andrey.cherny@tantorlabs.com>
2026-06-01 22:41 [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths Andrey Chernyy <andrey.cherny@tantorlabs.com>
2026-06-01 22:41 [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths Andrey Chernyy <andrey.cherny@tantorlabs.com>
2026-06-01 22:41 [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths Andrey Chernyy <andrey.cherny@tantorlabs.com>
2026-06-01 22:41 [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths Andrey Chernyy <andrey.cherny@tantorlabs.com>
2026-06-01 22:41 [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths Andrey Chernyy <andrey.cherny@tantorlabs.com>
2026-06-01 22:41 [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths Andrey Chernyy <andrey.cherny@tantorlabs.com>
2026-06-01 22:41 [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths Andrey Chernyy <andrey.cherny@tantorlabs.com>
2026-06-01 22:41 [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths Andrey Chernyy <andrey.cherny@tantorlabs.com>
2026-06-01 22:41 [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths Andrey Chernyy <andrey.cherny@tantorlabs.com>
2026-06-01 22:41 [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths Andrey Chernyy <andrey.cherny@tantorlabs.com>
2026-06-01 22:41 [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths Andrey Chernyy <andrey.cherny@tantorlabs.com>
2026-06-01 22:41 [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths Andrey Chernyy <andrey.cherny@tantorlabs.com>
2026-06-01 22:41 [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths Andrey Chernyy <andrey.cherny@tantorlabs.com>
2026-06-01 22:41 [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths Andrey Chernyy <andrey.cherny@tantorlabs.com>
2026-06-01 22:41 [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths Andrey Chernyy <andrey.cherny@tantorlabs.com>
2026-06-01 22:41 [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths Andrey Chernyy <andrey.cherny@tantorlabs.com>
2026-06-01 22:41 [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths Andrey Chernyy <andrey.cherny@tantorlabs.com>
2026-06-01 22:41 [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths Andrey Chernyy <andrey.cherny@tantorlabs.com>
2026-06-01 22:41 [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths Andrey Chernyy <andrey.cherny@tantorlabs.com>
2026-06-01 22:41 [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths Andrey Chernyy <andrey.cherny@tantorlabs.com>
2026-06-01 22:41 [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths Andrey Chernyy <andrey.cherny@tantorlabs.com>
2026-06-01 22:41 [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths Andrey Chernyy <andrey.cherny@tantorlabs.com>
2026-06-01 22:41 [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths Andrey Chernyy <andrey.cherny@tantorlabs.com>
2026-06-01 22:41 [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths Andrey Chernyy <andrey.cherny@tantorlabs.com>
2026-06-01 22:41 [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths Andrey Chernyy <andrey.cherny@tantorlabs.com>
2026-06-01 22:41 [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths Andrey Chernyy <andrey.cherny@tantorlabs.com>
2026-06-01 22:41 [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths Andrey Chernyy <andrey.cherny@tantorlabs.com>
2026-06-01 22:41 [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths Andrey Chernyy <andrey.cherny@tantorlabs.com>
2026-06-01 22:41 [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths Andrey Chernyy <andrey.cherny@tantorlabs.com>
2026-06-01 22:41 [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths Andrey Chernyy <andrey.cherny@tantorlabs.com>
2026-06-01 22:41 [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths Andrey Chernyy <andrey.cherny@tantorlabs.com>
2026-06-01 22:41 [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths Andrey Chernyy <andrey.cherny@tantorlabs.com>
2026-06-01 22:41 [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths Andrey Chernyy <andrey.cherny@tantorlabs.com>
2026-06-01 22:41 [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths Andrey Chernyy <andrey.cherny@tantorlabs.com>
2026-06-01 22:41 [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths Andrey Chernyy <andrey.cherny@tantorlabs.com>
2026-06-01 22:41 [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths Andrey Chernyy <andrey.cherny@tantorlabs.com>
2026-06-01 22:41 [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths Andrey Chernyy <andrey.cherny@tantorlabs.com>
2026-06-01 22:41 [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths Andrey Chernyy <andrey.cherny@tantorlabs.com>
2026-06-01 22:41 [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths Andrey Chernyy <andrey.cherny@tantorlabs.com>
2026-06-01 22:41 [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths Andrey Chernyy <andrey.cherny@tantorlabs.com>
2026-06-01 22:41 [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths Andrey Chernyy <andrey.cherny@tantorlabs.com>
2026-06-01 22:41 [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths Andrey Chernyy <andrey.cherny@tantorlabs.com>
2026-06-01 22:41 [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths Andrey Chernyy <andrey.cherny@tantorlabs.com>
2026-06-01 22:41 [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths Andrey Chernyy <andrey.cherny@tantorlabs.com>
2026-06-01 22:41 [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths Andrey Chernyy <andrey.cherny@tantorlabs.com>
2026-06-01 22:41 [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths Andrey Chernyy <andrey.cherny@tantorlabs.com>
2026-06-01 22:41 [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths Andrey Chernyy <andrey.cherny@tantorlabs.com>
2026-06-01 22:41 [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths Andrey Chernyy <andrey.cherny@tantorlabs.com>
2026-06-01 22:41 [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths Andrey Chernyy <andrey.cherny@tantorlabs.com>
2026-06-01 22:41 [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths Andrey Chernyy <andrey.cherny@tantorlabs.com>
2026-06-01 22:41 [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths Andrey Chernyy <andrey.cherny@tantorlabs.com>
2026-06-01 22:41 [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths Andrey Chernyy <andrey.cherny@tantorlabs.com>
2026-06-01 22:41 [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths Andrey Chernyy <andrey.cherny@tantorlabs.com>
2026-06-01 22:41 [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths Andrey Chernyy <andrey.cherny@tantorlabs.com>
2026-06-01 22:41 [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths Andrey Chernyy <andrey.cherny@tantorlabs.com>
2026-06-01 22:41 [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths Andrey Chernyy <andrey.cherny@tantorlabs.com>
2026-06-01 22:41 [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths Andrey Chernyy <andrey.cherny@tantorlabs.com>
2026-06-01 22:41 [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths Andrey Chernyy <andrey.cherny@tantorlabs.com>
2026-06-01 22:41 [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths Andrey Chernyy <andrey.cherny@tantorlabs.com>
2026-06-01 22:41 [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths Andrey Chernyy <andrey.cherny@tantorlabs.com>
2026-06-01 22:41 [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths Andrey Chernyy <andrey.cherny@tantorlabs.com>
2026-06-01 22:41 [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths Andrey Chernyy <andrey.cherny@tantorlabs.com>
2026-06-01 22:41 [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths Andrey Chernyy <andrey.cherny@tantorlabs.com>
2026-06-01 22:41 [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths Andrey Chernyy <andrey.cherny@tantorlabs.com>
2026-06-01 22:41 [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths Andrey Chernyy <andrey.cherny@tantorlabs.com>
2026-06-01 22:41 [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths Andrey Chernyy <andrey.cherny@tantorlabs.com>
2026-06-01 22:41 [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths Andrey Chernyy <andrey.cherny@tantorlabs.com>
2026-06-01 22:41 [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths Andrey Chernyy <andrey.cherny@tantorlabs.com>
2026-06-01 22:41 [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths Andrey Chernyy <andrey.cherny@tantorlabs.com>
2026-06-01 22:41 [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths Andrey Chernyy <andrey.cherny@tantorlabs.com>
2026-06-01 22:41 [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths Andrey Chernyy <andrey.cherny@tantorlabs.com>
2026-06-01 22:41 [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths Andrey Chernyy <andrey.cherny@tantorlabs.com>
2026-06-01 22:41 [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths Andrey Chernyy <andrey.cherny@tantorlabs.com>
2026-06-01 22:41 [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths Andrey Chernyy <andrey.cherny@tantorlabs.com>
2026-06-01 22:41 [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths Andrey Chernyy <andrey.cherny@tantorlabs.com>
2026-06-01 22:41 [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths Andrey Chernyy <andrey.cherny@tantorlabs.com>
2026-06-01 22:41 [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths Andrey Chernyy <andrey.cherny@tantorlabs.com>
2026-06-01 22:41 [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths Andrey Chernyy <andrey.cherny@tantorlabs.com>
2026-06-01 22:41 [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths Andrey Chernyy <andrey.cherny@tantorlabs.com>
2026-06-01 22:41 [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths Andrey Chernyy <andrey.cherny@tantorlabs.com>
2026-06-01 22:41 [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths Andrey Chernyy <andrey.cherny@tantorlabs.com>
2026-06-01 22:41 [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths Andrey Chernyy <andrey.cherny@tantorlabs.com>
2026-06-01 22:41 [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths Andrey Chernyy <andrey.cherny@tantorlabs.com>
2026-06-01 22:41 [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths Andrey Chernyy <andrey.cherny@tantorlabs.com>
2026-06-01 22:41 [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths Andrey Chernyy <andrey.cherny@tantorlabs.com>
2026-06-01 22:41 [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths Andrey Chernyy <andrey.cherny@tantorlabs.com>
2026-06-01 22:41 [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths Andrey Chernyy <andrey.cherny@tantorlabs.com>
2026-06-01 22:41 [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths Andrey Chernyy <andrey.cherny@tantorlabs.com>
2026-06-01 22:41 [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths Andrey Chernyy <andrey.cherny@tantorlabs.com>
2026-06-01 22:41 [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths Andrey Chernyy <andrey.cherny@tantorlabs.com>
2026-06-01 22:41 [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths Andrey Chernyy <andrey.cherny@tantorlabs.com>
2026-06-01 22:41 [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths Andrey Chernyy <andrey.cherny@tantorlabs.com>
2026-06-01 22:41 [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths Andrey Chernyy <andrey.cherny@tantorlabs.com>
2026-06-01 22:41 [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths Andrey Chernyy <andrey.cherny@tantorlabs.com>
2026-06-01 22:41 [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths Andrey Chernyy <andrey.cherny@tantorlabs.com>
2026-06-01 22:41 [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths Andrey Chernyy <andrey.cherny@tantorlabs.com>
2026-06-01 22:41 [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths Andrey Chernyy <andrey.cherny@tantorlabs.com>
2026-06-01 22:41 [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths Andrey Chernyy <andrey.cherny@tantorlabs.com>
2026-06-01 22:41 [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths Andrey Chernyy <andrey.cherny@tantorlabs.com>
2026-06-01 22:41 [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths Andrey Chernyy <andrey.cherny@tantorlabs.com>
2026-06-01 22:41 [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths Andrey Chernyy <andrey.cherny@tantorlabs.com>
2026-06-01 22:41 [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths Andrey Chernyy <andrey.cherny@tantorlabs.com>
2026-06-01 22:41 [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths Andrey Chernyy <andrey.cherny@tantorlabs.com>
2026-06-01 22:41 [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths Andrey Chernyy <andrey.cherny@tantorlabs.com>
2026-06-01 22:41 [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths Andrey Chernyy <andrey.cherny@tantorlabs.com>
2026-06-01 22:41 [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths Andrey Chernyy <andrey.cherny@tantorlabs.com>
2026-06-01 22:41 [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths Andrey Chernyy <andrey.cherny@tantorlabs.com>
2026-06-01 22:41 [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths Andrey Chernyy <andrey.cherny@tantorlabs.com>
2026-06-01 22:41 [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths Andrey Chernyy <andrey.cherny@tantorlabs.com>
2026-06-01 22:41 [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths Andrey Chernyy <andrey.cherny@tantorlabs.com>
2026-06-01 22:41 [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths Andrey Chernyy <andrey.cherny@tantorlabs.com>
2026-06-01 22:41 [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths Andrey Chernyy <andrey.cherny@tantorlabs.com>
2026-06-01 22:41 [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths Andrey Chernyy <andrey.cherny@tantorlabs.com>
2026-06-01 22:41 [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths Andrey Chernyy <andrey.cherny@tantorlabs.com>
2026-06-01 22:41 [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths Andrey Chernyy <andrey.cherny@tantorlabs.com>
2026-06-01 22:41 [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths Andrey Chernyy <andrey.cherny@tantorlabs.com>
2026-06-01 22:41 [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths Andrey Chernyy <andrey.cherny@tantorlabs.com>
2026-06-01 22:41 [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths Andrey Chernyy <andrey.cherny@tantorlabs.com>
2026-06-01 22:41 [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths Andrey Chernyy <andrey.cherny@tantorlabs.com>
2026-06-01 22:41 [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths Andrey Chernyy <andrey.cherny@tantorlabs.com>
2026-06-01 22:41 [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths Andrey Chernyy <andrey.cherny@tantorlabs.com>
2026-06-01 22:41 [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths Andrey Chernyy <andrey.cherny@tantorlabs.com>
2026-06-01 22:41 [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths Andrey Chernyy <andrey.cherny@tantorlabs.com>
2026-06-01 22:41 [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths Andrey Chernyy <andrey.cherny@tantorlabs.com>
2026-06-01 22:41 [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths Andrey Chernyy <andrey.cherny@tantorlabs.com>
2026-06-01 22:41 [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths Andrey Chernyy <andrey.cherny@tantorlabs.com>
2026-06-01 22:41 [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths Andrey Chernyy <andrey.cherny@tantorlabs.com>
2026-06-01 22:41 [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths Andrey Chernyy <andrey.cherny@tantorlabs.com>
2026-06-01 22:41 [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths Andrey Chernyy <andrey.cherny@tantorlabs.com>
2026-06-01 22:41 [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths Andrey Chernyy <andrey.cherny@tantorlabs.com>
2026-06-01 22:41 [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths Andrey Chernyy <andrey.cherny@tantorlabs.com>
2026-06-01 22:41 [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths Andrey Chernyy <andrey.cherny@tantorlabs.com>
2026-06-01 22:41 [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths Andrey Chernyy <andrey.cherny@tantorlabs.com>
2026-06-01 22:41 [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths Andrey Chernyy <andrey.cherny@tantorlabs.com>
2026-06-01 22:41 [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths Andrey Chernyy <andrey.cherny@tantorlabs.com>
2026-06-01 22:41 [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths Andrey Chernyy <andrey.cherny@tantorlabs.com>
2026-06-01 22:41 [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths Andrey Chernyy <andrey.cherny@tantorlabs.com>
2026-06-01 22:41 [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths Andrey Chernyy <andrey.cherny@tantorlabs.com>
2026-06-01 22:41 [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths Andrey Chernyy <andrey.cherny@tantorlabs.com>
2026-06-01 22:41 [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths Andrey Chernyy <andrey.cherny@tantorlabs.com>
2026-06-01 22:41 [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths Andrey Chernyy <andrey.cherny@tantorlabs.com>
2026-06-01 22:41 [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths Andrey Chernyy <andrey.cherny@tantorlabs.com>
2026-06-01 22:41 [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths Andrey Chernyy <andrey.cherny@tantorlabs.com>
2026-06-01 22:41 [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths Andrey Chernyy <andrey.cherny@tantorlabs.com>
2026-06-01 22:41 [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths Andrey Chernyy <andrey.cherny@tantorlabs.com>
2026-06-01 22:41 [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths Andrey Chernyy <andrey.cherny@tantorlabs.com>
2026-06-01 22:41 [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths Andrey Chernyy <andrey.cherny@tantorlabs.com>
2026-06-01 22:41 [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths Andrey Chernyy <andrey.cherny@tantorlabs.com>
2026-06-01 22:41 [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths Andrey Chernyy <andrey.cherny@tantorlabs.com>
2026-06-01 22:41 [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths Andrey Chernyy <andrey.cherny@tantorlabs.com>
2026-06-01 22:41 [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths Andrey Chernyy <andrey.cherny@tantorlabs.com>
2026-06-01 22:41 [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths Andrey Chernyy <andrey.cherny@tantorlabs.com>
2026-06-01 22:41 [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths Andrey Chernyy <andrey.cherny@tantorlabs.com>
2026-06-01 22:41 [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths Andrey Chernyy <andrey.cherny@tantorlabs.com>
2026-06-01 22:41 [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths Andrey Chernyy <andrey.cherny@tantorlabs.com>
2026-06-01 22:41 [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths Andrey Chernyy <andrey.cherny@tantorlabs.com>
2026-06-01 22:41 [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths Andrey Chernyy <andrey.cherny@tantorlabs.com>
2026-06-01 22:41 [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths Andrey Chernyy <andrey.cherny@tantorlabs.com>
2026-06-01 22:41 [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths Andrey Chernyy <andrey.cherny@tantorlabs.com>
2026-06-01 22:41 [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths Andrey Chernyy <andrey.cherny@tantorlabs.com>
2026-06-01 22:41 [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths Andrey Chernyy <andrey.cherny@tantorlabs.com>
2026-06-01 22:41 [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths Andrey Chernyy <andrey.cherny@tantorlabs.com>
2026-06-01 22:41 [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths Andrey Chernyy <andrey.cherny@tantorlabs.com>
2026-06-01 22:41 [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths Andrey Chernyy <andrey.cherny@tantorlabs.com>
2026-06-01 22:41 [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths Andrey Chernyy <andrey.cherny@tantorlabs.com>
2026-06-01 22:41 [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths Andrey Chernyy <andrey.cherny@tantorlabs.com>
2026-06-01 22:41 [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths Andrey Chernyy <andrey.cherny@tantorlabs.com>
2026-06-01 22:41 [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths Andrey Chernyy <andrey.cherny@tantorlabs.com>
2026-06-01 22:41 [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths Andrey Chernyy <andrey.cherny@tantorlabs.com>
2026-06-01 22:41 [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths Andrey Chernyy <andrey.cherny@tantorlabs.com>
2026-06-01 22:41 [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths Andrey Chernyy <andrey.cherny@tantorlabs.com>
2026-06-01 22:41 [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths Andrey Chernyy <andrey.cherny@tantorlabs.com>
2026-06-01 22:41 [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths Andrey Chernyy <andrey.cherny@tantorlabs.com>
2026-06-01 22:41 [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths Andrey Chernyy <andrey.cherny@tantorlabs.com>
2026-06-01 22:41 [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths Andrey Chernyy <andrey.cherny@tantorlabs.com>
2026-06-01 22:41 [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths Andrey Chernyy <andrey.cherny@tantorlabs.com>
2026-06-01 22:41 [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths Andrey Chernyy <andrey.cherny@tantorlabs.com>
2026-06-01 22:41 [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths Andrey Chernyy <andrey.cherny@tantorlabs.com>
2026-06-01 22:41 [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths Andrey Chernyy <andrey.cherny@tantorlabs.com>
2026-06-01 22:41 [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths Andrey Chernyy <andrey.cherny@tantorlabs.com>
2026-06-01 22:41 [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths Andrey Chernyy <andrey.cherny@tantorlabs.com>
2026-06-01 22:41 [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths Andrey Chernyy <andrey.cherny@tantorlabs.com>
2026-06-01 22:41 [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths Andrey Chernyy <andrey.cherny@tantorlabs.com>
2026-06-01 22:41 [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths Andrey Chernyy <andrey.cherny@tantorlabs.com>
2026-06-01 22:41 [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths Andrey Chernyy <andrey.cherny@tantorlabs.com>
2026-06-01 22:41 [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths Andrey Chernyy <andrey.cherny@tantorlabs.com>
2026-06-01 22:41 [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths Andrey Chernyy <andrey.cherny@tantorlabs.com>
2026-06-01 22:41 [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths Andrey Chernyy <andrey.cherny@tantorlabs.com>
2026-06-01 22:41 [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths Andrey Chernyy <andrey.cherny@tantorlabs.com>
2026-06-01 22:41 [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths Andrey Chernyy <andrey.cherny@tantorlabs.com>
2026-06-01 22:41 [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths Andrey Chernyy <andrey.cherny@tantorlabs.com>
2026-06-01 22:41 [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths Andrey Chernyy <andrey.cherny@tantorlabs.com>
2026-06-01 22:41 [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths Andrey Chernyy <andrey.cherny@tantorlabs.com>
2026-06-01 22:41 [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths Andrey Chernyy <andrey.cherny@tantorlabs.com>
2026-06-01 22:41 [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths Andrey Chernyy <andrey.cherny@tantorlabs.com>
2026-06-01 22:41 [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths Andrey Chernyy <andrey.cherny@tantorlabs.com>
2026-06-01 22:41 [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths Andrey Chernyy <andrey.cherny@tantorlabs.com>
2026-06-01 22:41 [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths Andrey Chernyy <andrey.cherny@tantorlabs.com>
2026-06-01 22:41 [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths Andrey Chernyy <andrey.cherny@tantorlabs.com>
2026-06-01 22:41 [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths Andrey Chernyy <andrey.cherny@tantorlabs.com>
2026-06-01 22:41 [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths Andrey Chernyy <andrey.cherny@tantorlabs.com>
2026-06-01 22:41 [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths Andrey Chernyy <andrey.cherny@tantorlabs.com>
2026-06-01 22:41 [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths Andrey Chernyy <andrey.cherny@tantorlabs.com>
2026-06-01 22:41 [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths Andrey Chernyy <andrey.cherny@tantorlabs.com>
2026-06-01 22:41 [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths Andrey Chernyy <andrey.cherny@tantorlabs.com>
2026-06-01 22:41 [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths Andrey Chernyy <andrey.cherny@tantorlabs.com>
2026-06-01 22:41 [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths Andrey Chernyy <andrey.cherny@tantorlabs.com>
2026-06-01 22:41 [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths Andrey Chernyy <andrey.cherny@tantorlabs.com>
2026-06-01 22:41 [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths Andrey Chernyy <andrey.cherny@tantorlabs.com>
2026-06-01 22:41 [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths Andrey Chernyy <andrey.cherny@tantorlabs.com>
2026-06-01 22:41 [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths Andrey Chernyy <andrey.cherny@tantorlabs.com>
2026-06-01 22:41 [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths Andrey Chernyy <andrey.cherny@tantorlabs.com>
2026-06-01 22:41 [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths Andrey Chernyy <andrey.cherny@tantorlabs.com>

This inbox is served by agora; see mirroring instructions
for how to clone and mirror all data and code used for this inbox