From a1c1727cb400b8ae61a13844d7e22ef38e7da79b Mon Sep 17 00:00:00 2001 From: Heikki Linnakangas Date: Mon, 10 Aug 2026 06:38:05 -0700 Subject: [PATCH] Use palloc_array() in pltcl and plperl to avoid overflow Some of these could overflow on 32-bit systems with the right input. Convert all cases where we called palloc() with multiplication to fix them. Not all of them were bugs, but it's better to be safe than sorry. Reported-by: Tulya Project, Team Dhiutsa, Bitecope Technologies Private Ltd Backpatch-through: 14 Security: CVE-2026-14677 --- src/pl/plperl/SPI.xs | 6 +++--- src/pl/plperl/plperl.c | 26 +++++++++++++------------- src/pl/tcl/pltcl.c | 16 ++++++++-------- 3 files changed, 24 insertions(+), 24 deletions(-) diff --git a/src/pl/plperl/SPI.xs b/src/pl/plperl/SPI.xs index e81432e6341..ba1e93970a8 100644 --- a/src/pl/plperl/SPI.xs +++ b/src/pl/plperl/SPI.xs @@ -75,7 +75,7 @@ spi_spi_prepare(sv, ...) char* query = sv2cstr(sv); if (items < 1) Perl_croak(aTHX_ "Usage: spi_prepare(query, ...)"); - argv = ( SV**) palloc(( items - 1) * sizeof(SV*)); + argv = palloc_array(SV*, items - 1); for ( i = 1; i < items; i++) argv[i - 1] = ST(i); RETVAL = plperl_spi_prepare(query, items - 1, argv); @@ -103,7 +103,7 @@ spi_spi_exec_prepared(sv, ...) offset++; } argc = items - offset; - argv = ( SV**) palloc( argc * sizeof(SV*)); + argv = palloc_array(SV*, argc); for ( i = 0; offset < items; offset++, i++) argv[i] = ST(offset); ret_hash = plperl_spi_exec_prepared(query, attr, argc, argv); @@ -123,7 +123,7 @@ spi_spi_query_prepared(sv, ...) if ( items < 1) Perl_croak(aTHX_ "Usage: spi_query_prepared(query, " "[\\@bind_values])"); - argv = ( SV**) palloc(( items - 1) * sizeof(SV*)); + argv = palloc_array(SV*, items - 1); for ( i = 1; i < items; i++) argv[i - 1] = ST(i); RETVAL = plperl_spi_query_prepared(query, items - 1, argv); diff --git a/src/pl/plperl/plperl.c b/src/pl/plperl/plperl.c index dbc6beeac92..eba91f2d7d6 100644 --- a/src/pl/plperl/plperl.c +++ b/src/pl/plperl/plperl.c @@ -1796,9 +1796,9 @@ plperl_modify_tuple(HV *hvTD, TriggerData *tdata, HeapTuple otup) tupdesc = tdata->tg_relation->rd_att; natts = tupdesc->natts; - modvalues = (Datum *) palloc0(natts * sizeof(Datum)); - modnulls = (bool *) palloc0(natts * sizeof(bool)); - modrepls = (bool *) palloc0(natts * sizeof(bool)); + modvalues = palloc0_array(Datum, natts); + modnulls = palloc0_array(bool, natts); + modrepls = palloc0_array(bool, natts); hv_iterinit(hvNew); while ((he = hv_iternext(hvNew))) @@ -2815,9 +2815,9 @@ compile_plperl_function(Oid fn_oid, bool is_trigger, bool is_event_trigger) prodesc->fn_xmin = HeapTupleHeaderGetRawXmin(procTup->t_data); prodesc->fn_tid = procTup->t_self; prodesc->nargs = procStruct->pronargs; - prodesc->arg_out_func = (FmgrInfo *) palloc0(prodesc->nargs * sizeof(FmgrInfo)); - prodesc->arg_is_rowtype = (bool *) palloc0(prodesc->nargs * sizeof(bool)); - prodesc->arg_arraytype = (Oid *) palloc0(prodesc->nargs * sizeof(Oid)); + prodesc->arg_out_func = palloc0_array(FmgrInfo, prodesc->nargs); + prodesc->arg_is_rowtype = palloc0_array(bool, prodesc->nargs); + prodesc->arg_arraytype = palloc0_array(Oid, prodesc->nargs); MemoryContextSwitchTo(oldcontext); /* Remember if function is STABLE/IMMUTABLE */ @@ -3610,9 +3610,9 @@ plperl_spi_prepare(char *query, int argc, SV **argv) snprintf(qdesc->qname, sizeof(qdesc->qname), "%p", qdesc); qdesc->plan_cxt = plan_cxt; qdesc->nargs = argc; - qdesc->argtypes = (Oid *) palloc(argc * sizeof(Oid)); - qdesc->arginfuncs = (FmgrInfo *) palloc(argc * sizeof(FmgrInfo)); - qdesc->argtypioparams = (Oid *) palloc(argc * sizeof(Oid)); + qdesc->argtypes = palloc_array(Oid, argc); + qdesc->arginfuncs = palloc_array(FmgrInfo, argc); + qdesc->argtypioparams = palloc_array(Oid, argc); MemoryContextSwitchTo(oldcontext); /************************************************************ @@ -3783,8 +3783,8 @@ plperl_spi_exec_prepared(char *query, HV *attr, int argc, SV **argv) ************************************************************/ if (argc > 0) { - nulls = (char *) palloc(argc); - argvalues = (Datum *) palloc(argc * sizeof(Datum)); + nulls = palloc_array(char, argc); + argvalues = palloc_array(Datum, argc); } else { @@ -3896,8 +3896,8 @@ plperl_spi_query_prepared(char *query, int argc, SV **argv) ************************************************************/ if (argc > 0) { - nulls = (char *) palloc(argc); - argvalues = (Datum *) palloc(argc * sizeof(Datum)); + nulls = palloc_array(char, argc); + argvalues = palloc_array(Datum, argc); } else { diff --git a/src/pl/tcl/pltcl.c b/src/pl/tcl/pltcl.c index 64fe71da8c7..e2c6d99a6de 100644 --- a/src/pl/tcl/pltcl.c +++ b/src/pl/tcl/pltcl.c @@ -1598,8 +1598,8 @@ compile_pltcl_function(Oid fn_oid, Oid tgreloid, prodesc->fn_xmin = HeapTupleHeaderGetRawXmin(procTup->t_data); prodesc->fn_tid = procTup->t_self; prodesc->nargs = procStruct->pronargs; - prodesc->arg_out_func = (FmgrInfo *) palloc0(prodesc->nargs * sizeof(FmgrInfo)); - prodesc->arg_is_rowtype = (bool *) palloc0(prodesc->nargs * sizeof(bool)); + prodesc->arg_out_func = palloc0_array(FmgrInfo, prodesc->nargs); + prodesc->arg_is_rowtype = palloc0_array(bool, prodesc->nargs); MemoryContextSwitchTo(oldcontext); /* Remember if function is STABLE/IMMUTABLE */ @@ -2118,7 +2118,7 @@ pltcl_quote(ClientData cdata, Tcl_Interp *interp, * grow to and initialize pointers ************************************************************/ cp1 = Tcl_GetStringFromObj(objv[1], &length); - tmp = palloc(length * 2 + 1); + tmp = palloc(add_size(mul_size(length, 2), 1)); cp2 = tmp; /************************************************************ @@ -2677,9 +2677,9 @@ pltcl_SPI_prepare(ClientData cdata, Tcl_Interp *interp, qdesc = palloc0_object(pltcl_query_desc); snprintf(qdesc->qname, sizeof(qdesc->qname), "%p", qdesc); qdesc->nargs = nargs; - qdesc->argtypes = (Oid *) palloc(nargs * sizeof(Oid)); - qdesc->arginfuncs = (FmgrInfo *) palloc(nargs * sizeof(FmgrInfo)); - qdesc->argtypioparams = (Oid *) palloc(nargs * sizeof(Oid)); + qdesc->argtypes = palloc_array(Oid, nargs); + qdesc->arginfuncs = palloc_array(FmgrInfo, nargs); + qdesc->argtypioparams = palloc_array(Oid, nargs); MemoryContextSwitchTo(oldcontext); /************************************************************ @@ -2922,7 +2922,7 @@ pltcl_SPI_execute_plan(ClientData cdata, Tcl_Interp *interp, * Setup the value array for SPI_execute_plan() using * the type specific input functions ************************************************************/ - argvalues = (Datum *) palloc(callObjc * sizeof(Datum)); + argvalues = palloc_array(Datum, callObjc); for (j = 0; j < callObjc; j++) { @@ -3296,7 +3296,7 @@ pltcl_build_tuple_result(Tcl_Interp *interp, Tcl_Obj **kvObjv, int kvObjc, attinmeta = NULL; } - values = (char **) palloc0(tupdesc->natts * sizeof(char *)); + values = palloc0_array(char *, tupdesc->natts); if (kvObjc % 2 != 0) ereport(ERROR,