From: Michael Paquier <michael@paquier.xyz>
To: Tomas Vondra <tomas.vondra@2ndquadrant.com>
Cc: Adam Scott <adam.c.scott@gmail.com>
Cc: pgsql-bugs@lists.postgresql.org
Subject: Re: BUG #16122: segfault pg_detoast_datum (datum=0x0) at fmgr.c:1833 numrange query
Date: Tue, 10 Dec 2019 14:38:15 +0900
Message-ID: <20191210053815.GI72921@paquier.xyz> (raw)
In-Reply-To: <20191119114056.GA516103@paquier.xyz>
References: <16122-eb35bc248c806c15@postgresql.org>
<20191118120312.cblcswef6vuqbijq@development>
<CA+s62-Mnj-x8_ZXh7tBVU3WJ3cKUsUL2HAp2YaJSXQPw1iypFw@mail.gmail.com>
<20191119014827.GC1614@paquier.xyz>
<20191119103813.xnsloisoxkwrxoim@development>
<20191119114056.GA516103@paquier.xyz>
On Tue, Nov 19, 2019 at 08:40:56PM +0900, Michael Paquier wrote:
> If you add an ANALYZE on the table natica_hdu_test after restoring, I
> am rather sure that you would reproduce the crash more quickly because
> the handling around the stats of the column are busted here. Anyway,
> taking my example of upthread, I have been also able to reproduce the
> problem on REL_10_STABLE even with assertions enabled: the trick is
> that you need to leave once the session after the analyze on the
> table. Then a SELECT within a new session is enough to crash the
> server.
So... I have looked more at this one, and from my previous example it
seems that we have a one-off error when looking up at the array
holding the histograms for ranges (lower and upper bound).
In my previous example, we get to build 101 RangeBounds when beginning
to calculate the range operator selectivity in
calc_hist_selectivity(). However, when we get to the point of
calc_hist_selectivity_contained(), upper_index gets calculated at 100
which is just at the limit of the indexed bounds, and the code would
happily look at the last bound as well as the one-after-the-last bound
as range_cmp_bounds() sees fit, but the latter just points to the
void. The code looks wrong since its introduction in 59d0bf9d and
it seems that the changes done for free_attstatsslot() in 9aab83f make
the issue more easily reproducible.
A fix like the rough POC attached addresses the issue, but I think
that's too naive to not count for the first bin in the ranges
evaluated. Tomas, you may be more familiar with this area of the code
than I am. What do you think?
--
Michael
Attachments:rangetype-stat-crash.patch (text/x-diff, 2.3K) downloaddiff --git a/src/backend/utils/adt/rangetypes_selfuncs.c b/src/backend/utils/adt/rangetypes_selfuncs.cindex ab4f86e3fd..abe3f6170d 100644--- a/src/backend/utils/adt/rangetypes_selfuncs.c+++ b/src/backend/utils/adt/rangetypes_selfuncs.c@@ -1045,7 +1045,9 @@ calc_hist_selectivity_contained(TypeCacheEntry *typcache,
bin_width = upper_bin_width;
sum_frac = 0.0;
- for (i = upper_index; i >= 0; i--)++ /* Make sure to not count for the first bin */+ for (i = upper_index - 1; i >= 0; i--)
{
double dist;
double length_hist_frac;
diff --git a/src/test/regress/expected/rangetypes.out b/src/test/regress/expected/rangetypes.outindex 6fd16bddd1..7656e5ea2c 100644--- a/src/test/regress/expected/rangetypes.out+++ b/src/test/regress/expected/rangetypes.out@@ -1431,3 +1431,16 @@ create function table_fail(i anyelement) returns table(i anyelement, r anyrange)
as $$ select $1, '[1,10]' $$ language sql;
ERROR: cannot determine result data type
DETAIL: A function returning "anyrange" must have at least one "anyrange" argument.
+-- Corner case with selectivity of range operators, per bug #16122.+CREATE TABLE rangetab (a numrange);+INSERT INTO rangetab+SELECT ('['|| (45.0 - a::numeric/10000000) || ',' ||+ (45.1 + a::numeric/10000000) || ')')::numrange+ FROM generate_series(1,1000) as a;+ANALYZE rangetab;+SELECT a FROM rangetab WHERE a <@ '[89.9999998611111,90.0000001388889)';+ a +---+(0 rows)++DROP TABLE rangetab;diff --git a/src/test/regress/sql/rangetypes.sql b/src/test/regress/sql/rangetypes.sqlindex 8960add976..b17e64113c 100644--- a/src/test/regress/sql/rangetypes.sql+++ b/src/test/regress/sql/rangetypes.sql@@ -507,3 +507,13 @@ create function inoutparam_fail(inout i anyelement, out r anyrange)
--should fail
create function table_fail(i anyelement) returns table(i anyelement, r anyrange)
as $$ select $1, '[1,10]' $$ language sql;
++-- Corner case with selectivity of range operators, per bug #16122.+CREATE TABLE rangetab (a numrange);+INSERT INTO rangetab+SELECT ('['|| (45.0 - a::numeric/10000000) || ',' ||+ (45.1 + a::numeric/10000000) || ')')::numrange+ FROM generate_series(1,1000) as a;+ANALYZE rangetab;+SELECT a FROM rangetab WHERE a <@ '[89.9999998611111,90.0000001388889)';+DROP TABLE rangetab;
signature.asc (application/pgp-signature, 832B) download
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: michael@paquier.xyz, tomas.vondra@2ndquadrant.com, adam.c.scott@gmail.com, pgsql-bugs@lists.postgresql.org
Subject: Re: BUG #16122: segfault pg_detoast_datum (datum=0x0) at fmgr.c:1833 numrange query
In-Reply-To: <20191210053815.GI72921@paquier.xyz>
* 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