diff options
Diffstat (limited to 'src/bin/pg_dump/pg_backup_archiver.c')
-rw-r--r-- | src/bin/pg_dump/pg_backup_archiver.c | 117 |
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++) |