diff --git a/fix-CVE-2024-4317.patch b/fix-CVE-2024-4317.patch new file mode 100644 index 0000000000000000000000000000000000000000..3930683254e120a0a32a620f0e0ae5cfa8efc83b --- /dev/null +++ b/fix-CVE-2024-4317.patch @@ -0,0 +1,129 @@ +From 6e29963edd55cfc038304322049d8fe697580f2c Mon Sep 17 00:00:00 2001 +From: Tom Lane +Date: Thu, 9 May 2024 13:16:21 -0400 +Subject: [PATCH] Fix recursive RECORD-returning plpython functions. + +If we recursed to a new call of the same function, with a different +coldeflist (AS clause), it would fail because the inner call would +overwrite the outer call's idea of what to return. This is vaguely +like 1d2fe56e4 and c5bec5426, but it's not due to any API decisions: +it's just that we computed the actual output rowtype at the start of +the call, and saved it in the per-procedure data structure. We can +fix it at basically zero cost by doing the computation at the end +of each call instead of the start. + +It's not clear that there's any real-world use-case for such a +function, but given that it doesn't cost anything to fix, +it'd be silly not to. + +Per report from Andreas Karlsson. Back-patch to all supported +branches. + +Discussion: https://postgr.es/m/1651a46d-3c15-4028-a8c1-d74937b54e19@proxel.se +--- + .../plpython/expected/plpython_composite.out | 14 ++++++++ + src/pl/plpython/plpy_exec.c | 33 ++++++++++--------- + src/pl/plpython/sql/plpython_composite.sql | 11 +++++++ + 3 files changed, 42 insertions(+), 16 deletions(-) + +diff --git a/src/pl/plpython/expected/plpython_composite.out b/src/pl/plpython/expected/plpython_composite.out +index bb101e0..674af93 100644 +--- a/src/pl/plpython/expected/plpython_composite.out ++++ b/src/pl/plpython/expected/plpython_composite.out +@@ -569,6 +569,20 @@ SELECT * FROM return_record_2('v3') AS (v1 int, v2 int, v3 int); + 1 | 2 | 3 + (1 row) + ++-- recursion with a different inner result type didn't use to work ++CREATE FUNCTION return_record_3(t text) RETURNS record AS $$ ++if t == "text": ++ plpy.execute("SELECT * FROM return_record_3('int') AS (a int)"); ++ return { "a": "x" } ++elif t == "int": ++ return { "a": 1 } ++$$ LANGUAGE plpython3u; ++SELECT * FROM return_record_3('text') AS (a text); ++ a ++--- ++ x ++(1 row) ++ + -- multi-dimensional array of composite types. + CREATE FUNCTION composite_type_as_list() RETURNS type_record[] AS $$ + return [[('first', 1), ('second', 1)], [('first', 2), ('second', 2)], [('first', 3), ('second', 3)]]; +diff --git a/src/pl/plpython/plpy_exec.c b/src/pl/plpython/plpy_exec.c +index 993a4e2..517b1fe 100644 +--- a/src/pl/plpython/plpy_exec.c ++++ b/src/pl/plpython/plpy_exec.c +@@ -231,7 +231,23 @@ PLy_exec_function(FunctionCallInfo fcinfo, PLyProcedure *proc) + } + else + { +- /* Normal conversion of result */ ++ /* ++ * Normal conversion of result. However, if the result is of type ++ * RECORD, we have to set up for that each time through, since it ++ * might be different from last time. ++ */ ++ if (proc->result.typoid == RECORDOID) ++ { ++ TupleDesc desc; ++ ++ if (get_call_result_type(fcinfo, NULL, &desc) != TYPEFUNC_COMPOSITE) ++ ereport(ERROR, ++ (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), ++ errmsg("function returning record called in context " ++ "that cannot accept type record"))); ++ PLy_output_setup_record(&proc->result, desc, proc); ++ } ++ + rv = PLy_output_convert(&proc->result, plrv, + &fcinfo->isnull); + } +@@ -450,21 +466,6 @@ PLy_function_build_args(FunctionCallInfo fcinfo, PLyProcedure *proc) + PLy_elog(ERROR, "PyDict_SetItemString() failed, while setting up arguments"); + arg = NULL; + } +- +- /* Set up output conversion for functions returning RECORD */ +- if (proc->result.typoid == RECORDOID) +- { +- TupleDesc desc; +- +- if (get_call_result_type(fcinfo, NULL, &desc) != TYPEFUNC_COMPOSITE) +- ereport(ERROR, +- (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), +- errmsg("function returning record called in context " +- "that cannot accept type record"))); +- +- /* cache the output conversion functions */ +- PLy_output_setup_record(&proc->result, desc, proc); +- } + } + PG_CATCH(); + { +diff --git a/src/pl/plpython/sql/plpython_composite.sql b/src/pl/plpython/sql/plpython_composite.sql +index 2175770..1bb9b83 100644 +--- a/src/pl/plpython/sql/plpython_composite.sql ++++ b/src/pl/plpython/sql/plpython_composite.sql +@@ -208,6 +208,17 @@ SELECT * FROM return_record_2('v4') AS (v1 int, v3 int, v2 int); + SELECT * FROM return_record_2('v3') AS (v1 int, v3 int, v2 int); + SELECT * FROM return_record_2('v3') AS (v1 int, v2 int, v3 int); + ++-- recursion with a different inner result type didn't use to work ++CREATE FUNCTION return_record_3(t text) RETURNS record AS $$ ++if t == "text": ++ plpy.execute("SELECT * FROM return_record_3('int') AS (a int)"); ++ return { "a": "x" } ++elif t == "int": ++ return { "a": 1 } ++$$ LANGUAGE plpython3u; ++ ++SELECT * FROM return_record_3('text') AS (a text); ++ + -- multi-dimensional array of composite types. + CREATE FUNCTION composite_type_as_list() RETURNS type_record[] AS $$ + return [[('first', 1), ('second', 1)], [('first', 2), ('second', 2)], [('first', 3), ('second', 3)]]; +-- +2.27.0 + diff --git a/libpq.spec b/libpq.spec index fbfe3c7e80a7699936803883348652cfdf4d9fb9..cfbca05e17464cc9df36e3ff2ded1af336e73e3d 100644 --- a/libpq.spec +++ b/libpq.spec @@ -1,6 +1,6 @@ Name: libpq Version: 15.6 -Release: 1 +Release: 2 Summary: PostgreSQL client library License: PostgreSQL Url: http://www.postgresql.org/ @@ -10,6 +10,7 @@ Patch0001: libpq-10.3-rpm-pgsql.patch Patch0002: libpq-10.3-var-run-socket.patch Patch0003: libpq-12.1-symbol-versioning.patch Patch0004: add-loongarch-support.patch +Patch0005: fix-CVE-2024-4317.patch BuildRequires: gcc glibc-devel bison flex gawk zlib-devel openssl-devel BuildRequires: krb5-devel openldap-devel gettext multilib-rpm-config @@ -80,6 +81,12 @@ cat pg_config-15.lang >>libpq-devel.lst %_libdir/pkgconfig/libpq.pc %changelog +* Fri May 10 2024 qz_cx wangqingzheng@kylinos.cn - 15.6-2 +- Type:CVE +- ID:NA +- SUG:NA +- DESC: fix CVE-2024-4317 + * Wed Apr 3 2024 xiejing - 15.6-1 - upgrade libpq to 15.6