From 96b9984c7acddf12b7d289be91af2b4a67860e80 Mon Sep 17 00:00:00 2001
From: Andrey Borodin <amborodin@acm.org>
Date: Tue, 30 May 2017 15:16:14 +0500
Subject: [PATCH] Use primes for hashtable size

We often use sizes equal to power of 2. This can be damaging for hashtable. I haven't found any mitigation for this in nginx code.
So I made my own.
For the explanation of problem see https://stackoverflow.com/questions/3980117/hash-table-why-size-should-be-prime

I didn't tested this with nginx, code is checked only for correctness of ngx_hash_min_prime().
Also beware that I've changed state of paremeter hinit. I'm not sure this is acceptable.
---
 src/core/ngx_hash.c | 148 ++++++++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 148 insertions(+)

diff --git a/src/core/ngx_hash.c b/src/core/ngx_hash.c
index 1944c7a21d..e49806c616 100644
--- a/src/core/ngx_hash.c
+++ b/src/core/ngx_hash.c
@@ -244,6 +244,153 @@ ngx_hash_find_combined(ngx_hash_combined_t *hash, ngx_uint_t key, u_char *name,
     return NULL;
 }
 
+static ngx_uint_t ngx_hash_min_prime(ngx_uint_t value) {
+    static ngx_uint_t primes[] =
+            {
+                    3,
+                    7,
+                    11,
+                    17,
+                    23,
+                    29,
+                    37,
+                    47,
+                    59,
+                    71,
+                    89,
+                    107,
+                    131,
+                    163,
+                    197,
+                    239,
+                    293,
+                    353,
+                    431,
+                    521,
+                    631,
+                    761,
+                    919,
+                    1103,
+                    1327,
+                    1597,
+                    1931,
+                    2333,
+                    2801,
+                    3371,
+                    4049,
+                    4861,
+                    5839,
+                    7013,
+                    8419,
+                    10103,
+                    12143,
+                    14591,
+                    17519,
+                    21023,
+                    25229,
+                    30293,
+                    36353,
+                    43627,
+                    52361,
+                    62851,
+                    75431,
+                    90523,
+                    108631,
+                    130363,
+                    156437,
+                    187751,
+                    225307,
+                    270371,
+                    324449,
+                    389357,
+                    467237,
+                    560689,
+                    672827,
+                    807403,
+                    968897,
+                    1162687,
+                    1395263,
+                    1674319,
+                    2009191,
+                    2411033,
+                    2893249,
+                    3471899,
+                    4166287,
+                    4999559,
+                    5999471,
+                    7199369,
+                    7919311,
+                    8711267,
+                    9582409,
+                    10540661,
+                    11594729,
+                    12754219,
+                    14029643,
+                    15432619,
+                    16975891,
+                    18673483,
+                    20540831,
+                    22594919,
+                    24854419,
+                    27339863,
+                    30073853,
+                    33081239,
+                    36389369,
+                    40028333,
+                    44031179,
+                    48434303,
+                    53277769,
+                    58605563,
+                    64466147,
+                    70912783,
+                    78004061,
+                    85804471,
+                    94384919,
+                    103823417,
+                    114205771,
+                    125626351,
+                    138189017,
+                    152007971,
+                    167208817,
+                    183929719,
+                    202322693,
+                    222554977,
+                    244810487,
+                    269291537,
+                    296220709,
+                    325842779,
+                    358427071,
+                    394269781,
+                    433696759,
+                    477066449,
+                    524773133,
+                    577250461,
+                    634975519,
+                    698473099,
+                    768320467,
+                    845152513,
+                    929667799,
+                    1022634581,
+                    1124898043,
+                    1237387859,
+                    1361126671,
+                    1497239377,
+                    1646963321,
+                    1811659669,
+                    1992825643,
+            };
+
+    for (size_t i = 0; i < sizeof(primes)/sizeof(*primes); ++i)
+    {
+        ngx_uint_t prime = primes[i];
+        if (prime >= value)
+        {
+            value = prime;
+            break;
+        }
+    }
+    return value;
+}
 
 #define NGX_HASH_ELT_SIZE(name)                                               \
     (sizeof(void *) + ngx_align((name)->key.len + 2, sizeof(void *)))
@@ -264,6 +411,7 @@ ngx_hash_init(ngx_hash_init_t *hinit, ngx_hash_key_t *names, ngx_uint_t nelts)
                       hinit->name, hinit->name, hinit->max_size);
         return NGX_ERROR;
     }
+    hinit->max_size = ngx_hash_min_prime(hinit->max_size);
 
     for (n = 0; n < nelts; n++) {
         if (hinit->bucket_size < NGX_HASH_ELT_SIZE(&names[n]) + sizeof(void *))
