Skip to content

Commit 4b948d8

Browse files
author
Commitfest Bot
committed
[CF 6449] BUG #19382: Server crash at __nss_database_lookup
This branch was automatically generated by a robot using patches from an email thread registered at: https://commitfest.postgresql.org/patch/6449 The branch will be overwritten each time a new patch version is posted to the thread, and also periodically to check for bitrot caused by changes on the master branch. Patch(es): https://www.postgresql.org/message-id/CAOVWO5rJ8sAtrBytkTmawjpBpOR453zYh7n3vaj5FfWx=bMM5w@mail.gmail.com Author(s): Surya Poondla
2 parents 1d1d7b0 + 8420847 commit 4b948d8

4 files changed

Lines changed: 906 additions & 1 deletion

File tree

src/pl/plpgsql/src/expected/plpgsql_record.out

Lines changed: 284 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -885,3 +885,287 @@ table two_int8s_tab;
885885
(42,42)
886886
(1 row)
887887

888+
-- Tests for bug #19382: server crash when ALTER TYPE is used mid-transaction
889+
-- in PL/pgSQL. Record variables populated before ALTER TYPE must not be
890+
-- returned, as the stored data no longer matches the current type definition.
891+
-- Case 1: Direct composite type change (INT -> TEXT)
892+
create type bug19382_foo as (a int, b int);
893+
create function bug19382_test_direct() returns record as $$
894+
declare r bug19382_foo := row(123, power(2, 30));
895+
begin
896+
alter type bug19382_foo alter attribute b type text;
897+
return r;
898+
end;
899+
$$ language plpgsql;
900+
select bug19382_test_direct();
901+
ERROR: cannot return record variable "r" after composite type "bug19382_foo" was altered
902+
CONTEXT: PL/pgSQL function bug19382_test_direct() line 5 at RETURN
903+
drop function bug19382_test_direct();
904+
drop type bug19382_foo cascade;
905+
-- Case 2: Nested composite type change
906+
create type bug19382_inner as (x int, y int);
907+
create type bug19382_outer as (a int, b bug19382_inner);
908+
create function bug19382_test_nested() returns record as $$
909+
declare r bug19382_outer;
910+
begin
911+
r := row(1, row(10, power(2, 30)::int4)::bug19382_inner)::bug19382_outer;
912+
alter type bug19382_inner alter attribute y type text;
913+
return r;
914+
end;
915+
$$ language plpgsql;
916+
select bug19382_test_nested();
917+
ERROR: cannot return record variable "r" after composite type "bug19382_inner" was altered
918+
CONTEXT: PL/pgSQL function bug19382_test_nested() line 6 at RETURN
919+
drop function bug19382_test_nested();
920+
drop type bug19382_outer cascade;
921+
drop type bug19382_inner cascade;
922+
-- Case 3: OUT parameter
923+
create type bug19382_foo1 as (a int, b int);
924+
create function bug19382_test_out(out r1 bug19382_foo1) as $$
925+
begin
926+
r1 := row(1, 2);
927+
alter type bug19382_foo1 alter attribute b type text;
928+
return;
929+
end;
930+
$$ language plpgsql;
931+
select bug19382_test_out();
932+
ERROR: cannot return record variable "r1" after composite type "bug19382_foo1" was altered
933+
CONTEXT: PL/pgSQL function bug19382_test_out() line 5 at RETURN
934+
drop function bug19382_test_out();
935+
drop type bug19382_foo1 cascade;
936+
-- Case 4: No ALTER TYPE (baseline — must not error)
937+
create type bug19382_foo2 as (a int, b int);
938+
create function bug19382_test_baseline() returns bug19382_foo2 as $$
939+
declare r bug19382_foo2 := row(1, 2);
940+
begin
941+
return r;
942+
end;
943+
$$ language plpgsql;
944+
select bug19382_test_baseline();
945+
bug19382_test_baseline
946+
------------------------
947+
(1,2)
948+
(1 row)
949+
950+
drop function bug19382_test_baseline();
951+
drop type bug19382_foo2;
952+
-- Case 5: Field-by-field assignment (dot notation)
953+
create type bug19382_foo3 as (a int, b int);
954+
create function bug19382_test_field_assign() returns record as $$
955+
declare r bug19382_foo3;
956+
begin
957+
r.a := 123;
958+
r.b := power(2, 30)::int4;
959+
alter type bug19382_foo3 alter attribute b type text;
960+
return r;
961+
end;
962+
$$ language plpgsql;
963+
select bug19382_test_field_assign();
964+
ERROR: cannot return record variable "r" after composite type "bug19382_foo3" was altered
965+
CONTEXT: PL/pgSQL function bug19382_test_field_assign() line 7 at RETURN
966+
drop function bug19382_test_field_assign();
967+
drop type bug19382_foo3 cascade;
968+
-- Case 6: SELECT INTO individual fields
969+
create type bug19382_foo4 as (a int, b int);
970+
create table bug19382_tbl (a int, b int);
971+
insert into bug19382_tbl values (123, power(2, 30)::int4);
972+
create function bug19382_test_select_into_field() returns record as $$
973+
declare r bug19382_foo4;
974+
begin
975+
select a, b into r.a, r.b from bug19382_tbl;
976+
alter type bug19382_foo4 alter attribute b type text;
977+
return r;
978+
end;
979+
$$ language plpgsql;
980+
select bug19382_test_select_into_field();
981+
ERROR: cannot return record variable "r" after composite type "bug19382_foo4" was altered
982+
CONTEXT: PL/pgSQL function bug19382_test_select_into_field() line 6 at RETURN
983+
drop function bug19382_test_select_into_field();
984+
drop table bug19382_tbl;
985+
drop type bug19382_foo4 cascade;
986+
-- Case 7: RAISE NOTICE with record variable (exec_eval_datum path)
987+
create type bug19382_foo5 as (a int, b int);
988+
create function bug19382_test_eval_datum() returns void as $$
989+
declare r bug19382_foo5;
990+
begin
991+
r.b := power(2, 30)::int4;
992+
alter type bug19382_foo5 alter attribute b type text;
993+
raise notice 'r = %', r;
994+
end;
995+
$$ language plpgsql;
996+
select bug19382_test_eval_datum();
997+
ERROR: cannot return record variable "r" after composite type "bug19382_foo5" was altered
998+
CONTEXT: PL/pgSQL function bug19382_test_eval_datum() line 6 at RAISE
999+
drop function bug19382_test_eval_datum();
1000+
drop type bug19382_foo5 cascade;
1001+
-- Case 8: Variable-to-variable copy after inner-type alter.
1002+
-- Reading r1 as an rvalue must detect the stale nested type.
1003+
create type bug19382_inner4 as (x int, y int);
1004+
create type bug19382_outer4 as (a int, b bug19382_inner4);
1005+
create function bug19382_test_var_copy() returns bug19382_outer4 as $$
1006+
declare r1 bug19382_outer4; r2 bug19382_outer4;
1007+
begin
1008+
r1 := row(1, row(10, power(2, 30)::int4)::bug19382_inner4)::bug19382_outer4;
1009+
alter type bug19382_inner4 alter attribute y type text;
1010+
r2 := r1;
1011+
return r2;
1012+
end;
1013+
$$ language plpgsql;
1014+
select bug19382_test_var_copy();
1015+
ERROR: cannot return record variable "r1" after composite type "bug19382_inner4" was altered
1016+
CONTEXT: PL/pgSQL function bug19382_test_var_copy() line 6 at assignment
1017+
drop function bug19382_test_var_copy();
1018+
drop type bug19382_outer4 cascade;
1019+
drop type bug19382_inner4 cascade;
1020+
-- Case 9: Whole-record reassignment after inner-type alter.
1021+
-- The second assignment builds fresh data matching the post-ALTER type;
1022+
-- the snapshot must refresh so the reassignment succeeds.
1023+
create type bug19382_inner3 as (x int, y int);
1024+
create type bug19382_outer3 as (a int, b bug19382_inner3);
1025+
create function bug19382_test_reassign() returns bug19382_outer3 as $$
1026+
declare r bug19382_outer3;
1027+
begin
1028+
r := row(1, row(10, 20)::bug19382_inner3)::bug19382_outer3;
1029+
alter type bug19382_inner3 alter attribute y type text;
1030+
r := row(1, row(10, 'hello')::bug19382_inner3)::bug19382_outer3;
1031+
return r;
1032+
end;
1033+
$$ language plpgsql;
1034+
select bug19382_test_reassign();
1035+
bug19382_test_reassign
1036+
------------------------
1037+
(1,"(10,hello)")
1038+
(1 row)
1039+
1040+
drop function bug19382_test_reassign();
1041+
drop type bug19382_outer3 cascade;
1042+
drop type bug19382_inner3 cascade;
1043+
-- Case 9 (outer-type variant): Whole-record reassignment after ALTER TYPE on
1044+
-- the record's own type. The reassigned bytes match the post-ALTER definition;
1045+
-- the outer-type identifier (er_tupdesc_id) on the ExpandedRecord must be
1046+
-- refreshed so check_record_type_not_altered() does not falsely reject.
1047+
create type bug19382_foo_outer_reassign as (a int, b int);
1048+
create function bug19382_test_outer_reassign() returns bug19382_foo_outer_reassign as $$
1049+
declare r bug19382_foo_outer_reassign;
1050+
begin
1051+
r := row(1, 2)::bug19382_foo_outer_reassign;
1052+
alter type bug19382_foo_outer_reassign alter attribute b type text;
1053+
r := row(1, 'hello')::bug19382_foo_outer_reassign;
1054+
return r;
1055+
end;
1056+
$$ language plpgsql;
1057+
select bug19382_test_outer_reassign();
1058+
bug19382_test_outer_reassign
1059+
------------------------------
1060+
(1,hello)
1061+
(1 row)
1062+
1063+
drop function bug19382_test_outer_reassign();
1064+
drop type bug19382_foo_outer_reassign cascade;
1065+
-- Case 10: Generic RECORD variable assigned via ROW::foo cast
1066+
-- The declared type is RECORDOID; effective type is discovered from the
1067+
-- assigned value's er_typeid. Must error, not crash.
1068+
create type bug19382_foo6 as (a int, b int);
1069+
create function bug19382_test_generic_record() returns record as $$
1070+
declare r record;
1071+
begin
1072+
r := row(123, power(2, 30)::int4)::bug19382_foo6;
1073+
alter type bug19382_foo6 alter attribute b type text;
1074+
return r;
1075+
end;
1076+
$$ language plpgsql;
1077+
select bug19382_test_generic_record();
1078+
ERROR: cannot return record variable "r" after composite type "bug19382_foo6" was altered
1079+
CONTEXT: PL/pgSQL function bug19382_test_generic_record() line 6 at RETURN
1080+
drop function bug19382_test_generic_record();
1081+
drop type bug19382_foo6 cascade;
1082+
-- Case 11: Generic RECORD with nested composite alter
1083+
create type bug19382_inner2 as (x int, y int);
1084+
create type bug19382_outer2 as (a int, b bug19382_inner2);
1085+
create function bug19382_test_generic_nested() returns record as $$
1086+
declare r record;
1087+
begin
1088+
r := row(1, row(10, power(2, 30)::int4)::bug19382_inner2)::bug19382_outer2;
1089+
alter type bug19382_inner2 alter attribute y type text;
1090+
return r;
1091+
end;
1092+
$$ language plpgsql;
1093+
select bug19382_test_generic_nested();
1094+
ERROR: cannot return record variable "r" after composite type "bug19382_inner2" was altered
1095+
CONTEXT: PL/pgSQL function bug19382_test_generic_nested() line 6 at RETURN
1096+
drop function bug19382_test_generic_nested();
1097+
drop type bug19382_outer2 cascade;
1098+
drop type bug19382_inner2 cascade;
1099+
-- Case 12: Anonymous rowtype baseline (RECORDOID with no ::foo cast).
1100+
-- Non-versionable rowtypes must not trigger a false positive.
1101+
create function bug19382_test_anon_baseline() returns record as $$
1102+
declare r record;
1103+
begin
1104+
select 1 as a, 2 as b into r;
1105+
return r;
1106+
end;
1107+
$$ language plpgsql;
1108+
select bug19382_test_anon_baseline();
1109+
bug19382_test_anon_baseline
1110+
-----------------------------
1111+
(1,2)
1112+
(1 row)
1113+
1114+
drop function bug19382_test_anon_baseline();
1115+
-- Case 13: RAISE NOTICE with generic RECORD (RECORDOID + reader path).
1116+
create type bug19382_foo7 as (a int, b int);
1117+
create function bug19382_test_generic_raise() returns void as $$
1118+
declare r record;
1119+
begin
1120+
r := row(1, power(2, 30)::int4)::bug19382_foo7;
1121+
alter type bug19382_foo7 alter attribute b type text;
1122+
raise notice 'r = %', r;
1123+
end;
1124+
$$ language plpgsql;
1125+
select bug19382_test_generic_raise();
1126+
ERROR: cannot return record variable "r" after composite type "bug19382_foo7" was altered
1127+
CONTEXT: PL/pgSQL function bug19382_test_generic_raise() line 6 at RAISE
1128+
drop function bug19382_test_generic_raise();
1129+
drop type bug19382_foo7 cascade;
1130+
-- Case 14: composite type reachable through an array attribute.
1131+
-- The element composite type must be tracked even though the attribute's
1132+
-- own type is an array; otherwise ALTER TYPE on the element goes undetected
1133+
-- and record_out() crashes reinterpreting the stored bytes.
1134+
create type bug19382_elem as (f1 int);
1135+
create type bug19382_arrparent as (arr bug19382_elem[]);
1136+
create function bug19382_test_array_elem() returns bug19382_arrparent as $$
1137+
declare r bug19382_arrparent;
1138+
begin
1139+
r := row(array[row(power(2, 30)::int4)::bug19382_elem]::bug19382_elem[])::bug19382_arrparent;
1140+
alter type bug19382_elem alter attribute f1 type text;
1141+
return r;
1142+
end;
1143+
$$ language plpgsql;
1144+
select bug19382_test_array_elem();
1145+
ERROR: cannot return record variable "r" after composite type "bug19382_elem" was altered
1146+
CONTEXT: PL/pgSQL function bug19382_test_array_elem() line 6 at RETURN
1147+
drop function bug19382_test_array_elem();
1148+
drop type bug19382_arrparent cascade;
1149+
drop type bug19382_elem cascade;
1150+
-- Case 15: array element composite, whole-record reassignment after ALTER
1151+
-- with fresh matching data must succeed (no false positive on arrays).
1152+
create type bug19382_elem2 as (f1 int);
1153+
create type bug19382_arrparent2 as (arr bug19382_elem2[]);
1154+
create function bug19382_test_array_reassign() returns bug19382_arrparent2 as $$
1155+
declare r bug19382_arrparent2;
1156+
begin
1157+
r := row(array[row(1)::bug19382_elem2]::bug19382_elem2[])::bug19382_arrparent2;
1158+
alter type bug19382_elem2 add attribute f2 text;
1159+
r := row(array[row(1, 'hi')::bug19382_elem2]::bug19382_elem2[])::bug19382_arrparent2;
1160+
return r;
1161+
end;
1162+
$$ language plpgsql;
1163+
select bug19382_test_array_reassign();
1164+
bug19382_test_array_reassign
1165+
------------------------------
1166+
("{""(1,hi)""}")
1167+
(1 row)
1168+
1169+
drop function bug19382_test_array_reassign();
1170+
drop type bug19382_arrparent2 cascade;
1171+
drop type bug19382_elem2 cascade;

0 commit comments

Comments
 (0)