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

Поиск
Список
Период
Сортировка
От PG Bug reporting form
Тема BUG #19421: PostgreSQL MERGE Crash: heap_compute_data_size() at heaptuple.c:236
Дата
Msg-id 19421-3d118fd489810af1@postgresql.org
обсуждение исходный текст
Ответы Re: BUG #19421: PostgreSQL MERGE Crash: heap_compute_data_size() at heaptuple.c:236
Список 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 по дате отправления: