Re: Confine vacuum skip logic to lazy_scan_skip
Tom Lane <tgl@sss.pgh.pa.us>
From: Tom Lane <tgl@sss.pgh.pa.us>
To: Thomas Munro <thomas.munro@gmail.com>
Cc: Noah Misch <noah@leadboat.com>,
Melanie Plageman <melanieplageman@gmail.com>,
vignesh C <vignesh21@gmail.com>, Andres Freund <andres@anarazel.de>,
Pg Hackers <pgsql-hackers@postgresql.org>,
Heikki Linnakangas <hlinnaka@iki.fi>,
Nazir Bilal Yavuz <byavuz81@gmail.com>,
Robert Haas <robertmhaas@gmail.com>,
"Andrey M. Borodin" <x4mmm@yandex-team.ru>
Date: 2025-10-22T16:12:08Z
Lists: pgsql-hackers
[ seizing on this old commit as being most closely related to the issue ]
Thomas Munro <thomas.munro@gmail.com> writes:
> On Tue, Jul 16, 2024 at 1:52 PM Noah Misch <noah@leadboat.com> wrote:
>> On Mon, Jul 15, 2024 at 03:26:32PM +1200, Thomas Munro wrote:
>> That's reasonable. radixtree already forbids mutations concurrent with
>> iteration, so there's no new concurrency hazard. One alternative is
>> per_buffer_data big enough for MaxOffsetNumber, but that might thrash caches
>> measurably. That patch is good to go apart from these trivialities:
> Thanks! I have pushed that patch, without those changes you didn't like.
The security team recently updated our Coverity instance to the latest
version, and it's started complaining as follows:
*** CID 1667418: Memory - corruptions (OVERRUN)
/srv/coverity/git/pgsql-git/postgresql/src/backend/access/heap/vacuumlazy.c: 2812 in lazy_vacuum_heap_rel()
2806 * already have the correct page pinned anyway.
2807 */
2808 visibilitymap_pin(vacrel->rel, blkno, &vmbuffer);
2809
2810 /* We need a non-cleanup exclusive lock to mark dead_items unused */
2811 LockBuffer(buf, BUFFER_LOCK_EXCLUSIVE);
>>> CID 1667418: Memory - corruptions (OVERRUN)
>>> Overrunning callee's array of size 291 by passing argument "num_offsets" (which evaluates to 2048) in call to "lazy_vacuum_heap_page".
2812 lazy_vacuum_heap_page(vacrel, blkno, buf, offsets,
2813 num_offsets, vmbuffer);
2814
2815 /* Now that we've vacuumed the page, record its available space */
2816 page = BufferGetPage(buf);
2817 freespace = PageGetHeapFreeSpace(page);
The reason it thinks that num_offsets could be as much as 2048 is
presumably the code a little bit above this:
OffsetNumber offsets[MaxOffsetNumber];
...
num_offsets = TidStoreGetBlockOffsets(iter_result, offsets, lengthof(offsets));
Assert(num_offsets <= lengthof(offsets));
However, lazy_vacuum_heap_page blindly assumes that the passed value
will be no more than MaxHeapTuplesPerPage. It seems like we ought
to get these two functions in sync, either both using MaxOffsetNumber
or both using MaxHeapTuplesPerPage for their array sizes.
It looks to me like MaxHeapTuplesPerPage should be sufficient.
Also, after reading TidStoreGetBlockOffsets I wonder if we
should replace that Assert with
num_offsets = Min(num_offsets, lengthof(offsets));
Thoughts?
regards, tom lane
Commits
-
Fix explicit valgrind interaction in read_stream.c.
- 57dca6faa9bd 17.5 landed
- 2a8a00674e97 18.0 landed
-
Reduce scope of heap vacuum per_buffer_data
- c623e8593ec4 18.0 landed
-
Use streaming read I/O in VACUUM's third phase
- c3e775e608f2 18.0 landed
-
Use streaming read I/O in VACUUM's first phase
- 9256822608f3 18.0 landed
-
Convert heap_vac_scan_next_block() boolean parameters to flags
- 32acad7d1d0a 18.0 landed
-
Refactor tidstore.c iterator buffering.
- f6bef362cac8 18.0 landed
-
Increase default vacuum_buffer_usage_limit to 2MB.
- 98f320eb2ef0 17.0 landed
-
Remove unneeded vacuum_delay_point from heap_vac_scan_get_next_block
- 3d8652cd3284 17.0 landed
-
Confine vacuum skip logic to lazy_scan_skip()
- 4e76f984a773 17.0 landed
-
Set all_visible_according_to_vm correctly with DISABLE_PAGE_SKIPPING
- 407cb6c6589f 16.3 landed
- 674e49c73c1c 17.0 landed
-
Tighten up VACUUM's approach to setting VM bits.
- 980ae173108e 16.0 cited