summaryrefslogtreecommitdiff
path: root/src/bin/pg_dump/pg_backup_archiver.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/bin/pg_dump/pg_backup_archiver.c')
-rw-r--r--src/bin/pg_dump/pg_backup_archiver.c117
1 files changed, 50 insertions, 67 deletions
diff --git a/src/bin/pg_dump/pg_backup_archiver.c b/src/bin/pg_dump/pg_backup_archiver.c
index 2c2f6fb4a95..a015c664598 100644
--- a/src/bin/pg_dump/pg_backup_archiver.c
+++ b/src/bin/pg_dump/pg_backup_archiver.c
@@ -77,7 +77,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, bool isData);
-static char *replace_line_endings(const char *str);
+static char *sanitize_line(const char *str, bool want_hyphen);
static void _doSetFixedOutputState(ArchiveHandle *AH);
static void _doSetSessionAuth(ArchiveHandle *AH, const char *user);
static void _reconnectToDB(ArchiveHandle *AH, const char *dbname);
@@ -1066,17 +1066,8 @@ WriteData(Archive *AHX, const void *data, size_t dLen)
/* Public */
TocEntry *
-ArchiveEntry(Archive *AHX,
- CatalogId catalogId, DumpId dumpId,
- const char *tag,
- const char *namespace,
- const char *tablespace,
- const char *owner,
- const char *desc, teSection section,
- const char *defn,
- const char *dropStmt, const char *copyStmt,
- const DumpId *deps, int nDeps,
- DataDumperPtr dumpFn, void *dumpArg)
+ArchiveEntry(Archive *AHX, CatalogId catalogId, DumpId dumpId,
+ ArchiveOpts *opts)
{
ArchiveHandle *AH = (ArchiveHandle *) AHX;
TocEntry *newToc;
@@ -1094,22 +1085,22 @@ ArchiveEntry(Archive *AHX,
newToc->catalogId = catalogId;
newToc->dumpId = dumpId;
- newToc->section = section;
-
- newToc->tag = pg_strdup(tag);
- newToc->namespace = namespace ? pg_strdup(namespace) : NULL;
- newToc->tablespace = tablespace ? pg_strdup(tablespace) : NULL;
- newToc->owner = pg_strdup(owner);
- newToc->desc = pg_strdup(desc);
- newToc->defn = pg_strdup(defn);
- newToc->dropStmt = pg_strdup(dropStmt);
- newToc->copyStmt = copyStmt ? pg_strdup(copyStmt) : NULL;
-
- if (nDeps > 0)
+ newToc->section = opts->section;
+
+ newToc->tag = pg_strdup(opts->tag);
+ newToc->namespace = opts->namespace ? pg_strdup(opts->namespace) : NULL;
+ newToc->tablespace = opts->tablespace ? pg_strdup(opts->tablespace) : NULL;
+ newToc->owner = opts->owner ? pg_strdup(opts->owner) : NULL;
+ newToc->desc = pg_strdup(opts->description);
+ newToc->defn = opts->createStmt ? pg_strdup(opts->createStmt) : NULL;
+ newToc->dropStmt = opts->dropStmt ? pg_strdup(opts->dropStmt) : NULL;
+ newToc->copyStmt = opts->copyStmt ? pg_strdup(opts->copyStmt) : NULL;
+
+ if (opts->nDeps > 0)
{
- newToc->dependencies = (DumpId *) pg_malloc(nDeps * sizeof(DumpId));
- memcpy(newToc->dependencies, deps, nDeps * sizeof(DumpId));
- newToc->nDeps = nDeps;
+ newToc->dependencies = (DumpId *) pg_malloc(opts->nDeps * sizeof(DumpId));
+ memcpy(newToc->dependencies, opts->deps, opts->nDeps * sizeof(DumpId));
+ newToc->nDeps = opts->nDeps;
}
else
{
@@ -1117,9 +1108,9 @@ ArchiveEntry(Archive *AHX,
newToc->nDeps = 0;
}
- newToc->dataDumper = dumpFn;
- newToc->dataDumperArg = dumpArg;
- newToc->hadDumper = dumpFn ? true : false;
+ newToc->dataDumper = opts->dumpFn;
+ newToc->dataDumperArg = opts->dumpArg;
+ newToc->hadDumper = opts->dumpFn ? true : false;
newToc->formatData = NULL;
newToc->dataLength = 0;
@@ -1152,7 +1143,7 @@ PrintTOCSummary(Archive *AHX)
ahprintf(AH, ";\n; Archive created at %s\n", stamp_str);
ahprintf(AH, "; dbname: %s\n; TOC Entries: %d\n; Compression: %d\n",
- replace_line_endings(AH->archdbname),
+ sanitize_line(AH->archdbname, false),
AH->tocCount, AH->compression);
switch (AH->format)
@@ -1197,21 +1188,10 @@ PrintTOCSummary(Archive *AHX)
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);
+ sanitized_name = sanitize_line(te->tag, false);
+ sanitized_schema = sanitize_line(te->namespace, true);
+ sanitized_owner = sanitize_line(te->owner, false);
ahprintf(AH, "%d; %u %u %s %s %s %s\n", te->dumpId,
te->catalogId.tableoid, te->catalogId.oid,
@@ -3577,21 +3557,9 @@ _printTocEntry(ArchiveHandle *AH, TocEntry *te, bool isData)
}
}
- /*
- * 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("-");
+ sanitized_name = sanitize_line(te->tag, false);
+ sanitized_schema = sanitize_line(te->namespace, true);
+ sanitized_owner = sanitize_line(ropt->noOwner ? NULL : te->owner, true);
ahprintf(AH, "-- %sName: %s; Type: %s; Schema: %s; Owner: %s",
pfx, sanitized_name, te->desc, sanitized_schema,
@@ -3605,7 +3573,7 @@ _printTocEntry(ArchiveHandle *AH, TocEntry *te, bool isData)
{
char *sanitized_tablespace;
- sanitized_tablespace = replace_line_endings(te->tablespace);
+ sanitized_tablespace = sanitize_line(te->tablespace, false);
ahprintf(AH, "; Tablespace: %s", sanitized_tablespace);
free(sanitized_tablespace);
}
@@ -3629,7 +3597,7 @@ _printTocEntry(ArchiveHandle *AH, TocEntry *te, bool isData)
}
else
{
- if (strlen(te->defn) > 0)
+ if (te->defn && strlen(te->defn) > 0)
ahprintf(AH, "%s\n\n", te->defn);
}
@@ -3640,7 +3608,8 @@ _printTocEntry(ArchiveHandle *AH, TocEntry *te, bool isData)
* with DROP commands must appear in one list or the other.
*/
if (!ropt->noOwner && !ropt->use_setsessauth &&
- strlen(te->owner) > 0 && strlen(te->dropStmt) > 0)
+ te->owner && strlen(te->owner) > 0 &&
+ te->dropStmt && strlen(te->dropStmt) > 0)
{
if (strcmp(te->desc, "AGGREGATE") == 0 ||
strcmp(te->desc, "BLOB") == 0 ||
@@ -3713,16 +3682,30 @@ _printTocEntry(ArchiveHandle *AH, TocEntry *te, bool isData)
}
/*
- * Sanitize a string to be included in an SQL comment or TOC listing,
- * by replacing any newlines with spaces.
- * The result is a freshly malloc'd string.
+ * Sanitize a string to be included in an SQL comment or TOC listing, by
+ * replacing any newlines with spaces. This ensures each logical output line
+ * is in fact one physical output line, 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).
+ *
+ * The result is a freshly malloc'd string. If the input string is NULL,
+ * return a malloc'ed empty string, unless want_hyphen, in which case return a
+ * malloc'ed hyphen.
+ *
+ * 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.
*/
static char *
-replace_line_endings(const char *str)
+sanitize_line(const char *str, bool want_hyphen)
{
char *result;
char *s;
+ if (!str)
+ return pg_strdup(want_hyphen ? "-" : "");
+
result = pg_strdup(str);
for (s = result; *s != '\0'; s++)