Validate ltree siglen GiST option to be int-aligned
authorAlexander Korotkov <[email protected]>
Sun, 23 Apr 2023 10:58:25 +0000 (13:58 +0300)
committerAlexander Korotkov <[email protected]>
Sun, 23 Apr 2023 11:30:09 +0000 (14:30 +0300)
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

contrib/ltree/expected/ltree.out
contrib/ltree/ltree_gist.c
contrib/ltree/sql/ltree.sql
doc/src/sgml/ltree.sgml

index 27122153c718bacfee9b168c18378463a6cb3ac0..984cd030cfae2376441521bd21999273e6bd2b9f 100644 (file)
@@ -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 
index 3cba2269d86d620317c623ac1768849fd7df7505..21b7d020286143e26c315387b7000f9c38d6a97c 100644 (file)
@@ -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();
 }
index 4623b57f7b5bc69c48f7a824af17e8542be1ed88..402096f6c465150aaae99f677cdabff4c9710542 100644 (file)
@@ -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';
index bb66e33944bdae5eb1cfee5f4b4e0f7ab1d86600..00a6ae70da327a8b69e9628a2557af1c6d7cf978 100644 (file)
@@ -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>