Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commitd55241a

Browse files
committed
Use whitelist to choose files scanned with pg_verify_checksums
The original implementation of pg_verify_checksums used a blacklist todecide which files should be skipped for scanning as they do not includedata checksums, like pg_internal.init or pg_control. However, thismissed two things:- Some files are created within builds of EXEC_BACKEND and these werenot listed, causing failures on Windows.- Extensions may create custom files in data folders, causing the toolto equally fail.This commit switches to a whitelist-like method instead by checking ifthe files to scan are authorized relation files. This is close to areverse-engineering of what is defined in relpath.c in charge ofbuilding the relation paths, and we could consider refactoring what thispatch does so as all routines are in a single place. This is left forlater.This is based on a suggestion from Andres Freund. TAP tests are updatedso as multiple file patterns are tested. The bug has been spotted byvarious buildfarm members as a result ofb34e84f which has introducedthe TAP tests of pg_verify_checksums.Author: Michael PaquierReviewed-by: Andrew Dunstan, Michael BanckDiscussion:https://postgr.es/m/20181012005614.GC26424@paquier.xyzBackpatch-through: 11
1 parent350410b commitd55241a

File tree

2 files changed

+116
-19
lines changed

2 files changed

+116
-19
lines changed

‎src/bin/pg_verify_checksums/pg_verify_checksums.c

Lines changed: 61 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515

1616
#include"catalog/pg_control.h"
1717
#include"common/controldata_utils.h"
18+
#include"common/relpath.h"
1819
#include"getopt_long.h"
1920
#include"pg_getopt.h"
2021
#include"storage/bufpage.h"
@@ -49,27 +50,69 @@ usage(void)
4950
printf(_("Report bugs to <pgsql-bugs@postgresql.org>.\n"));
5051
}
5152

52-
staticconstchar*constskip[]= {
53-
"pg_control",
54-
"pg_filenode.map",
55-
"pg_internal.init",
56-
"PG_VERSION",
57-
NULL,
58-
};
59-
53+
/*
54+
* isRelFileName
55+
*
56+
* Check if the given file name is authorized for checksum verification.
57+
*/
6058
staticbool
61-
skipfile(constchar*fn)
59+
isRelFileName(constchar*fn)
6260
{
63-
constchar*const*f;
64-
65-
if (strcmp(fn,".")==0||
66-
strcmp(fn,"..")==0)
61+
intpos;
62+
63+
/*----------
64+
* Only files including data checksums are authorized for verification.
65+
* This is guessed based on the file name by reverse-engineering
66+
* GetRelationPath() so make sure to update both code paths if any
67+
* updates are done. The following file name formats are allowed:
68+
* <digits>
69+
* <digits>.<segment>
70+
* <digits>_<forkname>
71+
* <digits>_<forkname>.<segment>
72+
*
73+
* Note that temporary files, beginning with 't', are also skipped.
74+
*
75+
*----------
76+
*/
77+
78+
/* A non-empty string of digits should follow */
79+
for (pos=0;isdigit((unsignedchar)fn[pos]);++pos)
80+
;
81+
/* leave if no digits */
82+
if (pos==0)
83+
return false;
84+
/* good to go if only digits */
85+
if (fn[pos]=='\0')
6786
return true;
6887

69-
for (f=skip;*f;f++)
70-
if (strcmp(*f,fn)==0)
71-
return true;
72-
return false;
88+
/* Authorized fork files can be scanned */
89+
if (fn[pos]=='_')
90+
{
91+
intforkchar=forkname_chars(&fn[pos+1],NULL);
92+
93+
if (forkchar <=0)
94+
return false;
95+
96+
pos+=forkchar+1;
97+
}
98+
99+
/* Check for an optional segment number */
100+
if (fn[pos]=='.')
101+
{
102+
intsegchar;
103+
104+
for (segchar=1;isdigit((unsignedchar)fn[pos+segchar]);++segchar)
105+
;
106+
107+
if (segchar <=1)
108+
return false;
109+
pos+=segchar;
110+
}
111+
112+
/* Now this should be the end */
113+
if (fn[pos]!='\0')
114+
return false;
115+
return true;
73116
}
74117

75118
staticvoid
@@ -146,7 +189,7 @@ scan_directory(const char *basedir, const char *subdir)
146189
charfn[MAXPGPATH];
147190
structstatst;
148191

149-
if (skipfile(de->d_name))
192+
if (!isRelFileName(de->d_name))
150193
continue;
151194

152195
snprintf(fn,sizeof(fn),"%s/%s",path,de->d_name);

‎src/bin/pg_verify_checksums/t/002_actions.pl

Lines changed: 55 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
use warnings;
66
use PostgresNode;
77
use TestLib;
8-
use Test::Moretests=>12;
8+
use Test::Moretests=>36;
99

1010
# Initialize node with checksums enabled.
1111
my$node = get_new_node('node_checksum');
@@ -17,6 +17,31 @@
1717
qr/Data page checksum version:.*1/,
1818
'checksums enabled in control file');
1919

20+
# Add set of dummy files with some contents. These should not be scanned
21+
# by the tool.
22+
append_to_file"$pgdata/global/123.","foo";
23+
append_to_file"$pgdata/global/123_","foo";
24+
append_to_file"$pgdata/global/123_.","foo";
25+
append_to_file"$pgdata/global/123.12t","foo";
26+
append_to_file"$pgdata/global/foo","foo2";
27+
append_to_file"$pgdata/global/t123","bar";
28+
append_to_file"$pgdata/global/123a","bar2";
29+
append_to_file"$pgdata/global/.123","foobar";
30+
append_to_file"$pgdata/global/_fsm","foobar2";
31+
append_to_file"$pgdata/global/_init","foobar3";
32+
append_to_file"$pgdata/global/_vm.123","foohoge";
33+
append_to_file"$pgdata/global/123_vm.123t","foohoge2";
34+
35+
# Those are correct but empty files, so they should pass through.
36+
append_to_file"$pgdata/global/99999","";
37+
append_to_file"$pgdata/global/99999.123","";
38+
append_to_file"$pgdata/global/99999_fsm","";
39+
append_to_file"$pgdata/global/99999_init","";
40+
append_to_file"$pgdata/global/99999_vm","";
41+
append_to_file"$pgdata/global/99999_init.123","";
42+
append_to_file"$pgdata/global/99999_fsm.123","";
43+
append_to_file"$pgdata/global/99999_vm.123","";
44+
2045
# Checksums pass on a newly-created cluster
2146
command_ok(['pg_verify_checksums','-D',$pgdata],
2247
"succeeds with offline cluster");
@@ -67,3 +92,32 @@
6792
[qr/Bad checksums:.*1/],
6893
[qr/checksum verification failed/],
6994
'fails for corrupted data on single relfilenode');
95+
96+
# Utility routine to check that pg_verify_checksums is able to detect
97+
# correctly-named relation files filled with some corrupted data.
98+
subfail_corrupt
99+
{
100+
my$node =shift;
101+
my$file =shift;
102+
my$pgdata =$node->data_dir;
103+
104+
# Create the file with some dummy data in it.
105+
append_to_file"$pgdata/global/$file","foo";
106+
107+
$node->command_checks_all(['pg_verify_checksums','-D',$pgdata],
108+
1,
109+
[qr/^$/],
110+
[qr/could not read block/],
111+
"fails for corrupted data in$file");
112+
}
113+
114+
# Authorized relation files filled with corrupted data cause the
115+
# checksum checks to fail.
116+
fail_corrupt($node,"99999");
117+
fail_corrupt($node,"99999.123");
118+
fail_corrupt($node,"99999_fsm");
119+
fail_corrupt($node,"99999_init");
120+
fail_corrupt($node,"99999_vm");
121+
fail_corrupt($node,"99999_init.123");
122+
fail_corrupt($node,"99999_fsm.123");
123+
fail_corrupt($node,"99999_vm.123");

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp