Skip to content

Commit 12bf118

Browse files
committed
Handle close() failures more robustly in pg_dump and pg_basebackup.
Coverity complained that applying get_gz_error after a failed gzclose, as we did in one place in pg_basebackup, is unsafe. I think it's right: it's entirely likely that the call is touching freed memory. Change that to inspect errno, as we do for other gzclose calls. Also, be careful to initialize errno to zero immediately before any gzclose() call where we care about the error status. (There are some calls where we don't, because we already failed at some previous step.) This ensures that we don't get a misleadingly irrelevant error code if gzclose() fails in a way that doesn't set errno. We could work harder at that, but it looks to me like all such cases are basically can't-happen if we're not misusing zlib, so it's not worth the extra notational cruft that would be required. Also, fix several places that simply failed to check for close-time errors at all, mostly at some remove from the close or gzclose itself; and one place that did check but didn't bother to report the errno. Back-patch to v12. These mistakes are older than that, but between the frontend logging API changes that happened in v12 and the fact that frontend code can't rely on %m before that, the patch would need substantial revision to work in older branches. It doesn't quite seem worth the trouble given the lack of related field complaints. Patch by me; thanks to Michael Paquier for review. Discussion: https://postgr.es/m/1343113.1636489231@sss.pgh.pa.us
1 parent 02bf176 commit 12bf118

File tree

6 files changed

+24
-7
lines changed

6 files changed

+24
-7
lines changed

src/bin/pg_basebackup/pg_basebackup.c

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1160,10 +1160,11 @@ ReceiveTarFile(PGconn *conn, PGresult *res, int rownum)
11601160
#ifdef HAVE_LIBZ
11611161
if (ztarfile != NULL)
11621162
{
1163+
errno = 0; /* in case gzclose() doesn't set it */
11631164
if (gzclose(ztarfile) != 0)
11641165
{
1165-
pg_log_error("could not close compressed file \"%s\": %s",
1166-
filename, get_gz_error(ztarfile));
1166+
pg_log_error("could not close compressed file \"%s\": %m",
1167+
filename);
11671168
exit(1);
11681169
}
11691170
}

src/bin/pg_basebackup/receivelog.c

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -74,7 +74,12 @@ mark_file_as_archived(StreamCtl *stream, const char *fname)
7474
return false;
7575
}
7676

77-
stream->walmethod->close(f, CLOSE_NORMAL);
77+
if (stream->walmethod->close(f, CLOSE_NORMAL) != 0)
78+
{
79+
pg_log_error("could not close archive status file \"%s\": %s",
80+
tmppath, stream->walmethod->getlasterror());
81+
return false;
82+
}
7883

7984
return true;
8085
}

src/bin/pg_basebackup/walmethods.c

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -236,7 +236,10 @@ dir_close(Walfile f, WalCloseMethod method)
236236

237237
#ifdef HAVE_LIBZ
238238
if (dir_data->compression > 0)
239+
{
240+
errno = 0; /* in case gzclose() doesn't set it */
239241
r = gzclose(df->gzfp);
242+
}
240243
else
241244
#endif
242245
r = close(df->fd);

src/bin/pg_dump/pg_backup_archiver.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -269,6 +269,7 @@ CloseArchive(Archive *AHX)
269269
AH->ClosePtr(AH);
270270

271271
/* Close the output */
272+
errno = 0; /* in case gzclose() doesn't set it */
272273
if (AH->gzOut)
273274
res = GZCLOSE(AH->OF);
274275
else if (AH->OF != stdout)
@@ -1582,6 +1583,7 @@ RestoreOutput(ArchiveHandle *AH, OutputContext savedContext)
15821583
{
15831584
int res;
15841585

1586+
errno = 0; /* in case gzclose() doesn't set it */
15851587
if (AH->gzOut)
15861588
res = GZCLOSE(AH->OF);
15871589
else

src/bin/pg_dump/pg_backup_directory.c

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -371,7 +371,8 @@ _EndData(ArchiveHandle *AH, TocEntry *te)
371371
lclContext *ctx = (lclContext *) AH->formatData;
372372

373373
/* Close the file */
374-
cfclose(ctx->dataFH);
374+
if (cfclose(ctx->dataFH) != 0)
375+
fatal("could not close data file: %m");
375376

376377
ctx->dataFH = NULL;
377378
}
@@ -686,7 +687,8 @@ _EndBlob(ArchiveHandle *AH, TocEntry *te, Oid oid)
686687
int len;
687688

688689
/* Close the BLOB data file itself */
689-
cfclose(ctx->dataFH);
690+
if (cfclose(ctx->dataFH) != 0)
691+
fatal("could not close blob data file: %m");
690692
ctx->dataFH = NULL;
691693

692694
/* register the blob in blobs.toc */
@@ -705,7 +707,8 @@ _EndBlobs(ArchiveHandle *AH, TocEntry *te)
705707
{
706708
lclContext *ctx = (lclContext *) AH->formatData;
707709

708-
cfclose(ctx->blobsTocFH);
710+
if (cfclose(ctx->blobsTocFH) != 0)
711+
fatal("could not close blobs TOC file: %m");
709712
ctx->blobsTocFH = NULL;
710713
}
711714

src/bin/pg_dump/pg_backup_tar.c

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -438,8 +438,11 @@ tarClose(ArchiveHandle *AH, TAR_MEMBER *th)
438438
* Close the GZ file since we dup'd. This will flush the buffers.
439439
*/
440440
if (AH->compression != 0)
441+
{
442+
errno = 0; /* in case gzclose() doesn't set it */
441443
if (GZCLOSE(th->zFH) != 0)
442-
fatal("could not close tar member");
444+
fatal("could not close tar member: %m");
445+
}
443446

444447
if (th->mode == 'w')
445448
_tarAddFile(AH, th); /* This will close the temp file */

0 commit comments

Comments
 (0)