summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAlexander Korotkov <akorotkov@postgresql.org>2023-04-23 13:58:25 +0300
committerAlexander Korotkov <akorotkov@postgresql.org>2023-04-23 14:30:09 +0300
commit8bbd0cce92be98de9f4f727b8bf66fe26e5831ea (patch)
tree4b43130fd13ea7a0ffe36e56da62ac872b64cd77
parentcd115c3530bd59bb0305d62ccef1c9504207ff4c (diff)
downloadpostgresql-8bbd0cce92be98de9f4f727b8bf66fe26e5831ea.tar.gz
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
-rw-r--r--contrib/ltree/expected/ltree.out9
-rw-r--r--contrib/ltree/ltree_gist.c17
-rw-r--r--contrib/ltree/sql/ltree.sql2
-rw-r--r--doc/src/sgml/ltree.sgml3
4 files changed, 27 insertions, 4 deletions
diff --git a/contrib/ltree/expected/ltree.out b/contrib/ltree/expected/ltree.out
index 27122153c7..984cd030cf 100644
--- a/contrib/ltree/expected/ltree.out
+++ b/contrib/ltree/expected/ltree.out
@@ -7835,10 +7835,15 @@ SELECT * FROM ltreetest WHERE t ? '{23.*.1,23.*.2}' order by t asc;
drop index tstidx;
create index tstidx on ltreetest using gist (t gist_ltree_ops(siglen=0));
ERROR: value 0 out of bounds for option "siglen"
-DETAIL: Valid values are between "1" and "2024".
+DETAIL: Valid values are between "4" and "2024".
create index tstidx on ltreetest using gist (t gist_ltree_ops(siglen=2025));
ERROR: value 2025 out of bounds for option "siglen"
-DETAIL: Valid values are between "1" and "2024".
+DETAIL: Valid values are between "4" and "2024".
+create index tstidx on ltreetest using gist (t gist_ltree_ops(siglen=2028));
+ERROR: value 2028 out of bounds for option "siglen"
+DETAIL: Valid values are between "4" and "2024".
+create index tstidx on ltreetest using gist (t gist_ltree_ops(siglen=2019));
+ERROR: siglen value must be a multiple of 4
create index tstidx on ltreetest using gist (t gist_ltree_ops(siglen=2024));
SELECT count(*) FROM ltreetest WHERE t < '12.3';
count
diff --git a/contrib/ltree/ltree_gist.c b/contrib/ltree/ltree_gist.c
index 3cba2269d8..21b7d02028 100644
--- a/contrib/ltree/ltree_gist.c
+++ b/contrib/ltree/ltree_gist.c
@@ -719,6 +719,18 @@ ltree_consistent(PG_FUNCTION_ARGS)
PG_RETURN_BOOL(res);
}
+static void
+ltree_gist_relopts_validator(void *parsed_options, relopt_value *vals,
+ int nvals)
+{
+ LtreeGistOptions *options = (LtreeGistOptions *) parsed_options;
+
+ if (options->siglen != INTALIGN(options->siglen))
+ ereport(ERROR,
+ (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
+ errmsg("siglen value must be a multiple of %d", ALIGNOF_INT)));
+}
+
Datum
ltree_gist_options(PG_FUNCTION_ARGS)
{
@@ -727,8 +739,11 @@ ltree_gist_options(PG_FUNCTION_ARGS)
init_local_reloptions(relopts, sizeof(LtreeGistOptions));
add_local_int_reloption(relopts, "siglen",
"signature length in bytes",
- LTREE_SIGLEN_DEFAULT, 1, LTREE_SIGLEN_MAX,
+ LTREE_SIGLEN_DEFAULT,
+ INTALIGN(1),
+ LTREE_SIGLEN_MAX,
offsetof(LtreeGistOptions, siglen));
+ register_reloptions_validator(relopts, ltree_gist_relopts_validator);
PG_RETURN_VOID();
}
diff --git a/contrib/ltree/sql/ltree.sql b/contrib/ltree/sql/ltree.sql
index 4623b57f7b..402096f6c4 100644
--- a/contrib/ltree/sql/ltree.sql
+++ b/contrib/ltree/sql/ltree.sql
@@ -331,6 +331,8 @@ SELECT * FROM ltreetest WHERE t ? '{23.*.1,23.*.2}' order by t asc;
drop index tstidx;
create index tstidx on ltreetest using gist (t gist_ltree_ops(siglen=0));
create index tstidx on ltreetest using gist (t gist_ltree_ops(siglen=2025));
+create index tstidx on ltreetest using gist (t gist_ltree_ops(siglen=2028));
+create index tstidx on ltreetest using gist (t gist_ltree_ops(siglen=2019));
create index tstidx on ltreetest using gist (t gist_ltree_ops(siglen=2024));
SELECT count(*) FROM ltreetest WHERE t < '12.3';
diff --git a/doc/src/sgml/ltree.sgml b/doc/src/sgml/ltree.sgml
index bb66e33944..00a6ae70da 100644
--- a/doc/src/sgml/ltree.sgml
+++ b/doc/src/sgml/ltree.sgml
@@ -637,7 +637,8 @@ Europe &amp; Russia*@ &amp; !Transportation
path labels as a bitmap signature. Its optional integer parameter
<literal>siglen</literal> determines the
signature length in bytes. The default signature length is 8 bytes.
- Valid values of signature length are between 1 and 2024 bytes. Longer
+ The length must be a positive multiple of <type>int</type> alignment
+ (4 bytes on most machines)) up to 2024. Longer
signatures lead to a more precise search (scanning a smaller fraction of the index and
fewer heap pages), at the cost of a larger index.
</para>