summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTom Lane2011-04-07 15:40:39 +0000
committerTom Lane2011-04-07 15:40:39 +0000
commit9a9c7c2eb10b8df67c5652a6678a172b83a262eb (patch)
tree94305159af841881b95b5a9a851ebd78c6d6b69a
parentcfce572aceb0a8c809f5f52b7c8002b9917bcb19 (diff)
Fix SortTocFromFile() to cope with lines that are too long for its buffer.
The original coding supposed that a dump TOC file could never contain lines longer than 1K. The folly of that was exposed by a recent report from Per-Olov Esgard. We only really need to see the first dozen or two bytes of each line, since we're just trying to read off the numeric ID at the start of the line; so there's no need for a particularly huge buffer. What there is a need for is logic to not process continuation bufferloads. Back-patch to all supported branches, since it's always been like this.
-rw-r--r--src/bin/pg_dump/pg_backup_archiver.c29
1 files changed, 24 insertions, 5 deletions
diff --git a/src/bin/pg_dump/pg_backup_archiver.c b/src/bin/pg_dump/pg_backup_archiver.c
index c8db8f3dea1..b0d9784b3fc 100644
--- a/src/bin/pg_dump/pg_backup_archiver.c
+++ b/src/bin/pg_dump/pg_backup_archiver.c
@@ -804,11 +804,8 @@ SortTocFromFile(Archive *AHX, RestoreOptions *ropt)
{
ArchiveHandle *AH = (ArchiveHandle *) AHX;
FILE *fh;
- char buf[1024];
- char *cmnt;
- char *endptr;
- DumpId id;
- TocEntry *te;
+ char buf[100];
+ bool incomplete_line;
TocEntry *tePrev;
/* Allocate space for the 'wanted' array, and init it */
@@ -824,8 +821,30 @@ SortTocFromFile(Archive *AHX, RestoreOptions *ropt)
die_horribly(AH, modulename, "could not open TOC file \"%s\": %s\n",
ropt->tocFile, strerror(errno));
+ incomplete_line = false;
while (fgets(buf, sizeof(buf), fh) != NULL)
{
+ bool prev_incomplete_line = incomplete_line;
+ int buflen;
+ char *cmnt;
+ char *endptr;
+ DumpId id;
+ TocEntry *te;
+
+ /*
+ * Some lines in the file might be longer than sizeof(buf). This is
+ * no problem, since we only care about the leading numeric ID which
+ * can be at most a few characters; but we have to skip continuation
+ * bufferloads when processing a long line.
+ */
+ buflen = strlen(buf);
+ if (buflen > 0 && buf[buflen - 1] == '\n')
+ incomplete_line = false;
+ else
+ incomplete_line = true;
+ if (prev_incomplete_line)
+ continue;
+
/* Truncate line at comment, if any */
cmnt = strchr(buf, ';');
if (cmnt != NULL)