Skip to main content
aboutsummaryrefslogtreecommitdiffstats
blob: 1d65e914ac20237d35ec7f96d40349c398ea5ef0 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
package org.eclipse.jetty.websocket.server.ab;

import java.util.ArrayList;
import java.util.Collection;
import java.util.List;

import org.eclipse.jetty.util.log.Log;
import org.eclipse.jetty.util.log.Logger;
import org.eclipse.jetty.websocket.api.StatusCode;
import org.eclipse.jetty.websocket.protocol.CloseInfo;
import org.eclipse.jetty.websocket.protocol.OpCode;
import org.eclipse.jetty.websocket.protocol.WebSocketFrame;
import org.eclipse.jetty.websocket.server.helper.Hex;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.Parameterized;
import org.junit.runners.Parameterized.Parameters;

/**
 * Tests of Known Bad UTF8 sequences that should trigger a {@link StatusCode#BAD_PAYLOAD} close and early connection termination
 */
@RunWith(Parameterized.class)
public class TestABCase6_BadUTF extends AbstractABCase
{
    private static final Logger LOG = Log.getLogger(TestABCase6_BadUTF.class);

    @Parameters
    public static Collection<String[]> data()
    {
        // The various Good UTF8 sequences as a String (hex form)
        List<String[]> data = new ArrayList<>();

        // @formatter:off
        // - differently unicode fragmented
        data.add(new String[]{ "6.3.1", "CEBAE1BDB9CF83CEBCCEB5EDA080656469746564" });
        // - partial/incomplete multi-byte code points
        data.add(new String[]{ "6.6.1", "CE" });
        data.add(new String[]{ "6.6.3", "CEBAE1" });
        data.add(new String[]{ "6.6.4", "CEBAE1BD" });
        data.add(new String[]{ "6.6.6", "CEBAE1BDB9CF" });
        data.add(new String[]{ "6.6.8", "CEBAE1BDB9CF83CE" });
        data.add(new String[]{ "6.6.10", "CEBAE1BDB9CF83CEBCCE" });
        // - first possible sequence length 5/6 (invalid code points)
        data.add(new String[]{ "6.8.1", "F888808080" });
        data.add(new String[]{ "6.8.2", "FC8480808080" });
        // - last possible sequence length (invalid code points)
        data.add(new String[]{ "6.10.1", "F7BFBFBF" });
        data.add(new String[]{ "6.10.2", "FBBFBFBFBF" });
        data.add(new String[]{ "6.10.3", "FDBFBFBFBFBF" });
        // - other boundary conditions
        data.add(new String[]{ "6.11.5", "F4908080" });
        // - unexpected continuation bytes
        data.add(new String[]{ "6.12.1", "80" });
        data.add(new String[]{ "6.12.2", "BF" });
        data.add(new String[]{ "6.12.3", "80BF" });
        data.add(new String[]{ "6.12.4", "80BF80" });
        data.add(new String[]{ "6.12.5", "80BF80BF" });
        data.add(new String[]{ "6.12.6", "80BF80BF80" });
        data.add(new String[]{ "6.12.7", "80BF80BF80BF" });
        data.add(new String[]{ "6.12.8", "808182838485868788898A8B8C8D8E8F909192939495969798999A9B9C9D9E9"
                + "FA0A1A2A3A4A5A6A7A8A9AAABACADAEAFB0B1B2B3B4B5B6B7B8B9BABBBCBDBE" });
        // - lonely start characters
        data.add(new String[]{ "6.13.1", "C020C120C220C320C420C520C620C720C820C920CA20CB20CC20CD20CE20CF2"
                + "0D020D120D220D320D420D520D620D720D820D920DA20DB20DC20DD20DE20" });
        data.add(new String[]{ "6.13.2", "E020E120E220E320E420E520E620E720E820E920EA20EB20EC20ED20EE20" });
        data.add(new String[]{ "6.13.3", "F020F120F220F320F420F520F620" });
        data.add(new String[]{ "6.13.4", "F820F920FA20" });
        data.add(new String[]{ "6.13.5", "FC20" });
        // - sequences with last continuation byte missing
        data.add(new String[]{ "6.14.1", "C0" });
        data.add(new String[]{ "6.14.2", "E080" });
        data.add(new String[]{ "6.14.3", "F08080" });
        data.add(new String[]{ "6.14.4", "F8808080" });
        data.add(new String[]{ "6.14.5", "FC80808080" });
        data.add(new String[]{ "6.14.6", "DF" });
        data.add(new String[]{ "6.14.7", "EFBF" });
        data.add(new String[]{ "6.14.8", "F7BFBF" });
        data.add(new String[]{ "6.14.9", "FBBFBFBF" });
        data.add(new String[]{ "6.14.10", "FDBFBFBFBF" });
        // - concatenation of incomplete sequences
        data.add(new String[]{ "6.15.1", "C0E080F08080F8808080FC80808080DFEFBFF7BFBFFBBFBFBFFDBFBFBFBF" });
        // - impossible bytes
        data.add(new String[]{ "6.16.1", "FE" });
        data.add(new String[]{ "6.16.2", "FF" });
        data.add(new String[]{ "6.16.3", "FEFEFFFF" });
        // - overlong ascii characters
        data.add(new String[]{ "6.17.1", "C0AF" });
        data.add(new String[]{ "6.17.2", "E080AF" });
        data.add(new String[]{ "6.17.3", "F08080AF" });
        data.add(new String[]{ "6.17.4", "F8808080AF" });
        data.add(new String[]{ "6.17.5", "FC80808080AF" });
        // - maximum overlong sequences
        data.add(new String[]{ "6.18.1", "C1BF" });
        data.add(new String[]{ "6.18.2", "E09FBF" });
        data.add(new String[]{ "6.18.3", "F08FBFBF" });
        data.add(new String[]{ "6.18.4", "F887BFBFBF" });
        data.add(new String[]{ "6.18.5", "FC83BFBFBFBF" });
        // - overlong representation of NUL character
        data.add(new String[]{ "6.19.1", "C080" });
        data.add(new String[]{ "6.19.2", "E08080" });
        data.add(new String[]{ "6.19.3", "F0808080" });
        data.add(new String[]{ "6.19.4", "F880808080" });
        data.add(new String[]{ "6.19.5", "FC8080808080" });
        // - single UTF-16 surrogates
        data.add(new String[]{ "6.20.1", "EDA080" });
        data.add(new String[]{ "6.20.2", "EDADBF" });
        data.add(new String[]{ "6.20.3", "EDAE80" });
        data.add(new String[]{ "6.20.4", "EDAFBF" });
        data.add(new String[]{ "6.20.5", "EDB080" });
        data.add(new String[]{ "6.20.6", "EDBE80" });
        data.add(new String[]{ "6.20.7", "EDBFBF" });
        // - paired UTF-16 surrogates
        data.add(new String[]{ "6.21.1", "EDA080EDB080" });
        data.add(new String[]{ "6.21.2", "EDA080EDBFBF" });
        data.add(new String[]{ "6.21.3", "EDADBFEDB080" });
        data.add(new String[]{ "6.21.4", "EDADBFEDBFBF" });
        data.add(new String[]{ "6.21.5", "EDAE80EDB080" });
        data.add(new String[]{ "6.21.6", "EDAE80EDBFBF" });
        data.add(new String[]{ "6.21.7", "EDAFBFEDB080" });
        data.add(new String[]{ "6.21.8", "EDAFBFEDBFBF" });
        // @formatter:on

        return data;
    }

    private final byte[] invalid;

    public TestABCase6_BadUTF(String testId, String hexMsg)
    {
        LOG.debug("Test ID: {}",testId);
        this.invalid = Hex.asByteArray(hexMsg);
    }

    @Test
    public void assertBadTextPayload() throws Exception
    {
        List<WebSocketFrame> send = new ArrayList<>();
        send.add(new WebSocketFrame(OpCode.TEXT).setPayload(invalid));
        send.add(new CloseInfo(StatusCode.NORMAL).asFrame());

        List<WebSocketFrame> expect = new ArrayList<>();
        expect.add(new CloseInfo(StatusCode.BAD_PAYLOAD).asFrame());

        Fuzzer fuzzer = new Fuzzer(this);
        try
        {
            fuzzer.connect();
            fuzzer.setSendMode(Fuzzer.SendMode.BULK);
            fuzzer.send(send);
            fuzzer.expect(expect);
        }
        finally
        {
            fuzzer.close();
        }
    }
}

Back to the top