v01-add-some-more-error-checks-into-_fileExistsInDirecto.patch
application/octet-stream
Filename: v01-add-some-more-error-checks-into-_fileExistsInDirecto.patch
Type: application/octet-stream
Part: 0
Patch
Same data as JSON:
GET /api/v1/attachments/:id/patch
the parsed metadata as JSON — format, series position, per-file stats; never the diff bytes.
API reference →
Format: format-patch
Series: patch v1
Subject: add some more error checks into _fileExistsInDirectory function to report "too long name" error.
| File | + | − |
|---|---|---|
| src/bin/pg_dump/pg_backup_archiver.c | 8 | 1 |
| src/bin/pg_dump/pg_dumpall.c | 18 | 4 |
| src/bin/pg_dump/pg_restore.c | 27 | 7 |
From c508fb100757e2968247865eaa0a678dd5afb146 Mon Sep 17 00:00:00 2001
From: Mahendra Singh Thalor <mahi6run@gmail.com>
Date: Fri, 11 Apr 2025 18:31:06 +0530
Subject: [PATCH] add some more error checks into _fileExistsInDirectory
function to report "too long name" error.
---
src/bin/pg_dump/pg_backup_archiver.c | 9 +++++++-
src/bin/pg_dump/pg_dumpall.c | 22 ++++++++++++++----
src/bin/pg_dump/pg_restore.c | 34 ++++++++++++++++++++++------
3 files changed, 53 insertions(+), 12 deletions(-)
diff --git a/src/bin/pg_dump/pg_backup_archiver.c b/src/bin/pg_dump/pg_backup_archiver.c
index f961162f365..30dcf5780a3 100644
--- a/src/bin/pg_dump/pg_backup_archiver.c
+++ b/src/bin/pg_dump/pg_backup_archiver.c
@@ -2218,9 +2218,16 @@ _fileExistsInDirectory(const char *dir, const char *filename)
struct stat st;
char buf[MAXPGPATH];
- if (snprintf(buf, MAXPGPATH, "%s/%s", dir, filename) >= MAXPGPATH)
+ if (strlen(dir) >= MAXPGPATH)
pg_fatal("directory name too long: \"%s\"", dir);
+ if (strlen(filename) >= MAXPGPATH)
+ pg_fatal("file name too long: \"%s\"", filename);
+
+ /* Now check path length of dir/filename */
+ if (snprintf(buf, MAXPGPATH, "%s/%s", dir, filename) >= MAXPGPATH)
+ pg_fatal("combined name of directory:\"%s\" and file:\"%s\" is too long", filename, dir);
+
return (stat(buf, &st) == 0 && S_ISREG(st.st_mode));
}
diff --git a/src/bin/pg_dump/pg_dumpall.c b/src/bin/pg_dump/pg_dumpall.c
index 3395d559518..f4a9bb07503 100644
--- a/src/bin/pg_dump/pg_dumpall.c
+++ b/src/bin/pg_dump/pg_dumpall.c
@@ -506,6 +506,9 @@ main(int argc, char *argv[])
if (statistics_only)
appendPQExpBufferStr(pgdumpopts, " --statistics-only");
+ if (filename && strlen(filename) >= MAXPGPATH)
+ pg_fatal("out file name:\"%s\" is too long", filename);
+
/*
* Open the output file if required, otherwise use stdout. If required,
* then create new directory and global.dat file.
@@ -517,7 +520,8 @@ main(int argc, char *argv[])
/* Create new directory or accept the empty existing directory. */
create_or_open_dir(filename);
- snprintf(global_path, MAXPGPATH, "%s/global.dat", filename);
+ if (snprintf(global_path, MAXPGPATH, "%s/global.dat", filename) >= MAXPGPATH)
+ pg_fatal("combined name of out file:\"%s\" and global.dat is too long", filename);
OPF = fopen(global_path, PG_BINARY_W);
if (!OPF)
@@ -1650,6 +1654,7 @@ dumpDatabases(PGconn *conn, ArchiveFormat archDumpFormat)
{
char map_file_path[MAXPGPATH];
+ /* No need to check path length as %s/global.dat was OK. */
snprintf(db_subdir, MAXPGPATH, "%s/databases", filename);
/* Create a subdirectory with 'databases' name under main directory. */
@@ -1689,11 +1694,20 @@ dumpDatabases(PGconn *conn, ArchiveFormat archDumpFormat)
if (archDumpFormat != archNull)
{
if (archDumpFormat == archCustom)
- snprintf(dbfilepath, MAXPGPATH, "\"%s\"/\"%s\".dmp", db_subdir, oid);
+ {
+ if (snprintf(dbfilepath, MAXPGPATH, "\"%s\"/\"%s\".dmp", db_subdir, oid) >= MAXPGPATH)
+ pg_fatal("combined name of file:\"%s\" and \"%s\".dmp is too long", db_subdir, oid);
+ }
else if (archDumpFormat == archTar)
- snprintf(dbfilepath, MAXPGPATH, "\"%s\"/\"%s\".tar", db_subdir, oid);
+ {
+ if (snprintf(dbfilepath, MAXPGPATH, "\"%s\"/\"%s\".tar", db_subdir, oid) >= MAXPGPATH)
+ pg_fatal("combined name of file:\"%s\" and \"%s\".tar is too long", db_subdir, oid);
+ }
else
- snprintf(dbfilepath, MAXPGPATH, "\"%s\"/\"%s\"", db_subdir, oid);
+ {
+ if (snprintf(dbfilepath, MAXPGPATH, "\"%s\"/\"%s\"", db_subdir, oid) >= MAXPGPATH)
+ pg_fatal("combined name of file:\"%s\" and \"%s\" is too long", db_subdir, oid);
+ }
/* Put one line entry for dboid and dbname in map file. */
fprintf(map_file, "%s %s\n", oid, dbname);
diff --git a/src/bin/pg_dump/pg_restore.c b/src/bin/pg_dump/pg_restore.c
index 24a44b81a95..157f7ac8c29 100644
--- a/src/bin/pg_dump/pg_restore.c
+++ b/src/bin/pg_dump/pg_restore.c
@@ -834,9 +834,16 @@ file_exists_in_directory(const char *dir, const char *filename)
struct stat st;
char buf[MAXPGPATH];
- if (snprintf(buf, MAXPGPATH, "%s/%s", dir, filename) >= MAXPGPATH)
+ if (strlen(dir) >= MAXPGPATH)
pg_fatal("directory name too long: \"%s\"", dir);
+ if (strlen(filename) >= MAXPGPATH)
+ pg_fatal("file name too long: \"%s\"", filename);
+
+ /* Now check path length of dir/filename */
+ if (snprintf(buf, MAXPGPATH, "%s/%s", dir, filename) >= MAXPGPATH)
+ pg_fatal("combined name of directory:\"%s\" and file:\"%s\" is too long", filename, dir);
+
return (stat(buf, &st) == 0 && S_ISREG(st.st_mode));
}
@@ -1190,6 +1197,10 @@ restore_all_databases(PGconn *conn, const char *dumpdirpath,
opts->cparams.override_dbname = NULL;
}
+ /*
+ * No need to check dumpdirpath/databases path as
+ * dumpdirpath/global.dat was OK.
+ */
snprintf(subdirdbpath, MAXPGPATH, "%s/databases", dumpdirpath);
/*
@@ -1197,17 +1208,23 @@ restore_all_databases(PGconn *conn, const char *dumpdirpath,
* {oid}.dmp file, use it. Otherwise try to use a directory called
* {oid}
*/
- snprintf(dbfilename, MAXPGPATH, "%u.tar", db_cell->oid);
+ snprintf(dbfilename, MAXPGPATH, "%u", db_cell->oid); /* path length is OK */
+
if (file_exists_in_directory(subdirdbpath, dbfilename))
- snprintf(subdirpath, MAXPGPATH, "%s/databases/%u.tar", dumpdirpath, db_cell->oid);
+ snprintf(subdirpath, MAXPGPATH, "%s/databases/%s", dumpdirpath, dbfilename);
else
{
- snprintf(dbfilename, MAXPGPATH, "%u.dmp", db_cell->oid);
-
+ snprintf(dbfilename, MAXPGPATH, "%u.tar", db_cell->oid);
if (file_exists_in_directory(subdirdbpath, dbfilename))
- snprintf(subdirpath, MAXPGPATH, "%s/databases/%u.dmp", dumpdirpath, db_cell->oid);
+ snprintf(subdirpath, MAXPGPATH, "%s/databases/%u.tar", dumpdirpath, db_cell->oid);
else
- snprintf(subdirpath, MAXPGPATH, "%s/databases/%u", dumpdirpath, db_cell->oid);
+ {
+ snprintf(dbfilename, MAXPGPATH, "%u.dmp", db_cell->oid);
+ if (file_exists_in_directory(subdirdbpath, dbfilename))
+ snprintf(subdirpath, MAXPGPATH, "%s/databases/%u.dmp", dumpdirpath, db_cell->oid);
+ else
+ snprintf(subdirpath, MAXPGPATH, "%s/databases/%u", dumpdirpath, db_cell->oid);
+ }
}
pg_log_info("restoring database \"%s\"", db_cell->str);
@@ -1364,6 +1381,9 @@ copy_or_print_global_file(const char *outfile, FILE *pfile)
OPF = stdout;
else
{
+ if (strlen(outfile) >= MAXPGPATH)
+ pg_fatal("out file name:\"%s\" is too long", outfile);
+
snprintf(out_file_path, MAXPGPATH, "%s", outfile);
OPF = fopen(out_file_path, PG_BINARY_W);
--
2.39.3