BUG #5472: Postgres hard crash in ...WHERE <bigint_col> IN (SELECT * FROM (VALUES (<int_value>), ...) AS t(col))

Started by Vlad Romascanualmost 16 years ago6 messagesbugs
Jump to latest
#1Vlad Romascanu
vromascanu@accurev.com

The following bug has been logged online:

Bug reference: 5472
Logged by: Vlad Romascanu
Email address: vromascanu@accurev.com
PostgreSQL version: 8.4.3
Operating system: Windows, Linux
Description: Postgres hard crash in ...WHERE <bigint_col> IN (SELECT
* FROM (VALUES (<int_value>),...) AS t(col))
Details:

The following reproducibly crashes Postgres 8.4.3 (segfault) inside
int84eq() on both Windows and Linux, but works just fine in 8.3.4:

CREATE TABLE t1 (
col1 bigint NOT NULL,
col2 integer NOT NULL,
CONSTRAINT t1_pkey PRIMARY KEY (col1, col2)
);

INSERT INTO t1 (col1, col2) VALUES (0,1),(1,2),(2,3);

SELECT col1, col2 FROM t1 WHERE col1 IN ( SELECT * FROM (VALUES (1),(2)) AS
t2(col1) )

Changing the above to...

SELECT col1, col2 FROM t1 WHERE col1::integer IN ( SELECT * FROM (VALUES
(1),(2)) AS t2(col1) )

...works again.

#2Alex Hunsaker
badalex@gmail.com
In reply to: Vlad Romascanu (#1)
Re: BUG #5472: Postgres hard crash in ...WHERE <bigint_col> IN (SELECT * FROM (VALUES (<int_value>),...) AS t(col))

On Tue, May 25, 2010 at 10:39, Vlad Romascanu <vromascanu@accurev.com> wrote:

The following reproducibly crashes Postgres 8.4.3 (segfault) inside
int84eq() on both Windows and Linux, but works just fine in 8.3.4:

Hrm... Both work for me (8.4.3 and 8.4.4).

--
=> SELECT col1, col2 FROM t1 WHERE col1 IN ( SELECT * FROM (VALUES (1),(2)) AS
(> t2(col1) )
-> ;
col1 | col2
------+------
1 | 2
2 | 3

=> SELECT col1, col2 FROM t1 WHERE col1::integer IN ( SELECT * FROM (VALUES
(> (1),(2)) AS t2(col1) );
col1 | col2
------+------
1 | 2
2 | 3

#3Alex Hunsaker
badalex@gmail.com
In reply to: Alex Hunsaker (#2)
Re: BUG #5472: Postgres hard crash in ...WHERE <bigint_col> IN (SELECT * FROM (VALUES (<int_value>),...) AS t(col))

On Tue, May 25, 2010 at 11:26, Alex Hunsaker <badalex@gmail.com> wrote:

On Tue, May 25, 2010 at 10:39, Vlad Romascanu <vromascanu@accurev.com> wrote:

The following reproducibly crashes Postgres 8.4.3 (segfault) inside
int84eq() on both Windows and Linux, but works just fine in 8.3.4:

Hrm... Both work for me (8.4.3 and 8.4.4).

Ahh it breaks on 32 bit

Program received signal SIGSEGV, Segmentation fault.
0x08276adf in int84eq (fcinfo=0xbfad27cc) at int8.c:271
271 PG_RETURN_BOOL(val1 == val2);
(gdb) bt
#0 0x08276adf in int84eq (fcinfo=0xbfad27cc) at int8.c:271
#1 0x082ee0bb in FunctionCall2 (flinfo=0x8923578, arg1=2, arg2=1) at
fmgr.c:1309
#2 0x0818c27e in execTuplesMatch (slot1=0x89228b8, slot2=0x8922878,
numCols=1, matchColIdx=0x891e628, eqfunctions=0x8923578,
evalContext=0x890c720)
at execGrouping.c:97
#3 0x081a479b in ExecUnique (node=0x8922e08) at nodeUnique.c:88
#4 0x08190278 in ExecProcNode (node=0x8922e08) at execProcnode.c:439
#5 0x081a2a6b in ExecNestLoop (node=0x8922c78) at nodeNestloop.c:120
#6 0x081902f8 in ExecProcNode (node=0x8922c78) at execProcnode.c:404
#7 0x0818f368 in ExecutePlan (queryDesc=0x891ab98,
direction=ForwardScanDirection, count=0) at execMain.c:1504

#4Tom Lane
tgl@sss.pgh.pa.us
In reply to: Vlad Romascanu (#1)
Re: BUG #5472: Postgres hard crash in ...WHERE <bigint_col> IN (SELECT * FROM (VALUES (<int_value>), ...) AS t(col))

"Vlad Romascanu" <vromascanu@accurev.com> writes:

Description: Postgres hard crash in ...WHERE <bigint_col> IN (SELECT
* FROM (VALUES (<int_value>),...) AS t(col))

Fixed, thanks for the report! Patch is here if you need it:
http://archives.postgresql.org/message-id/20100525174447.C0B007541D2@cvs.postgresql.org

regards, tom lane

#5Tom Lane
tgl@sss.pgh.pa.us
In reply to: Alex Hunsaker (#2)
Re: BUG #5472: Postgres hard crash in ...WHERE <bigint_col> IN (SELECT * FROM (VALUES (<int_value>), ...) AS t(col))

Alex Hunsaker <badalex@gmail.com> writes:

On Tue, May 25, 2010 at 10:39, Vlad Romascanu <vromascanu@accurev.com> wrote:

The following reproducibly crashes Postgres 8.4.3 (segfault) inside
int84eq() on both Windows and Linux, but works just fine in 8.3.4:

Hrm... Both work for me (8.4.3 and 8.4.4).

I think it wouldn't crash if you're using a build with pass-by-value
int8. It might even accidentally give correct answers, depending on
endianness etc.

regards, tom lane

#6Vlad Romascanu
vromascanu@accurev.com
In reply to: Alex Hunsaker (#2)
Re: BUG #5472: Postgres hard crash in ...WHERE <bigint_col> IN (SELECT * FROM (VALUES (<int_value>),...) AS t(col))

Interesting. I forgot to mention both the Linux and Windows Postgres builds I'm reproducing this on are 32-bit (!) builds, which is probably highly relevant. I was able to also reproduce the crash with 8.4.4-1 in addition to 8.4.3 on Windows (in both cases using the official builds from the Download Page), haven't tried 8.4.4-1 on Linux yet (I imagine it's also reproducible there -- again, 32-bit builds) but here's what I get with 8.4.3 on Linux:

db=# SELECT version();
version
--------------------------------------------------------------------------- PostgreSQL 8.4.3 on i686-pc-linux-gnu, compiled by GCC gcc (GCC) 3.4.6 20060404 (Red Hat 3.4.6-3), 32-bit
(1 row)

db=# CREATE TABLE t1 (
db(# col1 bigint NOT NULL,
db(# col2 integer NOT NULL,
db(# CONSTRAINT t1_pkey PRIMARY KEY (col1, col2)
db(# );
NOTICE: CREATE TABLE / PRIMARY KEY will create implicit index "t1_pkey" for table "t1"
CREATE TABLE

db=# INSERT INTO t1 (col1, col2) VALUES (0,1),(1,2),(2,3);
INSERT 0 3

db=# SELECT col1, col2 FROM t1 WHERE col1 IN ( SELECT * FROM (VALUES (1),(2)) AS t2(col1) );

***crash during SELECT***

Program received signal SIGSEGV, Segmentation fault.
0x082a9c53 in int84eq (fcinfo=0xbff41850) at int8.c:268
268 int64 val1 = PG_GETARG_INT64(0);

(gdb) bt 10
#0 0x082a9c53 in int84eq (fcinfo=0xbff41850) at int8.c:268
#1 0x08333479 in FunctionCall2 (flinfo=0x96cda28, arg1=2, arg2=1) at fmgr.c:1309
#2 0x0819408c in execTuplesMatch (slot1=0x96ccd68, slot2=0x96ccd28, numCols=1, matchColIdx=0x96ca5d0, eqfunctions=0x96cda28, evalContext=0x96af1c8) at execGrouping.c:97
#3 0x081b0413 in ExecUnique (node=0x96cd2b8) at nodeUnique.c:88
#4 0x08198b4c in ExecProcNode (node=0x96cd2b8) at execProcnode.c:439
#5 0x081ae201 in ExecNestLoop (node=0x96cd128) at nodeNestloop.c:120
#6 0x08198a9c in ExecProcNode (node=0x96cd128) at execProcnode.c:404
#7 0x08196765 in ExecutePlan (estate=0x96ccc98, planstate=0x96cd128, operation=CMD_SELECT, numberTuples=0, direction=ForwardScanDirection, dest=0x96cb558) at execMain.c:1504
#8 0x08194edc in standard_ExecutorRun (queryDesc=0x96bcc10, direction=ForwardScanDirection, count=0) at execMain.c:309
#9 0x08194e13 in ExecutorRun (queryDesc=0x96bcc10, direction=ForwardScanDirection, count=0) at execMain.c:258
(More stack frames follow...)

(gdb) list
263 * Is 64-bit val1 relop 32-bit val2?
264 */
265 Datum
266 int84eq(PG_FUNCTION_ARGS)
267 {
268 int64 val1 = PG_GETARG_INT64(0);
269 int32 val2 = PG_GETARG_INT32(1);
270
271 PG_RETURN_BOOL(val1 == val2);
272 }

(gdb) info locals
val1 = -4294967296
val2 = -1074522056

(gdb) print fcinfo->arg
$2 = {2, 1, 158151112, 138821913, 3220445320, 157483904, 3220445336, 137092009, 158151112, 138821913, 2, 3051643714, 2300, 2, 3220445368, 137002246, 2, 158151112, 1, 0,
158151112, 2, 3220445944, 137573318, 3220445408, 1, 3220445400, 135003796, 1, 4294967295, 3220445448, 158151112, 158152572, 0, 0, 73472, 2, 1, 0, 0, 3081857364, 16777217,
3220445496, 137720153, 860040, 158042512, 256, 860040, 0, 0, 3220445495, 1, 1, 21509248, 3220445544, 137480840, 134842733, 23, 2868, 0, 0, 3220445560, 136675993, 5, 23,
158119256, 3220445816, 137487882, 158002664, 3051025560, 23, 3220445587, 5856, 23, 3051025560, 1, 7156544, 23, 3220445676, 4294967295, 16780084, 0, 158042512, 0, 3051025520,
3051025528, 824, 1671777080, 0, 262142, 0, 137093708, 3, 1, 2, 1, 1, 158134024, 3220445704, 4}

(gdb) print sizeof(fcinfo->arg[0])
$3 = 4

The problem, it seems to me, is that the 64-bit quantity is passed by-value (squeezed into fcinfo->arg[0]'s 32-bits), whereas DatumGetInt64 expects it to have been passed by reference (this being a 32-bit build and all.)

I imagine all of the above will pass with flying colours on 64-bit builds if USE_FLOAT8_BYVAL ends up being #defined.

Cheers,
V.

-----Original Message-----
From: Alex Hunsaker [mailto:badalex@gmail.com]
Sent: Tuesday, May 25, 2010 1:27 PM
To: Vlad Romascanu
Cc: pgsql-bugs@postgresql.org
Subject: Re: [BUGS] BUG #5472: Postgres hard crash in ...WHERE <bigint_col> IN (SELECT * FROM (VALUES (<int_value>),...) AS t(col))

On Tue, May 25, 2010 at 10:39, Vlad Romascanu <vromascanu@accurev.com> wrote:

The following reproducibly crashes Postgres 8.4.3 (segfault) inside
int84eq() on both Windows and Linux, but works just fine in 8.3.4:

Hrm... Both work for me (8.4.3 and 8.4.4).

--
=> SELECT col1, col2 FROM t1 WHERE col1 IN ( SELECT * FROM (VALUES (1),(2)) AS
(> t2(col1) )
-> ;
col1 | col2
------+------
1 | 2
2 | 3

=> SELECT col1, col2 FROM t1 WHERE col1::integer IN ( SELECT * FROM (VALUES
(> (1),(2)) AS t2(col1) );
col1 | col2
------+------
1 | 2
2 | 3