Summary
plpgsql_check_function_tb crashes its PostgreSQL backend when it analyzes a
PL/pgSQL function that reads a record-typed OUT column into a local record
and subsequently assigns fields from that local record. The connection is
lost; PostgreSQL recovers and accepts new connections.
This report contains only a standalone synthetic fixture. It has no application
schema, business names, data, credentials, or project-specific SQL.
Environment
- PostgreSQL 18.4 on Debian arm64.
plpgsql_check built from official release v2.10.1
(7e1d6fcc6d3d5d5fd83337ea6a07003ddcaa3bf3).
- The extension was invoked with
fatal_errors := false and all other
analyzer options explicitly named below.
The same crash was also observed while evaluating v2.9.3 and the PGDG 2.9.2
package. The reproducer below is the smallest public-safe case currently
available; please use it as the primary diagnosis input.
Reproducer
Run this in a new database with plpgsql_check installed:
CREATE EXTENSION plpgsql_check;
CREATE TYPE demo_payload AS (value integer);
CREATE FUNCTION demo_produce_row(
OUT status_code integer,
OUT payload record
) LANGUAGE plpgsql AS $$
BEGIN
status_code := 0;
payload := ROW(1)::demo_payload;
END
$$;
CREATE FUNCTION demo_consume_row()
RETURNS void LANGUAGE plpgsql AS $$
DECLARE
fetched_row record;
typed_payload demo_payload;
observed_status integer;
BEGIN
SELECT * INTO STRICT fetched_row FROM demo_produce_row() AS result_row;
typed_payload := fetched_row.payload;
observed_status := fetched_row.status_code;
END
$$;
SELECT count(*)
FROM plpgsql_check_function_tb(
'demo_consume_row()'::regprocedure,
fatal_errors := false,
other_warnings := true,
performance_warnings := false,
extra_warnings := true,
security_warnings := false,
compatibility_warnings := false,
without_warnings := false,
all_warnings := false,
use_incomment_options := true,
incomment_options_usage_warning := false,
constant_tracing := true
);
Actual result
The client connection is closed. PostgreSQL logs a message equivalent to:
server process was terminated by signal 11: Segmentation fault
After the server finishes recovery, a new session can execute SELECT 1.
Expected result
plpgsql_check_function_tb should return diagnostics (or no rows) without
terminating the backend.
Narrowing controls
The crash does not occur in these variants:
- Declare
payload as demo_payload rather than record in
demo_produce_row.
- Keep
payload record and SELECT * INTO STRICT fetched_row, but remove
both assignments from fetched_row.
- Keep
payload record, but select only status_code into an integer target.
The suspected triggering shape is therefore:
record-typed OUT field
+ SELECT * INTO STRICT local_record
+ read one or more fields from local_record
Request
Could you please check it?
Summary
plpgsql_check_function_tbcrashes its PostgreSQL backend when it analyzes aPL/pgSQL function that reads a record-typed
OUTcolumn into a localrecordand subsequently assigns fields from that local record. The connection is
lost; PostgreSQL recovers and accepts new connections.
This report contains only a standalone synthetic fixture. It has no application
schema, business names, data, credentials, or project-specific SQL.
Environment
plpgsql_checkbuilt from official releasev2.10.1(
7e1d6fcc6d3d5d5fd83337ea6a07003ddcaa3bf3).fatal_errors := falseand all otheranalyzer options explicitly named below.
The same crash was also observed while evaluating
v2.9.3and the PGDG 2.9.2package. The reproducer below is the smallest public-safe case currently
available; please use it as the primary diagnosis input.
Reproducer
Run this in a new database with
plpgsql_checkinstalled:Actual result
The client connection is closed. PostgreSQL logs a message equivalent to:
After the server finishes recovery, a new session can execute
SELECT 1.Expected result
plpgsql_check_function_tbshould return diagnostics (or no rows) withoutterminating the backend.
Narrowing controls
The crash does not occur in these variants:
payloadasdemo_payloadrather thanrecordindemo_produce_row.payload recordandSELECT * INTO STRICT fetched_row, but removeboth assignments from
fetched_row.payload record, but select onlystatus_codeinto an integer target.The suspected triggering shape is therefore:
Request
Could you please check it?