Skip to content

Commit db9127c

Browse files
committed
Remove arbitrary FUNC_MAX_ARGS limit in int2vectorin and oidvectorin.
int2vectorin limited the number of array elements it'd take to FUNC_MAX_ARGS, which is probably fine for the traditional use-cases. But now that pg_publication_rel.prattrs is an int2vector, it's not fine at all: it's easy to construct cases where that can have up to about MaxTupleAttributeNumber entries. Trying to replicate such tables leads to logical-replication failures. As long as we have to touch this code anyway, let's just remove the a-priori limit altogether, and let it accept any size that'll be allowed by repalloc. (Note that since int2vector isn't toastable, we cannot store arrays longer than about BLCKSZ/2; but there is no good excuse for letting int2vectorin depend on that. Perhaps we will lift the no-toast restriction someday.) While at it, also improve the equivalent logic in oidvectorin. I don't know of any practical use-case for long oidvectors right now, but doing it right actually makes the code shorter. Per report from Erik Rijkers. Back-patch to v15 where pg_publication_rel.prattrs was added. Discussion: https://postgr.es/m/668ba539-33c5-8190-ca11-def2913cb94b@xs4all.nl
1 parent a8f7687 commit db9127c

File tree

2 files changed

+22
-29
lines changed

2 files changed

+22
-29
lines changed

src/backend/utils/adt/int.c

Lines changed: 11 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -142,11 +142,13 @@ int2vectorin(PG_FUNCTION_ARGS)
142142
{
143143
char *intString = PG_GETARG_CSTRING(0);
144144
int2vector *result;
145+
int nalloc;
145146
int n;
146147

147-
result = (int2vector *) palloc0(Int2VectorSize(FUNC_MAX_ARGS));
148+
nalloc = 32; /* arbitrary initial size guess */
149+
result = (int2vector *) palloc0(Int2VectorSize(nalloc));
148150

149-
for (n = 0; n < FUNC_MAX_ARGS; n++)
151+
for (n = 0;; n++)
150152
{
151153
long l;
152154
char *endp;
@@ -156,6 +158,12 @@ int2vectorin(PG_FUNCTION_ARGS)
156158
if (*intString == '\0')
157159
break;
158160

161+
if (n >= nalloc)
162+
{
163+
nalloc *= 2;
164+
result = (int2vector *) repalloc(result, Int2VectorSize(nalloc));
165+
}
166+
159167
errno = 0;
160168
l = strtol(intString, &endp, 10);
161169

@@ -175,17 +183,11 @@ int2vectorin(PG_FUNCTION_ARGS)
175183
ereport(ERROR,
176184
(errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
177185
errmsg("invalid input syntax for type %s: \"%s\"",
178-
"integer", intString)));
186+
"smallint", intString)));
179187

180188
result->values[n] = l;
181189
intString = endp;
182190
}
183-
while (*intString && isspace((unsigned char) *intString))
184-
intString++;
185-
if (*intString)
186-
ereport(ERROR,
187-
(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
188-
errmsg("int2vector has too many elements")));
189191

190192
SET_VARSIZE(result, Int2VectorSize(n));
191193
result->ndim = 1;
@@ -260,12 +262,6 @@ int2vectorrecv(PG_FUNCTION_ARGS)
260262
(errcode(ERRCODE_INVALID_BINARY_REPRESENTATION),
261263
errmsg("invalid int2vector data")));
262264

263-
/* check length for consistency with int2vectorin() */
264-
if (ARR_DIMS(result)[0] > FUNC_MAX_ARGS)
265-
ereport(ERROR,
266-
(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
267-
errmsg("oidvector has too many elements")));
268-
269265
PG_RETURN_POINTER(result);
270266
}
271267

src/backend/utils/adt/oid.c

Lines changed: 11 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -195,24 +195,27 @@ oidvectorin(PG_FUNCTION_ARGS)
195195
{
196196
char *oidString = PG_GETARG_CSTRING(0);
197197
oidvector *result;
198+
int nalloc;
198199
int n;
199200

200-
result = (oidvector *) palloc0(OidVectorSize(FUNC_MAX_ARGS));
201+
nalloc = 32; /* arbitrary initial size guess */
202+
result = (oidvector *) palloc0(OidVectorSize(nalloc));
201203

202-
for (n = 0; n < FUNC_MAX_ARGS; n++)
204+
for (n = 0;; n++)
203205
{
204206
while (*oidString && isspace((unsigned char) *oidString))
205207
oidString++;
206208
if (*oidString == '\0')
207209
break;
210+
211+
if (n >= nalloc)
212+
{
213+
nalloc *= 2;
214+
result = (oidvector *) repalloc(result, OidVectorSize(nalloc));
215+
}
216+
208217
result->values[n] = oidin_subr(oidString, &oidString);
209218
}
210-
while (*oidString && isspace((unsigned char) *oidString))
211-
oidString++;
212-
if (*oidString)
213-
ereport(ERROR,
214-
(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
215-
errmsg("oidvector has too many elements")));
216219

217220
SET_VARSIZE(result, OidVectorSize(n));
218221
result->ndim = 1;
@@ -289,12 +292,6 @@ oidvectorrecv(PG_FUNCTION_ARGS)
289292
(errcode(ERRCODE_INVALID_BINARY_REPRESENTATION),
290293
errmsg("invalid oidvector data")));
291294

292-
/* check length for consistency with oidvectorin() */
293-
if (ARR_DIMS(result)[0] > FUNC_MAX_ARGS)
294-
ereport(ERROR,
295-
(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
296-
errmsg("oidvector has too many elements")));
297-
298295
PG_RETURN_POINTER(result);
299296
}
300297

0 commit comments

Comments
 (0)