From: Alexander Lakhin <exclusion@gmail.com>
To: Richard Guo <guofenglinux@gmail.com>
To: Ankit Kumar Pandey <itsankitkp@gmail.com>
To: David Rowley <dgrowleyml@gmail.com>
To: Teodor Sigaev <teodor@sigaev.ru>
To: pgsql-bugs@lists.postgresql.org
Subject: Re: BUG #17888: Incorrect memory access in gist__int_ops for an input array with many elements
Date: Wed, 31 May 2023 09:00:00 +0300
Message-ID: <f7ab52bb-e0ee-4acd-9bb1-ac28d22e39f5@gmail.com> (raw)
In-Reply-To: <CAMbWs48s6Uhv9wngJVtv=7DGEyN9a-SzwBKsfz2hY7yS6z7ZQw@mail.gmail.com>
References: <17888-f72930e6b5ce8c14@postgresql.org>
<CAMbWs48s6Uhv9wngJVtv=7DGEyN9a-SzwBKsfz2hY7yS6z7ZQw@mail.gmail.com>
07.04.2023 11:57, Richard Guo wrote:
>
> On Fri, Apr 7, 2023 at 4:21 AM PG Bug reporting form <noreply@postgresql.org> wrote:
>
> NOTICE: input array is too big (199 maximum allowed, 1001 current), use
> gist__intbig_ops opclass instead
>
>
> In g_int_compress,
>
> if (ARRNELEMS(r) >= 2 * num_ranges)
> elog(NOTICE, "input array is too big (%d maximum allowed, %d current), use gist__intbig_ops opclass instead",
> 2 * num_ranges - 1, ARRNELEMS(r));
>
> Wondering why elog with NOTICE rather than Error here.
The NOTICE appeared there in commit 08ee64ebf5 (from year 2005) in an
attempt to get rid of flags (ISLEAFKEY(in)) [1] and probably expressed
an intention to play gently (don't break compatibility?).
The patch proposed at [2] looks correct to me. Thank you, Ankit!
Though I would add a simple case to the intarray regression test and also
add errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED) to other two places in
_int_gist.c for the sake of consistency.
Please look at the patches attached.
[1] https://www.postgresql.org/message-id/43786274.3020200%40sigaev.ru
[2] https://www.postgresql.org/message-id/796b65c3-57b7-bddf-b0d5-a8afafb8b627%40gmail.comAttachments:v2-01-gist-int-ops-overflow.patch (text/x-patch, 2.0K) downloaddiff --git a/contrib/intarray/_int_gist.c b/contrib/intarray/_int_gist.cindex 7a48ce624d..2c82b86dd1 100644--- a/contrib/intarray/_int_gist.c+++ b/contrib/intarray/_int_gist.c@@ -181,8 +181,9 @@ g_int_compress(PG_FUNCTION_ARGS)
PREPAREARR(r);
if (ARRNELEMS(r) >= 2 * num_ranges)
- elog(NOTICE, "input array is too big (%d maximum allowed, %d current), use gist__intbig_ops opclass instead",- 2 * num_ranges - 1, ARRNELEMS(r));+ ereport(ERROR,+ (errmsg("input array is too big (%d maximum allowed, %d current), use gist__intbig_ops opclass instead",+ 2 * num_ranges - 1, ARRNELEMS(r))));
retval = palloc(sizeof(GISTENTRY));
gistentryinit(*retval, PointerGetDatum(r),
diff --git a/contrib/intarray/expected/_int.out b/contrib/intarray/expected/_int.outindex 6abb17e2e5..cad37f1a24 100644--- a/contrib/intarray/expected/_int.out+++ b/contrib/intarray/expected/_int.out@@ -566,6 +566,8 @@ SELECT count(*) from test__int WHERE a @@ '!20 & !21';
6343
(1 row)
+INSERT INTO test__int SELECT array(SELECT x FROM generate_series(1, 1001) x); -- should fail+ERROR: input array is too big (199 maximum allowed, 1001 current), use gist__intbig_ops opclass instead
DROP INDEX text_idx;
CREATE INDEX text_idx on test__int using gist (a gist__int_ops(numranges = 0));
ERROR: value 0 out of bounds for option "numranges"
diff --git a/contrib/intarray/sql/_int.sql b/contrib/intarray/sql/_int.sqlindex d9d987bdb1..a947c4f8fd 100644--- a/contrib/intarray/sql/_int.sql+++ b/contrib/intarray/sql/_int.sql@@ -125,6 +125,8 @@ 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';
+INSERT INTO test__int SELECT array(SELECT x FROM generate_series(1, 1001) x); -- should fail+
DROP INDEX text_idx;
CREATE INDEX text_idx on test__int using gist (a gist__int_ops(numranges = 0));
CREATE INDEX text_idx on test__int using gist (a gist__int_ops(numranges = 253));
v2-02-gist-int-errcodes.patch (text/x-patch, 1.5K) downloaddiff --git a/contrib/intarray/_int_gist.c b/contrib/intarray/_int_gist.cindex 2c82b86dd1..98145fe370 100644--- a/contrib/intarray/_int_gist.c+++ b/contrib/intarray/_int_gist.c@@ -182,7 +182,8 @@ g_int_compress(PG_FUNCTION_ARGS)
if (ARRNELEMS(r) >= 2 * num_ranges)
ereport(ERROR,
- (errmsg("input array is too big (%d maximum allowed, %d current), use gist__intbig_ops opclass instead",+ (errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED),+ errmsg("input array is too big (%d maximum allowed, %d current), use gist__intbig_ops opclass instead",
2 * num_ranges - 1, ARRNELEMS(r))));
retval = palloc(sizeof(GISTENTRY));
@@ -271,7 +272,8 @@ g_int_compress(PG_FUNCTION_ARGS)
lenr = internal_size(dr, len);
if (lenr < 0 || lenr > MAXNUMELTS)
ereport(ERROR,
- (errmsg("data is too sparse, recreate index using gist__intbig_ops opclass instead")));+ (errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED),+ errmsg("data is too sparse, recreate index using gist__intbig_ops opclass instead")));
r = resize_intArrayType(r, len);
retval = palloc(sizeof(GISTENTRY));
@@ -333,7 +335,8 @@ g_int_decompress(PG_FUNCTION_ARGS)
lenr = internal_size(din, lenin);
if (lenr < 0 || lenr > MAXNUMELTS)
ereport(ERROR,
- (errmsg("compressed array is too big, recreate index using gist__intbig_ops opclass instead")));+ (errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED),+ errmsg("compressed array is too big, recreate index using gist__intbig_ops opclass instead")));
r = new_intArrayType(lenr);
dr = ARRPTR(r);
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Reply to all the recipients using the --to and --cc options:
reply via email
To: pgsql-bugs@postgresql.org
Cc: exclusion@gmail.com, guofenglinux@gmail.com, itsankitkp@gmail.com, dgrowleyml@gmail.com, teodor@sigaev.ru, pgsql-bugs@lists.postgresql.org
Subject: Re: BUG #17888: Incorrect memory access in gist__int_ops for an input array with many elements
In-Reply-To: <f7ab52bb-e0ee-4acd-9bb1-ac28d22e39f5@gmail.com>
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
This inbox is served by DDX for PostgreSQL; see mirroring instructions
for how to clone and mirror all data and code used for this inbox