Received: from malur.postgresql.org ([217.196.149.56]) by arkaria.postgresql.org with esmtps (TLS1.3) tls TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 (Exim 4.96) (envelope-from ) id 1vj5oe-006LNh-1s for pgsql-bugs@arkaria.postgresql.org; Fri, 23 Jan 2026 01:18:25 +0000 Received: from localhost ([127.0.0.1] helo=malur.postgresql.org) by malur.postgresql.org with esmtp (Exim 4.96) (envelope-from ) id 1vj5od-00FU2J-2U for pgsql-bugs@arkaria.postgresql.org; Fri, 23 Jan 2026 01:18:24 +0000 Received: from magus.postgresql.org ([2a02:c0:301:0:ffff::29]) by malur.postgresql.org with esmtps (TLS1.3) tls TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 (Exim 4.96) (envelope-from ) id 1vj5od-00FU2A-1H for pgsql-bugs@lists.postgresql.org; Fri, 23 Jan 2026 01:18:23 +0000 Received: from mail-vs1-xe31.google.com ([2607:f8b0:4864:20::e31]) by magus.postgresql.org with esmtps (TLS1.3) tls TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256 (Exim 4.98.2) (envelope-from ) id 1vj5ob-000000002Sx-1v8A for pgsql-bugs@lists.postgresql.org; Fri, 23 Jan 2026 01:18:23 +0000 Received: by mail-vs1-xe31.google.com with SMTP id ada2fe7eead31-5eeff7e8bb3so1693124137.1 for ; Thu, 22 Jan 2026 17:18:21 -0800 (PST) ARC-Seal: i=1; a=rsa-sha256; t=1769131099; cv=none; d=google.com; s=arc-20240605; b=E/0vwNggLv+oEMkLHvVevq9eERM9yyaemBguOXo1naWA0dTSZzUykZcoR8uEB7jriq ShIAkANFla0lOeNt6V1GLxzwKN4w08BWl8PBJKVWqcL5LNG4bWbLVAgmBc20qBEvm3GL JfTUMaWy95MyJe25rta0AoZsH002dKUem7x0QyKRQTQHngmzPa9lptsmFwpYoq6Sj+VO L1w92JkDBcvt525FM+TmD084xWq51ZlJ96nRbTJPgcdxCsBcegO9Ww0PBPBwLHbIHM3u hFZBmXveOj2lAdPIlEatpzg8CT8xxb13jUWi0FU5SU5ZIG9KaG/GGHrBHTzOV23zjJ1T cISA== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20240605; h=to:subject:message-id:date:from:in-reply-to:references:mime-version :dkim-signature; bh=uLdBcPWS4G07Ezy7TjsP+Zb9oAELTRjEZpeurSJS90U=; fh=6qDBmNXEu8fSx8ld+8sR8Keaj7dhCREHJB61if0ylS4=; b=eR4EC13y0i7XP/KX7s7BpV01oBa471nx1XXCHddX+xRUjvo+4i4w/iLfwERaYtTLH7 slzDvG1A7GqNwTpmdd46x+d/TKYqTS4LezN0SACKv778zuOeNqYWRhIjKB84brQLUPfN wA6xar/tTpt6/XqyWBdHkHMnSHLnEq4nBFVhnAPH75GaDa+P6QE6qxXFFplIn3oEh6b1 ZjK9wrAx0NPX3O0uR+UStjDO8qS2b8ZSqvd96t2hx9dwrlz3Xf7Un7hRCCI+L/4cOYBi AUBfGpXX67Iv5242aOO9TKcApqljuPF1zMAi2mapJZaIijGeoH5gewlB1LAAF2+QoZVu tHww==; darn=lists.postgresql.org ARC-Authentication-Results: i=1; mx.google.com; arc=none DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1769131099; x=1769735899; darn=lists.postgresql.org; h=to:subject:message-id:date:from:in-reply-to:references:mime-version :from:to:cc:subject:date:message-id:reply-to; bh=uLdBcPWS4G07Ezy7TjsP+Zb9oAELTRjEZpeurSJS90U=; b=kowltyPkVL7SH4iJMM/NIXJjGYmtwFdsGsP/DFzDvXd8LaZ0KTpF6vbY5EMgWPV+3X sqUiYMT2HSZ62w3o4h6P6qX6SDruDF6SyckU3WNgmKYnZs3lIdXHdT8z5xmAIzklNunj 6uxBAzKLd08aqutd2eJs7idXEEUH+l4DXxan5Z4HpPRRe1VetoJKBmDFeQhVorVGzEWX 18XF5uN3MeCnAvZZYBSrP6AE/QODxy0ax6TamMKUv27r1MpQxsc+IprPn2Jccj5+3+Hk kCQyhb71uTc942tqhyZku0MfH4dN7gCIG3JRwVKOropvpiuo15I6p6s16X6xgApnXABp OwxQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1769131099; x=1769735899; h=to:subject:message-id:date:from:in-reply-to:references:mime-version :x-gm-gg:x-gm-message-state:from:to:cc:subject:date:message-id :reply-to; bh=uLdBcPWS4G07Ezy7TjsP+Zb9oAELTRjEZpeurSJS90U=; b=uzvvy+uRW7u6F/BRYXmQmfAnhWLT7mhsMlFcQNOqqEEo3G3X5dXpwNEjasxnMT0s+b WhzuOYjDCbY76b+0YSl5gJHA2vu6jKCBcMcgXzvZ79+VASZJOLTJGhE/tUOEUzL4ev9i M5T9OAk+v78vyL5fVs/7EtAO/tjsXwk9baTX3RyQof/IQrWKT9dhzmcVP+g0rrrD5Pky xgT+ksVhkjPSRGUr1gHeDuchCnv9TvjhLmIljNr/dkUN7TUZUIV7jTyd+nDqrRDx7mal X88m/JqP1uXrLeQ6CF7CAoY4fxsqxsEDfDAzM17/aWzggKrTz7Nt7YORJZv5IbxliGVe dIOw== X-Forwarded-Encrypted: i=1; AJvYcCUy0CyhwAnV13Z4hwm7RLaAtX0EuMxeyISmyeWmkl6hxzuJClVu1dhatJyffli9iHP6Ucx73OUoOB5E@lists.postgresql.org X-Gm-Message-State: AOJu0YxTkU6/dbV4EZzhyY1YwnCtLTculATgEos21Vwt9NIMbw68SWxP TmhjAeCWJp7bWBG+yMaeypoN9IEz7uiaP/Y/+nrRR/lQGymwI7UbSb7AQGSzsZzlyeoradXE0/H ZbECFt6VdBehtEX80FtkbuHhZdY1/44YIjykv X-Gm-Gg: AZuq6aLuLR4XJCycoUcIplqB6e+MYpicTGF5Y3tMFpyOBvrZvfWOZUX03ORoLjWDt5q chlKayy0NZS5y1NrUcbkmk/hklBwyoDXa8mCqkPuL918LZY2OuKLs0kD8xRcPiS2lgoXyygkmgW 0dU1K8wUSVNLWArp0E6UXZZ6M5l5zDPX1f3isb3wbaPJ3e084RlyYmryFnXHCWYzTNi18XV1S05 z6hC0lbZTLzE9iYodiiy+SCSk5xC/IB4qgsCLJ+wNQjtyhC2bIbsEhOznzcZMAUGH/CuYo= X-Received: by 2002:a05:6102:441c:b0:5f1:c519:9506 with SMTP id ada2fe7eead31-5f54bb4c5c4mr607492137.17.1769131099485; Thu, 22 Jan 2026 17:18:19 -0800 (PST) MIME-Version: 1.0 References: <19382-4c2060ffee72759b@postgresql.org> In-Reply-To: <19382-4c2060ffee72759b@postgresql.org> From: surya poondla Date: Thu, 22 Jan 2026 17:18:08 -0800 X-Gm-Features: AZwV_QiN6rfFY89MpUcpDu0euebvDo4B1UE0RB_I_YhaLiY2BAEh5Ni2h85hkNM Message-ID: Subject: Re: BUG #19382: Server crash at __nss_database_lookup To: dllggyx@outlook.com, pgsql-bugs@lists.postgresql.org Content-Type: multipart/alternative; boundary="000000000000befa0e064903ee86" List-Id: List-Help: List-Subscribe: List-Post: List-Owner: List-Archive: Archived-At: Precedence: bulk --000000000000befa0e064903ee86 Content-Type: text/plain; charset="UTF-8" Hi Yuxiao, Kirill, Thank you for the test cases. I can reproduce this issue on PostgreSQL 17.6. I debugged it with lldb and found the root cause. When a composite type is altered mid-transaction while a PL/pgSQL record variable holds data of that type, the server crashes because it interprets old data using the new type definition without performing type conversion. The server crashes with this stack trace: * thread #1, queue = 'main-thread', stop reason = EXC_BAD_ACCESS (code=1, address=0x117e00000) frame #0: 0x0000000183c95320 libsystem_platform.dylib`_platform_memmove + 96 libsystem_platform.dylib`_platform_memmove: -> 0x183c95320 <+96>: ldnp q0, q1, [x1] 0x183c95324 <+100>: add x1, x1, #0x20 0x183c95328 <+104>: subs x2, x2, #0x20 0x183c9532c <+108>: b.hi 0x183c95318 ; <+88> Target 0: (postgres) stopped. (lldb) bt * thread #1, queue = 'main-thread', stop reason = EXC_BAD_ACCESS (code=1, address=0x117e00000) * frame #0: 0x0000000183c95320 libsystem_platform.dylib`_platform_memmove + 96 frame #1: 0x00000001030ef368 postgres`text_to_cstring(t=0x0000000117017b1c) at varlena.c:225:2 frame #2: 0x00000001030f0e58 postgres`textout(fcinfo=0x000000016d5f1b98) at varlena.c:594:2 frame #3: 0x000000010314ed14 postgres`FunctionCall1Coll(flinfo=0x0000000121808cd8, collation=0, arg1=4680940316) at fmgr.c:1139:11 frame #4: 0x0000000103150880 postgres`OutputFunctionCall(flinfo=0x0000000121808cd8, val=4680940316) at fmgr.c:1685:25 frame #5: 0x0000000103075c8c postgres`record_out(fcinfo=0x000000016d5f1d58) at rowtypes.c:435:11 frame #6: 0x000000010314ed14 postgres`FunctionCall1Coll(flinfo=0x0000000121808a28, collation=0, arg1=4940960546) at fmgr.c:1139:11 frame #7: 0x0000000103150880 postgres`OutputFunctionCall(flinfo=0x0000000121808a28, val=4940960546) at fmgr.c:1685:25 frame #8: 0x000000010282fa30 postgres`printtup(slot=0x00000001218087a8, self=0x00000001170102d8) at printtup.c:360:16 frame #9: 0x0000000102b8fdac postgres`ExecutePlan(queryDesc=0x0000000137010300, operation=CMD_SELECT, sendTuples=true, numberTuples=0, direction=ForwardScanDirection, dest=0x00000001170102d8) at execMain.c:1679:9 frame #10: 0x0000000102b8fb98 postgres`standard_ExecutorRun(queryDesc=0x0000000137010300, direction=ForwardScanDirection, count=0, execute_once=false) at execMain.c:360:3 frame #11: 0x0000000102b8f988 postgres`ExecutorRun(queryDesc=0x0000000137010300, direction=ForwardScanDirection, count=0, execute_once=false) at execMain.c:306:3 frame #12: 0x0000000102ee2bd4 postgres`PortalRunSelect(portal=0x000000012782c500, forward=true, count=0, dest=0x00000001170102d8) at pquery.c:922:4 frame #13: 0x0000000102ee2568 postgres`PortalRun(portal=0x000000012782c500, count=9223372036854775807, isTopLevel=true, run_once=true, dest=0x00000001170102d8, altdest=0x00000001170102d8, qc=0x000000016d5f21b8) at pquery.c:766:18 frame #14: 0x0000000102edce9c postgres`exec_simple_query(query_string="SELECT bar();") at postgres.c:1278:10 frame #15: 0x0000000102edbf6c postgres`PostgresMain(dbname="postgres", username="surya") at postgres.c:4767:7 frame #16: 0x0000000102ed3594 postgres`BackendMain(startup_data="", startup_data_len=4) at backend_startup.c:106:2 frame #17: 0x0000000102daf8f8 postgres`postmaster_child_launch(child_type=B_BACKEND, startup_data="", startup_data_len=4, client_sock=0x000000016d5f25b8) at launch_backend.c:277:3 frame #18: 0x0000000102db7708 postgres`BackendStartup(client_sock=0x000000016d5f25b8) at postmaster.c:3624:8 frame #19: 0x0000000102db4438 postgres`ServerLoop at postmaster.c:1678:6 frame #20: 0x0000000102db3324 postgres`PostmasterMain(argc=3, argv=0x000060000321d420) at postmaster.c:1376:11 frame #21: 0x0000000102c369c0 postgres`main(argc=3, argv=0x000060000321d420) at main.c:199:3 frame #22: 0x00000001838bab98 dyld`start + 6076 (lldb) The crash happens because textout() is called on integer data, and it interprets 1073741824 (2^30) as a memory pointer. I set breakpoints at two critical points to trace the issue: Breakpoint 1: ExpandedRecordGetDatum (when PL/pgSQL returns the record) At this point, the record still has complete version information: (lldb) p erh->er_tupdesc_id (uint64) 2 // Record was created with version 2 (lldb) p assign_record_type_identifier(erh->er_typeid, erh->er_typmod) (uint64) 4 // Current type is now version 4 (lldb) p erh->er_tupdesc->attrs[1].atttypid (Oid) 23 // Field b was INT4 when record was created (lldb) p ((TypeCacheEntry*)lookup_type_cache(erh->er_typeid, 0x00100))->tupDesc->attrs[1].atttypid (Oid) 25 // Field b is now TEXT in current definition Version mismatch detected (2 != 4). The record has integer data but the type definition changed to TEXT. Breakpoint 2: record_out (when converting record to text for output) After ExpandedRecordGetDatum flattens the record to HeapTupleHeader, the version information is lost: (lldb) p tupType (Oid) 32770 //Only type OID preserved (lldb) p tupTypmod (int32) -1 //Only typmod preserved (lldb) p tupdesc->attrs[1].atttypid (Oid) 25 // Uses current definition: TEXT When ExpandedRecordHeader is flattened to HeapTupleHeader, HeapTupleHeader only stores type OID and typmod but not the version identifier. This returns the current type definition (version 4, field b = TEXT), but the actual data is still from version 2 (field b = INT, value = 1073741824). The crash happens at rowtypes.c, when record_out() calls textout() on field b. Since textout() expects a text pointer but receives an integer, it tries to dereference 0x40000000 (1073741824 (2^30)), causing a segfault that leads to the crash. I believe the fix should be in pl_exec.c before the record is returned. At the point where we still have access to erh->er_tupdesc_id, and we can compare erh->er_tupdesc_id with current tupDesc_identifier, if they differ, the type was altered. For each field with changed type, apply conversion using exec_cast_value(). If conversion fails or no cast exists, raise a proper error, if not return the converted record with updated version This prevents crashes by either converting the data (INT to TEXT which should work) or raising a clean error message instead of a segfault. I am working on a patch for this. Kindly let me know your thoughts. --000000000000befa0e064903ee86 Content-Type: text/html; charset="UTF-8" Content-Transfer-Encoding: quoted-printable

Hi Yuxiao, Kirill,

Thank you for the test = cases.


I can= reproduce this issue on PostgreSQL 17.6. I debugged it with lldb and found= the root cause.

When = a composite type is altered mid-transaction while a PL/pgSQL record variabl= e holds data of that type, the server crashes because it interprets old dat= a using the new type definition without performing type conversion.


The s= erver crashes with this stack trace:

* thr= ead #1, queue =3D 'main-thread', stop reason =3D EXC_BAD_ACCESS (co= de=3D1, address=3D0x117e00000)

=C2=A0 =C2=A0 frame #0: 0x000= 0000183c95320 libsystem_platform.dylib`_platform_memmove + 96

libsy= stem_platform.dylib`_platform_memmove:

->= =C2=A0 0x183c95320 <+= 96>:=C2=A0 ldnp =C2=A0 q0, q1, [x1]

=C2=A0 =C2=A0 0x183c95324 <= ;+100>: add=C2=A0 =C2=A0 x1, x1, #0x20

=C2=A0 =C2=A0 0x183c95328 <= ;+104>: subs =C2=A0 x= 2, x2, #0x20

=C2=A0 =C2=A0 0x183c9532c <= ;+108>: b.hi =C2=A0 0= x183c95318=C2=A0 =C2=A0 = ; <+88>

Targe= t 0: (postgres) stopped.

(lldb= ) bt

* thr= ead #1, queue =3D 'main-thread', stop reason =3D EXC_BAD_ACCESS (co= de=3D1, address=3D0x117e00000)

=C2=A0 * frame #0: 0x00000001= 83c95320 libsystem_platform.dylib`_platform_memmove + 96

=C2=A0 =C2=A0 frame #1: 0x000= 00001030ef368 postgres`text_to_cstring(t=3D0x0000000117017b1c) at varlena.c= :225:2

=C2=A0 =C2=A0 frame #2: 0x000= 00001030f0e58 postgres`textout(fcinfo=3D0x000000016d5f1b98) at varlena.c:59= 4:2

=C2=A0 =C2=A0 frame #3: 0x000= 000010314ed14 postgres`FunctionCall1Coll(flinfo=3D0x0000000121808cd8, colla= tion=3D0, arg1=3D4680940316) at fmgr.c:1139:11

=C2=A0 =C2=A0 frame #4: 0x000= 0000103150880 postgres`OutputFunctionCall(flinfo=3D0x0000000121808cd8, val= =3D4680940316) at fmgr.c:1685:25

=C2=A0 =C2=A0 frame #5: 0x000= 0000103075c8c postgres`record_out(fcinfo=3D0x000000016d5f1d58) at rowtypes.= c:435:11

=C2=A0 =C2=A0 frame #6: 0x000= 000010314ed14 postgres`FunctionCall1Coll(flinfo=3D0x0000000121808a28, colla= tion=3D0, arg1=3D4940960546) at fmgr.c:1139:11

=C2=A0 =C2=A0 frame #7: 0x000= 0000103150880 postgres`OutputFunctionCall(flinfo=3D0x0000000121808a28, val= =3D4940960546) at fmgr.c:1685:25

=C2=A0 =C2=A0 frame #8: 0x000= 000010282fa30 postgres`printtup(slot=3D0x00000001218087a8, self=3D0x0000000= 1170102d8) at printtup.c:360:16

=C2=A0 =C2=A0 frame #9: 0x000= 0000102b8fdac postgres`ExecutePlan(queryDesc=3D0x0000000137010300, operatio= n=3DCMD_SELECT, sendTuples=3Dtrue, numberTuples=3D0, direction=3DForwardSca= nDirection, dest=3D0x00000001170102d8) at execMain.c:1679:9

=C2=A0 =C2=A0 frame #10: 0x00= 00000102b8fb98 postgres`standard_ExecutorRun(queryDesc=3D0x0000000137010300= , direction=3DForwardScanDirection, count=3D0, execute_once=3Dfalse) at exe= cMain.c:360:3

=C2=A0 =C2=A0 frame #11: 0x00= 00000102b8f988 postgres`ExecutorRun(queryDesc=3D0x0000000137010300, directi= on=3DForwardScanDirection, count=3D0, execute_once=3Dfalse) at execMain.c:3= 06:3

=C2=A0 =C2=A0 frame #12: 0x00= 00000102ee2bd4 postgres`PortalRunSelect(portal=3D0x000000012782c500, forwar= d=3Dtrue, count=3D0, dest=3D0x00000001170102d8) at pquery.c:922:4

=C2=A0 =C2=A0 frame #13: 0x00= 00000102ee2568 postgres`PortalRun(portal=3D0x000000012782c500, count=3D9223= 372036854775807, isTopLevel=3Dtrue, run_once=3Dtrue, dest=3D0x0000000117010= 2d8, altdest=3D0x00000001170102d8, qc=3D0x000000016d5f21b8) at pquery.c:766= :18

=C2=A0 =C2=A0 frame #14: 0x00= 00000102edce9c postgres`exec_simple_query(query_string=3D"SELECT bar()= ;") at postgres.c:1278:10

=C2=A0 =C2=A0 frame #15: 0x00= 00000102edbf6c postgres`PostgresMain(dbname=3D"postgres", usernam= e=3D"surya") at postgres.c:4767:7

=C2=A0 =C2=A0 frame #16: 0x00= 00000102ed3594 postgres`BackendMain(startup_data=3D"", startup_da= ta_len=3D4) at backend_startup.c:106:2

=C2=A0 =C2=A0 frame #17: 0x00= 00000102daf8f8 postgres`postmaster_child_launch(child_type=3DB_BACKEND, sta= rtup_data=3D"", startup_data_len=3D4, client_sock=3D0x000000016d5= f25b8) at launch_backend.c:277:3

=C2=A0 =C2=A0 frame #18: 0x00= 00000102db7708 postgres`BackendStartup(client_sock=3D0x000000016d5f25b8) at= postmaster.c:3624:8

=C2=A0 =C2=A0 frame #19: 0x00= 00000102db4438 postgres`ServerLoop at postmaster.c:1678:6

=C2=A0 =C2=A0 frame #20: 0x00= 00000102db3324 postgres`PostmasterMain(argc=3D3, argv=3D0x000060000321d420)= at postmaster.c:1376:11

=C2=A0 =C2=A0 frame #21: 0x00= 00000102c369c0 postgres`main(argc=3D3, argv=3D0x000060000321d420) at main.c= :199:3

=C2=A0 =C2=A0 frame #22: 0x00= 000001838bab98 dyld`start + 6076

(lldb= )



The c= rash happens because textout() is called on integer data, and it interprets= 1073741824 (2^30) as a memory pointer.


I set= breakpoints at two critical points to trace the issue:


Break= point 1: ExpandedRecordGetDatum (when PL/pgSQL returns the record)

At th= is point, the record still has complete version information:


(lldb= ) p erh->er_tupdesc_id

(uint= 64) 2=C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 // Record was c= reated with version 2


(lldb= ) p assign_record_type_identifier(erh->er_typeid, erh->er_typmod)

(uint= 64) 4=C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 // Current type= is now version 4


(lldb= ) p erh->er_tupdesc->attrs[1].atttypid

(Oid)= 23=C2=A0 =C2=A0 =C2=A0 =C2=A0 = =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 // Field b w= as INT4 when record was created


(lldb= ) p ((TypeCacheEntry*)lookup_type_cache(erh->er_typeid, 0x00100))->tu= pDesc->attrs[1].atttypid

(Oid)= 25=C2=A0 =C2=A0 =C2=A0 =C2=A0 = =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 // Field b i= s now TEXT in current definition


V= ersion mismatch detected (2 !=3D 4). The record has integer data but the ty= pe definition changed to TEXT.


Break= point 2: record_out (when converting record to text for output)

After= ExpandedRecordGetDatum flattens the record to HeapTupleHeader, the version= information is lost:


(lldb= ) p tupType

(Oid)= 32770=C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 //Only type OID preserved


(lldb= ) p tupTypmod

(int3= 2) -1=C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 //Only typmod p= reserved

(lldb= ) p tupdesc->attrs[1].atttypid

(Oid)= 25=C2=A0 =C2=A0 =C2=A0 =C2=A0 = =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 // Uses curr= ent definition: TEXT


When = ExpandedRecordHeader is flattened to HeapTupleHeader, HeapTupleHeader only = stores type OID and typmod but not the version identifier.


This = returns the current type definition (version 4, field b =3D TEXT), but the = actual data is still from version 2 (field b =3D INT, value =3D 1073741824)= .


The c= rash happens at rowtypes.c, when record_out() calls textout() on field b. S= ince textout() expects a text pointer but receives an integer, it tries to = dereference 0x40000000 (1073741824 (2^30)), causing a segfault that=C2=A0le= ads to the crash.



<= /p>

I bel= ieve the fix should be in pl_exec.c before the record is returned. At the p= oint where we still have access to erh->er_tupdesc_id, and we can compar= e erh->er_tupdesc_id with current tupDesc_identifier, if they differ, th= e type was altered. For each field with changed type, apply conversion usin= g exec_cast_value().

If co= nversion fails or no cast exists, raise a proper error, if not return the c= onverted record with updated version

This = prevents crashes by either converting the data (INT to TEXT which should wo= rk) or raising a clean error message instead of a segfault.


I am working on a patch for this.

Kindl= y let me know your thoughts.

--000000000000befa0e064903ee86--