diff --git a/src/bin/pg_dump/pg_backup_archiver.c b/src/bin/pg_dump/pg_backup_archiver.c index 9bf0639cbf..f64046b1a6 100644 --- a/src/bin/pg_dump/pg_backup_archiver.c +++ b/src/bin/pg_dump/pg_backup_archiver.c @@ -83,6 +83,7 @@ static ArchiveHandle *_allocAH(const char *FileSpec, const ArchiveFormat fmt, static void _getObjectDescription(PQExpBuffer buf, TocEntry *te, ArchiveHandle *AH); static void _printTocEntry(ArchiveHandle *AH, TocEntry *te, RestoreOptions *ropt, bool isData, bool acl_pass); +static char *replace_line_endings(const char *str); static void _doSetFixedOutputState(ArchiveHandle *AH); @@ -2803,6 +2804,9 @@ _printTocEntry(ArchiveHandle *AH, TocEntry *te, RestoreOptions *ropt, bool isDat if (!AH->noTocComments) { const char *pfx; + char *sanitized_name; + char *sanitized_schema; + char *sanitized_owner; if (isData) pfx = "Data for "; @@ -2824,12 +2828,39 @@ _printTocEntry(ArchiveHandle *AH, TocEntry *te, RestoreOptions *ropt, bool isDat ahprintf(AH, "\n"); } } + + /* + * Zap any line endings embedded in user-supplied fields, to prevent + * corruption of the dump (which could, in the worst case, present an + * SQL injection vulnerability if someone were to incautiously load a + * dump containing objects with maliciously crafted names). + */ + sanitized_name = replace_line_endings(te->tag); + if (te->namespace) + sanitized_schema = replace_line_endings(te->namespace); + else + sanitized_schema = strdup("-"); + if (!ropt->noOwner) + sanitized_owner = replace_line_endings(te->owner); + else + sanitized_owner = strdup("-"); + ahprintf(AH, "-- %sName: %s; Type: %s; Schema: %s; Owner: %s", - pfx, te->tag, te->desc, - te->namespace ? te->namespace : "-", - ropt->noOwner ? "-" : te->owner); + pfx, sanitized_name, te->desc, sanitized_schema, + sanitized_owner); + + free(sanitized_name); + free(sanitized_schema); + free(sanitized_owner); + if (te->tablespace && !ropt->noTablespace) - ahprintf(AH, "; Tablespace: %s", te->tablespace); + { + char *sanitized_tablespace; + + sanitized_tablespace = replace_line_endings(te->tablespace); + ahprintf(AH, "; Tablespace: %s", sanitized_tablespace); + free(sanitized_tablespace); + } ahprintf(AH, "\n"); if (AH->PrintExtraTocPtr !=NULL) @@ -2921,6 +2952,27 @@ _printTocEntry(ArchiveHandle *AH, TocEntry *te, RestoreOptions *ropt, bool isDat } } +/* + * Sanitize a string to be included in an SQL comment, by replacing any + * newlines with spaces. + */ +static char * +replace_line_endings(const char *str) +{ + char *result; + char *s; + + result = strdup(str); + + for (s = result; *s != '\0'; s++) + { + if (*s == '\n' || *s == '\r') + *s = ' '; + } + + return result; +} + void WriteHead(ArchiveHandle *AH) {