Mercurial > hg > nginx
annotate src/http/v2/ngx_http_v2_encode.c @ 8164:b71e69247483
Variables: avoid possible buffer overrun with some "$sent_http_*".
The existing logic to evaluate multi header "$sent_http_*" variables,
such as $sent_http_cache_control, as previously introduced in 1.23.0,
doesn't take into account that one or more elements can be cleared,
yet still present in a linked list, pointed to by the next field.
Such elements don't contribute to the resulting variable length, an
attempt to append a separator for them ends up in out of bounds write.
This is not possible with standard modules, though at least one third
party module is known to override multi header values this way, so it
makes sense to harden the logic.
The fix restores a generic boundary check.
author | Sergey Kandaurov <pluknet@nginx.com> |
---|---|
date | Mon, 01 May 2023 19:16:05 +0400 |
parents | 336084ff943b |
children |
rev | line source |
---|---|
7229
87e9e4aabf1b
HTTP/2: externalized various constants and interfaces.
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff
changeset
|
1 |
87e9e4aabf1b
HTTP/2: externalized various constants and interfaces.
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff
changeset
|
2 /* |
87e9e4aabf1b
HTTP/2: externalized various constants and interfaces.
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff
changeset
|
3 * Copyright (C) Nginx, Inc. |
87e9e4aabf1b
HTTP/2: externalized various constants and interfaces.
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff
changeset
|
4 * Copyright (C) Valentin V. Bartenev |
87e9e4aabf1b
HTTP/2: externalized various constants and interfaces.
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff
changeset
|
5 */ |
87e9e4aabf1b
HTTP/2: externalized various constants and interfaces.
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff
changeset
|
6 |
87e9e4aabf1b
HTTP/2: externalized various constants and interfaces.
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff
changeset
|
7 |
87e9e4aabf1b
HTTP/2: externalized various constants and interfaces.
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff
changeset
|
8 #include <ngx_config.h> |
87e9e4aabf1b
HTTP/2: externalized various constants and interfaces.
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff
changeset
|
9 #include <ngx_core.h> |
87e9e4aabf1b
HTTP/2: externalized various constants and interfaces.
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff
changeset
|
10 #include <ngx_http.h> |
87e9e4aabf1b
HTTP/2: externalized various constants and interfaces.
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff
changeset
|
11 |
87e9e4aabf1b
HTTP/2: externalized various constants and interfaces.
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff
changeset
|
12 |
87e9e4aabf1b
HTTP/2: externalized various constants and interfaces.
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff
changeset
|
13 static u_char *ngx_http_v2_write_int(u_char *pos, ngx_uint_t prefix, |
87e9e4aabf1b
HTTP/2: externalized various constants and interfaces.
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff
changeset
|
14 ngx_uint_t value); |
87e9e4aabf1b
HTTP/2: externalized various constants and interfaces.
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff
changeset
|
15 |
87e9e4aabf1b
HTTP/2: externalized various constants and interfaces.
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff
changeset
|
16 |
87e9e4aabf1b
HTTP/2: externalized various constants and interfaces.
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff
changeset
|
17 u_char * |
87e9e4aabf1b
HTTP/2: externalized various constants and interfaces.
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff
changeset
|
18 ngx_http_v2_string_encode(u_char *dst, u_char *src, size_t len, u_char *tmp, |
87e9e4aabf1b
HTTP/2: externalized various constants and interfaces.
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff
changeset
|
19 ngx_uint_t lower) |
87e9e4aabf1b
HTTP/2: externalized various constants and interfaces.
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff
changeset
|
20 { |
87e9e4aabf1b
HTTP/2: externalized various constants and interfaces.
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff
changeset
|
21 size_t hlen; |
87e9e4aabf1b
HTTP/2: externalized various constants and interfaces.
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff
changeset
|
22 |
7977
336084ff943b
Moved Huffman coding out of HTTP/2.
Ruslan Ermilov <ru@nginx.com>
parents:
7229
diff
changeset
|
23 hlen = ngx_http_huff_encode(src, len, tmp, lower); |
7229
87e9e4aabf1b
HTTP/2: externalized various constants and interfaces.
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff
changeset
|
24 |
87e9e4aabf1b
HTTP/2: externalized various constants and interfaces.
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff
changeset
|
25 if (hlen > 0) { |
87e9e4aabf1b
HTTP/2: externalized various constants and interfaces.
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff
changeset
|
26 *dst = NGX_HTTP_V2_ENCODE_HUFF; |
87e9e4aabf1b
HTTP/2: externalized various constants and interfaces.
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff
changeset
|
27 dst = ngx_http_v2_write_int(dst, ngx_http_v2_prefix(7), hlen); |
87e9e4aabf1b
HTTP/2: externalized various constants and interfaces.
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff
changeset
|
28 return ngx_cpymem(dst, tmp, hlen); |
87e9e4aabf1b
HTTP/2: externalized various constants and interfaces.
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff
changeset
|
29 } |
87e9e4aabf1b
HTTP/2: externalized various constants and interfaces.
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff
changeset
|
30 |
87e9e4aabf1b
HTTP/2: externalized various constants and interfaces.
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff
changeset
|
31 *dst = NGX_HTTP_V2_ENCODE_RAW; |
87e9e4aabf1b
HTTP/2: externalized various constants and interfaces.
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff
changeset
|
32 dst = ngx_http_v2_write_int(dst, ngx_http_v2_prefix(7), len); |
87e9e4aabf1b
HTTP/2: externalized various constants and interfaces.
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff
changeset
|
33 |
87e9e4aabf1b
HTTP/2: externalized various constants and interfaces.
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff
changeset
|
34 if (lower) { |
87e9e4aabf1b
HTTP/2: externalized various constants and interfaces.
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff
changeset
|
35 ngx_strlow(dst, src, len); |
87e9e4aabf1b
HTTP/2: externalized various constants and interfaces.
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff
changeset
|
36 return dst + len; |
87e9e4aabf1b
HTTP/2: externalized various constants and interfaces.
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff
changeset
|
37 } |
87e9e4aabf1b
HTTP/2: externalized various constants and interfaces.
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff
changeset
|
38 |
87e9e4aabf1b
HTTP/2: externalized various constants and interfaces.
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff
changeset
|
39 return ngx_cpymem(dst, src, len); |
87e9e4aabf1b
HTTP/2: externalized various constants and interfaces.
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff
changeset
|
40 } |
87e9e4aabf1b
HTTP/2: externalized various constants and interfaces.
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff
changeset
|
41 |
87e9e4aabf1b
HTTP/2: externalized various constants and interfaces.
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff
changeset
|
42 |
87e9e4aabf1b
HTTP/2: externalized various constants and interfaces.
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff
changeset
|
43 static u_char * |
87e9e4aabf1b
HTTP/2: externalized various constants and interfaces.
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff
changeset
|
44 ngx_http_v2_write_int(u_char *pos, ngx_uint_t prefix, ngx_uint_t value) |
87e9e4aabf1b
HTTP/2: externalized various constants and interfaces.
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff
changeset
|
45 { |
87e9e4aabf1b
HTTP/2: externalized various constants and interfaces.
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff
changeset
|
46 if (value < prefix) { |
87e9e4aabf1b
HTTP/2: externalized various constants and interfaces.
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff
changeset
|
47 *pos++ |= value; |
87e9e4aabf1b
HTTP/2: externalized various constants and interfaces.
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff
changeset
|
48 return pos; |
87e9e4aabf1b
HTTP/2: externalized various constants and interfaces.
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff
changeset
|
49 } |
87e9e4aabf1b
HTTP/2: externalized various constants and interfaces.
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff
changeset
|
50 |
87e9e4aabf1b
HTTP/2: externalized various constants and interfaces.
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff
changeset
|
51 *pos++ |= prefix; |
87e9e4aabf1b
HTTP/2: externalized various constants and interfaces.
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff
changeset
|
52 value -= prefix; |
87e9e4aabf1b
HTTP/2: externalized various constants and interfaces.
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff
changeset
|
53 |
87e9e4aabf1b
HTTP/2: externalized various constants and interfaces.
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff
changeset
|
54 while (value >= 128) { |
87e9e4aabf1b
HTTP/2: externalized various constants and interfaces.
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff
changeset
|
55 *pos++ = value % 128 + 128; |
87e9e4aabf1b
HTTP/2: externalized various constants and interfaces.
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff
changeset
|
56 value /= 128; |
87e9e4aabf1b
HTTP/2: externalized various constants and interfaces.
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff
changeset
|
57 } |
87e9e4aabf1b
HTTP/2: externalized various constants and interfaces.
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff
changeset
|
58 |
87e9e4aabf1b
HTTP/2: externalized various constants and interfaces.
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff
changeset
|
59 *pos++ = (u_char) value; |
87e9e4aabf1b
HTTP/2: externalized various constants and interfaces.
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff
changeset
|
60 |
87e9e4aabf1b
HTTP/2: externalized various constants and interfaces.
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff
changeset
|
61 return pos; |
87e9e4aabf1b
HTTP/2: externalized various constants and interfaces.
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff
changeset
|
62 } |