Commit f39ddd84 authored by Tom Lane's avatar Tom Lane

Sanitize newlines in object names in "pg_restore -l" output.

Commits 89e0bac8 et al replaced newlines with spaces in object names
printed in SQL comments, but we neglected to consider that the same
names are also printed by "pg_restore -l", and a newline would render
the output unparseable by "pg_restore -L".  Apply the same replacement
in "-l" output.  Since "pg_restore -L" doesn't actually examine any
object names, only the dump ID field that starts each line, this is
enough to fix things for its purposes.

The previous fix was treated as a security issue, and we might have
done that here as well, except that the issue was reported publicly
to start with.  Anyway it's hard to see how this could be exploited
for SQL injection; "pg_restore -L" doesn't do much with the file
except parse it for leading integers.

Per bug #14587 from Milos Urbanek.  Back-patch to all supported versions.

Discussion: https://postgr.es/m/20170310155318.1425.30483@wrigleys.postgresql.org
parent 8b358b42
...@@ -1104,7 +1104,8 @@ PrintTOCSummary(Archive *AHX) ...@@ -1104,7 +1104,8 @@ PrintTOCSummary(Archive *AHX)
ahprintf(AH, ";\n; Archive created at %s\n", stamp_str); ahprintf(AH, ";\n; Archive created at %s\n", stamp_str);
ahprintf(AH, "; dbname: %s\n; TOC Entries: %d\n; Compression: %d\n", ahprintf(AH, "; dbname: %s\n; TOC Entries: %d\n; Compression: %d\n",
AH->archdbname, AH->tocCount, AH->compression); replace_line_endings(AH->archdbname),
AH->tocCount, AH->compression);
switch (AH->format) switch (AH->format)
{ {
...@@ -1142,10 +1143,37 @@ PrintTOCSummary(Archive *AHX) ...@@ -1142,10 +1143,37 @@ PrintTOCSummary(Archive *AHX)
curSection = te->section; curSection = te->section;
if (ropt->verbose || if (ropt->verbose ||
(_tocEntryRequired(te, curSection, ropt) & (REQ_SCHEMA | REQ_DATA)) != 0) (_tocEntryRequired(te, curSection, ropt) & (REQ_SCHEMA | REQ_DATA)) != 0)
{
char *sanitized_name;
char *sanitized_schema;
char *sanitized_owner;
/*
* As in _printTocEntry(), sanitize strings that might contain
* newlines, to ensure that each logical output line is in fact
* one physical output line. This prevents confusion when the
* file is read by "pg_restore -L". Note that we currently don't
* bother to quote names, meaning that the name fields aren't
* automatically parseable. "pg_restore -L" doesn't care because
* it only examines the dumpId field, but someday we might want to
* try harder.
*/
sanitized_name = replace_line_endings(te->tag);
if (te->namespace)
sanitized_schema = replace_line_endings(te->namespace);
else
sanitized_schema = pg_strdup("-");
sanitized_owner = replace_line_endings(te->owner);
ahprintf(AH, "%d; %u %u %s %s %s %s\n", te->dumpId, ahprintf(AH, "%d; %u %u %s %s %s %s\n", te->dumpId,
te->catalogId.tableoid, te->catalogId.oid, te->catalogId.tableoid, te->catalogId.oid,
te->desc, te->namespace ? te->namespace : "-", te->desc, sanitized_schema, sanitized_name,
te->tag, te->owner); sanitized_owner);
free(sanitized_name);
free(sanitized_schema);
free(sanitized_owner);
}
if (ropt->verbose && te->nDeps > 0) if (ropt->verbose && te->nDeps > 0)
{ {
int i; int i;
...@@ -3531,8 +3559,9 @@ _printTocEntry(ArchiveHandle *AH, TocEntry *te, bool isData, bool acl_pass) ...@@ -3531,8 +3559,9 @@ _printTocEntry(ArchiveHandle *AH, TocEntry *te, bool isData, bool acl_pass)
} }
/* /*
* Sanitize a string to be included in an SQL comment, by replacing any * Sanitize a string to be included in an SQL comment or TOC listing,
* newlines with spaces. * by replacing any newlines with spaces.
* The result is a freshly malloc'd string.
*/ */
static char * static char *
replace_line_endings(const char *str) replace_line_endings(const char *str)
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment