Location via proxy:   [ UP ]  
[Report a bug]   [Manage cookies]                
Skip to content

Commit 6753f6c

Browse files
committed
Fix pg_dump's logic for eliding sequence limits that match the defaults.
The previous coding here applied atoi() to strings that could represent values too large to fit in an int. If the overflowed value happened to match one of the cases it was looking for, it would drop that limit value from the output, leading to incorrect restoration of the sequence. Avoid the unsafe behavior, and also make the logic cleaner by explicitly calculating the default min/max values for the appropriate kind of sequence. Reported and patched by Alexey Bashtanov, though I whacked his patch around a bit. Back-patch to v10 where the faulty logic was added. Discussion: https://postgr.es/m/cb85a9a5-946b-c7c4-9cf2-6cd6e25d7a33@imap.cc
1 parent 517e0fe commit 6753f6c

File tree

1 file changed

+29
-24
lines changed

1 file changed

+29
-24
lines changed

src/bin/pg_dump/pg_dump.c

Lines changed: 29 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -16337,6 +16337,10 @@ dumpSequence(Archive *fout, TableInfo *tbinfo)
1633716337
*seqtype;
1633816338
bool cycled;
1633916339
bool is_ascending;
16340+
int64 default_minv,
16341+
default_maxv;
16342+
char bufm[32],
16343+
bufx[32];
1634016344
PQExpBuffer query = createPQExpBuffer();
1634116345
PQExpBuffer delqry = createPQExpBuffer();
1634216346
PQExpBuffer labelq = createPQExpBuffer();
@@ -16406,40 +16410,41 @@ dumpSequence(Archive *fout, TableInfo *tbinfo)
1640616410
cache = PQgetvalue(res, 0, 5);
1640716411
cycled = (strcmp(PQgetvalue(res, 0, 6), "t") == 0);
1640816412

16409-
is_ascending = incby[0] != '-';
16410-
16411-
if (is_ascending && atoi(minv) == 1)
16412-
minv = NULL;
16413-
if (!is_ascending && atoi(maxv) == -1)
16414-
maxv = NULL;
16415-
16413+
/* Calculate default limits for a sequence of this type */
16414+
is_ascending = (incby[0] != '-');
1641616415
if (strcmp(seqtype, "smallint") == 0)
1641716416
{
16418-
if (!is_ascending && atoi(minv) == PG_INT16_MIN)
16419-
minv = NULL;
16420-
if (is_ascending && atoi(maxv) == PG_INT16_MAX)
16421-
maxv = NULL;
16417+
default_minv = is_ascending ? 1 : PG_INT16_MIN;
16418+
default_maxv = is_ascending ? PG_INT16_MAX : -1;
1642216419
}
1642316420
else if (strcmp(seqtype, "integer") == 0)
1642416421
{
16425-
if (!is_ascending && atoi(minv) == PG_INT32_MIN)
16426-
minv = NULL;
16427-
if (is_ascending && atoi(maxv) == PG_INT32_MAX)
16428-
maxv = NULL;
16422+
default_minv = is_ascending ? 1 : PG_INT32_MIN;
16423+
default_maxv = is_ascending ? PG_INT32_MAX : -1;
1642916424
}
1643016425
else if (strcmp(seqtype, "bigint") == 0)
1643116426
{
16432-
char bufm[100],
16433-
bufx[100];
16427+
default_minv = is_ascending ? 1 : PG_INT64_MIN;
16428+
default_maxv = is_ascending ? PG_INT64_MAX : -1;
16429+
}
16430+
else
16431+
{
16432+
exit_horribly(NULL, "unrecognized sequence type: %s\n", seqtype);
16433+
default_minv = default_maxv = 0; /* keep compiler quiet */
16434+
}
1643416435

16435-
snprintf(bufm, sizeof(bufm), INT64_FORMAT, PG_INT64_MIN);
16436-
snprintf(bufx, sizeof(bufx), INT64_FORMAT, PG_INT64_MAX);
16436+
/*
16437+
* 64-bit strtol() isn't very portable, so convert the limits to strings
16438+
* and compare that way.
16439+
*/
16440+
snprintf(bufm, sizeof(bufm), INT64_FORMAT, default_minv);
16441+
snprintf(bufx, sizeof(bufx), INT64_FORMAT, default_maxv);
1643716442

16438-
if (!is_ascending && strcmp(minv, bufm) == 0)
16439-
minv = NULL;
16440-
if (is_ascending && strcmp(maxv, bufx) == 0)
16441-
maxv = NULL;
16442-
}
16443+
/* Don't print minv/maxv if they match the respective default limit */
16444+
if (strcmp(minv, bufm) == 0)
16445+
minv = NULL;
16446+
if (strcmp(maxv, bufx) == 0)
16447+
maxv = NULL;
1644316448

1644416449
/*
1644516450
* DROP must be fully qualified in case same name appears in pg_catalog

0 commit comments

Comments
 (0)