src/http/modules/ngx_http_referer_module.c:289: error: Buffer Overrun L3
  Offset: [0, 2070] (⇐ [0, 24] + [0, 2046]) Size: [0, +oo] by call to `ngx_hash_init`.

src/http/modules/ngx_http_referer_module.c:280:5: Assignment
278. 
279.     hash.key = ngx_hash_key_lc;
280.     hash.max_size = 2048; /* TODO: referer_hash_max_size; */
         ^
281.     hash.bucket_size = 64; /* TODO: referer_hash_bucket_size; */
282.     hash.name = "referers_hash";

src/http/modules/ngx_http_referer_module.c:289:13: Call
287.         hash.temp_pool = NULL;
288. 
289.         if (ngx_hash_init(&hash, conf->keys->keys.elts, conf->keys->keys.nelts)
                 ^
290.             != NGX_OK)
291.         {

src/core/ngx_hash.c:250:1: <Offset trace>
248.     (sizeof(void *) + ngx_align((name)->key.len + 2, sizeof(void *)))
249. 
250. ngx_int_t
     ^
251. ngx_hash_init(ngx_hash_init_t *hinit, ngx_hash_key_t *names, ngx_uint_t nelts)
252. {

src/core/ngx_hash.c:250:1: Parameter `hinit->max_size`
  248.     (sizeof(void *) + ngx_align((name)->key.len + 2, sizeof(void *)))
  249. 
  250. ngx_int_t
       ^
  251. ngx_hash_init(ngx_hash_init_t *hinit, ngx_hash_key_t *names, ngx_uint_t nelts)
  252. {

src/core/ngx_hash.c:250:1: <Length trace>
248.     (sizeof(void *) + ngx_align((name)->key.len + 2, sizeof(void *)))
249. 
250. ngx_int_t
     ^
251. ngx_hash_init(ngx_hash_init_t *hinit, ngx_hash_key_t *names, ngx_uint_t nelts)
252. {

src/core/ngx_hash.c:250:1: Parameter `hinit->max_size`
  248.     (sizeof(void *) + ngx_align((name)->key.len + 2, sizeof(void *)))
  249. 
  250. ngx_int_t
       ^
  251. ngx_hash_init(ngx_hash_init_t *hinit, ngx_hash_key_t *names, ngx_uint_t nelts)
  252. {

src/core/ngx_hash.c:363:19: Call
  361. 
  362.     } else {
  363.         buckets = ngx_pcalloc(hinit->pool, size * sizeof(ngx_hash_elt_t *));
                         ^
  364.         if (buckets == NULL) {
  365.             ngx_free(test);

src/core/ngx_palloc.c:299:1: Parameter `size`
    297. 
    298. 
    299. void *
         ^
    300. ngx_pcalloc(ngx_pool_t *pool, size_t size)
    301. {

src/core/ngx_palloc.c:304:9: Call
    302.     void *p;
    303. 
    304.     p = ngx_palloc(pool, size);
                 ^
    305.     if (p) {
    306.         ngx_memzero(p, size);

src/core/ngx_palloc.c:126:13: Assignment
      124. 
      125.         do {
      126.             m = ngx_align_ptr(p->d.last, NGX_ALIGNMENT);
                       ^
      127. 
      128.             if ((size_t) (p->d.end - m) >= size) {

src/core/ngx_palloc.c:131:17: Assignment
      129.                 p->d.last = m + size;
      130. 
      131.                 return m;
                           ^
      132.             }
      133. 

src/core/ngx_palloc.c:304:5: Assignment
    302.     void *p;
    303. 
    304.     p = ngx_palloc(pool, size);
             ^
    305.     if (p) {
    306.         ngx_memzero(p, size);

src/core/ngx_palloc.c:309:5: Assignment
    307.     }
    308. 
    309.     return p;
             ^
    310. }
    311. 

src/core/ngx_hash.c:363:9: Assignment
  361. 
  362.     } else {
  363.         buckets = ngx_pcalloc(hinit->pool, size * sizeof(ngx_hash_elt_t *));
               ^
  364.         if (buckets == NULL) {
  365.             ngx_free(test);

src/core/ngx_hash.c:383:9: Array access: Offset: [0, 2070] (⇐ [0, 24] + [0, 2046]) Size: [0, +oo] by call to `ngx_hash_init` 
  381.         }
  382. 
  383.         buckets[i] = (ngx_hash_elt_t *) elts;
               ^
  384.         elts += test[i];
  385. 

ngx_int_t
ngx_hash_init(ngx_hash_init_t *hinit, ngx_hash_key_t *names, ngx_uint_t nelts)
{
    u_char          *elts;
    size_t           len;
    u_short         *test;
    ngx_uint_t       i, n, key, size, start, bucket_size;
    ngx_hash_elt_t  *elt, **buckets;
    for (n = 0; n < nelts; n++) {
        if (hinit->bucket_size < NGX_HASH_ELT_SIZE(&names[n]) + sizeof(void *))
        {
            ngx_log_error(NGX_LOG_EMERG, hinit->pool->log, 0,
                          "could not build the %s, you should "
                          "increase %s_bucket_size: %i",
                          hinit->name, hinit->name, hinit->bucket_size);
            return NGX_ERROR;
        }
    }
    test = ngx_alloc(hinit->max_size * sizeof(u_short), hinit->pool->log);
    if (test == NULL) {
        return NGX_ERROR;
    }
    bucket_size = hinit->bucket_size - sizeof(void *);
    start = nelts / (bucket_size / (2 * sizeof(void *)));
    start = start ? start : 1;
    if (hinit->max_size > 10000 && hinit->max_size / nelts < 100) {
        start = hinit->max_size - 1000;
    }
    for (size = start; size < hinit->max_size; size++) {
        ngx_memzero(test, size * sizeof(u_short));
        for (n = 0; n < nelts; n++) {
            if (names[n].key.data == NULL) {
                continue;
            }
            key = names[n].key_hash % size;
            test[key] = (u_short) (test[key] + NGX_HASH_ELT_SIZE(&names[n]));
#if 0
            ngx_log_error(NGX_LOG_ALERT, hinit->pool->log, 0,
                          "%ui: %ui %ui \"%V\"",
                          size, key, test[key], &names[n].key);
#endif
            if (test[key] > (u_short) bucket_size) {
                goto next;
            }
        }
        goto found;
    next:
        continue;
    }
    ngx_log_error(NGX_LOG_EMERG, hinit->pool->log, 0,
                  "could not build the %s, you should increase "
                  "either %s_max_size: %i or %s_bucket_size: %i",
                  hinit->name, hinit->name, hinit->max_size,
                  hinit->name, hinit->bucket_size);
    ngx_free(test);
    return NGX_ERROR;
found:
    for (i = 0; i < size; i++) {
        test[i] = sizeof(void *);
    }
    for (n = 0; n < nelts; n++) {
        if (names[n].key.data == NULL) {
            continue;
        }
        key = names[n].key_hash % size;
        test[key] = (u_short) (test[key] + NGX_HASH_ELT_SIZE(&names[n]));
    }
    len = 0;
    for (i = 0; i < size; i++) {
        if (test[i] == sizeof(void *)) {
            continue;
        }
        test[i] = (u_short) (ngx_align(test[i], ngx_cacheline_size));
        len += test[i];
    }
    if (hinit->hash == NULL) {
        hinit->hash = ngx_pcalloc(hinit->pool, sizeof(ngx_hash_wildcard_t)
                                             + size * sizeof(ngx_hash_elt_t *));
        if (hinit->hash == NULL) {
            ngx_free(test);
            return NGX_ERROR;
        }
        buckets = (ngx_hash_elt_t **)
                      ((u_char *) hinit->hash + sizeof(ngx_hash_wildcard_t));
    } else {
        buckets = ngx_pcalloc(hinit->pool, size * sizeof(ngx_hash_elt_t *));
        if (buckets == NULL) {
            ngx_free(test);
            return NGX_ERROR;
        }
    }
    elts = ngx_palloc(hinit->pool, len + ngx_cacheline_size);
    if (elts == NULL) {
        ngx_free(test);
        return NGX_ERROR;
    }
    elts = ngx_align_ptr(elts, ngx_cacheline_size);
    for (i = 0; i < size; i++) {
        if (test[i] == sizeof(void *)) {
            continue;
        }
        buckets[i] = (ngx_hash_elt_t *) elts;
        elts += test[i];
    }
    for (i = 0; i < size; i++) {
        test[i] = 0;
    }
    for (n = 0; n < nelts; n++) {
        if (names[n].key.data == NULL) {
            continue;
        }
        key = names[n].key_hash % size;
        elt = (ngx_hash_elt_t *) ((u_char *) buckets[key] + test[key]);
        elt->value = names[n].value;
        elt->len = (u_short) names[n].key.len;
        ngx_strlow(elt->name, names[n].key.data, names[n].key.len);
        test[key] = (u_short) (test[key] + NGX_HASH_ELT_SIZE(&names[n]));
    }
    for (i = 0; i < size; i++) {
        if (buckets[i] == NULL) {
            continue;
        }
        elt = (ngx_hash_elt_t *) ((u_char *) buckets[i] + test[i]);
        elt->value = NULL;
    }
    ngx_free(test);
    hinit->hash->buckets = buckets;
    hinit->hash->size = size;
#if 0
    for (i = 0; i < size; i++) {
        ngx_str_t   val;
        ngx_uint_t  key;
        elt = buckets[i];
        if (elt == NULL) {
            ngx_log_error(NGX_LOG_ALERT, hinit->pool->log, 0,
                          "%ui: NULL", i);
            continue;
        }
        while (elt->value) {
            val.len = elt->len;
            val.data = &elt->name[0];
            key = hinit->key(val.data, val.len);
            ngx_log_error(NGX_LOG_ALERT, hinit->pool->log, 0,
                          "%ui: %p \"%V\" %ui", i, elt, &val, key);
            elt = (ngx_hash_elt_t *) ngx_align_ptr(&elt->name[0] + elt->len,
                                                   sizeof(void *));
        }
    }
#endif
    return NGX_OK;
}
['static char *\nngx_http_referer_merge_conf(ngx_conf_t *cf, void *parent, void *child)\n{\n    ngx_http_referer_conf_t *prev = parent;\n    ngx_http_referer_conf_t *conf = child;\n    ngx_hash_init_t  hash;\n    if (conf->keys == NULL) {\n        conf->hash = prev->hash;\n#if (NGX_PCRE)\n        ngx_conf_merge_ptr_value(conf->regex, prev->regex, NULL);\n#endif\n        ngx_conf_merge_value(conf->no_referer, prev->no_referer, 0);\n        ngx_conf_merge_value(conf->blocked_referer, prev->blocked_referer, 0);\n        return NGX_CONF_OK;\n    }\n    if ((conf->no_referer == 1 || conf->blocked_referer == 1)\n        && conf->keys->keys.nelts == 0\n        && conf->keys->dns_wc_head.nelts == 0\n        && conf->keys->dns_wc_tail.nelts == 0)\n    {\n        ngx_log_error(NGX_LOG_EMERG, cf->log, 0,\n                      "the \\"none\\" or \\"blocked\\" referers are specified "\n                      "in the \\"valid_referers\\" directive "\n                      "without any valid referer");\n        return NGX_CONF_ERROR;\n    }\n    hash.key = ngx_hash_key_lc;\n    hash.max_size = 2048;\n    hash.bucket_size = 64;\n    hash.name = "referers_hash";\n    hash.pool = cf->pool;\n    if (conf->keys->keys.nelts) {\n        hash.hash = &conf->hash.hash;\n        hash.temp_pool = NULL;\n        if (ngx_hash_init(&hash, conf->keys->keys.elts, conf->keys->keys.nelts)\n            != NGX_OK)\n        {\n            return NGX_CONF_ERROR;\n        }\n    }\n    if (conf->keys->dns_wc_head.nelts) {\n        ngx_qsort(conf->keys->dns_wc_head.elts,\n                  (size_t) conf->keys->dns_wc_head.nelts,\n                  sizeof(ngx_hash_key_t),\n                  ngx_http_cmp_referer_wildcards);\n        hash.hash = NULL;\n        hash.temp_pool = cf->temp_pool;\n        if (ngx_hash_wildcard_init(&hash, conf->keys->dns_wc_head.elts,\n                                   conf->keys->dns_wc_head.nelts)\n            != NGX_OK)\n        {\n            return NGX_CONF_ERROR;\n        }\n        conf->hash.wc_head = (ngx_hash_wildcard_t *) hash.hash;\n    }\n    if (conf->keys->dns_wc_tail.nelts) {\n        ngx_qsort(conf->keys->dns_wc_tail.elts,\n                  (size_t) conf->keys->dns_wc_tail.nelts,\n                  sizeof(ngx_hash_key_t),\n                  ngx_http_cmp_referer_wildcards);\n        hash.hash = NULL;\n        hash.temp_pool = cf->temp_pool;\n        if (ngx_hash_wildcard_init(&hash, conf->keys->dns_wc_tail.elts,\n                                   conf->keys->dns_wc_tail.nelts)\n            != NGX_OK)\n        {\n            return NGX_CONF_ERROR;\n        }\n        conf->hash.wc_tail = (ngx_hash_wildcard_t *) hash.hash;\n    }\n#if (NGX_PCRE)\n    ngx_conf_merge_ptr_value(conf->regex, prev->regex, NULL);\n#endif\n    if (conf->no_referer == NGX_CONF_UNSET) {\n        conf->no_referer = 0;\n    }\n    if (conf->blocked_referer == NGX_CONF_UNSET) {\n        conf->blocked_referer = 0;\n    }\n    conf->keys = NULL;\n    return NGX_CONF_OK;\n}', 'ngx_int_t\nngx_hash_init(ngx_hash_init_t *hinit, ngx_hash_key_t *names, ngx_uint_t nelts)\n{\n    u_char          *elts;\n    size_t           len;\n    u_short         *test;\n    ngx_uint_t       i, n, key, size, start, bucket_size;\n    ngx_hash_elt_t  *elt, **buckets;\n    for (n = 0; n < nelts; n++) {\n        if (hinit->bucket_size < NGX_HASH_ELT_SIZE(&names[n]) + sizeof(void *))\n        {\n            ngx_log_error(NGX_LOG_EMERG, hinit->pool->log, 0,\n                          "could not build the %s, you should "\n                          "increase %s_bucket_size: %i",\n                          hinit->name, hinit->name, hinit->bucket_size);\n            return NGX_ERROR;\n        }\n    }\n    test = ngx_alloc(hinit->max_size * sizeof(u_short), hinit->pool->log);\n    if (test == NULL) {\n        return NGX_ERROR;\n    }\n    bucket_size = hinit->bucket_size - sizeof(void *);\n    start = nelts / (bucket_size / (2 * sizeof(void *)));\n    start = start ? start : 1;\n    if (hinit->max_size > 10000 && hinit->max_size / nelts < 100) {\n        start = hinit->max_size - 1000;\n    }\n    for (size = start; size < hinit->max_size; size++) {\n        ngx_memzero(test, size * sizeof(u_short));\n        for (n = 0; n < nelts; n++) {\n            if (names[n].key.data == NULL) {\n                continue;\n            }\n            key = names[n].key_hash % size;\n            test[key] = (u_short) (test[key] + NGX_HASH_ELT_SIZE(&names[n]));\n#if 0\n            ngx_log_error(NGX_LOG_ALERT, hinit->pool->log, 0,\n                          "%ui: %ui %ui \\"%V\\"",\n                          size, key, test[key], &names[n].key);\n#endif\n            if (test[key] > (u_short) bucket_size) {\n                goto next;\n            }\n        }\n        goto found;\n    next:\n        continue;\n    }\n    ngx_log_error(NGX_LOG_EMERG, hinit->pool->log, 0,\n                  "could not build the %s, you should increase "\n                  "either %s_max_size: %i or %s_bucket_size: %i",\n                  hinit->name, hinit->name, hinit->max_size,\n                  hinit->name, hinit->bucket_size);\n    ngx_free(test);\n    return NGX_ERROR;\nfound:\n    for (i = 0; i < size; i++) {\n        test[i] = sizeof(void *);\n    }\n    for (n = 0; n < nelts; n++) {\n        if (names[n].key.data == NULL) {\n            continue;\n        }\n        key = names[n].key_hash % size;\n        test[key] = (u_short) (test[key] + NGX_HASH_ELT_SIZE(&names[n]));\n    }\n    len = 0;\n    for (i = 0; i < size; i++) {\n        if (test[i] == sizeof(void *)) {\n            continue;\n        }\n        test[i] = (u_short) (ngx_align(test[i], ngx_cacheline_size));\n        len += test[i];\n    }\n    if (hinit->hash == NULL) {\n        hinit->hash = ngx_pcalloc(hinit->pool, sizeof(ngx_hash_wildcard_t)\n                                             + size * sizeof(ngx_hash_elt_t *));\n        if (hinit->hash == NULL) {\n            ngx_free(test);\n            return NGX_ERROR;\n        }\n        buckets = (ngx_hash_elt_t **)\n                      ((u_char *) hinit->hash + sizeof(ngx_hash_wildcard_t));\n    } else {\n        buckets = ngx_pcalloc(hinit->pool, size * sizeof(ngx_hash_elt_t *));\n        if (buckets == NULL) {\n            ngx_free(test);\n            return NGX_ERROR;\n        }\n    }\n    elts = ngx_palloc(hinit->pool, len + ngx_cacheline_size);\n    if (elts == NULL) {\n        ngx_free(test);\n        return NGX_ERROR;\n    }\n    elts = ngx_align_ptr(elts, ngx_cacheline_size);\n    for (i = 0; i < size; i++) {\n        if (test[i] == sizeof(void *)) {\n            continue;\n        }\n        buckets[i] = (ngx_hash_elt_t *) elts;\n        elts += test[i];\n    }\n    for (i = 0; i < size; i++) {\n        test[i] = 0;\n    }\n    for (n = 0; n < nelts; n++) {\n        if (names[n].key.data == NULL) {\n            continue;\n        }\n        key = names[n].key_hash % size;\n        elt = (ngx_hash_elt_t *) ((u_char *) buckets[key] + test[key]);\n        elt->value = names[n].value;\n        elt->len = (u_short) names[n].key.len;\n        ngx_strlow(elt->name, names[n].key.data, names[n].key.len);\n        test[key] = (u_short) (test[key] + NGX_HASH_ELT_SIZE(&names[n]));\n    }\n    for (i = 0; i < size; i++) {\n        if (buckets[i] == NULL) {\n            continue;\n        }\n        elt = (ngx_hash_elt_t *) ((u_char *) buckets[i] + test[i]);\n        elt->value = NULL;\n    }\n    ngx_free(test);\n    hinit->hash->buckets = buckets;\n    hinit->hash->size = size;\n#if 0\n    for (i = 0; i < size; i++) {\n        ngx_str_t   val;\n        ngx_uint_t  key;\n        elt = buckets[i];\n        if (elt == NULL) {\n            ngx_log_error(NGX_LOG_ALERT, hinit->pool->log, 0,\n                          "%ui: NULL", i);\n            continue;\n        }\n        while (elt->value) {\n            val.len = elt->len;\n            val.data = &elt->name[0];\n            key = hinit->key(val.data, val.len);\n            ngx_log_error(NGX_LOG_ALERT, hinit->pool->log, 0,\n                          "%ui: %p \\"%V\\" %ui", i, elt, &val, key);\n            elt = (ngx_hash_elt_t *) ngx_align_ptr(&elt->name[0] + elt->len,\n                                                   sizeof(void *));\n        }\n    }\n#endif\n    return NGX_OK;\n}', 'void *\nngx_pcalloc(ngx_pool_t *pool, size_t size)\n{\n    void *p;\n    p = ngx_palloc(pool, size);\n    if (p) {\n        ngx_memzero(p, size);\n    }\n    return p;\n}', 'void *\nngx_palloc(ngx_pool_t *pool, size_t size)\n{\n    u_char      *m;\n    ngx_pool_t  *p;\n    if (size <= pool->max) {\n        p = pool->current;\n        do {\n            m = ngx_align_ptr(p->d.last, NGX_ALIGNMENT);\n            if ((size_t) (p->d.end - m) >= size) {\n                p->d.last = m + size;\n                return m;\n            }\n            p = p->d.next;\n        } while (p);\n        return ngx_palloc_block(pool, size);\n    }\n    return ngx_palloc_large(pool, size);\n}']