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

Commit84c5e0d

Browse files
committed
Fix pg_restore's misdesigned code for detecting archive file format.
Despite the clear comments pointing out that the duplicative codesegments in ReadHead() and _discoverArchiveFormat() needed to bein sync, they were not: the latter did not bother to apply any ofthe sanity checks in the former. We'd missed noticing this partlybecause none of those checks would fail in scenarios we customarilytest, and partly because the oversight would be masked if bothsegments execute, which they would in cases other than needing toautodetect the format of a non-seekable stdin source. However,in a case meeting all these requirements --- for example, tryingto read a newer-than-supported archive format from non-seekablestdin --- pg_restore missed applying the version check and wouldlikely dump core or otherwise misbehave.The whole thing is silly anyway, because there seems little reasonto duplicate the logic beyond the one-line verification that thefile starts with "PGDMP". There seems to have been an undocumentedassumption that multiple major formats (major enough to requireseparate reader modules) would nonetheless share the first half-dozenfields of the custom-format header. This seems unlikely, so let'sfix it by just nuking the duplicate logic in _discoverArchiveFormat().Also get rid of the pointless attempt to seek back to the start ofthe file after successful autodetection. That wastes cycles andit means we have four behaviors to verify not two.Per bug #16951 from Sergey Koposov. This has been broken fordecades, so back-patch to all supported versions.Discussion:https://postgr.es/m/16951-a4dd68cf0de23048@postgresql.org
1 parenta126a95 commit84c5e0d

File tree

3 files changed

+51
-110
lines changed

3 files changed

+51
-110
lines changed

‎src/bin/pg_dump/pg_backup_archiver.c

Lines changed: 39 additions & 98 deletions
Original file line numberDiff line numberDiff line change
@@ -2086,6 +2086,7 @@ _discoverArchiveFormat(ArchiveHandle *AH)
20862086
if (AH->lookahead)
20872087
free(AH->lookahead);
20882088

2089+
AH->readHeader=0;
20892090
AH->lookaheadSize=512;
20902091
AH->lookahead=pg_malloc0(512);
20912092
AH->lookaheadLen=0;
@@ -2157,62 +2158,9 @@ _discoverArchiveFormat(ArchiveHandle *AH)
21572158

21582159
if (strncmp(sig,"PGDMP",5)==0)
21592160
{
2160-
intbyteread;
2161-
charvmaj,
2162-
vmin,
2163-
vrev;
2164-
2165-
/*
2166-
* Finish reading (most of) a custom-format header.
2167-
*
2168-
* NB: this code must agree with ReadHead().
2169-
*/
2170-
if ((byteread=fgetc(fh))==EOF)
2171-
READ_ERROR_EXIT(fh);
2172-
2173-
vmaj=byteread;
2174-
2175-
if ((byteread=fgetc(fh))==EOF)
2176-
READ_ERROR_EXIT(fh);
2177-
2178-
vmin=byteread;
2179-
2180-
/* Save these too... */
2181-
AH->lookahead[AH->lookaheadLen++]=vmaj;
2182-
AH->lookahead[AH->lookaheadLen++]=vmin;
2183-
2184-
/* Check header version; varies from V1.0 */
2185-
if (vmaj>1|| (vmaj==1&&vmin>0))/* Version > 1.0 */
2186-
{
2187-
if ((byteread=fgetc(fh))==EOF)
2188-
READ_ERROR_EXIT(fh);
2189-
2190-
vrev=byteread;
2191-
AH->lookahead[AH->lookaheadLen++]=vrev;
2192-
}
2193-
else
2194-
vrev=0;
2195-
2196-
AH->version=MAKE_ARCHIVE_VERSION(vmaj,vmin,vrev);
2197-
2198-
if ((AH->intSize=fgetc(fh))==EOF)
2199-
READ_ERROR_EXIT(fh);
2200-
AH->lookahead[AH->lookaheadLen++]=AH->intSize;
2201-
2202-
if (AH->version >=K_VERS_1_7)
2203-
{
2204-
if ((AH->offSize=fgetc(fh))==EOF)
2205-
READ_ERROR_EXIT(fh);
2206-
AH->lookahead[AH->lookaheadLen++]=AH->offSize;
2207-
}
2208-
else
2209-
AH->offSize=AH->intSize;
2210-
2211-
if ((byteread=fgetc(fh))==EOF)
2212-
READ_ERROR_EXIT(fh);
2213-
2214-
AH->format=byteread;
2215-
AH->lookahead[AH->lookaheadLen++]=AH->format;
2161+
/* It's custom format, stop here */
2162+
AH->format=archCustom;
2163+
AH->readHeader=1;
22162164
}
22172165
else
22182166
{
@@ -2249,22 +2197,15 @@ _discoverArchiveFormat(ArchiveHandle *AH)
22492197
AH->format=archTar;
22502198
}
22512199

2252-
/* If we can't seek, then mark the header as read */
2253-
if (fseeko(fh,0,SEEK_SET)!=0)
2254-
{
2255-
/*
2256-
* NOTE: Formats that use the lookahead buffer can unset this in their
2257-
* Init routine.
2258-
*/
2259-
AH->readHeader=1;
2260-
}
2261-
else
2262-
AH->lookaheadLen=0;/* Don't bother since we've reset the file */
2263-
2264-
/* Close the file */
2200+
/* Close the file if we opened it */
22652201
if (wantClose)
2202+
{
22662203
if (fclose(fh)!=0)
22672204
fatal("could not close input file: %m");
2205+
/* Forget lookahead, since we'll re-read header after re-opening */
2206+
AH->readHeader=0;
2207+
AH->lookaheadLen=0;
2208+
}
22682209

22692210
returnAH->format;
22702211
}
@@ -3773,7 +3714,9 @@ WriteHead(ArchiveHandle *AH)
37733714
void
37743715
ReadHead(ArchiveHandle*AH)
37753716
{
3776-
chartmpMag[7];
3717+
charvmaj,
3718+
vmin,
3719+
vrev;
37773720
intfmt;
37783721
structtmcrtm;
37793722

@@ -3785,48 +3728,46 @@ ReadHead(ArchiveHandle *AH)
37853728
*/
37863729
if (!AH->readHeader)
37873730
{
3788-
charvmaj,
3789-
vmin,
3790-
vrev;
3731+
chartmpMag[7];
37913732

37923733
AH->ReadBufPtr(AH,tmpMag,5);
37933734

37943735
if (strncmp(tmpMag,"PGDMP",5)!=0)
37953736
fatal("did not find magic string in file header");
3737+
}
37963738

3797-
vmaj=AH->ReadBytePtr(AH);
3798-
vmin=AH->ReadBytePtr(AH);
3739+
vmaj=AH->ReadBytePtr(AH);
3740+
vmin=AH->ReadBytePtr(AH);
37993741

3800-
if (vmaj>1|| (vmaj==1&&vmin>0))/* Version > 1.0 */
3801-
vrev=AH->ReadBytePtr(AH);
3802-
else
3803-
vrev=0;
3742+
if (vmaj>1|| (vmaj==1&&vmin>0))/* Version > 1.0 */
3743+
vrev=AH->ReadBytePtr(AH);
3744+
else
3745+
vrev=0;
38043746

3805-
AH->version=MAKE_ARCHIVE_VERSION(vmaj,vmin,vrev);
3747+
AH->version=MAKE_ARCHIVE_VERSION(vmaj,vmin,vrev);
38063748

3807-
if (AH->version<K_VERS_1_0||AH->version>K_VERS_MAX)
3808-
fatal("unsupported version (%d.%d) in file header",
3809-
vmaj,vmin);
3749+
if (AH->version<K_VERS_1_0||AH->version>K_VERS_MAX)
3750+
fatal("unsupported version (%d.%d) in file header",
3751+
vmaj,vmin);
38103752

3811-
AH->intSize=AH->ReadBytePtr(AH);
3812-
if (AH->intSize>32)
3813-
fatal("sanity check on integer size (%lu) failed",
3814-
(unsigned long)AH->intSize);
3753+
AH->intSize=AH->ReadBytePtr(AH);
3754+
if (AH->intSize>32)
3755+
fatal("sanity check on integer size (%lu) failed",
3756+
(unsigned long)AH->intSize);
38153757

3816-
if (AH->intSize>sizeof(int))
3817-
pg_log_warning("archive was made on a machine with larger integers, some operations might fail");
3758+
if (AH->intSize>sizeof(int))
3759+
pg_log_warning("archive was made on a machine with larger integers, some operations might fail");
38183760

3819-
if (AH->version >=K_VERS_1_7)
3820-
AH->offSize=AH->ReadBytePtr(AH);
3821-
else
3822-
AH->offSize=AH->intSize;
3761+
if (AH->version >=K_VERS_1_7)
3762+
AH->offSize=AH->ReadBytePtr(AH);
3763+
else
3764+
AH->offSize=AH->intSize;
38233765

3824-
fmt=AH->ReadBytePtr(AH);
3766+
fmt=AH->ReadBytePtr(AH);
38253767

3826-
if (AH->format!=fmt)
3827-
fatal("expected format (%d) differs from format found in file (%d)",
3828-
AH->format,fmt);
3829-
}
3768+
if (AH->format!=fmt)
3769+
fatal("expected format (%d) differs from format found in file (%d)",
3770+
AH->format,fmt);
38303771

38313772
if (AH->version >=K_VERS_1_2)
38323773
{

‎src/bin/pg_dump/pg_backup_archiver.h

Lines changed: 12 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -258,15 +258,21 @@ struct _archiveHandle
258258
time_tcreateDate;/* Date archive created */
259259

260260
/*
261-
* Fields used when discovering header. A format can always get the
262-
* previous read bytes from here...
261+
* Fields used when discovering archive format. For tar format, we load
262+
* the first block into the lookahead buffer, and verify that it looks
263+
* like a tar header. The tar module must then consume bytes from the
264+
* lookahead buffer before reading any more from the file. For custom
265+
* format, we load only the "PGDMP" marker into the buffer, and then set
266+
* readHeader after confirming it matches. The buffer is vestigial in
267+
* this case, as the subsequent code just checks readHeader and doesn't
268+
* examine the buffer.
263269
*/
264-
intreadHeader;/*Used iffile header has beenreadalready */
270+
intreadHeader;/*Set ifwe alreadyread"PGDMP" marker */
265271
char*lookahead;/* Buffer used when reading header to discover
266272
* format */
267-
size_tlookaheadSize;/*Size of allocated buffer */
268-
size_tlookaheadLen;/* Length of data in lookahead */
269-
pgoff_tlookaheadPos;/* Current read position in lookahead buffer */
273+
size_tlookaheadSize;/*Allocated size of buffer */
274+
size_tlookaheadLen;/* Length ofvaliddata in lookahead */
275+
size_tlookaheadPos;/* Current read position in lookahead buffer */
270276

271277
ArchiveEntryPtrTypeArchiveEntryPtr;/* Called for each metadata object */
272278
StartDataPtrTypeStartDataPtr;/* Called when table data is about to be

‎src/bin/pg_dump/pg_backup_tar.c

Lines changed: 0 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -228,12 +228,6 @@ InitArchiveFmt_Tar(ArchiveHandle *AH)
228228

229229
ctx->hasSeek=checkSeek(ctx->tarFH);
230230

231-
/*
232-
* Forcibly unmark the header as read since we use the lookahead
233-
* buffer
234-
*/
235-
AH->readHeader=0;
236-
237231
ctx->FH= (void*)tarOpen(AH,"toc.dat",'r');
238232
ReadHead(AH);
239233
ReadToc(AH);

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp