Skip to content

Commit 647fa50

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 3f244d0 commit 647fa50

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
@@ -143,11 +143,13 @@ int2vectorin(PG_FUNCTION_ARGS)
143143
char *intString = PG_GETARG_CSTRING(0);
144144
Node *escontext = fcinfo->context;
145145
int2vector *result;
146+
int nalloc;
146147
int n;
147148

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

150-
for (n = 0; n < FUNC_MAX_ARGS; n++)
152+
for (n = 0;; n++)
151153
{
152154
long l;
153155
char *endp;
@@ -157,6 +159,12 @@ int2vectorin(PG_FUNCTION_ARGS)
157159
if (*intString == '\0')
158160
break;
159161

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

@@ -176,17 +184,11 @@ int2vectorin(PG_FUNCTION_ARGS)
176184
ereturn(escontext, (Datum) 0,
177185
(errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
178186
errmsg("invalid input syntax for type %s: \"%s\"",
179-
"integer", intString)));
187+
"smallint", intString)));
180188

181189
result->values[n] = l;
182190
intString = endp;
183191
}
184-
while (*intString && isspace((unsigned char) *intString))
185-
intString++;
186-
if (*intString)
187-
ereturn(escontext, (Datum) 0,
188-
(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
189-
errmsg("int2vector has too many elements")));
190192

191193
SET_VARSIZE(result, Int2VectorSize(n));
192194
result->ndim = 1;
@@ -261,12 +263,6 @@ int2vectorrecv(PG_FUNCTION_ARGS)
261263
(errcode(ERRCODE_INVALID_BINARY_REPRESENTATION),
262264
errmsg("invalid int2vector data")));
263265

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

src/backend/utils/adt/oid.c

Lines changed: 11 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -115,27 +115,30 @@ oidvectorin(PG_FUNCTION_ARGS)
115115
char *oidString = PG_GETARG_CSTRING(0);
116116
Node *escontext = fcinfo->context;
117117
oidvector *result;
118+
int nalloc;
118119
int n;
119120

120-
result = (oidvector *) palloc0(OidVectorSize(FUNC_MAX_ARGS));
121+
nalloc = 32; /* arbitrary initial size guess */
122+
result = (oidvector *) palloc0(OidVectorSize(nalloc));
121123

122-
for (n = 0; n < FUNC_MAX_ARGS; n++)
124+
for (n = 0;; n++)
123125
{
124126
while (*oidString && isspace((unsigned char) *oidString))
125127
oidString++;
126128
if (*oidString == '\0')
127129
break;
130+
131+
if (n >= nalloc)
132+
{
133+
nalloc *= 2;
134+
result = (oidvector *) repalloc(result, OidVectorSize(nalloc));
135+
}
136+
128137
result->values[n] = uint32in_subr(oidString, &oidString,
129138
"oid", escontext);
130139
if (SOFT_ERROR_OCCURRED(escontext))
131140
PG_RETURN_NULL();
132141
}
133-
while (*oidString && isspace((unsigned char) *oidString))
134-
oidString++;
135-
if (*oidString)
136-
ereturn(escontext, (Datum) 0,
137-
(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
138-
errmsg("oidvector has too many elements")));
139142

140143
SET_VARSIZE(result, OidVectorSize(n));
141144
result->ndim = 1;
@@ -212,12 +215,6 @@ oidvectorrecv(PG_FUNCTION_ARGS)
212215
(errcode(ERRCODE_INVALID_BINARY_REPRESENTATION),
213216
errmsg("invalid oidvector data")));
214217

215-
/* check length for consistency with oidvectorin() */
216-
if (ARR_DIMS(result)[0] > FUNC_MAX_ARGS)
217-
ereport(ERROR,
218-
(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
219-
errmsg("oidvector has too many elements")));
220-
221218
PG_RETURN_POINTER(result);
222219
}
223220

0 commit comments

Comments
 (0)