diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/backend/access/transam/xlog.c | 19 | ||||
-rw-r--r-- | src/backend/access/transam/xlogrecovery.c | 12 | ||||
-rw-r--r-- | src/backend/backup/backup_manifest.c | 6 | ||||
-rw-r--r-- | src/backend/backup/basebackup.c | 35 | ||||
-rw-r--r-- | src/backend/backup/basebackup_copy.c | 2 | ||||
-rw-r--r-- | src/include/backup/backup_manifest.h | 2 | ||||
-rw-r--r-- | src/include/backup/basebackup.h | 2 |
7 files changed, 49 insertions, 29 deletions
diff --git a/src/backend/access/transam/xlog.c b/src/backend/access/transam/xlog.c index cea13e3d582..40461923ea3 100644 --- a/src/backend/access/transam/xlog.c +++ b/src/backend/access/transam/xlog.c @@ -8579,9 +8579,22 @@ do_pg_backup_start(const char *backupidstr, bool fast, List **tablespaces, char *relpath = NULL; char *s; PGFileType de_type; + char *badp; + Oid tsoid; - /* Skip anything that doesn't look like a tablespace */ - if (strspn(de->d_name, "0123456789") != strlen(de->d_name)) + /* + * Try to parse the directory name as an unsigned integer. + * + * Tablespace directories should be positive integers that can be + * represented in 32 bits, with no leading zeroes or trailing + * garbage. If we come across a name that doesn't meet those + * criteria, skip it. + */ + if (de->d_name[0] < '1' || de->d_name[1] > '9') + continue; + errno = 0; + tsoid = strtoul(de->d_name, &badp, 10); + if (*badp != '\0' || errno == EINVAL || errno == ERANGE) continue; snprintf(fullpath, sizeof(fullpath), "pg_tblspc/%s", de->d_name); @@ -8656,7 +8669,7 @@ do_pg_backup_start(const char *backupidstr, bool fast, List **tablespaces, } ti = palloc(sizeof(tablespaceinfo)); - ti->oid = pstrdup(de->d_name); + ti->oid = tsoid; ti->path = pstrdup(linkpath); ti->rpath = relpath; ti->size = -1; diff --git a/src/backend/access/transam/xlogrecovery.c b/src/backend/access/transam/xlogrecovery.c index d6f2bb82865..315e4b27cb8 100644 --- a/src/backend/access/transam/xlogrecovery.c +++ b/src/backend/access/transam/xlogrecovery.c @@ -678,7 +678,7 @@ InitWalRecovery(ControlFileData *ControlFile, bool *wasShutdown_ptr, tablespaceinfo *ti = lfirst(lc); char *linkloc; - linkloc = psprintf("pg_tblspc/%s", ti->oid); + linkloc = psprintf("pg_tblspc/%u", ti->oid); /* * Remove the existing symlink if any and Create the symlink @@ -692,7 +692,6 @@ InitWalRecovery(ControlFileData *ControlFile, bool *wasShutdown_ptr, errmsg("could not create symbolic link \"%s\": %m", linkloc))); - pfree(ti->oid); pfree(ti->path); pfree(ti); } @@ -1341,6 +1340,8 @@ read_tablespace_map(List **tablespaces) { if (!was_backslash && (ch == '\n' || ch == '\r')) { + char *endp; + if (i == 0) continue; /* \r immediately followed by \n */ @@ -1360,7 +1361,12 @@ read_tablespace_map(List **tablespaces) str[n++] = '\0'; ti = palloc0(sizeof(tablespaceinfo)); - ti->oid = pstrdup(str); + errno = 0; + ti->oid = strtoul(str, &endp, 10); + if (*endp != '\0' || errno == EINVAL || errno == ERANGE) + ereport(FATAL, + (errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE), + errmsg("invalid data in file \"%s\"", TABLESPACE_MAP))); ti->path = pstrdup(str + n); *tablespaces = lappend(*tablespaces, ti); diff --git a/src/backend/backup/backup_manifest.c b/src/backend/backup/backup_manifest.c index cee62165246..aeed362a9ad 100644 --- a/src/backend/backup/backup_manifest.c +++ b/src/backend/backup/backup_manifest.c @@ -97,7 +97,7 @@ FreeBackupManifest(backup_manifest_info *manifest) * Add an entry to the backup manifest for a file. */ void -AddFileToBackupManifest(backup_manifest_info *manifest, const char *spcoid, +AddFileToBackupManifest(backup_manifest_info *manifest, Oid spcoid, const char *pathname, size_t size, pg_time_t mtime, pg_checksum_context *checksum_ctx) { @@ -114,9 +114,9 @@ AddFileToBackupManifest(backup_manifest_info *manifest, const char *spcoid, * pathname relative to the data directory (ignoring the intermediate * symlink traversal). */ - if (spcoid != NULL) + if (OidIsValid(spcoid)) { - snprintf(pathbuf, sizeof(pathbuf), "pg_tblspc/%s/%s", spcoid, + snprintf(pathbuf, sizeof(pathbuf), "pg_tblspc/%u/%s", spcoid, pathname); pathname = pathbuf; } diff --git a/src/backend/backup/basebackup.c b/src/backend/backup/basebackup.c index b126d9c8907..b537f462197 100644 --- a/src/backend/backup/basebackup.c +++ b/src/backend/backup/basebackup.c @@ -75,14 +75,15 @@ typedef struct pg_checksum_type manifest_checksum_type; } basebackup_options; -static int64 sendTablespace(bbsink *sink, char *path, char *spcoid, bool sizeonly, +static int64 sendTablespace(bbsink *sink, char *path, Oid spcoid, bool sizeonly, struct backup_manifest_info *manifest); static int64 sendDir(bbsink *sink, const char *path, int basepathlen, bool sizeonly, List *tablespaces, bool sendtblspclinks, - backup_manifest_info *manifest, const char *spcoid); + backup_manifest_info *manifest, Oid spcoid); static bool sendFile(bbsink *sink, const char *readfilename, const char *tarfilename, - struct stat *statbuf, bool missing_ok, Oid dboid, - backup_manifest_info *manifest, const char *spcoid); + struct stat *statbuf, bool missing_ok, + Oid dboid, Oid spcoid, + backup_manifest_info *manifest); static off_t read_file_data_into_buffer(bbsink *sink, const char *readfilename, int fd, off_t offset, size_t length, @@ -305,7 +306,7 @@ perform_base_backup(basebackup_options *opt, bbsink *sink) if (tmp->path == NULL) tmp->size = sendDir(sink, ".", 1, true, state.tablespaces, - true, NULL, NULL); + true, NULL, InvalidOid); else tmp->size = sendTablespace(sink, tmp->path, tmp->oid, true, NULL); @@ -346,7 +347,7 @@ perform_base_backup(basebackup_options *opt, bbsink *sink) /* Then the bulk of the files... */ sendDir(sink, ".", 1, false, state.tablespaces, - sendtblspclinks, &manifest, NULL); + sendtblspclinks, &manifest, InvalidOid); /* ... and pg_control after everything else. */ if (lstat(XLOG_CONTROL_FILE, &statbuf) != 0) @@ -355,11 +356,11 @@ perform_base_backup(basebackup_options *opt, bbsink *sink) errmsg("could not stat file \"%s\": %m", XLOG_CONTROL_FILE))); sendFile(sink, XLOG_CONTROL_FILE, XLOG_CONTROL_FILE, &statbuf, - false, InvalidOid, &manifest, NULL); + false, InvalidOid, InvalidOid, &manifest); } else { - char *archive_name = psprintf("%s.tar", ti->oid); + char *archive_name = psprintf("%u.tar", ti->oid); bbsink_begin_archive(sink, archive_name); @@ -623,8 +624,8 @@ perform_base_backup(basebackup_options *opt, bbsink *sink) (errcode_for_file_access(), errmsg("could not stat file \"%s\": %m", pathbuf))); - sendFile(sink, pathbuf, pathbuf, &statbuf, false, InvalidOid, - &manifest, NULL); + sendFile(sink, pathbuf, pathbuf, &statbuf, false, + InvalidOid, InvalidOid, &manifest); /* unconditionally mark file as archived */ StatusFilePath(pathbuf, fname, ".done"); @@ -1087,7 +1088,7 @@ sendFileWithContent(bbsink *sink, const char *filename, const char *content, _tarWritePadding(sink, len); - AddFileToBackupManifest(manifest, NULL, filename, len, + AddFileToBackupManifest(manifest, InvalidOid, filename, len, (pg_time_t) statbuf.st_mtime, &checksum_ctx); } @@ -1099,7 +1100,7 @@ sendFileWithContent(bbsink *sink, const char *filename, const char *content, * Only used to send auxiliary tablespaces, not PGDATA. */ static int64 -sendTablespace(bbsink *sink, char *path, char *spcoid, bool sizeonly, +sendTablespace(bbsink *sink, char *path, Oid spcoid, bool sizeonly, backup_manifest_info *manifest) { int64 size; @@ -1154,7 +1155,7 @@ sendTablespace(bbsink *sink, char *path, char *spcoid, bool sizeonly, static int64 sendDir(bbsink *sink, const char *path, int basepathlen, bool sizeonly, List *tablespaces, bool sendtblspclinks, backup_manifest_info *manifest, - const char *spcoid) + Oid spcoid) { DIR *dir; struct dirent *de; @@ -1416,8 +1417,8 @@ sendDir(bbsink *sink, const char *path, int basepathlen, bool sizeonly, if (!sizeonly) sent = sendFile(sink, pathbuf, pathbuf + basepathlen + 1, &statbuf, - true, isDbDir ? atooid(lastDir + 1) : InvalidOid, - manifest, spcoid); + true, isDbDir ? atooid(lastDir + 1) : InvalidOid, spcoid, + manifest); if (sent || sizeonly) { @@ -1486,8 +1487,8 @@ is_checksummed_file(const char *fullpath, const char *filename) */ static bool sendFile(bbsink *sink, const char *readfilename, const char *tarfilename, - struct stat *statbuf, bool missing_ok, Oid dboid, - backup_manifest_info *manifest, const char *spcoid) + struct stat *statbuf, bool missing_ok, Oid dboid, Oid spcoid, + backup_manifest_info *manifest) { int fd; BlockNumber blkno = 0; diff --git a/src/backend/backup/basebackup_copy.c b/src/backend/backup/basebackup_copy.c index fee30c21e10..3bdbe1f9890 100644 --- a/src/backend/backup/basebackup_copy.c +++ b/src/backend/backup/basebackup_copy.c @@ -407,7 +407,7 @@ SendTablespaceList(List *tablespaces) } else { - values[0] = ObjectIdGetDatum(strtoul(ti->oid, NULL, 10)); + values[0] = ObjectIdGetDatum(ti->oid); values[1] = CStringGetTextDatum(ti->path); } if (ti->size >= 0) diff --git a/src/include/backup/backup_manifest.h b/src/include/backup/backup_manifest.h index d41b4399806..5a481dbcf5a 100644 --- a/src/include/backup/backup_manifest.h +++ b/src/include/backup/backup_manifest.h @@ -39,7 +39,7 @@ extern void InitializeBackupManifest(backup_manifest_info *manifest, backup_manifest_option want_manifest, pg_checksum_type manifest_checksum_type); extern void AddFileToBackupManifest(backup_manifest_info *manifest, - const char *spcoid, + Oid spcoid, const char *pathname, size_t size, pg_time_t mtime, pg_checksum_context *checksum_ctx); diff --git a/src/include/backup/basebackup.h b/src/include/backup/basebackup.h index 3e68abc2bb7..1432d9c206b 100644 --- a/src/include/backup/basebackup.h +++ b/src/include/backup/basebackup.h @@ -27,7 +27,7 @@ */ typedef struct { - char *oid; /* tablespace's OID, as a decimal string */ + Oid oid; /* tablespace's OID */ char *path; /* full path to tablespace's directory */ char *rpath; /* relative path if it's within PGDATA, else * NULL */ |