This is an automated email from the ASF dual-hosted git repository.

reshke pushed a commit to branch REL_2_STABLE
in repository https://gitbox.apache.org/repos/asf/cloudberry.git

commit a7b9fe5bd13812bd3df19dfc5173f3fbfcd9b031
Author: Nathan Bossart <[email protected]>
AuthorDate: Mon May 11 05:13:52 2026 -0700

    refint: Fix SQL injection and buffer overruns.
    
    Maliciously crafted key value updates could achieve SQL injection
    within check_foreign_key().  To fix, ensure new key values are
    properly quoted and escaped in the internally generated SQL
    statements.  While at it, avoid potential buffer overruns by
    replacing the stack buffers for internally generated SQL statements
    with StringInfo.
    
    Reported-by: Nikolay Samokhvalov <[email protected]>
    Author: Nathan Bossart <[email protected]>
    Reviewed-by: Noah Misch <[email protected]>
    Reviewed-by: Tom Lane <[email protected]>
    Reviewed-by: Fujii Masao <[email protected]>
    Security: CVE-2026-6637
    Backpatch-through: 14
---
 contrib/spi/refint.c | 84 ++++++++++++++++++++++++----------------------------
 1 file changed, 38 insertions(+), 46 deletions(-)

diff --git a/contrib/spi/refint.c b/contrib/spi/refint.c
index 5a40d56d05d..3bed330e752 100644
--- a/contrib/spi/refint.c
+++ b/contrib/spi/refint.c
@@ -166,21 +166,24 @@ check_primary_key(PG_FUNCTION_ARGS)
        if (plan->nplans <= 0)
        {
                SPIPlanPtr      pplan;
-               char            sql[8192];
+               StringInfoData sql;
+
+               initStringInfo(&sql);
 
                /*
                 * Construct query: SELECT 1 FROM _referenced_relation_ WHERE 
Pkey1 =
                 * $1 [AND Pkey2 = $2 [...]]
                 */
-               snprintf(sql, sizeof(sql), "select 1 from %s where ", relname);
-               for (i = 0; i < nkeys; i++)
+               appendStringInfo(&sql, "select 1 from %s where ", relname);
+               for (i = 1; i <= nkeys; i++)
                {
-                       snprintf(sql + strlen(sql), sizeof(sql) - strlen(sql), 
"%s = $%d %s",
-                                        args[i + nkeys + 1], i + 1, (i < nkeys 
- 1) ? "and " : "");
+                       appendStringInfo(&sql, "%s = $%d ", args[i + nkeys], i);
+                       if (i < nkeys)
+                               appendStringInfoString(&sql, "and ");
                }
 
                /* Prepare plan for query */
-               pplan = SPI_prepare(sql, nkeys, argtypes);
+               pplan = SPI_prepare(sql.data, nkeys, argtypes);
                if (pplan == NULL)
                        /* internal error */
                        elog(ERROR, "check_primary_key: SPI_prepare returned 
%s", SPI_result_code_string(SPI_result));
@@ -196,6 +199,8 @@ check_primary_key(PG_FUNCTION_ARGS)
                                                                                
                                sizeof(SPIPlanPtr));
                *(plan->splan) = pplan;
                plan->nplans = 1;
+
+               pfree(sql.data);
        }
 
        /*
@@ -416,7 +421,6 @@ check_foreign_key(PG_FUNCTION_ARGS)
        if (plan->nplans <= 0)
        {
                SPIPlanPtr      pplan;
-               char            sql[8192];
                char      **args2 = args;
 
                plan->splan = (SPIPlanPtr *) 
MemoryContextAlloc(TopMemoryContext,
@@ -424,6 +428,10 @@ check_foreign_key(PG_FUNCTION_ARGS)
 
                for (r = 0; r < nrefs; r++)
                {
+                       StringInfoData sql;
+
+                       initStringInfo(&sql);
+
                        relname = args2[0];
 
                        /*---------
@@ -437,8 +445,7 @@ check_foreign_key(PG_FUNCTION_ARGS)
                         *---------
                         */
                        if (action == 'r')
-
-                               snprintf(sql, sizeof(sql), "select 1 from %s 
where ", relname);
+                               appendStringInfo(&sql, "select 1 from %s where 
", relname);
 
                        /*---------
                         * For 'C'ascade action we construct DELETE query
@@ -465,43 +472,24 @@ check_foreign_key(PG_FUNCTION_ARGS)
                                        char       *nv;
                                        int                     k;
 
-                                       snprintf(sql, sizeof(sql), "update %s 
set ", relname);
+                                       appendStringInfo(&sql, "update %s set 
", relname);
                                        for (k = 1; k <= nkeys; k++)
                                        {
-                                               int                     
is_char_type = 0;
-                                               char       *type;
-
                                                fn = SPI_fnumber(tupdesc, 
args_temp[k - 1]);
                                                Assert(fn > 0); /* already 
checked above */
                                                nv = SPI_getvalue(newtuple, 
tupdesc, fn);
-                                               type = SPI_gettype(tupdesc, fn);
-
-                                               if (strcmp(type, "text") == 0 ||
-                                                       strcmp(type, "varchar") 
== 0 ||
-                                                       strcmp(type, "char") == 
0 ||
-                                                       strcmp(type, "bpchar") 
== 0 ||
-                                                       strcmp(type, "date") == 
0 ||
-                                                       strcmp(type, 
"timestamp") == 0)
-                                                       is_char_type = 1;
-#ifdef DEBUG_QUERY
-                                               elog(DEBUG4, "check_foreign_key 
Debug value %s type %s %d",
-                                                        nv, type, 
is_char_type);
-#endif
 
-                                               /*
-                                                * is_char_type =1 i set ' ' 
for define a new value
-                                                */
-                                               snprintf(sql + strlen(sql), 
sizeof(sql) - strlen(sql),
-                                                                " %s = %s%s%s 
%s ",
-                                                                args2[k], 
(is_char_type > 0) ? "'" : "",
-                                                                nv, 
(is_char_type > 0) ? "'" : "", (k < nkeys) ? ", " : "");
+                                               appendStringInfo(&sql, " %s = 
%s ",
+                                                                               
 args2[k], quote_literal_cstr(nv));
+                                               if (k < nkeys)
+                                                       
appendStringInfoString(&sql, ", ");
                                        }
-                                       strcat(sql, " where ");
+                                       appendStringInfoString(&sql, " where ");
 
                                }
                                else
                                        /* DELETE */
-                                       snprintf(sql, sizeof(sql), "delete from 
%s where ", relname);
+                                       appendStringInfo(&sql, "delete from %s 
where ", relname);
 
                        }
 
@@ -513,25 +501,26 @@ check_foreign_key(PG_FUNCTION_ARGS)
                         */
                        else if (action == 's')
                        {
-                               snprintf(sql, sizeof(sql), "update %s set ", 
relname);
+                               appendStringInfo(&sql, "update %s set ", 
relname);
                                for (i = 1; i <= nkeys; i++)
                                {
-                                       snprintf(sql + strlen(sql), sizeof(sql) 
- strlen(sql),
-                                                        "%s = null%s",
-                                                        args2[i], (i < nkeys) 
? ", " : "");
+                                       appendStringInfo(&sql, "%s = null", 
args2[i]);
+                                       if (i < nkeys)
+                                               appendStringInfoString(&sql, ", 
");
                                }
-                               strcat(sql, " where ");
+                               appendStringInfoString(&sql, " where ");
                        }
 
                        /* Construct WHERE qual */
                        for (i = 1; i <= nkeys; i++)
                        {
-                               snprintf(sql + strlen(sql), sizeof(sql) - 
strlen(sql), "%s = $%d %s",
-                                                args2[i], i, (i < nkeys) ? 
"and " : "");
+                               appendStringInfo(&sql, "%s = $%d ", args2[i], 
i);
+                               if (i < nkeys)
+                                       appendStringInfoString(&sql, "and ");
                        }
 
                        /* Prepare plan for query */
-                       pplan = SPI_prepare(sql, nkeys, argtypes);
+                       pplan = SPI_prepare(sql.data, nkeys, argtypes);
                        if (pplan == NULL)
                                /* internal error */
                                elog(ERROR, "check_foreign_key: SPI_prepare 
returned %s", SPI_result_code_string(SPI_result));
@@ -547,11 +536,14 @@ check_foreign_key(PG_FUNCTION_ARGS)
                        plan->splan[r] = pplan;
 
                        args2 += nkeys + 1; /* to the next relation */
+
+#ifdef DEBUG_QUERY
+                       elog(DEBUG4, "check_foreign_key Debug Query is :  %s ", 
sql.data);
+#endif
+
+                       pfree(sql.data);
                }
                plan->nplans = nrefs;
-#ifdef DEBUG_QUERY
-               elog(DEBUG4, "check_foreign_key Debug Query is :  %s ", sql);
-#endif
        }
 
        /*


---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to