Mercurial > hg > nginx
annotate src/http/modules/ngx_http_addition_filter_module.c @ 6986:0cdee26605f3
Cleaned up r->headers_out.headers allocation error handling.
If initialization of a header failed for some reason after ngx_list_push(),
leaving the header as is can result in uninitialized memory access by
the header filter or the log module. The fix is to clear partially
initialized headers in case of errors.
For the Cache-Control header, the fix is to postpone pushing
r->headers_out.cache_control until its value is completed.
author | Sergey Kandaurov <pluknet@nginx.com> |
---|---|
date | Thu, 20 Apr 2017 18:26:37 +0300 |
parents | ebba2f980489 |
children | f583559aadc7 |
rev | line source |
---|---|
629 | 1 |
2 /* | |
3 * Copyright (C) Igor Sysoev | |
4412 | 4 * Copyright (C) Nginx, Inc. |
629 | 5 */ |
6 | |
7 | |
8 #include <ngx_config.h> | |
9 #include <ngx_core.h> | |
10 #include <ngx_http.h> | |
11 | |
12 | |
13 typedef struct { | |
2167 | 14 ngx_str_t before_body; |
15 ngx_str_t after_body; | |
16 | |
17 ngx_hash_t types; | |
18 ngx_array_t *types_keys; | |
629 | 19 } ngx_http_addition_conf_t; |
20 | |
21 | |
22 typedef struct { | |
2167 | 23 ngx_uint_t before_body_sent; |
629 | 24 } ngx_http_addition_ctx_t; |
25 | |
26 | |
27 static void *ngx_http_addition_create_conf(ngx_conf_t *cf); | |
28 static char *ngx_http_addition_merge_conf(ngx_conf_t *cf, void *parent, | |
29 void *child); | |
681 | 30 static ngx_int_t ngx_http_addition_filter_init(ngx_conf_t *cf); |
629 | 31 |
32 | |
33 static ngx_command_t ngx_http_addition_commands[] = { | |
34 | |
35 { ngx_string("add_before_body"), | |
36 NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1, | |
37 ngx_conf_set_str_slot, | |
38 NGX_HTTP_LOC_CONF_OFFSET, | |
39 offsetof(ngx_http_addition_conf_t, before_body), | |
40 NULL }, | |
41 | |
42 { ngx_string("add_after_body"), | |
43 NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1, | |
44 ngx_conf_set_str_slot, | |
45 NGX_HTTP_LOC_CONF_OFFSET, | |
46 offsetof(ngx_http_addition_conf_t, after_body), | |
47 NULL }, | |
48 | |
3146
29ba1de1ab0b
fix typo in addition_types directive name
Igor Sysoev <igor@sysoev.ru>
parents:
2912
diff
changeset
|
49 { ngx_string("addition_types"), |
2167 | 50 NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_1MORE, |
51 ngx_http_types_slot, | |
52 NGX_HTTP_LOC_CONF_OFFSET, | |
53 offsetof(ngx_http_addition_conf_t, types_keys), | |
54 &ngx_http_html_default_types[0] }, | |
55 | |
629 | 56 ngx_null_command |
57 }; | |
58 | |
59 | |
60 static ngx_http_module_t ngx_http_addition_filter_module_ctx = { | |
61 NULL, /* preconfiguration */ | |
681 | 62 ngx_http_addition_filter_init, /* postconfiguration */ |
629 | 63 |
64 NULL, /* create main configuration */ | |
65 NULL, /* init main configuration */ | |
66 | |
67 NULL, /* create server configuration */ | |
68 NULL, /* merge server configuration */ | |
69 | |
70 ngx_http_addition_create_conf, /* create location configuration */ | |
71 ngx_http_addition_merge_conf /* merge location configuration */ | |
72 }; | |
73 | |
74 | |
75 ngx_module_t ngx_http_addition_filter_module = { | |
76 NGX_MODULE_V1, | |
77 &ngx_http_addition_filter_module_ctx, /* module context */ | |
78 ngx_http_addition_commands, /* module directives */ | |
79 NGX_HTTP_MODULE, /* module type */ | |
80 NULL, /* init master */ | |
681 | 81 NULL, /* init module */ |
629 | 82 NULL, /* init process */ |
83 NULL, /* init thread */ | |
84 NULL, /* exit thread */ | |
85 NULL, /* exit process */ | |
86 NULL, /* exit master */ | |
87 NGX_MODULE_V1_PADDING | |
88 }; | |
89 | |
90 | |
91 static ngx_http_output_header_filter_pt ngx_http_next_header_filter; | |
92 static ngx_http_output_body_filter_pt ngx_http_next_body_filter; | |
93 | |
94 | |
95 static ngx_int_t | |
96 ngx_http_addition_header_filter(ngx_http_request_t *r) | |
97 { | |
98 ngx_http_addition_ctx_t *ctx; | |
99 ngx_http_addition_conf_t *conf; | |
100 | |
2167 | 101 if (r->headers_out.status != NGX_HTTP_OK || r != r->main) { |
629 | 102 return ngx_http_next_header_filter(r); |
103 } | |
104 | |
631 | 105 conf = ngx_http_get_module_loc_conf(r, ngx_http_addition_filter_module); |
106 | |
107 if (conf->before_body.len == 0 && conf->after_body.len == 0) { | |
108 return ngx_http_next_header_filter(r); | |
109 } | |
110 | |
2167 | 111 if (ngx_http_test_content_type(r, &conf->types) == NULL) { |
629 | 112 return ngx_http_next_header_filter(r); |
113 } | |
114 | |
115 ctx = ngx_pcalloc(r->pool, sizeof(ngx_http_addition_ctx_t)); | |
116 if (ctx == NULL) { | |
117 return NGX_ERROR; | |
118 } | |
119 | |
120 ngx_http_set_ctx(r, ctx, ngx_http_addition_filter_module); | |
121 | |
122 ngx_http_clear_content_length(r); | |
123 ngx_http_clear_accept_ranges(r); | |
5733
e491b26fa5a1
Entity tags: downgrade strong etags to weak ones as needed.
Maxim Dounin <mdounin@mdounin.ru>
parents:
4746
diff
changeset
|
124 ngx_http_weak_etag(r); |
629 | 125 |
126 return ngx_http_next_header_filter(r); | |
127 } | |
128 | |
129 | |
130 static ngx_int_t | |
131 ngx_http_addition_body_filter(ngx_http_request_t *r, ngx_chain_t *in) | |
132 { | |
133 ngx_int_t rc; | |
134 ngx_uint_t last; | |
135 ngx_chain_t *cl; | |
758
86bb73dc8d40
fix <!--#include virtual=... wait="yes" -->
Igor Sysoev <igor@sysoev.ru>
parents:
681
diff
changeset
|
136 ngx_http_request_t *sr; |
629 | 137 ngx_http_addition_ctx_t *ctx; |
138 ngx_http_addition_conf_t *conf; | |
139 | |
140 if (in == NULL || r->header_only) { | |
141 return ngx_http_next_body_filter(r, in); | |
142 } | |
143 | |
144 ctx = ngx_http_get_module_ctx(r, ngx_http_addition_filter_module); | |
145 | |
146 if (ctx == NULL) { | |
147 return ngx_http_next_body_filter(r, in); | |
148 } | |
149 | |
150 conf = ngx_http_get_module_loc_conf(r, ngx_http_addition_filter_module); | |
151 | |
152 if (!ctx->before_body_sent) { | |
153 ctx->before_body_sent = 1; | |
154 | |
155 if (conf->before_body.len) { | |
2377
87b8c44906b5
*) refactor subrequest handling, now they run as separate posted requests
Igor Sysoev <igor@sysoev.ru>
parents:
2167
diff
changeset
|
156 if (ngx_http_subrequest(r, &conf->before_body, NULL, &sr, NULL, 0) |
87b8c44906b5
*) refactor subrequest handling, now they run as separate posted requests
Igor Sysoev <igor@sysoev.ru>
parents:
2167
diff
changeset
|
157 != NGX_OK) |
87b8c44906b5
*) refactor subrequest handling, now they run as separate posted requests
Igor Sysoev <igor@sysoev.ru>
parents:
2167
diff
changeset
|
158 { |
87b8c44906b5
*) refactor subrequest handling, now they run as separate posted requests
Igor Sysoev <igor@sysoev.ru>
parents:
2167
diff
changeset
|
159 return NGX_ERROR; |
629 | 160 } |
161 } | |
162 } | |
163 | |
846
c2cae54f2045
fix add_before_body without add_after_body
Igor Sysoev <igor@sysoev.ru>
parents:
777
diff
changeset
|
164 if (conf->after_body.len == 0) { |
c2cae54f2045
fix add_before_body without add_after_body
Igor Sysoev <igor@sysoev.ru>
parents:
777
diff
changeset
|
165 ngx_http_set_ctx(r, NULL, ngx_http_addition_filter_module); |
c2cae54f2045
fix add_before_body without add_after_body
Igor Sysoev <igor@sysoev.ru>
parents:
777
diff
changeset
|
166 return ngx_http_next_body_filter(r, in); |
c2cae54f2045
fix add_before_body without add_after_body
Igor Sysoev <igor@sysoev.ru>
parents:
777
diff
changeset
|
167 } |
c2cae54f2045
fix add_before_body without add_after_body
Igor Sysoev <igor@sysoev.ru>
parents:
777
diff
changeset
|
168 |
629 | 169 last = 0; |
170 | |
171 for (cl = in; cl; cl = cl->next) { | |
172 if (cl->buf->last_buf) { | |
173 cl->buf->last_buf = 0; | |
6723
ebba2f980489
Addition filter: set last_in_chain flag when clearing last_buf.
Roman Arutyunyan <arut@nginx.com>
parents:
5733
diff
changeset
|
174 cl->buf->last_in_chain = 1; |
631 | 175 cl->buf->sync = 1; |
629 | 176 last = 1; |
177 } | |
178 } | |
179 | |
180 rc = ngx_http_next_body_filter(r, in); | |
181 | |
631 | 182 if (rc == NGX_ERROR || !last || conf->after_body.len == 0) { |
629 | 183 return rc; |
184 } | |
185 | |
2377
87b8c44906b5
*) refactor subrequest handling, now they run as separate posted requests
Igor Sysoev <igor@sysoev.ru>
parents:
2167
diff
changeset
|
186 if (ngx_http_subrequest(r, &conf->after_body, NULL, &sr, NULL, 0) |
87b8c44906b5
*) refactor subrequest handling, now they run as separate posted requests
Igor Sysoev <igor@sysoev.ru>
parents:
2167
diff
changeset
|
187 != NGX_OK) |
87b8c44906b5
*) refactor subrequest handling, now they run as separate posted requests
Igor Sysoev <igor@sysoev.ru>
parents:
2167
diff
changeset
|
188 { |
87b8c44906b5
*) refactor subrequest handling, now they run as separate posted requests
Igor Sysoev <igor@sysoev.ru>
parents:
2167
diff
changeset
|
189 return NGX_ERROR; |
629 | 190 } |
191 | |
631 | 192 ngx_http_set_ctx(r, NULL, ngx_http_addition_filter_module); |
629 | 193 |
194 return ngx_http_send_special(r, NGX_HTTP_LAST); | |
195 } | |
196 | |
197 | |
198 static ngx_int_t | |
681 | 199 ngx_http_addition_filter_init(ngx_conf_t *cf) |
629 | 200 { |
201 ngx_http_next_header_filter = ngx_http_top_header_filter; | |
202 ngx_http_top_header_filter = ngx_http_addition_header_filter; | |
203 | |
204 ngx_http_next_body_filter = ngx_http_top_body_filter; | |
205 ngx_http_top_body_filter = ngx_http_addition_body_filter; | |
206 | |
207 return NGX_OK; | |
208 } | |
209 | |
210 | |
211 static void * | |
212 ngx_http_addition_create_conf(ngx_conf_t *cf) | |
213 { | |
214 ngx_http_addition_conf_t *conf; | |
215 | |
216 conf = ngx_pcalloc(cf->pool, sizeof(ngx_http_addition_conf_t)); | |
217 if (conf == NULL) { | |
2912
c7d57b539248
return NULL instead of NGX_CONF_ERROR on a create conf failure
Igor Sysoev <igor@sysoev.ru>
parents:
2377
diff
changeset
|
218 return NULL; |
629 | 219 } |
220 | |
221 /* | |
222 * set by ngx_pcalloc(): | |
223 * | |
2167 | 224 * conf->before_body = { 0, NULL }; |
225 * conf->after_body = { 0, NULL }; | |
226 * conf->types = { NULL }; | |
227 * conf->types_keys = NULL; | |
629 | 228 */ |
229 | |
230 return conf; | |
231 } | |
232 | |
233 | |
234 static char * | |
235 ngx_http_addition_merge_conf(ngx_conf_t *cf, void *parent, void *child) | |
236 { | |
237 ngx_http_addition_conf_t *prev = parent; | |
238 ngx_http_addition_conf_t *conf = child; | |
239 | |
240 ngx_conf_merge_str_value(conf->before_body, prev->before_body, ""); | |
241 ngx_conf_merge_str_value(conf->after_body, prev->after_body, ""); | |
242 | |
3372
6b8e5c882e47
support "*" in gzip_types, ssi_types, etc
Igor Sysoev <igor@sysoev.ru>
parents:
3146
diff
changeset
|
243 if (ngx_http_merge_types(cf, &conf->types_keys, &conf->types, |
6b8e5c882e47
support "*" in gzip_types, ssi_types, etc
Igor Sysoev <igor@sysoev.ru>
parents:
3146
diff
changeset
|
244 &prev->types_keys, &prev->types, |
2167 | 245 ngx_http_html_default_types) |
246 != NGX_OK) | |
247 { | |
248 return NGX_CONF_ERROR; | |
249 } | |
250 | |
629 | 251 return NGX_CONF_OK; |
252 } |