Skip to content

Commit 36f1afe

Browse files
committed
File and output body sizes limiting postponed to next release
1 parent 354a1d4 commit 36f1afe

File tree

2 files changed

+43
-68
lines changed

2 files changed

+43
-68
lines changed

Changelog

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,8 +8,6 @@ Version 2.0.4
88
and CPU are not used. Calculation could be requested via specifying variables
99
$upload_file_md5, $upload_file_md5_uc, $upload_file_sha1 and $upload_file_sha1_uc.
1010
* Fixed bug: missing CRLF at the end of resulting body.
11-
* Added feature: limiting file size and resulting body size via upload_max_file_size
12-
and upload_max_output_body_len.
1311
* Change: optimized out some unnecessary memory allocations and zeroeing.
1412

1513
Version 2.0.3

ngx_http_upload_module.c

Lines changed: 43 additions & 66 deletions
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,6 @@
3838
#define NGX_UPLOAD_NOMEM -2
3939
#define NGX_UPLOAD_IOERROR -3
4040
#define NGX_UPLOAD_SCRIPTERROR -4
41-
#define NGX_UPLOAD_TOOLARGE -5
4241

4342
/*
4443
* State of multipart/form-data parser
@@ -82,9 +81,7 @@ typedef struct {
8281
ngx_path_t *store_path;
8382
ngx_uint_t store_access;
8483
size_t buffer_size;
85-
size_t max_file_size;
8684
size_t max_header_len;
87-
size_t max_output_body_len;
8885
ngx_array_t *field_templates;
8986
ngx_array_t *aggregate_field_templates;
9087
ngx_array_t *field_filters;
@@ -160,6 +157,8 @@ static ngx_int_t ngx_http_upload_md5_variable(ngx_http_request_t *r,
160157
ngx_http_variable_value_t *v, uintptr_t data);
161158
static ngx_int_t ngx_http_upload_sha1_variable(ngx_http_request_t *r,
162159
ngx_http_variable_value_t *v, uintptr_t data);
160+
static ngx_int_t ngx_http_upload_file_size_variable(ngx_http_request_t *r,
161+
ngx_http_variable_value_t *v, uintptr_t data);
163162
static char *ngx_http_upload_pass(ngx_conf_t *cf, ngx_command_t *cmd, void *conf);
164163

165164
static ngx_int_t ngx_http_upload_start_handler(ngx_http_upload_ctx_t *u);
@@ -258,8 +257,9 @@ ngx_int_t upload_parse_content_type(ngx_http_upload_ctx_t *upload_ctx, ngx_str_t
258257
* NGX_UPLOAD_NOMEM insufficient memory
259258
* NGX_UPLOAD_IOERROR input-output error
260259
* NGX_UPLOAD_SCRIPTERROR nginx script engine failed
260+
* NGX_UPLOAD_TOOLARGE field body is too large
261261
*/
262-
int upload_process_buf(ngx_http_upload_ctx_t *upload_ctx, u_char *start, u_char *end);
262+
ngx_int_t upload_process_buf(ngx_http_upload_ctx_t *upload_ctx, u_char *start, u_char *end);
263263

264264
static ngx_command_t ngx_http_upload_commands[] = { /* {{{ */
265265

@@ -304,16 +304,6 @@ static ngx_command_t ngx_http_upload_commands[] = { /* {{{ */
304304
offsetof(ngx_http_upload_loc_conf_t, buffer_size),
305305
NULL },
306306

307-
/*
308-
* Specifies the maximal size of a file which could be uploaded
309-
*/
310-
{ ngx_string("upload_max_file_size"),
311-
NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
312-
ngx_conf_set_size_slot,
313-
NGX_HTTP_LOC_CONF_OFFSET,
314-
offsetof(ngx_http_upload_loc_conf_t, max_file_size),
315-
NULL },
316-
317307
/*
318308
* Specifies the maximal length of the part header
319309
*/
@@ -324,16 +314,6 @@ static ngx_command_t ngx_http_upload_commands[] = { /* {{{ */
324314
offsetof(ngx_http_upload_loc_conf_t, max_header_len),
325315
NULL },
326316

327-
/*
328-
* Specifies the maximal length of resulting body
329-
*/
330-
{ ngx_string("upload_max_output_body_len"),
331-
NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
332-
ngx_conf_set_size_slot,
333-
NGX_HTTP_LOC_CONF_OFFSET,
334-
offsetof(ngx_http_upload_loc_conf_t, max_output_body_len),
335-
NULL },
336-
337317
/*
338318
* Specifies the field to set in altered response body
339319
*/
@@ -439,6 +419,10 @@ static ngx_http_variable_t ngx_http_upload_aggregate_variables[] = { /* {{{ */
439419
(uintptr_t) "0123456789ABCDEF",
440420
NGX_HTTP_VAR_CHANGEABLE|NGX_HTTP_VAR_NOCACHEABLE|NGX_HTTP_VAR_NOHASH, 0 },
441421

422+
{ ngx_string("upload_file_size"), NULL, ngx_http_upload_file_size_variable,
423+
(uintptr_t) offsetof(ngx_http_upload_ctx_t, output_file.offset),
424+
NGX_HTTP_VAR_CHANGEABLE|NGX_HTTP_VAR_NOCACHEABLE|NGX_HTTP_VAR_NOHASH, 0 },
425+
442426
{ ngx_null_string, NULL, NULL, 0, 0, 0 }
443427
}; /* }}} */
444428

@@ -539,14 +523,6 @@ static ngx_int_t ngx_http_upload_body_handler(ngx_http_request_t *r) { /* {{{ */
539523
ngx_buf_t *b;
540524
ngx_chain_t *cl;
541525

542-
if(ulcf->max_output_body_len && ctx->output_body_len + ctx->boundary.len
543-
+ 4 > ulcf->max_output_body_len)
544-
{
545-
ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
546-
"client has sent too large request body");
547-
return NGX_HTTP_REQUEST_ENTITY_TOO_LARGE;
548-
}
549-
550526
ctx->output_body_len += ctx->boundary.len + 4;
551527

552528
/*
@@ -802,7 +778,7 @@ static void ngx_http_upload_finish_handler(ngx_http_upload_ctx_t *u) { /* {{{ */
802778
if (ngx_http_script_run(r, &aggregate_field_name, af[i].field_lengths->elts, 0,
803779
af[i].field_values->elts) == NULL)
804780
{
805-
return;
781+
goto rollback;
806782
}
807783
}
808784

@@ -812,20 +788,24 @@ static void ngx_http_upload_finish_handler(ngx_http_upload_ctx_t *u) { /* {{{ */
812788
if (ngx_http_script_run(r, &aggregate_field_value, af[i].value_lengths->elts, 0,
813789
af[i].value_values->elts) == NULL)
814790
{
815-
return;
791+
goto rollback;
816792
}
817793
}
818794

819795
rc = ngx_http_upload_append_field(u, &aggregate_field_name, &aggregate_field_value);
820796

821797
if(rc != NGX_OK)
822-
return;
798+
goto rollback;
823799
}
824800
}
825801
}
826802

827803
// Checkpoint current output chain state
828804
u->checkpoint = u->last;
805+
return;
806+
807+
rollback:
808+
ngx_http_upload_abort_handler(u);
829809
} /* }}} */
830810

831811
static void ngx_http_upload_abort_handler(ngx_http_upload_ctx_t *u) { /* {{{ */
@@ -858,17 +838,10 @@ static void ngx_http_upload_abort_handler(ngx_http_upload_ctx_t *u) { /* {{{ */
858838

859839
static ngx_int_t ngx_http_upload_flush_output_buffer(ngx_http_upload_ctx_t *u, u_char *buf, size_t len) { /* {{{ */
860840
ngx_http_request_t *r = u->request;
861-
ngx_http_upload_loc_conf_t *ulcf = ngx_http_get_module_loc_conf(r, ngx_http_upload_module);
862841
ngx_buf_t *b;
863842
ngx_chain_t *cl;
864843

865844
if(u->is_file) {
866-
if(ulcf->max_file_size && u->output_file.offset + len > ulcf->max_file_size) {
867-
ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
868-
"client has sent too large file \"%V\"", &u->output_file.name);
869-
return NGX_UPLOAD_TOOLARGE;
870-
}
871-
872845
if(u->md5_ctx)
873846
MD5Update(&u->md5_ctx->md5, buf, len);
874847

@@ -882,14 +855,6 @@ static ngx_int_t ngx_http_upload_flush_output_buffer(ngx_http_upload_ctx_t *u, u
882855
}else
883856
return NGX_OK;
884857
}else{
885-
if(ulcf->max_output_body_len && u->output_body_len + len > ulcf->max_output_body_len) {
886-
ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
887-
"client has sent too large field \"%V\"", &u->field_name);
888-
return NGX_UPLOAD_TOOLARGE;
889-
}
890-
891-
u->output_body_len += len;
892-
893858
b = ngx_create_temp_buf(u->request->pool, len);
894859

895860
if (b == NULL) {
@@ -997,9 +962,7 @@ ngx_http_upload_create_loc_conf(ngx_conf_t *cf)
997962
conf->store_access = NGX_CONF_UNSET_UINT;
998963

999964
conf->buffer_size = NGX_CONF_UNSET_SIZE;
1000-
conf->max_file_size = NGX_CONF_UNSET_SIZE;
1001965
conf->max_header_len = NGX_CONF_UNSET_SIZE;
1002-
conf->max_output_body_len = NGX_CONF_UNSET_SIZE;
1003966

1004967
/*
1005968
* conf->field_templates,
@@ -1031,18 +994,10 @@ ngx_http_upload_merge_loc_conf(ngx_conf_t *cf, void *parent, void *child)
1031994
prev->buffer_size,
1032995
(size_t) ngx_pagesize);
1033996

1034-
ngx_conf_merge_size_value(conf->max_file_size,
1035-
prev->max_file_size,
1036-
(size_t) 0);
1037-
1038997
ngx_conf_merge_size_value(conf->max_header_len,
1039998
prev->max_header_len,
1040999
(size_t) 512);
10411000

1042-
ngx_conf_merge_size_value(conf->max_output_body_len,
1043-
prev->max_output_body_len,
1044-
(size_t) 256 * 1024);
1045-
10461001
if(conf->field_templates == NULL) {
10471002
conf->field_templates = prev->field_templates;
10481003
}
@@ -1189,6 +1144,32 @@ ngx_http_upload_sha1_variable(ngx_http_request_t *r,
11891144
return NGX_OK;
11901145
} /* }}} */
11911146

1147+
static ngx_int_t /* {{{ ngx_http_upload_file_size_variable */
1148+
ngx_http_upload_file_size_variable(ngx_http_request_t *r,
1149+
ngx_http_variable_value_t *v, uintptr_t data)
1150+
{
1151+
ngx_http_upload_ctx_t *u;
1152+
u_char *p;
1153+
off_t *value;
1154+
1155+
u = ngx_http_get_module_ctx(r, ngx_http_upload_module);
1156+
1157+
value = (off_t *) ((char *) u + data);
1158+
1159+
p = ngx_palloc(r->pool, NGX_OFF_T_LEN);
1160+
if (p == NULL) {
1161+
return NGX_ERROR;
1162+
}
1163+
1164+
v->len = ngx_sprintf(p, "%O", *value) - p;
1165+
v->valid = 1;
1166+
v->no_cacheable = 0;
1167+
v->not_found = 0;
1168+
v->data = p;
1169+
1170+
return NGX_OK;
1171+
} /* }}} */
1172+
11921173
static char * /* {{{ ngx_http_upload_set_form_field */
11931174
ngx_http_upload_set_form_field(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
11941175
{
@@ -1281,7 +1262,7 @@ ngx_http_upload_set_form_field(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
12811262

12821263
/*
12831264
* ngx_http_script_compile does check for final bracket earlier,
1284-
* so we don't need to care about it, which simplifies things
1265+
* therefore we don't need to care about it, which simplifies things
12851266
*/
12861267
if(match != NULL
12871268
&& ((match - value[i].data >= 1 && match[-1] == '$')
@@ -1595,8 +1576,6 @@ ngx_http_do_read_upload_client_request_body(ngx_http_request_t *r)
15951576
return NGX_HTTP_BAD_REQUEST;
15961577
case NGX_UPLOAD_IOERROR:
15971578
return NGX_HTTP_SERVICE_UNAVAILABLE;
1598-
case NGX_UPLOAD_TOOLARGE:
1599-
return NGX_HTTP_REQUEST_ENTITY_TOO_LARGE;
16001579
case NGX_UPLOAD_NOMEM: case NGX_UPLOAD_SCRIPTERROR:
16011580
default:
16021581
return NGX_HTTP_INTERNAL_SERVER_ERROR;
@@ -1676,8 +1655,6 @@ ngx_http_do_read_upload_client_request_body(ngx_http_request_t *r)
16761655
return NGX_HTTP_BAD_REQUEST;
16771656
case NGX_UPLOAD_IOERROR:
16781657
return NGX_HTTP_SERVICE_UNAVAILABLE;
1679-
case NGX_UPLOAD_TOOLARGE:
1680-
return NGX_HTTP_REQUEST_ENTITY_TOO_LARGE;
16811658
case NGX_UPLOAD_NOMEM: case NGX_UPLOAD_SCRIPTERROR:
16821659
default:
16831660
return NGX_HTTP_INTERNAL_SERVER_ERROR;
@@ -1999,7 +1976,7 @@ void upload_putc(ngx_http_upload_ctx_t *upload_ctx, u_char c) { /* {{{ */
19991976
}
20001977
} /* }}} */
20011978

2002-
int upload_process_buf(ngx_http_upload_ctx_t *upload_ctx, u_char *start, u_char *end) { /* {{{ */
1979+
ngx_int_t upload_process_buf(ngx_http_upload_ctx_t *upload_ctx, u_char *start, u_char *end) { /* {{{ */
20031980

20041981
u_char *p;
20051982
ngx_int_t rc;

0 commit comments

Comments
 (0)