# HG changeset patch # User Valentin Bartenev # Date 1375804720 -14400 # Node ID 12dd27b74117262486264e7f11d0dd7d6320fdf6 # Parent 31932b5464f0230d5039fafed94c33f495da35f6 Fixed memory leaks in the root and auth_basic_user_file directives. If a relative path is set by variables, then the ngx_conf_full_name() function was called while processing requests, which causes allocations from the cycle pool. A new function that takes pool as an argument was introduced. diff --git a/src/core/ngx_conf_file.c b/src/core/ngx_conf_file.c --- a/src/core/ngx_conf_file.c +++ b/src/core/ngx_conf_file.c @@ -12,7 +12,6 @@ static ngx_int_t ngx_conf_handler(ngx_conf_t *cf, ngx_int_t last); static ngx_int_t ngx_conf_read_token(ngx_conf_t *cf); -static ngx_int_t ngx_conf_test_full_name(ngx_str_t *name); static void ngx_conf_flush_files(ngx_cycle_t *cycle); @@ -801,95 +800,10 @@ ngx_conf_include(ngx_conf_t *cf, ngx_com ngx_int_t ngx_conf_full_name(ngx_cycle_t *cycle, ngx_str_t *name, ngx_uint_t conf_prefix) { - size_t len; - u_char *p, *n, *prefix; - ngx_int_t rc; - - rc = ngx_conf_test_full_name(name); - - if (rc == NGX_OK) { - return rc; - } - - if (conf_prefix) { - len = cycle->conf_prefix.len; - prefix = cycle->conf_prefix.data; - - } else { - len = cycle->prefix.len; - prefix = cycle->prefix.data; - } - -#if (NGX_WIN32) - - if (rc == 2) { - len = rc; - } - -#endif - - n = ngx_pnalloc(cycle->pool, len + name->len + 1); - if (n == NULL) { - return NGX_ERROR; - } - - p = ngx_cpymem(n, prefix, len); - ngx_cpystrn(p, name->data, name->len + 1); - - name->len += len; - name->data = n; - - return NGX_OK; -} - - -static ngx_int_t -ngx_conf_test_full_name(ngx_str_t *name) -{ -#if (NGX_WIN32) - u_char c0, c1; - - c0 = name->data[0]; - - if (name->len < 2) { - if (c0 == '/') { - return 2; - } - - return NGX_DECLINED; - } - - c1 = name->data[1]; - - if (c1 == ':') { - c0 |= 0x20; - - if ((c0 >= 'a' && c0 <= 'z')) { - return NGX_OK; - } - - return NGX_DECLINED; - } - - if (c1 == '/') { - return NGX_OK; - } - - if (c0 == '/') { - return 2; - } - - return NGX_DECLINED; - -#else - - if (name->data[0] == '/') { - return NGX_OK; - } - - return NGX_DECLINED; - -#endif + return ngx_get_full_name(cycle->pool, + conf_prefix ? &cycle->conf_prefix: + &cycle->prefix, + name); } diff --git a/src/core/ngx_file.c b/src/core/ngx_file.c --- a/src/core/ngx_file.c +++ b/src/core/ngx_file.c @@ -9,11 +9,102 @@ #include +static ngx_int_t ngx_test_full_name(ngx_str_t *name); + + static ngx_atomic_t temp_number = 0; ngx_atomic_t *ngx_temp_number = &temp_number; ngx_atomic_int_t ngx_random_number = 123456; +ngx_int_t +ngx_get_full_name(ngx_pool_t *pool, ngx_str_t *prefix, ngx_str_t *name) +{ + size_t len; + u_char *p, *n; + ngx_int_t rc; + + rc = ngx_test_full_name(name); + + if (rc == NGX_OK) { + return rc; + } + + len = prefix->len; + +#if (NGX_WIN32) + + if (rc == 2) { + len = rc; + } + +#endif + + n = ngx_pnalloc(pool, len + name->len + 1); + if (n == NULL) { + return NGX_ERROR; + } + + p = ngx_cpymem(n, prefix->data, len); + ngx_cpystrn(p, name->data, name->len + 1); + + name->len += len; + name->data = n; + + return NGX_OK; +} + + +static ngx_int_t +ngx_test_full_name(ngx_str_t *name) +{ +#if (NGX_WIN32) + u_char c0, c1; + + c0 = name->data[0]; + + if (name->len < 2) { + if (c0 == '/') { + return 2; + } + + return NGX_DECLINED; + } + + c1 = name->data[1]; + + if (c1 == ':') { + c0 |= 0x20; + + if ((c0 >= 'a' && c0 <= 'z')) { + return NGX_OK; + } + + return NGX_DECLINED; + } + + if (c1 == '/') { + return NGX_OK; + } + + if (c0 == '/') { + return 2; + } + + return NGX_DECLINED; + +#else + + if (name->data[0] == '/') { + return NGX_OK; + } + + return NGX_DECLINED; + +#endif +} + + ssize_t ngx_write_chain_to_temp_file(ngx_temp_file_t *tf, ngx_chain_t *chain) { diff --git a/src/core/ngx_file.h b/src/core/ngx_file.h --- a/src/core/ngx_file.h +++ b/src/core/ngx_file.h @@ -122,6 +122,9 @@ struct ngx_tree_ctx_s { }; +ngx_int_t ngx_get_full_name(ngx_pool_t *pool, ngx_str_t *prefix, + ngx_str_t *name); + ssize_t ngx_write_chain_to_temp_file(ngx_temp_file_t *tf, ngx_chain_t *chain); ngx_int_t ngx_create_temp_file(ngx_file_t *file, ngx_path_t *path, ngx_pool_t *pool, ngx_uint_t persistent, ngx_uint_t clean, diff --git a/src/http/ngx_http_core_module.c b/src/http/ngx_http_core_module.c --- a/src/http/ngx_http_core_module.c +++ b/src/http/ngx_http_core_module.c @@ -2016,7 +2016,9 @@ ngx_http_map_uri_to_path(ngx_http_reques return NULL; } - if (ngx_conf_full_name((ngx_cycle_t *) ngx_cycle, path, 0) != NGX_OK) { + if (ngx_get_full_name(r->pool, (ngx_str_t *) &ngx_cycle->prefix, path) + != NGX_OK) + { return NULL; } diff --git a/src/http/ngx_http_script.c b/src/http/ngx_http_script.c --- a/src/http/ngx_http_script.c +++ b/src/http/ngx_http_script.c @@ -1334,7 +1334,11 @@ ngx_http_script_full_name_code(ngx_http_ value.data = e->buf.data; value.len = e->pos - e->buf.data; - if (ngx_conf_full_name((ngx_cycle_t *) ngx_cycle, &value, code->conf_prefix) + if (ngx_get_full_name(e->request->pool, + code->conf_prefix + ? (ngx_str_t *) &ngx_cycle->conf_prefix: + (ngx_str_t *) &ngx_cycle->prefix, + &value) != NGX_OK) { e->ip = ngx_http_script_exit; diff --git a/src/http/ngx_http_variables.c b/src/http/ngx_http_variables.c --- a/src/http/ngx_http_variables.c +++ b/src/http/ngx_http_variables.c @@ -1374,7 +1374,9 @@ ngx_http_variable_document_root(ngx_http return NGX_ERROR; } - if (ngx_conf_full_name((ngx_cycle_t *) ngx_cycle, &path, 0) != NGX_OK) { + if (ngx_get_full_name(r->pool, (ngx_str_t *) &ngx_cycle->prefix, &path) + != NGX_OK) + { return NGX_ERROR; } @@ -1416,7 +1418,9 @@ ngx_http_variable_realpath_root(ngx_http path.data[path.len - 1] = '\0'; - if (ngx_conf_full_name((ngx_cycle_t *) ngx_cycle, &path, 0) != NGX_OK) { + if (ngx_get_full_name(r->pool, (ngx_str_t *) &ngx_cycle->prefix, &path) + != NGX_OK) + { return NGX_ERROR; } }