Skip to content

Commit 0cf205e

Browse files
committed
amcheck: Fix posting tree checks in gin_index_check()
Fix two issues in parent_key validation in posting trees: * It's not enough to check stack->parentblk is valid to determine if the parentkey is valid. It's possible parentblk is set to a valid block number, but parentkey is invalid. So check parentkey directly. * We don't need to invalidate parentkey for all child pages of the rightmost page. It's enough to invalidate it for the rightmost child only, which means we can check more cases (less false negatives). Issues reported by Arseniy Mukhin, along with a proposed patch. Review by Andrey M. Borodin, cleanup and improvements by me. Author: Arseniy Mukhin <arseniy.mukhin.dev@gmail.com> Reviewed-by: Andrey M. Borodin <x4mmm@yandex-team.ru> Discussion: https://postgr.es/m/CAE7r3MJ611B9TE=YqBBncewp7-k64VWs+sjk7XF6fJUX77uFBA@mail.gmail.com
1 parent cdd1a43 commit 0cf205e

File tree

2 files changed

+43
-8
lines changed

2 files changed

+43
-8
lines changed

contrib/amcheck/t/006_verify_gin.pl

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@
3636
invalid_entry_columns_order_test();
3737
inconsistent_with_parent_key__parent_key_corrupted_test();
3838
inconsistent_with_parent_key__child_key_corrupted_test();
39+
inconsistent_with_parent_key__parent_key_corrupted_posting_tree_test();
3940

4041
sub invalid_entry_order_leaf_page_test
4142
{
@@ -237,6 +238,44 @@ sub inconsistent_with_parent_key__child_key_corrupted_test
237238
like($stderr, qr/$expected/);
238239
}
239240

241+
sub inconsistent_with_parent_key__parent_key_corrupted_posting_tree_test
242+
{
243+
my $relname = "test";
244+
my $indexname = "test_gin_idx";
245+
246+
$node->safe_psql(
247+
'postgres', qq(
248+
DROP TABLE IF EXISTS $relname;
249+
CREATE TABLE $relname (a text[]);
250+
INSERT INTO $relname (a) select ('{aaaaa}') from generate_series(1,10000);
251+
CREATE INDEX $indexname ON $relname USING gin (a);
252+
));
253+
my $relpath = relation_filepath($indexname);
254+
255+
$node->stop;
256+
257+
my $blkno = 2; # posting tree root
258+
259+
# we have a posting tree for 'aaaaa' key with the root at 2nd block
260+
# and two leaf pages 3 and 4. replace 4th page's high key with (1,1)
261+
# so that there are tid's in leaf page that are larger then the new high key.
262+
my $find = pack('S*', 0, 4, 0) . '....';
263+
my $replace = pack('S*', 0, 4, 0, 1, 1);
264+
string_replace_block(
265+
$relpath,
266+
$find,
267+
$replace,
268+
$blkno
269+
);
270+
271+
$node->start;
272+
273+
my ($result, $stdout, $stderr) = $node->psql('postgres', qq(SELECT gin_index_check('$indexname')));
274+
my $expected = "index \"$indexname\": tid exceeds parent's high key in postingTree leaf on block 4";
275+
like($stderr, qr/$expected/);
276+
}
277+
278+
240279
# Returns the filesystem path for the named relation.
241280
sub relation_filepath
242281
{

contrib/amcheck/verify_gin.c

Lines changed: 4 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -345,7 +345,7 @@ gin_check_posting_tree_parent_keys_consistency(Relation rel, BlockNumber posting
345345
* Check if this tuple is consistent with the downlink in the
346346
* parent.
347347
*/
348-
if (stack->parentblk != InvalidBlockNumber && i == maxoff &&
348+
if (i == maxoff && ItemPointerIsValid(&stack->parentkey) &&
349349
ItemPointerCompare(&stack->parentkey, &posting_item->key) < 0)
350350
ereport(ERROR,
351351
(errcode(ERRCODE_INDEX_CORRUPTED),
@@ -358,14 +358,10 @@ gin_check_posting_tree_parent_keys_consistency(Relation rel, BlockNumber posting
358358
ptr->depth = stack->depth + 1;
359359

360360
/*
361-
* Set rightmost parent key to invalid item pointer. Its value
362-
* is 'Infinity' and not explicitly stored.
361+
* The rightmost parent key is always invalid item pointer.
362+
* Its value is 'Infinity' and not explicitly stored.
363363
*/
364-
if (rightlink == InvalidBlockNumber)
365-
ItemPointerSetInvalid(&ptr->parentkey);
366-
else
367-
ptr->parentkey = posting_item->key;
368-
364+
ptr->parentkey = posting_item->key;
369365
ptr->parentblk = stack->blkno;
370366
ptr->blkno = BlockIdGetBlockNumber(&posting_item->child_blkno);
371367
ptr->next = stack->next;

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy