63
63
64
64
#include "postgres.h"
65
65
66
+ #include <limits.h>
67
+
66
68
#include "access/xact.h"
67
69
#include "storage/shmem.h"
68
70
#include "storage/spin.h"
@@ -199,6 +201,8 @@ static void hdefault(HTAB *hashp);
199
201
static int choose_nelem_alloc (Size entrysize );
200
202
static bool init_htab (HTAB * hashp , long nelem );
201
203
static void hash_corrupted (HTAB * hashp );
204
+ static long next_pow2_long (long num );
205
+ static int next_pow2_int (long num );
202
206
static void register_seq_scan (HTAB * hashp );
203
207
static void deregister_seq_scan (HTAB * hashp );
204
208
static bool has_seq_scans (HTAB * hashp );
@@ -373,8 +377,13 @@ hash_create(const char *tabname, long nelem, HASHCTL *info, int flags)
373
377
{
374
378
/* Doesn't make sense to partition a local hash table */
375
379
Assert (flags & HASH_SHARED_MEM );
376
- /* # of partitions had better be a power of 2 */
377
- Assert (info -> num_partitions == (1L << my_log2 (info -> num_partitions )));
380
+
381
+ /*
382
+ * The number of partitions had better be a power of 2. Also, it must
383
+ * be less than INT_MAX (see init_htab()), so call the int version of
384
+ * next_pow2.
385
+ */
386
+ Assert (info -> num_partitions == next_pow2_int (info -> num_partitions ));
378
387
379
388
hctl -> num_partitions = info -> num_partitions ;
380
389
}
@@ -515,7 +524,6 @@ init_htab(HTAB *hashp, long nelem)
515
524
{
516
525
HASHHDR * hctl = hashp -> hctl ;
517
526
HASHSEGMENT * segp ;
518
- long lnbuckets ;
519
527
int nbuckets ;
520
528
int nsegs ;
521
529
@@ -530,9 +538,7 @@ init_htab(HTAB *hashp, long nelem)
530
538
* number of buckets. Allocate space for the next greater power of two
531
539
* number of buckets
532
540
*/
533
- lnbuckets = (nelem - 1 ) / hctl -> ffactor + 1 ;
534
-
535
- nbuckets = 1 << my_log2 (lnbuckets );
541
+ nbuckets = next_pow2_int ((nelem - 1 ) / hctl -> ffactor + 1 );
536
542
537
543
/*
538
544
* In a partitioned table, nbuckets must be at least equal to
@@ -550,7 +556,7 @@ init_htab(HTAB *hashp, long nelem)
550
556
* Figure number of directory segments needed, round up to a power of 2
551
557
*/
552
558
nsegs = (nbuckets - 1 ) / hctl -> ssize + 1 ;
553
- nsegs = 1 << my_log2 (nsegs );
559
+ nsegs = next_pow2_int (nsegs );
554
560
555
561
/*
556
562
* Make sure directory is big enough. If pre-allocated directory is too
@@ -620,9 +626,9 @@ hash_estimate_size(long num_entries, Size entrysize)
620
626
elementAllocCnt ;
621
627
622
628
/* estimate number of buckets wanted */
623
- nBuckets = 1L << my_log2 ((num_entries - 1 ) / DEF_FFACTOR + 1 );
629
+ nBuckets = next_pow2_long ((num_entries - 1 ) / DEF_FFACTOR + 1 );
624
630
/* # of segments needed for nBuckets */
625
- nSegments = 1L << my_log2 ((nBuckets - 1 ) / DEF_SEGSIZE + 1 );
631
+ nSegments = next_pow2_long ((nBuckets - 1 ) / DEF_SEGSIZE + 1 );
626
632
/* directory entries */
627
633
nDirEntries = DEF_DIRSIZE ;
628
634
while (nDirEntries < nSegments )
@@ -663,9 +669,9 @@ hash_select_dirsize(long num_entries)
663
669
nDirEntries ;
664
670
665
671
/* estimate number of buckets wanted */
666
- nBuckets = 1L << my_log2 ((num_entries - 1 ) / DEF_FFACTOR + 1 );
672
+ nBuckets = next_pow2_long ((num_entries - 1 ) / DEF_FFACTOR + 1 );
667
673
/* # of segments needed for nBuckets */
668
- nSegments = 1L << my_log2 ((nBuckets - 1 ) / DEF_SEGSIZE + 1 );
674
+ nSegments = next_pow2_long ((nBuckets - 1 ) / DEF_SEGSIZE + 1 );
669
675
/* directory entries */
670
676
nDirEntries = DEF_DIRSIZE ;
671
677
while (nDirEntries < nSegments )
@@ -1397,11 +1403,32 @@ my_log2(long num)
1397
1403
int i ;
1398
1404
long limit ;
1399
1405
1406
+ /* guard against too-large input, which would put us into infinite loop */
1407
+ if (num > LONG_MAX / 2 )
1408
+ num = LONG_MAX / 2 ;
1409
+
1400
1410
for (i = 0 , limit = 1 ; limit < num ; i ++ , limit <<= 1 )
1401
1411
;
1402
1412
return i ;
1403
1413
}
1404
1414
1415
+ /* calculate first power of 2 >= num, bounded to what will fit in a long */
1416
+ static long
1417
+ next_pow2_long (long num )
1418
+ {
1419
+ /* my_log2's internal range check is sufficient */
1420
+ return 1L << my_log2 (num );
1421
+ }
1422
+
1423
+ /* calculate first power of 2 >= num, bounded to what will fit in an int */
1424
+ static int
1425
+ next_pow2_int (long num )
1426
+ {
1427
+ if (num > INT_MAX / 2 )
1428
+ num = INT_MAX / 2 ;
1429
+ return 1 << my_log2 (num );
1430
+ }
1431
+
1405
1432
1406
1433
/************************* SEQ SCAN TRACKING ************************/
1407
1434
0 commit comments