fix: avoid using uninitialized memory#172
fix: avoid using uninitialized memory#172buriedpot wants to merge 1 commit intopostgrespro:masterfrom
Conversation
|
I strongly recommend prioritizing the review and applying of this fix. |
|
You can observe that a concurrent VACUUM may set a page’s maxoff to zero in rumvacuum.c: if (newMaxOff > 0)
memcpy(RumDataPageGetData(newPage), cleaned, newSize);
pfree(cleaned);
RumPageGetOpaque(newPage)->maxoff = newMaxOff;
updateItemIndexes(newPage, attnum, &gvs->rumstate);When newMaxOff == 0, the page ends up with no valid items. entry->nlist = maxoff;
ptr = RumDataPageGetData(page);
for (i = FirstOffsetNumber; i <= maxoff; i = OffsetNumberNext(i))
{
ptr = rumDataPageLeafRead(ptr, entry->attnum, &item, true,
rumstate);
entry->list[i - FirstOffsetNumber] = item;
}
LockBuffer(entry->buffer, RUM_UNLOCK);
entry->isFinished = setListPositionScanEntry(rumstate, entry);
if (!entry->isFinished)
entry->curItem = entry->list[entry->offset];Since the loop body is never executed when maxoff == 0, entry->list remains uninitialized. Yet, if setListPositionScanEntry() returns false (which can happen even with an empty list under certain scan states), entry->curItem will point to garbage memory — leading to a crash. |
|
Hi! Thanks for the report. For some reason, I couldn't reproduce it the first time, but after a while I tried again and the problem was reproduced. Could you please reopen the pull request? I'll review and merge it soon. |
OK. I have a comprehensive fix that has been verified. Please allow me to update this PR—just a moment. |
During a RUM index scan, if a concurrent VACUUM completes and removes all items from a posting tree leaf page or a posting list, entry->nlist can become zero. In this case, entry->curItem may point to uninitialized memory, leading to a crash. The commit fixes this bug.
d3b2caa to
1fa2417
Compare
Hi, I have updated the commit. |
Thanks! |
|
Is there anything we can do to help get this fix merged and released? Thank you! |
Hi! |
|
Just a note that I'm having this issue in production atm. Apreciate all your hard work on the fix! |
Fix crash in RUM index scan when VACUUM removes all items from a posting tree leaf page
During a RUM index scan, if a concurrent
VACUUMoperation completes and removes all entries from a posting tree leaf page, the scan entry’snlistfield may become zero. In this state, thecurItempointer can end up referencing uninitialized or invalid memory, leading to a backend crash.This commit resolves the issue by ensuring that
curItemis properly handled (or not dereferenced) whennlist == 0, thus preventing undefined behavior during index scans under concurrent vacuuming.Reproduction Steps
1. Prepare test data
2. Trigger the race condition using GDB
Backend 1 (VACUUM):
Attach GDB and set a breakpoint at
rumVacuumPostingTreeLeaves.Run:
Let it pause at the breakpoint.
Backend 2 (Query):
Attach another GDB instance and set a breakpoint at
startScanEntry.Run:
Let it pause at the breakpoint.
Resume execution:
First, continue Backend 1 to completion (so VACUUM fully removes all items from the leaf page).
Then, continue Backend 2.
→ The query backend will crash due to accessing invalid memory via
entry->curItemwhenentry->nlist == 0.This fix ensures safe handling of empty posting lists during scans, eliminating the crash under concurrent VACUUM and query workloads. The related issue is #168 and #99.