Description
Description
Using sapi_apache2 and performing a POST query with the "transfer-encoding: chunk" header, if the query is interrupted before all chunked/data were sent, PHP still accept the partial content received and execute normally, returning a 200 status.
Per RFC, it should return 400, which apache2 does if the php module is not activated. Also php should either not get executed at all, or warned in some way that the content is partial.
Looking at this closely, it seems the issue comes from the following code:
In function php_apache_sapi_read_post of sapi_apache2.c
lines 196-205 (on PHP8.2 branch):
while (ap_get_brigade(r->input_filters, brigade, AP_MODE_READBYTES, APR_BLOCK_READ, len) == APR_SUCCESS) {
apr_brigade_flatten(brigade, buf, &len);
apr_brigade_cleanup(brigade);
tlen += len;
if (tlen == count_bytes || !len) {
break;
}
buf += len;
len = count_bytes - tlen;
}
return tlen;
The return of ap_get_brigade
exit normally if it receives anything other than APR_SUCCESS and in particular does not check if it returns APR_INCOMPLETE in which case it should return a 400 response code.
I checked a quick and dirty fix:
apr_status_t ast;
ast = ap_get_brigade(r->input_filters, brigade, AP_MODE_READBYTES, APR_BLOCK_READ, len);
while (ast == APR_SUCCESS) {
apr_brigade_flatten(brigade, buf, &len);
apr_brigade_cleanup(brigade);
tlen += len;
if (tlen == count_bytes || !len) {
break;
}
buf += len;
len = count_bytes - tlen;
ast = ap_get_brigade(r->input_filters, brigade, AP_MODE_READBYTES, APR_BLOCK_READ, len);
}
if (ast == APR_INCOMPLETE) {
ctx->r->status = 400;
}
return tlen;
And it returns 400 correctly (but clearly I am not suggesting this as the correct fix, just demonstrating that the ap_get_bricade() return code should be taken care of).
PHP Version
8.0+
Operating System
Ubuntu 18.04+