BUG #19421: PostgreSQL MERGE Crash: heap_compute_data_size() at heaptuple.c:236 - Mailing list pgsql-bugs
| From | PG Bug reporting form |
|---|---|
| Subject | BUG #19421: PostgreSQL MERGE Crash: heap_compute_data_size() at heaptuple.c:236 |
| Date | |
| Msg-id | 19421-3d118fd489810af1@postgresql.org Whole thread Raw |
| Responses |
Re: BUG #19421: PostgreSQL MERGE Crash: heap_compute_data_size() at heaptuple.c:236
|
| List | pgsql-bugs |
The following bug has been logged on the website:
Bug reference: 19421
Logged by: chunling qin
Email address: 303677365@qq.com
PostgreSQL version: 15.5
Operating system: centos
Description:
-- PostgreSQL MERGE SIGSEGV Minimal Reproduction
-- Crash location: heap_compute_data_size() at heaptuple.c:236
-- Cleanup
DROP TABLE IF EXISTS child_tbl CASCADE;
DROP TABLE IF EXISTS parent_tbl CASCADE;
-- 1. Create parent table
CREATE TABLE parent_tbl (
id int not null,
val int
);
-- 2. Create child table with variable-length column and different column
order
CREATE TABLE child_tbl (
filler text, -- variable-length column, will be dropped
val int,
id int not null,
CHECK (id > 0)
);
-- 3. Drop variable-length column to create dropped column
ALTER TABLE child_tbl DROP COLUMN filler;
-- 4. Establish inheritance
ALTER TABLE child_tbl INHERIT parent_tbl;
-- 5. Add NO INHERIT constraint so only child table is selected for INSERT
ALTER TABLE parent_tbl ADD CONSTRAINT pcheck CHECK (id < 0) NO INHERIT;
-- 6. Execute MERGE - crashes here
MERGE INTO parent_tbl p
USING (VALUES (1)) AS src(id) ON p.id = src.id
WHEN NOT MATCHED THEN INSERT (id, val) VALUES (src.id, 100);
[root@VM-253-35-tencentos pgdata]#
[root@VM-253-35-tencentos pgdata]#
[root@VM-253-35-tencentos pgdata]#
[root@VM-253-35-tencentos pgdata]#
[root@VM-253-35-tencentos pgdata]#
[root@VM-253-35-tencentos pgdata]# cat /data/pgdata/BUG_REPORT.md
# Bug Report: SIGSEGV in MERGE INTO inheritance table with dropped column
## Summary
PostgreSQL server crashes with SIGSEGV when executing `MERGE ... WHEN NOT
MATCHED THEN INSERT` on an inheritance parent table, where the child table
has a dropped variable-length column and a different column order than the
parent.
## PostgreSQL Version
PostgreSQL 15.5
## Minimal Reproduction
```sql
-- 1. Create parent table
CREATE TABLE parent_tbl (
id int not null,
val int
);
-- 2. Create child table with variable-length column and different column
order
CREATE TABLE child_tbl (
filler text, -- variable-length column, will be dropped
val int,
id int not null,
CHECK (id > 0)
);
-- 3. Drop variable-length column (creates dropped column with attlen=-1)
ALTER TABLE child_tbl DROP COLUMN filler;
-- 4. Establish inheritance
ALTER TABLE child_tbl INHERIT parent_tbl;
-- 5. Add NO INHERIT constraint so only child table is selected for INSERT
ALTER TABLE parent_tbl ADD CONSTRAINT pcheck CHECK (id < 0) NO INHERIT;
-- 6. Execute MERGE - crashes here
MERGE INTO parent_tbl p
USING (VALUES (1)) AS src(id) ON p.id = src.id
WHEN NOT MATCHED THEN INSERT (id, val) VALUES (src.id, 100);
```
## Crash Location
```
#0 heap_compute_data_size() at heaptuple.c:236
#1 heap_form_tuple()
#2 tts_buffer_heap_materialize()
#3 ExecMaterializeSlot()
#4 ExecInsert()
#5 ExecMergeNotMatched() at nodeModifyTable.c:3172
```
## Root Cause Analysis
The crash occurs due to improper handling of dropped columns in the tuple
slot during MERGE INSERT:
1. The child table has 3 attributes: `[dropped(attlen=-1), val, id]`
2. Due to constraint exclusion (NO INHERIT constraint on parent), only the
child table is selected as the result relation (`mt_nrels=1`)
3. The `ri_newTupleSlot` uses the child table's TupleDescriptor (3 columns)
4. The projection only fills values for the 2 valid columns
5. **Bug**: The dropped column's `isnull[0]` is `false` but `values[0]` is
`0` (null pointer)
6. `heap_compute_data_size()` attempts to call
`VARATT_CAN_MAKE_SHORT(DatumGetPointer(0))` on the variable-length dropped
column, causing SIGSEGV
## Key Conditions
- Child table must have a **dropped variable-length column** (attlen = -1)
- Child table must have **different column order** than parent (created
independently, then inherited)
- Constraint exclusion must result in **only child table** being selected as
result relation
- Execute `MERGE ... WHEN NOT MATCHED THEN INSERT`
## Expected Behavior
The MERGE statement should either:
1. Properly set `isnull[i] = true` for dropped columns in the projection
slot, or
2. Skip dropped columns when computing data size in
`heap_compute_data_size()`
## Actual Behavior
Server crashes with SIGSEGV (signal 11).
pgsql-bugs by date: