Convert newlines to spaces in names written in pg_dump comments.

pg_dump was incautious about sanitizing object names that are emitted
within SQL comments in its output script.  A name containing a newline
would at least render the script syntactically incorrect.  Maliciously
crafted object names could present a SQL injection risk when the script
is reloaded.

Reported by Heikki Linnakangas, patch by Robert Haas

Security: CVE-2012-0868
This commit is contained in:
Tom Lane 2012-02-23 15:53:09 -05:00
parent 077711c2e3
commit 89e0bac86d

View File

@ -99,6 +99,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);
@ -2932,6 +2933,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 ";
@ -2953,12 +2957,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 = pg_strdup("-");
if (!ropt->noOwner)
sanitized_owner = replace_line_endings(te->owner);
else
sanitized_owner = pg_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)
@ -3053,6 +3084,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 = pg_strdup(str);
for (s = result; *s != '\0'; s++)
{
if (*s == '\n' || *s == '\r')
*s = ' ';
}
return result;
}
void
WriteHead(ArchiveHandle *AH)
{