From f965132abc3520f06dbfc8d5f89222cf00728e00 Mon Sep 17 00:00:00 2001 From: Ranier Vilela Date: Sun, 11 Jul 2021 16:17:50 -0300 Subject: [PATCH] _bt_restore_page have issues can lead a memory corrupt, when recovery tries restore index tuples to a page. First the maximum index tuples per page varies that system to system. at Windows 64 bits, the MaxIndexTuplesPerPage is 408. The int *len* parameter allows 268.435.455 index tuples per page. 2.147.483.647 / sizeof(IndexTupleData) = 268.435.455 /* IndexTupleData size is 8 bytes */ So if _bt_restore_page tries restore a file corrupted or maliciously created, can write after array bounds. Fix by checking and raising a error PANIC in this case. Another issue is that _bt_restore_page can increment the pointer *from*, to after bounds that can point. Fix by removing the unnecessary increment. While there, reduce scope of two variables. Author: Ranier Vilela (ranier.vf@gmail.com) --- src/backend/access/nbtree/nbtxlog.c | 17 ++++++++++------- 1 file changed, 10 insertions(+), 7 deletions(-) diff --git a/src/backend/access/nbtree/nbtxlog.c b/src/backend/access/nbtree/nbtxlog.c index c2e920f159..8fe80bc8ff 100644 --- a/src/backend/access/nbtree/nbtxlog.c +++ b/src/backend/access/nbtree/nbtxlog.c @@ -35,16 +35,19 @@ static MemoryContext opCtx; /* working memory for operations */ * the one with highest item number appears first (lowest on the page). */ static void -_bt_restore_page(Page page, char *from, int len) +_bt_restore_page(Page page, char *from, Size len) { - IndexTupleData itupdata; - Size itemsz; - char *end = from + len; + const char *end = from + len; Item items[MaxIndexTuplesPerPage]; uint16 itemsizes[MaxIndexTuplesPerPage]; int i; int nitems; + /* Protect against corrupted recovery file */ + nitems = (len / sizeof(IndexTupleData)); + if (nitems < 0 || nitems > MaxIndexTuplesPerPage) + elog(PANIC, "_bt_restore_page: cannot restore %d items to page", nitems); + /* * To get the items back in the original order, we add them to the page in * reverse. To figure out where one tuple ends and another begins, we @@ -53,6 +56,9 @@ _bt_restore_page(Page page, char *from, int len) i = 0; while (from < end) { + IndexTupleData itupdata; + Size itemsz; + /* * As we step through the items, 'from' won't always be properly * aligned, so we need to use memcpy(). Further, we use Item (which @@ -73,12 +79,9 @@ _bt_restore_page(Page page, char *from, int len) nitems = i; for (i = nitems - 1; i >= 0; i--) - { if (PageAddItem(page, items[i], itemsizes[i], nitems - i, false, false) == InvalidOffsetNumber) elog(PANIC, "_bt_restore_page: cannot add item to page"); - from += itemsz; - } } static void -- 2.32.0.windows.1