Skip to content

Commit f4a4a18

Browse files
committed
Validate ltree siglen GiST option to be int-aligned
Unaligned siglen could lead to an unaligned access to subsequent key fields. Backpatch to 13, where opclass options were introduced. Reported-by: Alexander Lakhin Bug: 17847 Discussion: https://postgr.es/m/17847-171232970bea406b%40postgresql.org Reviewed-by: Tom Lane, Pavel Borisov, Alexander Lakhin Backpatch-through: 13
1 parent 9ef5a35 commit f4a4a18

File tree

4 files changed

+27
-4
lines changed

4 files changed

+27
-4
lines changed

contrib/ltree/expected/ltree.out

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7821,10 +7821,15 @@ SELECT * FROM ltreetest WHERE t ? '{23.*.1,23.*.2}' order by t asc;
78217821
drop index tstidx;
78227822
create index tstidx on ltreetest using gist (t gist_ltree_ops(siglen=0));
78237823
ERROR: value 0 out of bounds for option "siglen"
7824-
DETAIL: Valid values are between "1" and "2024".
7824+
DETAIL: Valid values are between "4" and "2024".
78257825
create index tstidx on ltreetest using gist (t gist_ltree_ops(siglen=2025));
78267826
ERROR: value 2025 out of bounds for option "siglen"
7827-
DETAIL: Valid values are between "1" and "2024".
7827+
DETAIL: Valid values are between "4" and "2024".
7828+
create index tstidx on ltreetest using gist (t gist_ltree_ops(siglen=2028));
7829+
ERROR: value 2028 out of bounds for option "siglen"
7830+
DETAIL: Valid values are between "4" and "2024".
7831+
create index tstidx on ltreetest using gist (t gist_ltree_ops(siglen=2019));
7832+
ERROR: siglen value must be a multiple of 4
78287833
create index tstidx on ltreetest using gist (t gist_ltree_ops(siglen=2024));
78297834
SELECT count(*) FROM ltreetest WHERE t < '12.3';
78307835
count

contrib/ltree/ltree_gist.c

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -716,6 +716,18 @@ ltree_consistent(PG_FUNCTION_ARGS)
716716
PG_RETURN_BOOL(res);
717717
}
718718

719+
static void
720+
ltree_gist_relopts_validator(void *parsed_options, relopt_value *vals,
721+
int nvals)
722+
{
723+
LtreeGistOptions *options = (LtreeGistOptions *) parsed_options;
724+
725+
if (options->siglen != INTALIGN(options->siglen))
726+
ereport(ERROR,
727+
(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
728+
errmsg("siglen value must be a multiple of %d", ALIGNOF_INT)));
729+
}
730+
719731
Datum
720732
ltree_gist_options(PG_FUNCTION_ARGS)
721733
{
@@ -724,8 +736,11 @@ ltree_gist_options(PG_FUNCTION_ARGS)
724736
init_local_reloptions(relopts, sizeof(LtreeGistOptions));
725737
add_local_int_reloption(relopts, "siglen",
726738
"signature length in bytes",
727-
LTREE_SIGLEN_DEFAULT, 1, LTREE_SIGLEN_MAX,
739+
LTREE_SIGLEN_DEFAULT,
740+
INTALIGN(1),
741+
LTREE_SIGLEN_MAX,
728742
offsetof(LtreeGistOptions, siglen));
743+
register_reloptions_validator(relopts, ltree_gist_relopts_validator);
729744

730745
PG_RETURN_VOID();
731746
}

contrib/ltree/sql/ltree.sql

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -325,6 +325,8 @@ SELECT * FROM ltreetest WHERE t ? '{23.*.1,23.*.2}' order by t asc;
325325
drop index tstidx;
326326
create index tstidx on ltreetest using gist (t gist_ltree_ops(siglen=0));
327327
create index tstidx on ltreetest using gist (t gist_ltree_ops(siglen=2025));
328+
create index tstidx on ltreetest using gist (t gist_ltree_ops(siglen=2028));
329+
create index tstidx on ltreetest using gist (t gist_ltree_ops(siglen=2019));
328330
create index tstidx on ltreetest using gist (t gist_ltree_ops(siglen=2024));
329331

330332
SELECT count(*) FROM ltreetest WHERE t < '12.3';

doc/src/sgml/ltree.sgml

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -636,7 +636,8 @@ Europe &amp; Russia*@ &amp; !Transportation
636636
path labels as a bitmap signature. Its optional integer parameter
637637
<literal>siglen</literal> determines the
638638
signature length in bytes. The default signature length is 8 bytes.
639-
Valid values of signature length are between 1 and 2024 bytes. Longer
639+
The length must be a positive multiple of <type>int</type> alignment
640+
(4 bytes on most machines)) up to 2024. Longer
640641
signatures lead to a more precise search (scanning a smaller fraction of the index and
641642
fewer heap pages), at the cost of a larger index.
642643
</para>

0 commit comments

Comments
 (0)