From cd3534caf75aeb8397c7754a26a8e3722508bbd2 Mon Sep 17 00:00:00 2001
From: Mark Dilger <mark.dilger@enterprisedb.com>
Date: Thu, 8 Apr 2021 10:24:40 -0700
Subject: [PATCH v19 3/3] amcheck: additional regression test coverage

Adding regression checks for two corruption checks added in prior
commit.  We now verify that corruption reports are generated when we
set a toast pointer's va_toastrelid to the wrong Oid or set a toast
pointer's va_rawsize to an overlarge value.
---
 src/bin/pg_amcheck/t/004_verify_heapam.pl | 31 ++++++++++++++++++++---
 1 file changed, 28 insertions(+), 3 deletions(-)

diff --git a/src/bin/pg_amcheck/t/004_verify_heapam.pl b/src/bin/pg_amcheck/t/004_verify_heapam.pl
index 307f14611c..e64801c7e1 100644
--- a/src/bin/pg_amcheck/t/004_verify_heapam.pl
+++ b/src/bin/pg_amcheck/t/004_verify_heapam.pl
@@ -224,7 +224,7 @@ my $rel = $node->safe_psql('postgres', qq(SELECT pg_relation_filepath('public.te
 my $relpath = "$pgdata/$rel";
 
 # Insert data and freeze public.test
-use constant ROWCOUNT => 16;
+use constant ROWCOUNT => 18;
 $node->safe_psql('postgres', qq(
 	INSERT INTO public.test (a, b, c)
 		VALUES (
@@ -240,6 +240,13 @@ my $relfrozenxid = $node->safe_psql('postgres',
 my $datfrozenxid = $node->safe_psql('postgres',
 	q(select datfrozenxid from pg_database where datname = 'postgres'));
 
+# Find our toast relation id
+my $toastrelid = $node->safe_psql('postgres', qq(
+	SELECT c.reltoastrelid
+		FROM pg_catalog.pg_class c
+		WHERE c.oid = 'public.test'::regclass
+		));
+
 # Sanity check that our 'test' table has a relfrozenxid newer than the
 # datfrozenxid for the database, and that the datfrozenxid is greater than the
 # first normal xid.  We rely on these invariants in some of our tests.
@@ -296,7 +303,7 @@ close($file)
 $node->start;
 
 # Ok, Xids and page layout look ok.  We can run corruption tests.
-plan tests => 19;
+plan tests => 22;
 
 # Check that pg_amcheck runs against the uncorrupted table without error.
 $node->command_ok(['pg_amcheck', '-p', $port, 'postgres'],
@@ -501,7 +508,7 @@ for (my $tupidx = 0; $tupidx < ROWCOUNT; $tupidx++)
 		push @expected,
 			qr/${header}multitransaction ID 4 equals or exceeds next valid multitransaction ID 1/;
 	}
-	elsif ($offnum == 15)	# Last offnum must equal ROWCOUNT
+	elsif ($offnum == 15)
 	{
 		# Set both HEAP_XMAX_COMMITTED and HEAP_XMAX_IS_MULTI
 		$tup->{t_infomask} |= HEAP_XMAX_COMMITTED;
@@ -511,6 +518,24 @@ for (my $tupidx = 0; $tupidx < ROWCOUNT; $tupidx++)
 		push @expected,
 			qr/${header}multitransaction ID 4000000000 precedes relation minimum multitransaction ID threshold 1/;
 	}
+	elsif ($offnum == 16)
+	{
+		# Corrupt column c's toast pointer va_toastrelid field
+		my $otherid = $toastrelid + 1;
+		$tup->{c_va_toastrelid} = $otherid;
+		$header = header(0, $offnum, 2);
+		push @expected,
+			qr/${header}toast value \d+ toast relation oid $otherid differs from expected oid $toastrelid/;
+	}
+	elsif ($offnum == 17)	# Last offnum should equal ROWCOUNT-1
+	{
+		# Corrupt column c's toast pointer va_rawsize field with a value
+		# exceeding maximum allowable allocation size
+		$tup->{c_va_rawsize} = 0x40000000;
+		$header = header(0, $offnum, 2);
+		push @expected,
+			qr/${header}toast value \d+ rawsize 1073741824 exceeds limit 1073741823/;
+	}
 	write_tuple($file, $offset, $tup);
 }
 close($file)
-- 
2.21.1 (Apple Git-122.3)

