From 59a3c0425960483f73b6c352268949a0c44b677a Mon Sep 17 00:00:00 2001 From: Jianghua Yang Date: Thu, 19 Mar 2026 09:06:31 -0700 Subject: [PATCH] Fix file descriptor leak when dup()+fdopen()/gzdopen() fails in pg_dump compression backends When fd >= 0, the compression open functions called fdopen(dup(fd), mode) or gzdopen(dup(fd), mode) directly. If dup() succeeded but fdopen()/gzdopen() failed, the duplicated file descriptor was leaked because POSIX specifies that fdopen() does not close the fd on failure. Fix by saving the dup() result in a local variable and explicitly calling close() on it if the subsequent wrapping call fails. Affected backends: compress_gzip.c, compress_lz4.c, compress_none.c, compress_zstd.c. The zstd fix also ensures pg_free(zstdcs) is called on all failure paths after the allocation. --- src/bin/pg_dump/compress_gzip.c | 20 ++++++++++++++++---- src/bin/pg_dump/compress_lz4.c | 27 ++++++++++++++++++++++----- src/bin/pg_dump/compress_none.c | 20 ++++++++++++++++---- src/bin/pg_dump/compress_zstd.c | 28 ++++++++++++++++++++++------ 4 files changed, 76 insertions(+), 19 deletions(-) diff --git a/src/bin/pg_dump/compress_gzip.c b/src/bin/pg_dump/compress_gzip.c index c9ce8a53aaa..60c553ba25a 100644 --- a/src/bin/pg_dump/compress_gzip.c +++ b/src/bin/pg_dump/compress_gzip.c @@ -386,12 +386,24 @@ Gzip_open(const char *path, int fd, const char *mode, CompressFileHandle *CFH) strcpy(mode_compression, mode); if (fd >= 0) - gzfp = gzdopen(dup(fd), mode_compression); + { + int dup_fd = dup(fd); + + if (dup_fd < 0) + return false; + gzfp = gzdopen(dup_fd, mode_compression); + if (gzfp == NULL) + { + close(dup_fd); + return false; + } + } else + { gzfp = gzopen(path, mode_compression); - - if (gzfp == NULL) - return false; + if (gzfp == NULL) + return false; + } CFH->private_data = gzfp; diff --git a/src/bin/pg_dump/compress_lz4.c b/src/bin/pg_dump/compress_lz4.c index 0aa519fbb67..0a7872116e7 100644 --- a/src/bin/pg_dump/compress_lz4.c +++ b/src/bin/pg_dump/compress_lz4.c @@ -715,13 +715,30 @@ LZ4Stream_open(const char *path, int fd, const char *mode, LZ4State *state = (LZ4State *) CFH->private_data; if (fd >= 0) - state->fp = fdopen(dup(fd), mode); + { + int dup_fd = dup(fd); + + if (dup_fd < 0) + { + state->errcode = errno; + return false; + } + state->fp = fdopen(dup_fd, mode); + if (state->fp == NULL) + { + state->errcode = errno; + close(dup_fd); + return false; + } + } else - state->fp = fopen(path, mode); - if (state->fp == NULL) { - state->errcode = errno; - return false; + state->fp = fopen(path, mode); + if (state->fp == NULL) + { + state->errcode = errno; + return false; + } } return true; diff --git a/src/bin/pg_dump/compress_none.c b/src/bin/pg_dump/compress_none.c index d862d8ca6e9..743e2ce94b5 100644 --- a/src/bin/pg_dump/compress_none.c +++ b/src/bin/pg_dump/compress_none.c @@ -231,12 +231,24 @@ open_none(const char *path, int fd, const char *mode, CompressFileHandle *CFH) Assert(CFH->private_data == NULL); if (fd >= 0) - CFH->private_data = fdopen(dup(fd), mode); + { + int dup_fd = dup(fd); + + if (dup_fd < 0) + return false; + CFH->private_data = fdopen(dup_fd, mode); + if (CFH->private_data == NULL) + { + close(dup_fd); + return false; + } + } else + { CFH->private_data = fopen(path, mode); - - if (CFH->private_data == NULL) - return false; + if (CFH->private_data == NULL) + return false; + } return true; } diff --git a/src/bin/pg_dump/compress_zstd.c b/src/bin/pg_dump/compress_zstd.c index cf2db2649ac..68f1d815917 100644 --- a/src/bin/pg_dump/compress_zstd.c +++ b/src/bin/pg_dump/compress_zstd.c @@ -523,14 +523,30 @@ Zstd_open(const char *path, int fd, const char *mode, } if (fd >= 0) - fp = fdopen(dup(fd), mode); - else - fp = fopen(path, mode); + { + int dup_fd = dup(fd); - if (fp == NULL) + if (dup_fd < 0) + { + pg_free(zstdcs); + return false; + } + fp = fdopen(dup_fd, mode); + if (fp == NULL) + { + close(dup_fd); + pg_free(zstdcs); + return false; + } + } + else { - pg_free(zstdcs); - return false; + fp = fopen(path, mode); + if (fp == NULL) + { + pg_free(zstdcs); + return false; + } } zstdcs->fp = fp; -- 2.50.1 (Apple Git-155)