diff --git a/src/detail/impl/filter.hpp b/src/detail/impl/filter.hpp index 55b01115..5eac87e2 100644 --- a/src/detail/impl/filter.hpp +++ b/src/detail/impl/filter.hpp @@ -32,27 +32,16 @@ process_impl( auto it_o = buffers::begin(out); auto it_i = buffers::begin(in); - if(it_o == buffers::end(out) || it_i == buffers::end(in)) + if( it_o == buffers::end(out) || + it_i == buffers::end(in) ) return rv; - auto ob = *it_o; - auto ib = *it_i; + auto ob = *it_o++; + auto ib = *it_i++; for(;;) { - if(ob.size() == 0) - { - if(++it_o == buffers::end(out)) - return rv; - ob = *it_o; - } - - if(ib.size() == 0) - { - if(++it_i == buffers::end(in)) - return rv; - ib = *it_i; - } - + // empty buffers may be passed, and this is + // intentional and valid. results rs = process_impl(ob, ib, more); rv.out_bytes += rs.out_bytes; @@ -60,11 +49,33 @@ process_impl( rv.ec = rs.ec; rv.finished = rs.finished; - if(rv.finished || rv.ec) + if( rv.finished || rv.ec ) return rv; ob = buffers::sans_prefix(ob, rs.out_bytes); ib = buffers::sans_prefix(ib, rs.in_bytes); + + if( ob.size() == 0 ) + { + if( it_o == buffers::end(out) ) + return rv; + ob = *it_o++; + } + + if( ib.size() == 0 ) + { + if( it_i == buffers::end(in) ) + { + // if `more == false` we return only + // when `out` buffers are full. + if( more ) + return rv; + } + else + { + ib = *it_i++; + } + } } } diff --git a/src/parser.cpp b/src/parser.cpp index eaba0e9f..c55d5315 100644 --- a/src/parser.cpp +++ b/src/parser.cpp @@ -152,7 +152,6 @@ class inflator_filter results.in_bytes += in.size() - params.avail_in; results.out_bytes += out.size() - params.avail_out; - // TODO: limit the cases where buf_err is valid if( ec.failed() && ec != zlib::error::buf_err ) { @@ -169,7 +168,7 @@ class inflator_filter in = buffers::suffix(in, params.avail_in); out = buffers::suffix(out, params.avail_out); - if( in.size() == 0 || out.size() == 0) + if( in.size() == 0 || out.size() == 0 ) return results; } } @@ -393,10 +392,6 @@ parse_chunked( BOOST_HTTP_PROTO_RETURN_EC( error::need_data); - if( output.capacity() == 0 ) - BOOST_HTTP_PROTO_RETURN_EC( - error::in_place_overflow); - auto chunk = buffers::prefix(input.data(), clamp(chunk_remain_, input.size())); @@ -420,6 +415,10 @@ parse_chunked( if( rs.finished && chunk_remain_ != 0 ) BOOST_HTTP_PROTO_RETURN_EC( error::bad_payload); + + if( output.capacity() == 0 ) + BOOST_HTTP_PROTO_RETURN_EC( + error::in_place_overflow); } else { @@ -1189,14 +1188,6 @@ parse( { if( how_ == how::in_place ) { - if( body_buf_->capacity() == 0 ) - { - // in_place buffer limit - ec = BOOST_HTTP_PROTO_ERR( - error::in_place_overflow); - return; - } - auto rs = [&]() -> detail::filter::results { if( h_.md.payload == payload::size ) @@ -1251,14 +1242,15 @@ parse( return; } + if( body_buf_->capacity() == 0 ) + { + ec = BOOST_HTTP_PROTO_ERR( + error::in_place_overflow); + return; + } + if( got_eof_ ) { - if( body_buf_->capacity() == 0 ) - { - ec = BOOST_HTTP_PROTO_ERR( - error::in_place_overflow); - return; - } ec = BOOST_HTTP_PROTO_ERR( error::incomplete); st_ = state::reset; // unrecoverable @@ -1706,7 +1698,7 @@ on_headers( auto const n0 = overread > svc_.cfg.min_buffer ? overread : svc_.cfg.min_buffer; - auto const n1 = cap - n0; + auto const n1 = svc_.cfg.min_buffer; cb0_ = { p , n0, overread }; cb1_ = { p + n0 , n1 }; diff --git a/src/serializer.cpp b/src/serializer.cpp index ba759af2..dc77efb3 100644 --- a/src/serializer.cpp +++ b/src/serializer.cpp @@ -61,13 +61,14 @@ class deflator_filter results.in_bytes += in.size() - params.avail_in; results.out_bytes += out.size() - params.avail_out; - if(ec.failed()) + if( ec.failed() && + ec != zlib::error::buf_err) { results.ec = ec; return results; } - if(ec == zlib::error::stream_end) + if( ec == zlib::error::stream_end ) { results.finished = true; return results; @@ -76,9 +77,13 @@ class deflator_filter in = buffers::suffix(in, params.avail_in); out = buffers::suffix(out, params.avail_out); - if(in.size() == 0) + if( out.size() == 0 ) + return results; + + if( in.size() == 0 ) { - if(results.out_bytes == 0) + if( results.out_bytes == 0 && + flush == zlib::flush::none ) { // TODO: Is flush::block the right choice? // We might need a filter::flush() interface