diff --git a/contrib/amcheck/t/001_verify_heapam.pl b/contrib/amcheck/t/001_verify_heapam.pl
index e7526c17b8..9d93ad197c 100644
--- a/contrib/amcheck/t/001_verify_heapam.pl
+++ b/contrib/amcheck/t/001_verify_heapam.pl
@@ -4,7 +4,7 @@ use warnings;
 use PostgresNode;
 use TestLib;
 
-use Test::More tests => 65;
+use Test::More tests => 55;
 
 my ($node, $result);
 
@@ -28,19 +28,19 @@ check_all_options_uncorrupted('test', 'plain');
 #
 fresh_test_table('test');
 corrupt_first_page('test');
-detects_corruption(
+detects_heap_corruption(
 	"verify_heapam('test')",
 	"plain corrupted table");
-detects_corruption(
+detects_heap_corruption(
 	"verify_heapam('test', skip := 'all-visible')",
 	"plain corrupted table skipping all-visible");
-detects_corruption(
+detects_heap_corruption(
 	"verify_heapam('test', skip := 'all-frozen')",
 	"plain corrupted table skipping all-frozen");
-detects_corruption(
+detects_heap_corruption(
 	"verify_heapam('test', check_toast := false)",
 	"plain corrupted table skipping toast");
-detects_corruption(
+detects_heap_corruption(
 	"verify_heapam('test', startblock := 0, endblock := 0)",
 	"plain corrupted table checking only block zero");
 
@@ -50,71 +50,13 @@ detects_corruption(
 fresh_test_table('test');
 $node->safe_psql('postgres', q(VACUUM FREEZE test));
 corrupt_first_page('test');
-detects_corruption(
+detects_heap_corruption(
 	"verify_heapam('test')",
 	"all-frozen corrupted table");
 detects_no_corruption(
 	"verify_heapam('test', skip := 'all-frozen')",
 	"all-frozen corrupted table skipping all-frozen");
 
-#
-# Check a corrupt table with corrupt page header
-#
-fresh_test_table('test');
-corrupt_first_page_and_header('test');
-detects_corruption(
-	"verify_heapam('test')",
-	"corrupted test table with bad page header");
-
-#
-# Check an uncorrupted table with corrupt toast page header
-#
-fresh_test_table('test');
-my $toast = get_toast_for('test');
-corrupt_first_page_and_header($toast);
-detects_corruption(
-	"verify_heapam('test', check_toast := true)",
-	"table with corrupted toast page header checking toast");
-detects_no_corruption(
-	"verify_heapam('test', check_toast := false)",
-	"table with corrupted toast page header skipping toast");
-detects_corruption(
-	"verify_heapam('$toast')",
-	"corrupted toast page header");
-
-#
-# Check an uncorrupted table with corrupt toast
-#
-fresh_test_table('test');
-$toast = get_toast_for('test');
-corrupt_first_page($toast);
-detects_corruption(
-	"verify_heapam('test', check_toast := true)",
-	"table with corrupted toast checking toast");
-detects_no_corruption(
-	"verify_heapam('test', check_toast := false)",
-	"table with corrupted toast skipping toast");
-detects_corruption(
-	"verify_heapam('$toast')",
-	"corrupted toast table");
-
-#
-# Check an uncorrupted all-frozen table with corrupt toast
-#
-fresh_test_table('test');
-$node->safe_psql('postgres', q(VACUUM FREEZE test));
-$toast = get_toast_for('test');
-corrupt_first_page($toast);
-detects_corruption(
-	"verify_heapam('test', check_toast := true)",
-	"all-frozen table with corrupted toast checking toast");
-detects_no_corruption(
-	"verify_heapam('test', check_toast := false)",
-	"all-frozen table with corrupted toast skipping toast");
-detects_corruption(
-	"verify_heapam('$toast')",
-	"corrupted toast table of all-frozen table");
-
 # Returns the filesystem path for the named relation.
 sub relation_filepath
 {
@@ -154,46 +96,43 @@ sub fresh_test_table
 
 # Stops the test node, corrupts the first page of the named relation, and
 # restarts the node.
-sub corrupt_first_page_internal
+sub corrupt_first_page
 {
-	my ($relname, $corrupt_header) = @_;
+	my ($relname) = @_;
 	my $relpath = relation_filepath($relname);
 
 	$node->stop;
 	my $fh;
-	open($fh, '+<', $relpath);
+	open($fh, '+<', $relpath)
+		or BAIL_OUT("open failed: $!");;
 	binmode $fh;
 
-	# If we corrupt the header, postgres won't allow the page into the buffer.
-	syswrite($fh, '\xFF\xFF\xFF\xFF', 8) if ($corrupt_header);
-
-	# Corrupt at least the line pointers.  Exactly what this corrupts will
-	# depend on the page, as it may run past the line pointers into the user
-	# data.  We stop short of writing 2048 bytes (2k), the smallest supported
-	# page size, as we don't want to corrupt the next page.
-	seek($fh, 32, 0);
-	syswrite($fh, '\x77\x77\x77\x77', 500);
-	close($fh);
+	# Corrupt the first two line pointers.  To be stable across platforms,
+	# we use 0x77777777 and 0xAAAAAAAA for the first two, which are bitwise
+	# reverses of each other.
+	seek($fh, 24, 0)
+		or BAIL_OUT("seek failed: $!");;
+	syswrite($fh, pack("L*", 0x77777777, 0xAAAAAAAA))
+		or BAIL_OUT("syswrite failed: $!");
+	close($fh)
+		or BAIL_OUT("close failed: $!");
 	$node->start;
 }
 
-sub corrupt_first_page
-{
-	corrupt_first_page_internal($_[0], undef);
-}
-
-sub corrupt_first_page_and_header
+sub detects_heap_corruption
 {
-	corrupt_first_page_internal($_[0], 1);
+	my ($function, $testname) = @_;
+	detects_corruption($function, $testname,
+		qr/line pointer redirection to item at offset \d+ exceeds maximum offset \d+/);
 }
 
 sub detects_corruption
 {
-	my ($function, $testname) = @_;
+	my ($function, $testname, $re) = @_;
 
 	my $result = $node->safe_psql('postgres',
-		qq(SELECT COUNT(*) > 0 FROM $function));
-	is($result, 't', $testname);
+		qq(SELECT * FROM $function));
+	like($result, $re, $testname);
 }
 
 sub detects_no_corruption
@@ -201,8 +140,8 @@ sub detects_no_corruption
 	my ($function, $testname) = @_;
 
 	my $result = $node->safe_psql('postgres',
-		qq(SELECT COUNT(*) = 0 FROM $function));
-	is($result, 't', $testname);
+		qq(SELECT * FROM $function));
+	is($result, '', $testname);
 }
 
 # Check various options are stable (don't abort) and do not report corruption
