Packages
bandit
0.6.9
1.12.0
1.11.1
1.11.0
1.10.4
1.10.3
1.10.2
1.10.1
1.10.0
retired
1.9.0
1.8.0
1.7.0
1.6.11
1.6.10
1.6.9
1.6.8
1.6.7
1.6.6
1.6.5
1.6.4
1.6.3
1.6.2
1.6.1
1.6.0
1.5.7
1.5.6
1.5.5
1.5.4
1.5.3
1.5.2
1.5.1
1.5.0
1.4.2
1.4.1
1.4.0
1.3.0
1.2.3
1.2.2
1.2.1
1.2.0
1.1.3
1.1.2
1.1.1
1.1.0
1.0.0
1.0.0-pre.18
1.0.0-pre.17
1.0.0-pre.16
1.0.0-pre.15
1.0.0-pre.14
1.0.0-pre.13
1.0.0-pre.12
1.0.0-pre.11
1.0.0-pre.10
1.0.0-pre.9
1.0.0-pre.8
1.0.0-pre.7
1.0.0-pre.6
1.0.0-pre.5
1.0.0-pre.4
1.0.0-pre.3
1.0.0-pre.2
1.0.0-pre.1
0.7.7
0.7.6
0.7.5
0.7.4
0.7.3
0.7.2
0.7.1
0.7.0
0.6.11
0.6.10
0.6.9
0.6.8
0.6.7
0.6.6
0.6.5
0.6.4
0.6.3
0.6.2
0.6.1
0.6.0
0.5.11
0.5.10
0.5.9
0.5.8
0.5.7
0.5.6
0.5.5
0.5.4
0.5.3
0.5.2
0.5.1
0.5.0
0.4.10
0.4.9
0.4.8
0.4.7
0.4.6
0.4.5
0.4.4
0.4.3
0.4.2
0.4.1
0.4.0
0.3.9
0.3.8
0.3.7
0.3.6
0.3.5
0.3.4
0.3.3
0.3.2
0.2.3
0.2.2
0.2.1
0.2.0
0.1.1
0.1.0
A pure-Elixir HTTP server built for Plug & WebSock apps
Security advisory:
This version has known vulnerabilities.
View advisories
Current section
Files
Jump to
Current section
Files
test/bandit/websocket/frame_deserialization_test.exs
defmodule WebSocketFrameDeserializationTest do
use ExUnit.Case, async: true
import Bandit.WebSocket.Frame, only: [mask: 2]
alias Bandit.WebSocket.Frame
describe "reserved flag parsing" do
test "errors on reserved flag 1 being set" do
frame = <<0x1::1, 0x1::3, 0x1::4, 1::1, 0::7, 0x01020304::32>>
assert Frame.deserialize(frame) == {{:error, "Received unsupported RSV flags 1"}, <<>>}
end
test "errors on reserved flag 2 being set" do
frame = <<0x1::1, 0x2::3, 0x1::4, 1::1, 0::7, 0x01020304::32>>
assert Frame.deserialize(frame) == {{:error, "Received unsupported RSV flags 2"}, <<>>}
end
end
describe "frame size" do
test "parses 2 byte frames" do
payload = String.duplicate("a", 2)
masked_payload = Frame.mask(payload, 1234)
frame = <<0x1::1, 0x0::3, 0x1::4, 1::1, 2::7, 1234::32, masked_payload::binary>>
assert Frame.deserialize(frame) ==
{{:ok, %Frame.Text{fin: true, compressed: false, data: payload}}, <<>>}
end
test "parses 10 byte frames" do
payload = String.duplicate("a", 10)
masked_payload = Frame.mask(payload, 1234)
frame = <<0x1::1, 0x0::3, 0x1::4, 1::1, 10::7, 1234::32, masked_payload::binary>>
assert Frame.deserialize(frame) ==
{{:ok, %Frame.Text{fin: true, compressed: false, data: payload}}, <<>>}
end
test "parses frames up to 125 bytes" do
payload = String.duplicate("a", 125)
masked_payload = Frame.mask(payload, 1234)
frame = <<0x1::1, 0x0::3, 0x1::4, 1::1, 125::7, 1234::32, masked_payload::binary>>
assert Frame.deserialize(frame) ==
{{:ok, %Frame.Text{fin: true, compressed: false, data: payload}}, <<>>}
end
test "parses frames 126 bytes long" do
payload = String.duplicate("a", 126)
masked_payload = Frame.mask(payload, 1234)
frame = <<0x1::1, 0x0::3, 0x1::4, 1::1, 126::7, 126::16, 1234::32, masked_payload::binary>>
assert Frame.deserialize(frame) ==
{{:ok, %Frame.Text{fin: true, compressed: false, data: payload}}, <<>>}
end
test "parses frames 127 bytes long" do
payload = String.duplicate("a", 127)
masked_payload = Frame.mask(payload, 1234)
frame = <<0x1::1, 0x0::3, 0x1::4, 1::1, 126::7, 127::16, 1234::32, masked_payload::binary>>
assert Frame.deserialize(frame) ==
{{:ok, %Frame.Text{fin: true, compressed: false, data: payload}}, <<>>}
end
test "parses frames 16_000 bytes long" do
payload = String.duplicate("a", 16_000)
masked_payload = Frame.mask(payload, 1234)
frame =
<<0x1::1, 0x0::3, 0x1::4, 1::1, 126::7, 16_000::16, 1234::32, masked_payload::binary>>
assert Frame.deserialize(frame) ==
{{:ok, %Frame.Text{fin: true, compressed: false, data: payload}}, <<>>}
end
test "parses frames 1_000_000 bytes long" do
payload = String.duplicate("a", 1_000_000)
masked_payload = Frame.mask(payload, 1234)
frame =
<<0x1::1, 0x0::3, 0x1::4, 1::1, 127::7, 1_000_000::64, 1234::32, masked_payload::binary>>
assert Frame.deserialize(frame) ==
{{:ok, %Frame.Text{fin: true, compressed: false, data: payload}}, <<>>}
end
end
describe "insufficient data" do
test "asks for more" do
frame = <<0x1::1, 0x0::3, 0x1::4, 1::1, 125::7, 0::32, 1, 2, 3>>
assert Frame.deserialize(frame) == {{:more, frame}, <<>>}
end
end
describe "extra data" do
test "returns extra data" do
frame = <<0x1::1, 0x0::3, 0x1::4, 1::1, 1::7, 0::32, 1, 2, 3>>
assert Frame.deserialize(frame) ==
{{:ok, %Frame.Text{fin: true, compressed: false, data: <<1>>}}, <<2, 3>>}
end
end
describe "unknown frame types" do
test "returns an Unknown frame" do
frame = <<0x1::1, 0x0::3, 0xF::4, 1::1, 1::7, 0::32, 1, 2, 3>>
assert Frame.deserialize(frame) ==
{{:error, "unknown opcode #{15}"}, <<2, 3>>}
end
end
describe "CONTINUATION frames" do
test "deserializes frames with fin bit set" do
frame =
<<0x1::1, 0x0::3, 0x0::4, 1::1, 5::7, 0x01020304::32,
mask(<<1, 2, 3, 4, 5>>, 0x01020304)::binary>>
assert Frame.deserialize(frame) ==
{{:ok, %Frame.Continuation{fin: true, data: <<1, 2, 3, 4, 5>>}}, <<>>}
end
test "deserializes frames with fin bit clear" do
frame =
<<0x0::1, 0x0::3, 0x0::4, 1::1, 5::7, 0x01020304::32,
mask(<<1, 2, 3, 4, 5>>, 0x01020304)::binary>>
assert Frame.deserialize(frame) ==
{{:ok, %Frame.Continuation{fin: false, data: <<1, 2, 3, 4, 5>>}}, <<>>}
end
test "refuses frame with per-message compressed bit set" do
frame =
<<0x0::1, 0x4::3, 0x0::4, 1::1, 5::7, 0x01020304::32,
mask(<<1, 2, 3, 4, 5>>, 0x01020304)::binary>>
assert Frame.deserialize(frame) ==
{{:error, "Cannot have a compressed continuation frame (RFC7692§6.1)"}, <<>>}
end
end
describe "TEXT frames" do
test "deserializes frames with fin and per-message compressed bits clear" do
frame =
<<0x0::1, 0x0::3, 0x1::4, 1::1, 5::7, 0x01020304::32,
mask(<<1, 2, 3, 4, 5>>, 0x01020304)::binary>>
assert Frame.deserialize(frame) ==
{{:ok, %Frame.Text{fin: false, compressed: false, data: <<1, 2, 3, 4, 5>>}}, <<>>}
end
test "deserializes frames with fin bit set" do
frame =
<<0x1::1, 0x0::3, 0x1::4, 1::1, 5::7, 0x01020304::32,
mask(<<1, 2, 3, 4, 5>>, 0x01020304)::binary>>
assert Frame.deserialize(frame) ==
{{:ok, %Frame.Text{fin: true, compressed: false, data: <<1, 2, 3, 4, 5>>}}, <<>>}
end
test "deserializes frames with per-message compressed bit set" do
frame =
<<0x0::1, 0x4::3, 0x1::4, 1::1, 5::7, 0x01020304::32,
mask(<<1, 2, 3, 4, 5>>, 0x01020304)::binary>>
assert Frame.deserialize(frame) ==
{{:ok, %Frame.Text{fin: false, compressed: true, data: <<1, 2, 3, 4, 5>>}}, <<>>}
end
end
describe "BINARY frames" do
test "deserializes frames with fin and per-message compressed bits clear" do
frame =
<<0x0::1, 0x0::3, 0x2::4, 1::1, 5::7, 0x01020304::32,
mask(<<1, 2, 3, 4, 5>>, 0x01020304)::binary>>
assert Frame.deserialize(frame) ==
{{:ok, %Frame.Binary{fin: false, compressed: false, data: <<1, 2, 3, 4, 5>>}},
<<>>}
end
test "deserializes frames with fin bit set" do
frame =
<<0x1::1, 0x0::3, 0x2::4, 1::1, 5::7, 0x01020304::32,
mask(<<1, 2, 3, 4, 5>>, 0x01020304)::binary>>
assert Frame.deserialize(frame) ==
{{:ok, %Frame.Binary{fin: true, compressed: false, data: <<1, 2, 3, 4, 5>>}}, <<>>}
end
test "deserializes frames with per-message compressed bit set" do
frame =
<<0x0::1, 0x4::3, 0x2::4, 1::1, 5::7, 0x01020304::32,
mask(<<1, 2, 3, 4, 5>>, 0x01020304)::binary>>
assert Frame.deserialize(frame) ==
{{:ok, %Frame.Binary{fin: false, compressed: true, data: <<1, 2, 3, 4, 5>>}}, <<>>}
end
end
describe "CONNECTION_CLOSE frames" do
test "deserializes frames with code and message" do
payload = String.duplicate("a", 123)
frame =
<<0x1::1, 0x0::3, 0x8::4, 1::1, 125::7, 0x01020304::32,
mask(<<1000::16, payload::binary>>, 0x01020304)::binary>>
assert Frame.deserialize(frame) ==
{{:ok, %Frame.ConnectionClose{code: 1000, reason: payload}}, <<>>}
end
test "deserializes frames with code" do
frame =
<<0x1::1, 0x0::3, 0x8::4, 1::1, 2::7, 0x01020304::32,
mask(<<1000::16>>, 0x01020304)::binary>>
assert Frame.deserialize(frame) == {{:ok, %Frame.ConnectionClose{code: 1000}}, <<>>}
end
test "deserializes frames with no payload" do
frame = <<0x1::1, 0x0::3, 0x8::4, 1::1, 0::7, 0x01020304::32>>
assert Frame.deserialize(frame) == {{:ok, %Frame.ConnectionClose{}}, <<>>}
end
test "refuses frame with invalid payload" do
frame = <<0x1::1, 0x0::3, 0x8::4, 1::1, 1::7, 0x01020304::32, 1>>
assert Frame.deserialize(frame) ==
{{:error, "Invalid connection close payload (RFC6455§5.5)"}, <<>>}
end
test "refuses frame with overly large payload" do
payload = String.duplicate("a", 126)
frame = <<0x1::1, 0x0::3, 0x8::4, 1::1, 126::7, 126::16, 0x01020304::32, payload::binary>>
assert Frame.deserialize(frame) ==
{{:error, "Invalid connection close payload (RFC6455§5.5)"}, <<>>}
end
test "refuses frames with fin bit clear" do
frame = <<0x0::1, 0x0::3, 0x8::4, 1::1, 0::7, 0x01020304::32>>
assert Frame.deserialize(frame) ==
{{:error, "Cannot have a fragmented connection close frame (RFC6455§5.5)"}, <<>>}
end
test "refuses frame with per-message compressed bit set" do
frame = <<0x1::1, 0x4::3, 0x8::4, 1::1, 0::7, 0x01020304::32>>
assert Frame.deserialize(frame) ==
{{:error, "Cannot have a compressed connection close frame (RFC7692§6.1)"}, <<>>}
end
end
describe "PING frames" do
test "deserializes frames with data" do
payload = String.duplicate("a", 125)
frame =
<<0x1::1, 0x0::3, 0x9::4, 1::1, 125::7, 0x01020304::32,
mask(payload, 0x01020304)::binary>>
assert Frame.deserialize(frame) ==
{{:ok, %Frame.Ping{data: payload}}, <<>>}
end
test "deserializes frames with no payload" do
frame = <<0x1::1, 0x0::3, 0x9::4, 1::1, 0::7, 0x01020304::32>>
assert Frame.deserialize(frame) == {{:ok, %Frame.Ping{}}, <<>>}
end
test "refuses frame with overly large payload" do
payload = String.duplicate("a", 126)
frame = <<0x1::1, 0x0::3, 0x9::4, 1::1, 126::7, 126::16, 0x01020304::32, payload::binary>>
assert Frame.deserialize(frame) ==
{{:error, "Invalid ping payload (RFC6455§5.5.2)"}, <<>>}
end
test "refuses frames with fin bit clear" do
frame = <<0x0::1, 0x0::3, 0x9::4, 1::1, 0::7, 0x01020304::32>>
assert Frame.deserialize(frame) ==
{{:error, "Cannot have a fragmented ping frame (RFC6455§5.5.2)"}, <<>>}
end
test "refuses frames with per-message compressed bit set" do
frame = <<0x1::1, 0x4::3, 0x9::4, 1::1, 0::7, 0x01020304::32>>
assert Frame.deserialize(frame) ==
{{:error, "Cannot have a compressed ping frame (RFC7692§6.1)"}, <<>>}
end
end
describe "PONG frames" do
test "deserializes frames with data" do
payload = String.duplicate("a", 125)
frame =
<<0x1::1, 0x0::3, 0xA::4, 1::1, 125::7, 0x01020304::32,
mask(payload, 0x01020304)::binary>>
assert Frame.deserialize(frame) ==
{{:ok, %Frame.Pong{data: payload}}, <<>>}
end
test "deserializes frames with no payload" do
frame = <<0x1::1, 0x0::3, 0xA::4, 1::1, 0::7, 0x01020304::32>>
assert Frame.deserialize(frame) == {{:ok, %Frame.Pong{}}, <<>>}
end
test "refuses frame with overly large payload" do
payload = String.duplicate("a", 126)
frame = <<0x1::1, 0x0::3, 0xA::4, 1::1, 126::7, 126::16, 0x01020304::32, payload::binary>>
assert Frame.deserialize(frame) ==
{{:error, "Invalid pong payload (RFC6455§5.5.3)"}, <<>>}
end
test "refuses frames with fin bit clear" do
frame = <<0x0::1, 0x0::3, 0xA::4, 1::1, 0::7, 0x01020304::32>>
assert Frame.deserialize(frame) ==
{{:error, "Cannot have a fragmented pong frame (RFC6455§5.5.3)"}, <<>>}
end
test "refuses frames with per-message compressed bit set" do
frame = <<0x1::1, 0x4::3, 0xA::4, 1::1, 0::7, 0x01020304::32>>
assert Frame.deserialize(frame) ==
{{:error, "Cannot have a compressed pong frame (RFC7692§6.1)"}, <<>>}
end
end
end