mirror of
https://github.com/postgres/postgres.git
synced 2025-07-11 10:01:57 +03:00
Fix integer-overflow problem in intarray's g_int_decompress().
An array element equal to INT_MAX gave this code indigestion,
causing an infinite loop that surely ended in SIGSEGV. We fixed
some nearby problems awhile ago (cf 757c5182f
) but missed this.
Report and diagnosis by Alexander Lakhin (bug #18273); patch by me
Discussion: https://postgr.es/m/18273-9a832d1da122600c@postgresql.org
This commit is contained in:
@ -287,8 +287,7 @@ g_int_decompress(PG_FUNCTION_ARGS)
|
|||||||
ArrayType *in;
|
ArrayType *in;
|
||||||
int lenin;
|
int lenin;
|
||||||
int *din;
|
int *din;
|
||||||
int i,
|
int i;
|
||||||
j;
|
|
||||||
|
|
||||||
in = DatumGetArrayTypeP(entry->key);
|
in = DatumGetArrayTypeP(entry->key);
|
||||||
|
|
||||||
@ -332,9 +331,12 @@ g_int_decompress(PG_FUNCTION_ARGS)
|
|||||||
dr = ARRPTR(r);
|
dr = ARRPTR(r);
|
||||||
|
|
||||||
for (i = 0; i < lenin; i += 2)
|
for (i = 0; i < lenin; i += 2)
|
||||||
for (j = din[i]; j <= din[i + 1]; j++)
|
{
|
||||||
|
/* use int64 for j in case din[i + 1] is INT_MAX */
|
||||||
|
for (int64 j = din[i]; j <= din[i + 1]; j++)
|
||||||
if ((!i) || *(dr - 1) != j)
|
if ((!i) || *(dr - 1) != j)
|
||||||
*dr++ = j;
|
*dr++ = (int) j;
|
||||||
|
}
|
||||||
|
|
||||||
if (in != (ArrayType *) DatumGetPointer(entry->key))
|
if (in != (ArrayType *) DatumGetPointer(entry->key))
|
||||||
pfree(in);
|
pfree(in);
|
||||||
|
@ -6998,3 +6998,4 @@
|
|||||||
{173,208,229}
|
{173,208,229}
|
||||||
{6,22,142,267,299}
|
{6,22,142,267,299}
|
||||||
{22,122,173,245,293}
|
{22,122,173,245,293}
|
||||||
|
{1,2,101,102,201,202,2147483647}
|
||||||
|
@ -464,13 +464,13 @@ SELECT count(*) from test__int WHERE a @@ '(20&23)|(50&68)';
|
|||||||
SELECT count(*) from test__int WHERE a @@ '20 | !21';
|
SELECT count(*) from test__int WHERE a @@ '20 | !21';
|
||||||
count
|
count
|
||||||
-------
|
-------
|
||||||
6566
|
6567
|
||||||
(1 row)
|
(1 row)
|
||||||
|
|
||||||
SELECT count(*) from test__int WHERE a @@ '!20 & !21';
|
SELECT count(*) from test__int WHERE a @@ '!20 & !21';
|
||||||
count
|
count
|
||||||
-------
|
-------
|
||||||
6343
|
6344
|
||||||
(1 row)
|
(1 row)
|
||||||
|
|
||||||
SET enable_seqscan = off; -- not all of these would use index by default
|
SET enable_seqscan = off; -- not all of these would use index by default
|
||||||
@ -538,13 +538,13 @@ SELECT count(*) from test__int WHERE a @@ '(20&23)|(50&68)';
|
|||||||
SELECT count(*) from test__int WHERE a @@ '20 | !21';
|
SELECT count(*) from test__int WHERE a @@ '20 | !21';
|
||||||
count
|
count
|
||||||
-------
|
-------
|
||||||
6566
|
6567
|
||||||
(1 row)
|
(1 row)
|
||||||
|
|
||||||
SELECT count(*) from test__int WHERE a @@ '!20 & !21';
|
SELECT count(*) from test__int WHERE a @@ '!20 & !21';
|
||||||
count
|
count
|
||||||
-------
|
-------
|
||||||
6343
|
6344
|
||||||
(1 row)
|
(1 row)
|
||||||
|
|
||||||
INSERT INTO test__int SELECT array(SELECT x FROM generate_series(1, 1001) x); -- should fail
|
INSERT INTO test__int SELECT array(SELECT x FROM generate_series(1, 1001) x); -- should fail
|
||||||
@ -614,13 +614,13 @@ SELECT count(*) from test__int WHERE a @@ '(20&23)|(50&68)';
|
|||||||
SELECT count(*) from test__int WHERE a @@ '20 | !21';
|
SELECT count(*) from test__int WHERE a @@ '20 | !21';
|
||||||
count
|
count
|
||||||
-------
|
-------
|
||||||
6566
|
6567
|
||||||
(1 row)
|
(1 row)
|
||||||
|
|
||||||
SELECT count(*) from test__int WHERE a @@ '!20 & !21';
|
SELECT count(*) from test__int WHERE a @@ '!20 & !21';
|
||||||
count
|
count
|
||||||
-------
|
-------
|
||||||
6343
|
6344
|
||||||
(1 row)
|
(1 row)
|
||||||
|
|
||||||
DROP INDEX text_idx;
|
DROP INDEX text_idx;
|
||||||
@ -688,13 +688,13 @@ SELECT count(*) from test__int WHERE a @@ '(20&23)|(50&68)';
|
|||||||
SELECT count(*) from test__int WHERE a @@ '20 | !21';
|
SELECT count(*) from test__int WHERE a @@ '20 | !21';
|
||||||
count
|
count
|
||||||
-------
|
-------
|
||||||
6566
|
6567
|
||||||
(1 row)
|
(1 row)
|
||||||
|
|
||||||
SELECT count(*) from test__int WHERE a @@ '!20 & !21';
|
SELECT count(*) from test__int WHERE a @@ '!20 & !21';
|
||||||
count
|
count
|
||||||
-------
|
-------
|
||||||
6343
|
6344
|
||||||
(1 row)
|
(1 row)
|
||||||
|
|
||||||
RESET enable_seqscan;
|
RESET enable_seqscan;
|
||||||
|
Reference in New Issue
Block a user