-
Notifications
You must be signed in to change notification settings - Fork 2k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
bugfix: Fix handling of new list elements #2177
Conversation
@oxpa |
Makes sense, will do |
@oxpa got the following error. the header type is ngx_table_elt_t for the nginx older than 1.23 which does not have the next member
https://app.travis-ci.com/github/openresty/lua-nginx-module/jobs/599726670#L2356 |
Sorry, didn't check this. Will fix and check it works pre-1.23.0. |
I have pushed the commit but I'm yet to test it. |
The code doesn't create a new element but rather goes through existing in a list and possibly updates their values. This element was created elsewhere and should already have proper 'next' value. |
I still don't see a problem. The 'h->next' value is either NULL or a valid pointer to a next element. |
Forgive me pasting the source code. static ngx_int_t
ngx_http_variable_headers_internal(ngx_http_request_t *r,
ngx_http_variable_value_t *v, uintptr_t data, u_char sep)
{
size_t len;
u_char *p;
ngx_table_elt_t *h, *th;
h = *(ngx_table_elt_t **) ((char *) r + data);
len = 0;
for (th = h; th; th = th->next) {
if (th->hash == 0) {
continue;
}
len += th->value.len + 2; /* variable data size 'len' caculating */
}
if (len == 0) {
v->not_found = 1;
return NGX_OK;
}
len -= 2; /* not including trailing sep and space */
v->valid = 1;
v->no_cacheable = 0;
v->not_found = 0;
if (h->next == NULL) {
v->len = h->value.len;
v->data = h->value.data;
return NGX_OK;
}
p = ngx_pnalloc(r->pool, len);
if (p == NULL) {
return NGX_ERROR;
}
v->len = len;
v->data = p;
for (th = h; th; th = th->next) {
if (th->hash == 0) {
continue;
}
p = ngx_copy(p, th->value.data, th->value.len);
if (th->next == NULL) {. /* th->next has valid value while th->hash is 0 */
break;
}
*p++ = sep; *p++ = ' '; /* here is the problem, since the variable data size is 'len', not including
extra sep and space, this will lead heap-buffer-overflow problem */
}
return NGX_OK;
} |
@ssdr while I'm not sure how to trigger this, the overall idea seems correct. Let me have a think. Though this seems a bit more complex than I can handle =) |
or even not 'continuous tail' but rather 'the last header value should be the last element in a list'. This seems proper wording. |
If there are any bug there, we should try to add a test case to cover it. |
Another solution: Since h->next is valid value and it's hash might be 0, maybe ...
for (th = h; th; th = th->next) {
if (th->hash == 0) {
continue;
}
p = ngx_copy(p, th->value.data, th->value.len);
if (th->next == NULL) {
break;
}
*p++ = sep; *p++ = ' '; // maybe here needs some conditions, since th->next->hash might be 0
}
... |
There have been a test case in 016-resp-header.t TEST 34, use openresty-asan binary will lead test case failed. Non-asan binary needs gdb to check it:
|
I don't think editing nginx sources would be the right solution: there may be other places where this problem may arise |
fixed in nginx: https://hg.nginx.org/nginx/rev/b71e69247483 |
ngx_list_push return an uninitialized element. Each of them needs 'next' element set to either zero or valid pointer.
The problem become apparent after #2063 : it fixes variable handling but leaves problems with uninitialized 'next' elements.
I managed to improve at least two tests to make the problem reveal itself on linux.
Adding MALLOC_PERTURB_ forces glib to initialize allocated memory with a non-zero value. This allows code to fail quicker: you don't have to wait till nginx pool reuses a chunk.
As I'm not really familiar with the code, so I might have missed a place or two more with similar problem.
Also, I guess, it makes sense to add MALLOC_PERTURB_ to all tests.
I hereby granted the copyright of the changes in this pull request
to the authors of this lua-nginx-module project.