* Return the limit on bytes in request msg body
* @param r The current request
* @return the maximum number of bytes in the request msg body
- * @deffunc unsigned long ap_get_limit_req_body(const request_rec *r)
+ * @deffunc apr_off_t ap_get_limit_req_body(const request_rec *r)
*/
-AP_DECLARE(unsigned long) ap_get_limit_req_body(const request_rec *r);
+AP_DECLARE(apr_off_t) ap_get_limit_req_body(const request_rec *r);
/**
* Return the limit on bytes in XML request msg body
#ifdef RLIMIT_NPROC
struct rlimit *limit_nproc;
#endif
- unsigned long limit_req_body; /* limit on bytes in request msg body */
+ apr_off_t limit_req_body; /* limit on bytes in request msg body */
long limit_xml_body; /* limit on bytes in XML request msg body */
/* logging options */
typedef struct http_filter_ctx {
apr_off_t remaining;
+ apr_off_t limit;
+ apr_off_t limit_used;
enum {
BODY_NONE,
BODY_LENGTH,
const char *tenc, *lenp;
f->ctx = ctx = apr_palloc(f->r->pool, sizeof(*ctx));
ctx->state = BODY_NONE;
+ ctx->remaining = 0;
+ ctx->limit_used = 0;
+ ctx->limit = ap_get_limit_req_body(f->r);
tenc = apr_table_get(f->r->headers_in, "Transfer-Encoding");
lenp = apr_table_get(f->r->headers_in, "Content-Length");
ctx->state = BODY_LENGTH;
ctx->remaining = atol(lenp);
}
+
+ /* If we have a limit in effect and we know the C-L ahead of
+ * time, stop it here if it is invalid.
+ */
+ if (ctx->limit && ctx->limit < ctx->remaining) {
+ ap_log_rerror(APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, 0, f->r,
+ "Requested content-length of %" APR_OFF_T_FMT
+ " is larger than the configured limit"
+ " of %" APR_OFF_T_FMT, ctx->remaining, ctx->limit);
+ ap_die(HTTP_REQUEST_ENTITY_TOO_LARGE, f->r);
+ return APR_EGENERAL;
+ }
}
}
ctx->remaining -= *readbytes;
}
+ /* We have a limit in effect. */
+ if (ctx->limit) {
+ /* FIXME: Note that we might get slightly confused on chunked inputs
+ * as we'd need to compensate for the chunk lengths which may not
+ * really count. This seems to be up for interpretation. */
+ ctx->limit_used += *readbytes;
+ if (ctx->limit < ctx->limit_used) {
+ ap_log_rerror(APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, 0, f->r,
+ "Read content-length of %" APR_OFF_T_FMT
+ " is larger than the configured limit"
+ " of %" APR_OFF_T_FMT, ctx->limit_used, ctx->limit);
+ ap_die(HTTP_REQUEST_ENTITY_TOO_LARGE, f->r);
+ return APR_EGENERAL;
+ }
+ }
+
return APR_SUCCESS;
}
{
const char *tenc = apr_table_get(r->headers_in, "Transfer-Encoding");
const char *lenp = apr_table_get(r->headers_in, "Content-Length");
- apr_off_t max_body;
r->read_body = read_policy;
r->read_chunked = 0;
return HTTP_REQUEST_ENTITY_TOO_LARGE;
}
- max_body = ap_get_limit_req_body(r);
- if (max_body && (r->remaining > max_body)) {
- /* XXX shouldn't we enforce this for chunked encoding too? */
- ap_log_rerror(APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, 0, r,
- "Request content-length of %s is larger than "
- "the configured limit of %" APR_OFF_T_FMT, lenp,
- max_body);
- return HTTP_REQUEST_ENTITY_TOO_LARGE;
- }
-
#ifdef AP_DEBUG
{
/* Make sure ap_getline() didn't leave any droppings. */
return apr_psprintf(p, "%s://%s:%u%s", ap_http_method(r), host, port, uri);
}
-AP_DECLARE(unsigned long) ap_get_limit_req_body(const request_rec *r)
+AP_DECLARE(apr_off_t) ap_get_limit_req_body(const request_rec *r)
{
core_dir_config *d =
(core_dir_config *)ap_get_module_config(r->per_dir_config, &core_module);
{
core_dir_config *conf=conf_;
const char *err = ap_check_cmd_context(cmd, NOT_IN_LIMIT);
+ char *errp;
if (err != NULL) {
return err;
}
* Instead we have an idiotic define in httpd.h that prevents
* it from being used even when it is available. Sheesh.
*/
- conf->limit_req_body = (unsigned long)strtol(arg, (char **)NULL, 10);
+ conf->limit_req_body = (apr_off_t)strtol(arg, &errp, 10);
+ if (*errp != '\0') {
+ return "LimitRequestBody requires a non-negative integer.";
+ }
return NULL;
}