mirror of
https://github.com/postgres/postgres.git
synced 2025-06-26 12:21:12 +03:00
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
This commit is contained in:
@ -601,7 +601,7 @@ ReadControlFile(void)
|
|||||||
fprintf(stderr,
|
fprintf(stderr,
|
||||||
_("%s: pg_control specifies invalid WAL segment size (%d bytes); proceed with caution \n"),
|
_("%s: pg_control specifies invalid WAL segment size (%d bytes); proceed with caution \n"),
|
||||||
progname, WalSegSz);
|
progname, WalSegSz);
|
||||||
guessed = true;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
@ -678,7 +678,7 @@ GuessControlValues(void)
|
|||||||
ControlFile.floatFormat = FLOATFORMAT_VALUE;
|
ControlFile.floatFormat = FLOATFORMAT_VALUE;
|
||||||
ControlFile.blcksz = BLCKSZ;
|
ControlFile.blcksz = BLCKSZ;
|
||||||
ControlFile.relseg_size = RELSEG_SIZE;
|
ControlFile.relseg_size = RELSEG_SIZE;
|
||||||
ControlFile.xlog_blcksz = XLOG_BLCKSZ;
|
WalSegSz = ControlFile.xlog_blcksz = XLOG_BLCKSZ;
|
||||||
ControlFile.xlog_seg_size = DEFAULT_XLOG_SEG_SIZE;
|
ControlFile.xlog_seg_size = DEFAULT_XLOG_SEG_SIZE;
|
||||||
ControlFile.nameDataLen = NAMEDATALEN;
|
ControlFile.nameDataLen = NAMEDATALEN;
|
||||||
ControlFile.indexMaxKeys = INDEX_MAX_KEYS;
|
ControlFile.indexMaxKeys = INDEX_MAX_KEYS;
|
||||||
|
47
src/bin/pg_resetwal/t/002_corrupted.pl
Normal file
47
src/bin/pg_resetwal/t/002_corrupted.pl
Normal file
@ -0,0 +1,47 @@
|
|||||||
|
# Tests for handling a corrupted pg_control
|
||||||
|
|
||||||
|
use strict;
|
||||||
|
use warnings;
|
||||||
|
|
||||||
|
use PostgresNode;
|
||||||
|
use TestLib;
|
||||||
|
use Test::More tests => 6;
|
||||||
|
|
||||||
|
my $node = get_new_node('main');
|
||||||
|
$node->init;
|
||||||
|
|
||||||
|
my $pg_control = $node->data_dir . '/global/pg_control';
|
||||||
|
my $size = (stat($pg_control))[7];
|
||||||
|
|
||||||
|
# Read out the head of the file to get PG_CONTROL_VERSION in
|
||||||
|
# particular.
|
||||||
|
my $data;
|
||||||
|
open my $fh, '<', $pg_control or BAIL_OUT($!);
|
||||||
|
binmode $fh;
|
||||||
|
read $fh, $data, 16;
|
||||||
|
close $fh;
|
||||||
|
|
||||||
|
# Fill pg_control with zeros
|
||||||
|
open $fh, '>', $pg_control or BAIL_OUT($!);
|
||||||
|
binmode $fh;
|
||||||
|
print $fh pack("x[$size]");
|
||||||
|
close $fh;
|
||||||
|
|
||||||
|
command_checks_all([ 'pg_resetwal', '-n', $node->data_dir ],
|
||||||
|
0,
|
||||||
|
[ qr/pg_control version number/ ],
|
||||||
|
[ qr/pg_resetwal: pg_control exists but is broken or wrong version; ignoring it/ ],
|
||||||
|
'processes corrupted pg_control all zeroes');
|
||||||
|
|
||||||
|
# Put in the previously saved header data. This uses a different code
|
||||||
|
# path internally, allowing us to process a zero WAL segment size.
|
||||||
|
open $fh, '>', $pg_control or BAIL_OUT($!);
|
||||||
|
binmode $fh;
|
||||||
|
print $fh $data, pack("x[" . ($size - 16) . "]");
|
||||||
|
close $fh;
|
||||||
|
|
||||||
|
command_checks_all([ 'pg_resetwal', '-n', $node->data_dir ],
|
||||||
|
0,
|
||||||
|
[ qr/pg_control version number/ ],
|
||||||
|
[ qr/\Qpg_resetwal: pg_control specifies invalid WAL segment size (0 bytes); proceed with caution\E/ ],
|
||||||
|
'processes zero WAL segment size');
|
Reference in New Issue
Block a user