Simplify SortTocFromFile() by removing fixed buffer-size limit.
authorTom Lane <tgl@sss.pgh.pa.us>
Tue, 22 Sep 2020 20:03:32 +0000 (16:03 -0400)
committerTom Lane <tgl@sss.pgh.pa.us>
Tue, 22 Sep 2020 20:03:32 +0000 (16:03 -0400)
pg_restore previously coped with overlength TOC-file lines using some
complicated logic to ignore additional bufferloads.  While this isn't
wrong, since we don't expect that the interesting part of a line would
run to more than a dozen or so bytes, it's more complex than it needs
to be.  Use a StringInfo instead of a fixed-size buffer so that we can
process long lines as single entities and thus not need the extra
logic.

Daniel Gustafsson

Discussion: https://postgr.es/m/48A4FA71-524E-41B9-953A-FD04EF36E2E7@yesql.se

src/bin/pg_dump/pg_backup_archiver.c

index bc4757829430da59b9fdb209003293019aea0282..3567e9f365f53bdec991279cc2fcfc918874f135 100644 (file)
 #include <io.h>
 #endif
 
+#include "common/string.h"
 #include "dumputils.h"
 #include "fe_utils/string_utils.h"
+#include "lib/stringinfo.h"
 #include "libpq/libpq-fs.h"
 #include "parallel.h"
 #include "pg_backup_archiver.h"
@@ -1367,8 +1369,7 @@ SortTocFromFile(Archive *AHX)
        ArchiveHandle *AH = (ArchiveHandle *) AHX;
        RestoreOptions *ropt = AH->public.ropt;
        FILE       *fh;
-       char            buf[100];
-       bool            incomplete_line;
+       StringInfoData linebuf;
 
        /* Allocate space for the 'wanted' array, and init it */
        ropt->idWanted = (bool *) pg_malloc0(sizeof(bool) * AH->maxDumpId);
@@ -1378,45 +1379,33 @@ SortTocFromFile(Archive *AHX)
        if (!fh)
                fatal("could not open TOC file \"%s\": %m", ropt->tocFile);
 
-       incomplete_line = false;
-       while (fgets(buf, sizeof(buf), fh) != NULL)
+       initStringInfo(&linebuf);
+
+       while (pg_get_line_buf(fh, &linebuf))
        {
-               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, ';');
+               cmnt = strchr(linebuf.data, ';');
                if (cmnt != NULL)
+               {
                        cmnt[0] = '\0';
+                       linebuf.len = cmnt - linebuf.data;
+               }
 
                /* Ignore if all blank */
-               if (strspn(buf, " \t\r\n") == strlen(buf))
+               if (strspn(linebuf.data, " \t\r\n") == linebuf.len)
                        continue;
 
                /* Get an ID, check it's valid and not already seen */
-               id = strtol(buf, &endptr, 10);
-               if (endptr == buf || id <= 0 || id > AH->maxDumpId ||
+               id = strtol(linebuf.data, &endptr, 10);
+               if (endptr == linebuf.data || id <= 0 || id > AH->maxDumpId ||
                        ropt->idWanted[id - 1])
                {
-                       pg_log_warning("line ignored: %s", buf);
+                       pg_log_warning("line ignored: %s", linebuf.data);
                        continue;
                }
 
@@ -1443,6 +1432,8 @@ SortTocFromFile(Archive *AHX)
                _moveBefore(AH->toc, te);
        }
 
+       pg_free(linebuf.data);
+
        if (fclose(fh) != 0)
                fatal("could not close TOC file: %m");
 }