On Sat, Aug 08, 2026 at 10:26:40PM -0500, Bryan Green wrote:
> An out-of-memory error during the first LockAcquire for a lock tag leaves a
> LOCALLOCK that crashes the next acquire of the same tag.  The initial
> lockOwners allocation is done with maxLockOwners already set to 8 and
> lockOwners still NULL; if that allocation throws, the entry survives in that
> state.  The next acquire takes the existing-entry path, where the only check
> is numLockOwners >= maxLockOwners (0 >= 8, false), so it skips the
> allocation and GrantLockLocal() dereferences the NULL pointer.

     else
     {
         /* Make sure there will be room to remember the lock */
-        if (locallock->numLockOwners >= locallock->maxLockOwners)
+        if (locallock->lockOwners == NULL)
+        {
+            /* A prior acquisition left the array unallocated after OOM. */
+            locallock->maxLockOwners = 8;
+            locallock->lockOwners = (LOCALLOCKOWNER *)
+                MemoryContextAlloc(TopMemoryContext,
+                                   locallock->maxLockOwners * 
sizeof(LOCALLOCKOWNER));
+        }
+        else if (locallock->numLockOwners >= locallock->maxLockOwners)
         {
             int            newsize = locallock->maxLockOwners * 2;

I can buy that.  The allocation failing would leave lockOwners NULL
while there is an entry in LockMethodLocalHash that we may try to
re-access later.  Just doing an extra allocation if we find out that
lockOwners is not set seems like a solution good enough.

Thanks for the report.  Will look again at it later.
--
Michael

Attachment: signature.asc
Description: PGP signature

Reply via email to