Fix off-by-one in LimitAdditionalPins()
authorAndres Freund <andres@anarazel.de>
Tue, 25 Jul 2023 02:07:52 +0000 (19:07 -0700)
committerAndres Freund <andres@anarazel.de>
Tue, 25 Jul 2023 02:07:52 +0000 (19:07 -0700)
Due to the bug LimitAdditionalPins() could return 0, violating
LimitAdditionalPins()'s API ("One additional pin is always allowed"). This
could be hit when setting shared_buffers very low and using a fair amount of
concurrency.

This bug was introduced in 31966b151e6a.

Author: "Anton A. Melnikov" <aamelnikov@inbox.ru>
Reported-by: "Anton A. Melnikov" <aamelnikov@inbox.ru>
Reported-by: Victoria Shepard
Discussion: https://postgr.es/m/ae46f2fb-5586-3de0-b54b-1bb0f6410ebd@inbox.ru
Backpatch: 16-

src/backend/storage/buffer/bufmgr.c

index a7e3b9bb1d3cf1d09624fc71e02b79ef73269c31..df22aaa1c52a43aab888cd62afef97e7b838de7f 100644 (file)
@@ -1767,7 +1767,7 @@ LimitAdditionalPins(uint32 *additional_pins)
         */
        max_proportional_pins -= PrivateRefCountOverflowed + REFCOUNT_ARRAY_ENTRIES;
 
-       if (max_proportional_pins < 0)
+       if (max_proportional_pins <= 0)
                max_proportional_pins = 1;
 
        if (*additional_pins > max_proportional_pins)