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

From: Vlad Romascanu <vromascanu(at)accurev(dot)com>
To: Alex Hunsaker <badalex(at)gmail(dot)com>
Cc: "pgsql-bugs(at)postgresql(dot)org" <pgsql-bugs(at)postgresql(dot)org>
Subject: Re: BUG #5472: Postgres hard crash in ...WHERE <bigint_col> IN (SELECT * FROM (VALUES (<int_value>),...) AS t(col))
Date: 2010-05-25 18:18:46
Message-ID: A5F029F3C1691945A75D058F8FDDFFA85A750D96EC@34093-MBX-C07.mex07a.mlsrvr.com
Views: Raw Message | Whole Thread | Download mbox | Resend email
Thread:
Lists: pgsql-bugs

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(at)gmail(dot)com]
Sent: Tuesday, May 25, 2010 1:27 PM
To: Vlad Romascanu
Cc: pgsql-bugs(at)postgresql(dot)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(at)accurev(dot)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

In response to

Browse pgsql-bugs by date

  From Date Subject
Next Message Christopher.Hotchkiss 2010-05-25 18:30:19 Re: BUG #5471: Postgres License Url is Misspelled
Previous Message Tom Lane 2010-05-25 17:49:19 Re: BUG #5472: Postgres hard crash in ...WHERE <bigint_col> IN (SELECT * FROM (VALUES (<int_value>), ...) AS t(col))