mirror of
				https://github.com/postgres/postgres.git
				synced 2025-11-03 09:13:20 +03:00 
			
		
		
		
	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
This commit is contained in:
		@@ -7821,10 +7821,15 @@ SELECT * FROM ltreetest WHERE t ? '{23.*.1,23.*.2}' order by t asc;
 | 
				
			|||||||
drop index tstidx;
 | 
					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=0));
 | 
				
			||||||
ERROR:  value 0 out of bounds for option "siglen"
 | 
					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));
 | 
					create index tstidx on ltreetest using gist (t gist_ltree_ops(siglen=2025));
 | 
				
			||||||
ERROR:  value 2025 out of bounds for option "siglen"
 | 
					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));
 | 
					create index tstidx on ltreetest using gist (t gist_ltree_ops(siglen=2024));
 | 
				
			||||||
SELECT count(*) FROM ltreetest WHERE t <  '12.3';
 | 
					SELECT count(*) FROM ltreetest WHERE t <  '12.3';
 | 
				
			||||||
 count 
 | 
					 count 
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -716,6 +716,18 @@ ltree_consistent(PG_FUNCTION_ARGS)
 | 
				
			|||||||
	PG_RETURN_BOOL(res);
 | 
						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
 | 
					Datum
 | 
				
			||||||
ltree_gist_options(PG_FUNCTION_ARGS)
 | 
					ltree_gist_options(PG_FUNCTION_ARGS)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
@@ -724,8 +736,11 @@ ltree_gist_options(PG_FUNCTION_ARGS)
 | 
				
			|||||||
	init_local_reloptions(relopts, sizeof(LtreeGistOptions));
 | 
						init_local_reloptions(relopts, sizeof(LtreeGistOptions));
 | 
				
			||||||
	add_local_int_reloption(relopts, "siglen",
 | 
						add_local_int_reloption(relopts, "siglen",
 | 
				
			||||||
							"signature length in bytes",
 | 
												"signature length in bytes",
 | 
				
			||||||
							LTREE_SIGLEN_DEFAULT, 1, LTREE_SIGLEN_MAX,
 | 
												LTREE_SIGLEN_DEFAULT,
 | 
				
			||||||
 | 
												INTALIGN(1),
 | 
				
			||||||
 | 
												LTREE_SIGLEN_MAX,
 | 
				
			||||||
							offsetof(LtreeGistOptions, siglen));
 | 
												offsetof(LtreeGistOptions, siglen));
 | 
				
			||||||
 | 
						register_reloptions_validator(relopts, ltree_gist_relopts_validator);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	PG_RETURN_VOID();
 | 
						PG_RETURN_VOID();
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -325,6 +325,8 @@ SELECT * FROM ltreetest WHERE t ? '{23.*.1,23.*.2}' order by t asc;
 | 
				
			|||||||
drop index tstidx;
 | 
					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=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=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));
 | 
					create index tstidx on ltreetest using gist (t gist_ltree_ops(siglen=2024));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
SELECT count(*) FROM ltreetest WHERE t <  '12.3';
 | 
					SELECT count(*) FROM ltreetest WHERE t <  '12.3';
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -636,7 +636,8 @@ Europe & Russia*@ & !Transportation
 | 
				
			|||||||
     path labels as a bitmap signature.  Its optional integer parameter
 | 
					     path labels as a bitmap signature.  Its optional integer parameter
 | 
				
			||||||
     <literal>siglen</literal> determines the
 | 
					     <literal>siglen</literal> determines the
 | 
				
			||||||
     signature length in bytes.  The default signature length is 8 bytes.
 | 
					     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
 | 
					     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.
 | 
					     fewer heap pages), at the cost of a larger index.
 | 
				
			||||||
    </para>
 | 
					    </para>
 | 
				
			||||||
 
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user