Location via proxy:   [ UP ]  
[Report a bug]   [Manage cookies]                
Skip to content

Commit f1a074b

Browse files
committed
pg_resetwal: Prevent division-by-zero errors
Handle the case where the pg_control file specifies a WAL segment size of 0 bytes. This would previously have led to a division by zero error. Change this to assume the whole file is corrupt and go to guess everything. Discussion: https://www.postgresql.org/message-id/a6163ad7-cc99-fdd1-dfad-25df73032ab8%402ndquadrant.com
1 parent 86f5759 commit f1a074b

File tree

2 files changed

+49
-2
lines changed

2 files changed

+49
-2
lines changed

src/bin/pg_resetwal/pg_resetwal.c

+2-2
Original file line numberDiff line numberDiff line change
@@ -601,7 +601,7 @@ ReadControlFile(void)
601601
fprintf(stderr,
602602
_("%s: pg_control specifies invalid WAL segment size (%d bytes); proceed with caution \n"),
603603
progname, WalSegSz);
604-
guessed = true;
604+
return false;
605605
}
606606

607607
return true;
@@ -678,7 +678,7 @@ GuessControlValues(void)
678678
ControlFile.floatFormat = FLOATFORMAT_VALUE;
679679
ControlFile.blcksz = BLCKSZ;
680680
ControlFile.relseg_size = RELSEG_SIZE;
681-
ControlFile.xlog_blcksz = XLOG_BLCKSZ;
681+
WalSegSz = ControlFile.xlog_blcksz = XLOG_BLCKSZ;
682682
ControlFile.xlog_seg_size = DEFAULT_XLOG_SEG_SIZE;
683683
ControlFile.nameDataLen = NAMEDATALEN;
684684
ControlFile.indexMaxKeys = INDEX_MAX_KEYS;
+47
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
# Tests for handling a corrupted pg_control
2+
3+
use strict;
4+
use warnings;
5+
6+
use PostgresNode;
7+
use TestLib;
8+
use Test::More tests => 6;
9+
10+
my $node = get_new_node('main');
11+
$node->init;
12+
13+
my $pg_control = $node->data_dir . '/global/pg_control';
14+
my $size = (stat($pg_control))[7];
15+
16+
# Read out the head of the file to get PG_CONTROL_VERSION in
17+
# particular.
18+
my $data;
19+
open my $fh, '<', $pg_control or BAIL_OUT($!);
20+
binmode $fh;
21+
read $fh, $data, 16;
22+
close $fh;
23+
24+
# Fill pg_control with zeros
25+
open $fh, '>', $pg_control or BAIL_OUT($!);
26+
binmode $fh;
27+
print $fh pack("x[$size]");
28+
close $fh;
29+
30+
command_checks_all([ 'pg_resetwal', '-n', $node->data_dir ],
31+
0,
32+
[ qr/pg_control version number/ ],
33+
[ qr/pg_resetwal: pg_control exists but is broken or wrong version; ignoring it/ ],
34+
'processes corrupted pg_control all zeroes');
35+
36+
# Put in the previously saved header data. This uses a different code
37+
# path internally, allowing us to process a zero WAL segment size.
38+
open $fh, '>', $pg_control or BAIL_OUT($!);
39+
binmode $fh;
40+
print $fh $data, pack("x[" . ($size - 16) . "]");
41+
close $fh;
42+
43+
command_checks_all([ 'pg_resetwal', '-n', $node->data_dir ],
44+
0,
45+
[ qr/pg_control version number/ ],
46+
[ qr/\Qpg_resetwal: pg_control specifies invalid WAL segment size (0 bytes); proceed with caution\E/ ],
47+
'processes zero WAL segment size');

0 commit comments

Comments
 (0)