Re: logrep stuck with 'ERROR: int2vector has too many elements' - Mailing list pgsql-hackers

From Tom Lane
Subject Re: logrep stuck with 'ERROR: int2vector has too many elements'
Date
Msg-id 1688010.1673813836@sss.pgh.pa.us
Whole thread Raw
In response to Re: logrep stuck with 'ERROR: int2vector has too many elements'  (Andres Freund <andres@anarazel.de>)
Responses Re: logrep stuck with 'ERROR: int2vector has too many elements'
List pgsql-hackers
Andres Freund <andres@anarazel.de> writes:
> On 2023-01-15 14:39:41 -0500, Tom Lane wrote:
>> But I suppose we are stuck with that, seeing that this datatype choice
>> is effectively part of the logrep protocol now.  I think the only
>> reasonable solution is to get rid of the FUNC_MAX_ARGS restriction
>> in int2vectorin.  We probably ought to back-patch that as far as
>> pg_publication_rel.prattrs exists, too.

> Are you thinking of introducing another, or just "rely" on too long arrays to
> trigger errors when forming tuples?

There's enough protections already, eg repalloc will complain if you
try to go past 1GB.  I'm thinking of the attached for HEAD (it'll
take minor mods to back-patch).

            regards, tom lane

diff --git a/src/backend/utils/adt/int.c b/src/backend/utils/adt/int.c
index e47c15a54f..44d1c7ad0c 100644
--- a/src/backend/utils/adt/int.c
+++ b/src/backend/utils/adt/int.c
@@ -143,11 +143,13 @@ int2vectorin(PG_FUNCTION_ARGS)
     char       *intString = PG_GETARG_CSTRING(0);
     Node       *escontext = fcinfo->context;
     int2vector *result;
+    int            nalloc;
     int            n;
 
-    result = (int2vector *) palloc0(Int2VectorSize(FUNC_MAX_ARGS));
+    nalloc = 32;                /* arbitrary initial size guess */
+    result = (int2vector *) palloc0(Int2VectorSize(nalloc));
 
-    for (n = 0; n < FUNC_MAX_ARGS; n++)
+    for (n = 0;; n++)
     {
         long        l;
         char       *endp;
@@ -157,6 +159,12 @@ int2vectorin(PG_FUNCTION_ARGS)
         if (*intString == '\0')
             break;
 
+        if (n >= nalloc)
+        {
+            nalloc *= 2;
+            result = (int2vector *) repalloc(result, Int2VectorSize(nalloc));
+        }
+
         errno = 0;
         l = strtol(intString, &endp, 10);
 
@@ -176,17 +184,11 @@ int2vectorin(PG_FUNCTION_ARGS)
             ereturn(escontext, (Datum) 0,
                     (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
                      errmsg("invalid input syntax for type %s: \"%s\"",
-                            "integer", intString)));
+                            "smallint", intString)));
 
         result->values[n] = l;
         intString = endp;
     }
-    while (*intString && isspace((unsigned char) *intString))
-        intString++;
-    if (*intString)
-        ereturn(escontext, (Datum) 0,
-                (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
-                 errmsg("int2vector has too many elements")));
 
     SET_VARSIZE(result, Int2VectorSize(n));
     result->ndim = 1;
@@ -261,12 +263,6 @@ int2vectorrecv(PG_FUNCTION_ARGS)
                 (errcode(ERRCODE_INVALID_BINARY_REPRESENTATION),
                  errmsg("invalid int2vector data")));
 
-    /* check length for consistency with int2vectorin() */
-    if (ARR_DIMS(result)[0] > FUNC_MAX_ARGS)
-        ereport(ERROR,
-                (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
-                 errmsg("oidvector has too many elements")));
-
     PG_RETURN_POINTER(result);
 }
 
diff --git a/src/backend/utils/adt/oid.c b/src/backend/utils/adt/oid.c
index 697588313d..3f7af5b3a0 100644
--- a/src/backend/utils/adt/oid.c
+++ b/src/backend/utils/adt/oid.c
@@ -115,27 +115,30 @@ oidvectorin(PG_FUNCTION_ARGS)
     char       *oidString = PG_GETARG_CSTRING(0);
     Node       *escontext = fcinfo->context;
     oidvector  *result;
+    int            nalloc;
     int            n;
 
-    result = (oidvector *) palloc0(OidVectorSize(FUNC_MAX_ARGS));
+    nalloc = 32;                /* arbitrary initial size guess */
+    result = (oidvector *) palloc0(OidVectorSize(nalloc));
 
-    for (n = 0; n < FUNC_MAX_ARGS; n++)
+    for (n = 0;; n++)
     {
         while (*oidString && isspace((unsigned char) *oidString))
             oidString++;
         if (*oidString == '\0')
             break;
+
+        if (n >= nalloc)
+        {
+            nalloc *= 2;
+            result = (oidvector *) repalloc(result, OidVectorSize(nalloc));
+        }
+
         result->values[n] = uint32in_subr(oidString, &oidString,
                                           "oid", escontext);
         if (SOFT_ERROR_OCCURRED(escontext))
             PG_RETURN_NULL();
     }
-    while (*oidString && isspace((unsigned char) *oidString))
-        oidString++;
-    if (*oidString)
-        ereturn(escontext, (Datum) 0,
-                (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
-                 errmsg("oidvector has too many elements")));
 
     SET_VARSIZE(result, OidVectorSize(n));
     result->ndim = 1;
@@ -212,12 +215,6 @@ oidvectorrecv(PG_FUNCTION_ARGS)
                 (errcode(ERRCODE_INVALID_BINARY_REPRESENTATION),
                  errmsg("invalid oidvector data")));
 
-    /* check length for consistency with oidvectorin() */
-    if (ARR_DIMS(result)[0] > FUNC_MAX_ARGS)
-        ereport(ERROR,
-                (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
-                 errmsg("oidvector has too many elements")));
-
     PG_RETURN_POINTER(result);
 }


pgsql-hackers by date:

Previous
From: Andrey Chudnovsky
Date:
Subject: Re: [PoC] Federated Authn/z with OAUTHBEARER
Next
From: Andres Freund
Date:
Subject: Re: Sampling-based timing for EXPLAIN ANALYZE