Skip to content

Commit

Permalink
Limited recursion when evaluating variables.
Browse files Browse the repository at this point in the history
Unlimited recursion might cause stack exhaustion in some misconfigurations.
  • Loading branch information
mdocguard committed Dec 21, 2016
1 parent 7fab8d0 commit d1f524d
Show file tree
Hide file tree
Showing 2 changed files with 61 additions and 13 deletions.
36 changes: 30 additions & 6 deletions src/http/ngx_http_variables.c
Original file line number Diff line number Diff line change
Expand Up @@ -366,6 +366,9 @@ ngx_http_variable_value_t ngx_http_variable_true_value =
ngx_http_variable("1");


static ngx_uint_t ngx_http_variable_depth = 100;


ngx_http_variable_t *
ngx_http_add_variable(ngx_conf_t *cf, ngx_str_t *name, ngx_uint_t flags)
{
Expand Down Expand Up @@ -517,16 +520,29 @@ ngx_http_get_indexed_variable(ngx_http_request_t *r, ngx_uint_t index)

v = cmcf->variables.elts;

if (ngx_http_variable_depth == 0) {
ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
"cycle while evaluating variable \"%V\"",
&v[index].name);
return NULL;
}

ngx_http_variable_depth--;

if (v[index].get_handler(r, &r->variables[index], v[index].data)
== NGX_OK)
{
ngx_http_variable_depth++;

if (v[index].flags & NGX_HTTP_VAR_NOCACHEABLE) {
r->variables[index].no_cacheable = 1;
}

return &r->variables[index];
}

ngx_http_variable_depth++;

r->variables[index].valid = 0;
r->variables[index].not_found = 1;

Expand Down Expand Up @@ -568,17 +584,25 @@ ngx_http_get_variable(ngx_http_request_t *r, ngx_str_t *name, ngx_uint_t key)
if (v) {
if (v->flags & NGX_HTTP_VAR_INDEXED) {
return ngx_http_get_flushed_variable(r, v->index);
}

} else {
if (ngx_http_variable_depth == 0) {
ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
"cycle while evaluating variable \"%V\"", name);
return NULL;
}

vv = ngx_palloc(r->pool, sizeof(ngx_http_variable_value_t));
ngx_http_variable_depth--;

if (vv && v->get_handler(r, vv, v->data) == NGX_OK) {
return vv;
}
vv = ngx_palloc(r->pool, sizeof(ngx_http_variable_value_t));

return NULL;
if (vv && v->get_handler(r, vv, v->data) == NGX_OK) {
ngx_http_variable_depth++;
return vv;
}

ngx_http_variable_depth++;
return NULL;
}

vv = ngx_palloc(r->pool, sizeof(ngx_http_variable_value_t));
Expand Down
38 changes: 31 additions & 7 deletions src/stream/ngx_stream_variables.c
Original file line number Diff line number Diff line change
Expand Up @@ -119,6 +119,9 @@ ngx_stream_variable_value_t ngx_stream_variable_true_value =
ngx_stream_variable("1");


static ngx_uint_t ngx_stream_variable_depth = 100;


ngx_stream_variable_t *
ngx_stream_add_variable(ngx_conf_t *cf, ngx_str_t *name, ngx_uint_t flags)
{
Expand Down Expand Up @@ -270,16 +273,29 @@ ngx_stream_get_indexed_variable(ngx_stream_session_t *s, ngx_uint_t index)

v = cmcf->variables.elts;

if (ngx_stream_variable_depth == 0) {
ngx_log_error(NGX_LOG_ERR, s->connection->log, 0,
"cycle while evaluating variable \"%V\"",
&v[index].name);
return NULL;
}

ngx_stream_variable_depth--;

if (v[index].get_handler(s, &s->variables[index], v[index].data)
== NGX_OK)
{
ngx_stream_variable_depth++;

if (v[index].flags & NGX_STREAM_VAR_NOCACHEABLE) {
s->variables[index].no_cacheable = 1;
}

return &s->variables[index];
}

ngx_stream_variable_depth++;

s->variables[index].valid = 0;
s->variables[index].not_found = 1;

Expand Down Expand Up @@ -322,18 +338,26 @@ ngx_stream_get_variable(ngx_stream_session_t *s, ngx_str_t *name,
if (v) {
if (v->flags & NGX_STREAM_VAR_INDEXED) {
return ngx_stream_get_flushed_variable(s, v->index);
}

} else {
if (ngx_stream_variable_depth == 0) {
ngx_log_error(NGX_LOG_ERR, s->connection->log, 0,
"cycle while evaluating variable \"%V\"", name);
return NULL;
}

vv = ngx_palloc(s->connection->pool,
sizeof(ngx_stream_variable_value_t));
ngx_stream_variable_depth--;

if (vv && v->get_handler(s, vv, v->data) == NGX_OK) {
return vv;
}
vv = ngx_palloc(s->connection->pool,
sizeof(ngx_stream_variable_value_t));

return NULL;
if (vv && v->get_handler(s, vv, v->data) == NGX_OK) {
ngx_stream_variable_depth++;
return vv;
}

ngx_stream_variable_depth++;
return NULL;
}

vv = ngx_palloc(s->connection->pool, sizeof(ngx_stream_variable_value_t));
Expand Down

0 comments on commit d1f524d

Please sign in to comment.