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