Re: BUG #16369: Segmentation Faults and Data Corruption with Generated Columns

From: David Rowley <dgrowleyml(at)gmail(dot)com>
To: cameron(dot)ezell(at)clearcapital(dot)com, pgsql-bugs(at)lists(dot)postgresql(dot)org, peter(dot)eisentraut(at)2ndquadrant(dot)com
Subject: Re: BUG #16369: Segmentation Faults and Data Corruption with Generated Columns
Date: 2020-04-15 23:35:57
Message-ID: CAApHDvr7xeMcfGRWQ0rxtagw7CKbjEcjPKfKQAU4KdEcZm6XkQ@mail.gmail.com
Views: Raw Message | Whole Thread | Download mbox | Resend email
Thread:
Lists: pgsql-bugs

On Thu, 16 Apr 2020 at 08:53, PG Bug reporting form
<noreply(at)postgresql(dot)org> wrote:
> -- On CentOS 8, this bug is triggered with a hostname with 10+ characters.
> On MacOS 10.14.6, 19+ characters.
> INSERT INTO test.bug_report(hostname, device, mount, used_space_bytes,
> avail_space_bytes) VALUES ('12345678901234567890', 'devtmpfs', '/dev', 0,
> 6047076131313);commit;
> -- This should immediately crash the postgres service
--LOCATION: palloc, mcxt.c:934

Thanks for the report. This is certainly a bug.

I slightly simplified the test case to become:

drop table if exists crash;

CREATE TABLE crash (
id bigint generated by default as identity,
hostname varchar,
hostname_short varchar GENERATED ALWAYS AS (hostname) STORED,
device text,
mount text,
used_space_bytes bigint,
used_space_gb bigint GENERATED ALWAYS AS (used_space_bytes) STORED,
avail_space_bytes bigint,
avail_space_gb bigint GENERATED ALWAYS AS (avail_space_bytes) STORED,
inserted_dts timestamp with time zone NOT NULL DEFAULT clock_timestamp(),
inserted_by text NOT NULL DEFAULT session_user
);

INSERT INTO crash (hostname, device, mount, used_space_bytes,
avail_space_bytes) VALUES ('12345678901234567', 'devtmpfs', '/dev', 0,
6047076131313); -- no crash
INSERT INTO crash (hostname, device, mount, used_space_bytes,
avail_space_bytes) VALUES ('123456789012345678', 'devtmpfs', '/dev',
0, 6047076131313); -- crash

The crash occurs during ExecComputeStoredGenerated() when calculating
the hostname_short column. When we call ExecEvalExpr() for that
column, the eval function just returns the value of the Datum in the
"hostname" column, which is stored in "slot". This happens to be a
pointer into the tuple. This results in a crash because, later in that
function, we do ExecClearTuple(slot), which frees the memory for that
tuple.

I suppose it normally works because generally the calculation will be
using some SQL function which will return some calculated value which
is allocated, but in this case, we just return the pointer to the
memory in the tuple slot.

I'd say the fix should be to just datumCopy() the result of the
calculation. i.e the attached.

David

Attachment Content-Type Size
fix_generated_column_crash.patch application/octet-stream 661 bytes

In response to

Responses

Browse pgsql-bugs by date

  From Date Subject
Next Message Tom Lane 2020-04-15 23:52:21 Re: BUG #16369: Segmentation Faults and Data Corruption with Generated Columns
Previous Message Tomas Vondra 2020-04-15 21:38:16 Re: BUG #16352: Data corruption in few tables