Bug reference: 19466 Logged by: HaoGang Mao Email address: haogangmao@gmail.com PostgreSQL version: 18.3 Operating system: Linux Description:
PostgreSQL version: 18.3 OS: Linux (Docker)
Summary: PostgreSQL crashes with SIGSEGV when a cursor is open over a composite type and the type is modified via ALTER TYPE during the same transaction, followed by a second FETCH.
Reproduction steps (minimal): CREATE TYPE foo AS (a INT, b INT); BEGIN; DECLARE c CURSOR FOR SELECT (i, power(2, 30))::foo FROM generate_series(1,10) i; FETCH c; ALTER TYPE foo ALTER ATTRIBUTE b TYPE TEXT; FETCH c; COMMIT;
Expected: Error message (type modified during active cursor) Actual: Server process terminated with signal 11 (Segmentation fault)
Server log: client backend (PID 85) was terminated by signal 11: Segmentation fault Failed process was running: [above SQL]
Hypothesis: The cursor holds a reference to the tuple descriptor for type "foo". After ALTER TYPE modifies the type, the descriptor may be invalidated while the cursor still holds a dangling pointer to it. The second FETCH dereferences this invalid pointer.
I confirmed the crash on master and traced the root cause. EEOP_ROW was the only rowtype-aware expression step that cached its TupleDesc at init time without an ExprEvalRowtypeCache guard. When ALTER TYPE changes an attribute's storage properties (e.g. int to text), the stale descriptor leads to SIGSEGV.
Attached patch adds the same ExprEvalRowtypeCache check that EEOP_FIELDSELECT, EEOP_FIELDSTORE_DEFORM, etc. already use. With the fix the reproducer gets a clean error instead of crashing.