Author: rhuijben Date: Sat Oct 31 13:52:51 2015 New Revision: 1711632 URL: http://svn.apache.org/viewvc?rev=1711632&view=rev Log: Tweak the http2 frame buckets to always return frame size errors when there is less data in the frame than expected. APR_EOF notifies success, which is not the right way to report missing data.
* buckets/http2_frame_buckets.c (serf_http2_unframe_read, serf_http2_unframe_read_iovec, serf_http2_unpad_read_padsize): Properly handle APR_EOF. (serf_http2_unpad_read): When reading more than payload, try to read the padding as well, instead of explicitly keeping that for the next read. (serf_http2_unpad_read_iovec): Properly handle APR_EOF. Modified: serf/trunk/buckets/http2_frame_buckets.c Modified: serf/trunk/buckets/http2_frame_buckets.c URL: http://svn.apache.org/viewvc/serf/trunk/buckets/http2_frame_buckets.c?rev=1711632&r1=1711631&r2=1711632&view=diff ============================================================================== --- serf/trunk/buckets/http2_frame_buckets.c (original) +++ serf/trunk/buckets/http2_frame_buckets.c Sat Oct 31 13:52:51 2015 @@ -227,6 +227,8 @@ serf_http2_unframe_read(serf_bucket_t *b if (!SERF_BUCKET_READ_ERROR(status)) status = APR_EOF; } + else if (APR_STATUS_IS_EOF(status)) + return SERF_ERROR_HTTP2_FRAME_SIZE_ERROR; } return status; @@ -280,6 +282,8 @@ serf_http2_unframe_read_iovec(serf_bucke if (!SERF_BUCKET_READ_ERROR(status)) status = APR_EOF; } + else if (APR_STATUS_IS_EOF(status)) + return SERF_ERROR_HTTP2_FRAME_SIZE_ERROR; } return status; @@ -418,6 +422,8 @@ serf_http2_unpad_read_padsize(serf_bucke ctx->payload_remaining = (apr_size_t)remaining - ctx->pad_length; } + else if (APR_STATUS_IS_EOF(status)) + status = SERF_ERROR_HTTP2_FRAME_SIZE_ERROR; else if (!status) status = APR_EAGAIN; @@ -467,19 +473,37 @@ serf_http2_unpad_read(serf_bucket_t *buc *len = 0; return status; } - else if (ctx->payload_remaining == 0) + else if (ctx->payload_remaining == 0 + && ctx->pad_remaining == 0) { *len = 0; - return serf_http2_unpad_read_padding(bucket); + return APR_EOF; } - if (requested > ctx->payload_remaining) - requested = ctx->payload_remaining; + + if (requested >= ctx->payload_remaining) + requested = ctx->payload_remaining + ctx->pad_remaining; status = serf_bucket_read(ctx->stream, requested, data, len); if (! SERF_BUCKET_READ_ERROR(status)) { - ctx->payload_remaining -= *len; + if (*len <= ctx->payload_remaining) + ctx->payload_remaining -= *len; + else + { + ctx->pad_remaining -= (*len - ctx->payload_remaining); + *len = ctx->payload_remaining; + ctx->payload_remaining = 0; + + if (ctx->pad_remaining == 0) + status = APR_EOF; + } + + if (APR_STATUS_IS_EOF(status) + && (ctx->pad_remaining != 0 || ctx->payload_remaining != 0)) + { + status = SERF_ERROR_HTTP2_FRAME_SIZE_ERROR; + } } return status; @@ -508,6 +532,7 @@ serf_http2_unpad_read_iovec(serf_bucket_ return serf_http2_unpad_read_padding(bucket); } + /* ### Can we read data and padding in one go? */ if (requested > ctx->payload_remaining) requested = ctx->payload_remaining; @@ -522,6 +547,12 @@ serf_http2_unpad_read_iovec(serf_bucket_ len += vecs[i].iov_len; ctx->payload_remaining -= len; + + if (APR_STATUS_IS_EOF(status) + && (ctx->pad_remaining != 0 || ctx->payload_remaining != 0)) + { + status = SERF_ERROR_HTTP2_FRAME_SIZE_ERROR; + } } return status;