BUG #19421: PostgreSQL MERGE Crash: heap_compute_data_size() at heaptuple.c:236

From: PG Bug reporting form <noreply(at)postgresql(dot)org>
To: pgsql-bugs(at)lists(dot)postgresql(dot)org
Cc: 303677365(at)qq(dot)com
Subject: BUG #19421: PostgreSQL MERGE Crash: heap_compute_data_size() at heaptuple.c:236
Date: 2026-02-28 01:26:07
Message-ID: 19421-3d118fd489810af1@postgresql.org
Views: Whole Thread | Raw Message | Download mbox | Resend email
Thread:
Lists: pgsql-bugs

The following bug has been logged on the website:

Bug reference: 19421
Logged by: chunling qin
Email address: 303677365(at)qq(dot)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(at)VM-253-35-tencentos pgdata]#
[root(at)VM-253-35-tencentos pgdata]#
[root(at)VM-253-35-tencentos pgdata]#
[root(at)VM-253-35-tencentos pgdata]#
[root(at)VM-253-35-tencentos pgdata]#
[root(at)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).

Responses

Browse pgsql-bugs by date

  From Date Subject
Next Message Tom Lane 2026-02-28 19:56:02 Re: BUG #19421: PostgreSQL MERGE Crash: heap_compute_data_size() at heaptuple.c:236
Previous Message Tom Lane 2026-02-27 21:52:07 Re: Major Version Upgrade failure due to orphan roles entries in catalog