mirror of
https://github.com/nginx/nginx.git
synced 2025-06-06 17:02:39 +08:00
Fix of rbtree lookup on hash collisions.
Previous code incorrectly assumed that nodes with identical keys are linked together. This might not be true after tree rebalance. Patch by Lanshun Zhou.
This commit is contained in:
parent
53d9677de4
commit
7ca6c1ff78
@ -1142,20 +1142,15 @@ ngx_open_file_lookup(ngx_open_file_cache_t *cache, ngx_str_t *name,
|
|||||||
|
|
||||||
/* hash == node->key */
|
/* hash == node->key */
|
||||||
|
|
||||||
do {
|
file = (ngx_cached_open_file_t *) node;
|
||||||
file = (ngx_cached_open_file_t *) node;
|
|
||||||
|
|
||||||
rc = ngx_strcmp(name->data, file->name);
|
rc = ngx_strcmp(name->data, file->name);
|
||||||
|
|
||||||
if (rc == 0) {
|
if (rc == 0) {
|
||||||
return file;
|
return file;
|
||||||
}
|
}
|
||||||
|
|
||||||
node = (rc < 0) ? node->left : node->right;
|
node = (rc < 0) ? node->left : node->right;
|
||||||
|
|
||||||
} while (node != sentinel && hash == node->key);
|
|
||||||
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return NULL;
|
return NULL;
|
||||||
|
@ -1689,20 +1689,15 @@ ngx_resolver_lookup_name(ngx_resolver_t *r, ngx_str_t *name, uint32_t hash)
|
|||||||
|
|
||||||
/* hash == node->key */
|
/* hash == node->key */
|
||||||
|
|
||||||
do {
|
rn = (ngx_resolver_node_t *) node;
|
||||||
rn = (ngx_resolver_node_t *) node;
|
|
||||||
|
|
||||||
rc = ngx_memn2cmp(name->data, rn->name, name->len, rn->nlen);
|
rc = ngx_memn2cmp(name->data, rn->name, name->len, rn->nlen);
|
||||||
|
|
||||||
if (rc == 0) {
|
if (rc == 0) {
|
||||||
return rn;
|
return rn;
|
||||||
}
|
}
|
||||||
|
|
||||||
node = (rc < 0) ? node->left : node->right;
|
node = (rc < 0) ? node->left : node->right;
|
||||||
|
|
||||||
} while (node != sentinel && hash == node->key);
|
|
||||||
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* not found */
|
/* not found */
|
||||||
|
@ -1801,44 +1801,39 @@ ngx_ssl_get_cached_session(ngx_ssl_conn_t *ssl_conn, u_char *id, int len,
|
|||||||
|
|
||||||
/* hash == node->key */
|
/* hash == node->key */
|
||||||
|
|
||||||
do {
|
sess_id = (ngx_ssl_sess_id_t *) node;
|
||||||
sess_id = (ngx_ssl_sess_id_t *) node;
|
|
||||||
|
|
||||||
rc = ngx_memn2cmp(id, sess_id->id,
|
rc = ngx_memn2cmp(id, sess_id->id, (size_t) len, (size_t) node->data);
|
||||||
(size_t) len, (size_t) node->data);
|
|
||||||
if (rc == 0) {
|
|
||||||
|
|
||||||
if (sess_id->expire > ngx_time()) {
|
if (rc == 0) {
|
||||||
ngx_memcpy(buf, sess_id->session, sess_id->len);
|
|
||||||
|
|
||||||
ngx_shmtx_unlock(&shpool->mutex);
|
if (sess_id->expire > ngx_time()) {
|
||||||
|
ngx_memcpy(buf, sess_id->session, sess_id->len);
|
||||||
|
|
||||||
p = buf;
|
ngx_shmtx_unlock(&shpool->mutex);
|
||||||
sess = d2i_SSL_SESSION(NULL, &p, sess_id->len);
|
|
||||||
|
|
||||||
return sess;
|
p = buf;
|
||||||
}
|
sess = d2i_SSL_SESSION(NULL, &p, sess_id->len);
|
||||||
|
|
||||||
ngx_queue_remove(&sess_id->queue);
|
return sess;
|
||||||
|
|
||||||
ngx_rbtree_delete(&cache->session_rbtree, node);
|
|
||||||
|
|
||||||
ngx_slab_free_locked(shpool, sess_id->session);
|
|
||||||
#if (NGX_PTR_SIZE == 4)
|
|
||||||
ngx_slab_free_locked(shpool, sess_id->id);
|
|
||||||
#endif
|
|
||||||
ngx_slab_free_locked(shpool, sess_id);
|
|
||||||
|
|
||||||
sess = NULL;
|
|
||||||
|
|
||||||
goto done;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
node = (rc < 0) ? node->left : node->right;
|
ngx_queue_remove(&sess_id->queue);
|
||||||
|
|
||||||
} while (node != sentinel && hash == node->key);
|
ngx_rbtree_delete(&cache->session_rbtree, node);
|
||||||
|
|
||||||
break;
|
ngx_slab_free_locked(shpool, sess_id->session);
|
||||||
|
#if (NGX_PTR_SIZE == 4)
|
||||||
|
ngx_slab_free_locked(shpool, sess_id->id);
|
||||||
|
#endif
|
||||||
|
ngx_slab_free_locked(shpool, sess_id);
|
||||||
|
|
||||||
|
sess = NULL;
|
||||||
|
|
||||||
|
goto done;
|
||||||
|
}
|
||||||
|
|
||||||
|
node = (rc < 0) ? node->left : node->right;
|
||||||
}
|
}
|
||||||
|
|
||||||
done:
|
done:
|
||||||
@ -1908,31 +1903,26 @@ ngx_ssl_remove_session(SSL_CTX *ssl, ngx_ssl_session_t *sess)
|
|||||||
|
|
||||||
/* hash == node->key */
|
/* hash == node->key */
|
||||||
|
|
||||||
do {
|
sess_id = (ngx_ssl_sess_id_t *) node;
|
||||||
sess_id = (ngx_ssl_sess_id_t *) node;
|
|
||||||
|
|
||||||
rc = ngx_memn2cmp(id, sess_id->id, len, (size_t) node->data);
|
rc = ngx_memn2cmp(id, sess_id->id, len, (size_t) node->data);
|
||||||
|
|
||||||
if (rc == 0) {
|
if (rc == 0) {
|
||||||
|
|
||||||
ngx_queue_remove(&sess_id->queue);
|
ngx_queue_remove(&sess_id->queue);
|
||||||
|
|
||||||
ngx_rbtree_delete(&cache->session_rbtree, node);
|
ngx_rbtree_delete(&cache->session_rbtree, node);
|
||||||
|
|
||||||
ngx_slab_free_locked(shpool, sess_id->session);
|
ngx_slab_free_locked(shpool, sess_id->session);
|
||||||
#if (NGX_PTR_SIZE == 4)
|
#if (NGX_PTR_SIZE == 4)
|
||||||
ngx_slab_free_locked(shpool, sess_id->id);
|
ngx_slab_free_locked(shpool, sess_id->id);
|
||||||
#endif
|
#endif
|
||||||
ngx_slab_free_locked(shpool, sess_id);
|
ngx_slab_free_locked(shpool, sess_id);
|
||||||
|
|
||||||
goto done;
|
goto done;
|
||||||
}
|
}
|
||||||
|
|
||||||
node = (rc < 0) ? node->left : node->right;
|
node = (rc < 0) ? node->left : node->right;
|
||||||
|
|
||||||
} while (node != sentinel && hash == node->key);
|
|
||||||
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
done:
|
done:
|
||||||
|
@ -325,20 +325,15 @@ ngx_http_limit_conn_lookup(ngx_rbtree_t *rbtree, ngx_http_variable_value_t *vv,
|
|||||||
|
|
||||||
/* hash == node->key */
|
/* hash == node->key */
|
||||||
|
|
||||||
do {
|
lcn = (ngx_http_limit_conn_node_t *) &node->color;
|
||||||
lcn = (ngx_http_limit_conn_node_t *) &node->color;
|
|
||||||
|
|
||||||
rc = ngx_memn2cmp(vv->data, lcn->data,
|
rc = ngx_memn2cmp(vv->data, lcn->data,
|
||||||
(size_t) vv->len, (size_t) lcn->len);
|
(size_t) vv->len, (size_t) lcn->len);
|
||||||
if (rc == 0) {
|
if (rc == 0) {
|
||||||
return node;
|
return node;
|
||||||
}
|
}
|
||||||
|
|
||||||
node = (rc < 0) ? node->left : node->right;
|
node = (rc < 0) ? node->left : node->right;
|
||||||
|
|
||||||
} while (node != sentinel && hash == node->key);
|
|
||||||
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return NULL;
|
return NULL;
|
||||||
|
@ -385,47 +385,42 @@ ngx_http_limit_req_lookup(ngx_http_limit_req_limit_t *limit, ngx_uint_t hash,
|
|||||||
|
|
||||||
/* hash == node->key */
|
/* hash == node->key */
|
||||||
|
|
||||||
do {
|
lr = (ngx_http_limit_req_node_t *) &node->color;
|
||||||
lr = (ngx_http_limit_req_node_t *) &node->color;
|
|
||||||
|
|
||||||
rc = ngx_memn2cmp(data, lr->data, len, (size_t) lr->len);
|
rc = ngx_memn2cmp(data, lr->data, len, (size_t) lr->len);
|
||||||
|
|
||||||
if (rc == 0) {
|
if (rc == 0) {
|
||||||
ngx_queue_remove(&lr->queue);
|
ngx_queue_remove(&lr->queue);
|
||||||
ngx_queue_insert_head(&ctx->sh->queue, &lr->queue);
|
ngx_queue_insert_head(&ctx->sh->queue, &lr->queue);
|
||||||
|
|
||||||
ms = (ngx_msec_int_t) (now - lr->last);
|
ms = (ngx_msec_int_t) (now - lr->last);
|
||||||
|
|
||||||
excess = lr->excess - ctx->rate * ngx_abs(ms) / 1000 + 1000;
|
excess = lr->excess - ctx->rate * ngx_abs(ms) / 1000 + 1000;
|
||||||
|
|
||||||
if (excess < 0) {
|
if (excess < 0) {
|
||||||
excess = 0;
|
excess = 0;
|
||||||
}
|
|
||||||
|
|
||||||
*ep = excess;
|
|
||||||
|
|
||||||
if ((ngx_uint_t) excess > limit->burst) {
|
|
||||||
return NGX_BUSY;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (account) {
|
|
||||||
lr->excess = excess;
|
|
||||||
lr->last = now;
|
|
||||||
return NGX_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
lr->count++;
|
|
||||||
|
|
||||||
ctx->node = lr;
|
|
||||||
|
|
||||||
return NGX_AGAIN;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
node = (rc < 0) ? node->left : node->right;
|
*ep = excess;
|
||||||
|
|
||||||
} while (node != sentinel && hash == node->key);
|
if ((ngx_uint_t) excess > limit->burst) {
|
||||||
|
return NGX_BUSY;
|
||||||
|
}
|
||||||
|
|
||||||
break;
|
if (account) {
|
||||||
|
lr->excess = excess;
|
||||||
|
lr->last = now;
|
||||||
|
return NGX_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
lr->count++;
|
||||||
|
|
||||||
|
ctx->node = lr;
|
||||||
|
|
||||||
|
return NGX_AGAIN;
|
||||||
|
}
|
||||||
|
|
||||||
|
node = (rc < 0) ? node->left : node->right;
|
||||||
}
|
}
|
||||||
|
|
||||||
*ep = 0;
|
*ep = 0;
|
||||||
|
@ -799,21 +799,16 @@ ngx_http_file_cache_lookup(ngx_http_file_cache_t *cache, u_char *key)
|
|||||||
|
|
||||||
/* node_key == node->key */
|
/* node_key == node->key */
|
||||||
|
|
||||||
do {
|
fcn = (ngx_http_file_cache_node_t *) node;
|
||||||
fcn = (ngx_http_file_cache_node_t *) node;
|
|
||||||
|
|
||||||
rc = ngx_memcmp(&key[sizeof(ngx_rbtree_key_t)], fcn->key,
|
rc = ngx_memcmp(&key[sizeof(ngx_rbtree_key_t)], fcn->key,
|
||||||
NGX_HTTP_CACHE_KEY_LEN - sizeof(ngx_rbtree_key_t));
|
NGX_HTTP_CACHE_KEY_LEN - sizeof(ngx_rbtree_key_t));
|
||||||
|
|
||||||
if (rc == 0) {
|
if (rc == 0) {
|
||||||
return fcn;
|
return fcn;
|
||||||
}
|
}
|
||||||
|
|
||||||
node = (rc < 0) ? node->left : node->right;
|
node = (rc < 0) ? node->left : node->right;
|
||||||
|
|
||||||
} while (node != sentinel && node_key == node->key);
|
|
||||||
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* not found */
|
/* not found */
|
||||||
|
Loading…
Reference in New Issue
Block a user