comparison src/stream/ngx_stream_variables.c @ 6851:8cd97c14b0e2

Limited recursion when evaluating variables. Unlimited recursion might cause stack exhaustion in some misconfigurations.
author Ruslan Ermilov <ru@nginx.com>
date Wed, 21 Dec 2016 22:01:24 +0300
parents b9f78a4e3597
children d2b2ff157da5
comparison
equal deleted inserted replaced
6850:41cb1b64561d 6851:8cd97c14b0e2
115 115
116 ngx_stream_variable_value_t ngx_stream_variable_null_value = 116 ngx_stream_variable_value_t ngx_stream_variable_null_value =
117 ngx_stream_variable(""); 117 ngx_stream_variable("");
118 ngx_stream_variable_value_t ngx_stream_variable_true_value = 118 ngx_stream_variable_value_t ngx_stream_variable_true_value =
119 ngx_stream_variable("1"); 119 ngx_stream_variable("1");
120
121
122 static ngx_uint_t ngx_stream_variable_depth = 100;
120 123
121 124
122 ngx_stream_variable_t * 125 ngx_stream_variable_t *
123 ngx_stream_add_variable(ngx_conf_t *cf, ngx_str_t *name, ngx_uint_t flags) 126 ngx_stream_add_variable(ngx_conf_t *cf, ngx_str_t *name, ngx_uint_t flags)
124 { 127 {
268 return &s->variables[index]; 271 return &s->variables[index];
269 } 272 }
270 273
271 v = cmcf->variables.elts; 274 v = cmcf->variables.elts;
272 275
276 if (ngx_stream_variable_depth == 0) {
277 ngx_log_error(NGX_LOG_ERR, s->connection->log, 0,
278 "cycle while evaluating variable \"%V\"",
279 &v[index].name);
280 return NULL;
281 }
282
283 ngx_stream_variable_depth--;
284
273 if (v[index].get_handler(s, &s->variables[index], v[index].data) 285 if (v[index].get_handler(s, &s->variables[index], v[index].data)
274 == NGX_OK) 286 == NGX_OK)
275 { 287 {
288 ngx_stream_variable_depth++;
289
276 if (v[index].flags & NGX_STREAM_VAR_NOCACHEABLE) { 290 if (v[index].flags & NGX_STREAM_VAR_NOCACHEABLE) {
277 s->variables[index].no_cacheable = 1; 291 s->variables[index].no_cacheable = 1;
278 } 292 }
279 293
280 return &s->variables[index]; 294 return &s->variables[index];
281 } 295 }
296
297 ngx_stream_variable_depth++;
282 298
283 s->variables[index].valid = 0; 299 s->variables[index].valid = 0;
284 s->variables[index].not_found = 1; 300 s->variables[index].not_found = 1;
285 301
286 return NULL; 302 return NULL;
320 v = ngx_hash_find(&cmcf->variables_hash, key, name->data, name->len); 336 v = ngx_hash_find(&cmcf->variables_hash, key, name->data, name->len);
321 337
322 if (v) { 338 if (v) {
323 if (v->flags & NGX_STREAM_VAR_INDEXED) { 339 if (v->flags & NGX_STREAM_VAR_INDEXED) {
324 return ngx_stream_get_flushed_variable(s, v->index); 340 return ngx_stream_get_flushed_variable(s, v->index);
325 341 }
326 } else { 342
327 343 if (ngx_stream_variable_depth == 0) {
328 vv = ngx_palloc(s->connection->pool, 344 ngx_log_error(NGX_LOG_ERR, s->connection->log, 0,
329 sizeof(ngx_stream_variable_value_t)); 345 "cycle while evaluating variable \"%V\"", name);
330
331 if (vv && v->get_handler(s, vv, v->data) == NGX_OK) {
332 return vv;
333 }
334
335 return NULL; 346 return NULL;
336 } 347 }
348
349 ngx_stream_variable_depth--;
350
351 vv = ngx_palloc(s->connection->pool,
352 sizeof(ngx_stream_variable_value_t));
353
354 if (vv && v->get_handler(s, vv, v->data) == NGX_OK) {
355 ngx_stream_variable_depth++;
356 return vv;
357 }
358
359 ngx_stream_variable_depth++;
360 return NULL;
337 } 361 }
338 362
339 vv = ngx_palloc(s->connection->pool, sizeof(ngx_stream_variable_value_t)); 363 vv = ngx_palloc(s->connection->pool, sizeof(ngx_stream_variable_value_t));
340 if (vv == NULL) { 364 if (vv == NULL) {
341 return NULL; 365 return NULL;