From 482de55a96f9b68664a4d8b638f887138e26c5e8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lo=C3=AFc=20Hoguin?= Date: Tue, 23 Jan 2018 16:14:18 +0100 Subject: Fix a miscount of output flow control window for HTTP/2 The miscount occurred because of a faulty iolist split function. The bug should now be corrected, a PropEr test has been added and a regression test has also been added. --- src/cowboy_iolists.erl | 32 ++++++++++++++++++++++++++++++-- 1 file changed, 30 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/cowboy_iolists.erl b/src/cowboy_iolists.erl index 51e0f33..d04d0ae 100644 --- a/src/cowboy_iolists.erl +++ b/src/cowboy_iolists.erl @@ -16,6 +16,10 @@ -export([split/2]). +-ifdef(TEST). +-include_lib("proper/include/proper.hrl"). +-endif. + -spec split(non_neg_integer(), iodata()) -> {iodata(), iodata()}. split(N, Iolist) -> case split(N, Iolist, []) of @@ -44,7 +48,13 @@ split(N, [Char|Tail], Acc) when is_integer(Char) -> split(N, [List|Tail], Acc0) -> case split(N, List, Acc0) of {ok, Before, After} -> - {ok, Before, [After|Tail]}; + IolistSize = iolist_size(Before), + if + IolistSize < N -> + split(N - IolistSize, [After|Tail], Before); + true -> + {ok, Before, [After|Tail]} + end; {more, More, Acc} -> split(More, Tail, Acc) end. @@ -60,7 +70,8 @@ split_test_() -> {10, "Hello!", "Hello!", ""}, {10, <<"Hello!">>, "Hello!", ""}, {10, ["He", [<<"ll">>], $o, [["!"]]], "Hello!", ""}, - {10, ["Hel"|<<"lo!">>], "Hello!", ""} + {10, ["Hel"|<<"lo!">>], "Hello!", ""}, + {10, [[<<>>|<<>>], [], <<"Hello world!">>], "Hello worl", "d!"} ], [{iolist_to_binary(V), fun() -> {B, A} = split(N, V), @@ -68,4 +79,21 @@ split_test_() -> true = iolist_to_binary(RA) =:= iolist_to_binary(A) end} || {N, V, RB, RA} <- Tests]. +prop_split_test() -> + ?FORALL({N, Input}, + {non_neg_integer(), iolist()}, + begin + Size = iolist_size(Input), + {Before, After} = split(N, Input), + if + N >= Size -> + ((iolist_size(After) =:= 0) + andalso iolist_to_binary(Before) =:= iolist_to_binary(Input)); + true -> + <> = iolist_to_binary(Input), + (ExpectBefore =:= iolist_to_binary(Before)) + andalso (ExpectAfter =:= iolist_to_binary(After)) + end + end). + -endif. -- cgit v1.2.3