1 /*
2  * Copyright (c) 2017 Fastly, Kazuho Oku
3  *
4  * Permission is hereby granted, free of charge, to any person obtaining a copy
5  * of this software and associated documentation files (the "Software"), to
6  * deal in the Software without restriction, including without limitation the
7  * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
8  * sell copies of the Software, and to permit persons to whom the Software is
9  * furnished to do so, subject to the following conditions:
10  *
11  * The above copyright notice and this permission notice shall be included in
12  * all copies or substantial portions of the Software.
13  *
14  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17  * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
19  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
20  * IN THE SOFTWARE.
21  */
22 #include "quicly/frame.h"
23 #include "test.h"
24 
test_ack_decode_underflow(void)25 static void test_ack_decode_underflow(void)
26 {
27     quicly_ack_frame_t decoded;
28 
29     { /* ack pn=0 */
30         const uint8_t pat[] = {0, 0, 0, 0}, *src = pat;
31         ok(quicly_decode_ack_frame(&src, pat + sizeof(pat), &decoded, 0) == 0);
32         ok(src == pat + sizeof(pat));
33         ok(decoded.largest_acknowledged == 0);
34         ok(decoded.num_gaps == 0);
35         ok(decoded.ack_block_lengths[0] == 1);
36         ok(decoded.smallest_acknowledged == 0);
37     }
38     { /* underflow in first block length */
39         const uint8_t pat[] = {0, 0, 0, 1}, *src = pat;
40         ok(quicly_decode_ack_frame(&src, pat + sizeof(pat), &decoded, 0) != 0);
41     }
42 
43     { /* frame with gap going down to pn=0 */
44         const uint8_t pat[] = {2, 0, 1, 0, 0, 0}, *src = pat;
45         ok(quicly_decode_ack_frame(&src, pat + sizeof(pat), &decoded, 0) == 0);
46         ok(src == pat + sizeof(pat));
47         ok(decoded.largest_acknowledged == 2);
48         ok(decoded.num_gaps == 1);
49         ok(decoded.ack_block_lengths[0] == 1);
50         ok(decoded.ack_block_lengths[1] == 1);
51         ok(decoded.smallest_acknowledged == 0);
52     }
53 
54     { /* additional block length going negative */
55         const uint8_t pat[] = {2, 0, 1, 0, 0, 1}, *src = pat;
56         ok(quicly_decode_ack_frame(&src, pat + sizeof(pat), &decoded, 0) != 0);
57     }
58     { /* gap going negative */
59         const uint8_t pat[] = {2, 0, 1, 0, 3, 0}, *src = pat;
60         ok(quicly_decode_ack_frame(&src, pat + sizeof(pat), &decoded, 0) != 0);
61     }
62 }
63 
test_ack_decode(void)64 static void test_ack_decode(void)
65 {
66     {
67         const uint8_t pat[] = {0x34, 0x00, 0x00, 0x11}, *src = pat;
68         quicly_ack_frame_t decoded;
69         ok(quicly_decode_ack_frame(&src, pat + sizeof(pat), &decoded, 0) == 0);
70         ok(src == pat + sizeof(pat));
71         ok(decoded.largest_acknowledged == 0x34);
72         ok(decoded.num_gaps == 0);
73         ok(decoded.ack_block_lengths[0] == 0x12);
74         ok(decoded.smallest_acknowledged == 0x34 - 0x12 + 1);
75     }
76 
77     {
78         const uint8_t pat[] = {0x34, 0x00, 0x02, 0x00, 0x01, 0x02, 0x03, 0x04}, *src = pat;
79         quicly_ack_frame_t decoded;
80         ok(quicly_decode_ack_frame(&src, pat + sizeof(pat), &decoded, 0) == 0);
81         ok(src == pat + sizeof(pat));
82         ok(decoded.largest_acknowledged == 0x34);
83         ok(decoded.num_gaps == 2);
84         ok(decoded.ack_block_lengths[0] == 1);
85         ok(decoded.gaps[0] == 2);
86         ok(decoded.ack_block_lengths[1] == 3);
87         ok(decoded.gaps[1] == 4);
88         ok(decoded.ack_block_lengths[2] == 5);
89         ok(decoded.smallest_acknowledged == 0x34 - 1 - 2 - 3 - 4 - 5 + 1);
90     }
91 
92     { /* Bogus ACK Frame larger than the internal buffer */
93         uint8_t pat[1024], *end = pat;
94         const uint8_t *src = pat;
95         uint64_t i, range_sum;
96         quicly_ack_frame_t decoded;
97         end = quicly_encodev(end, 0xFA00);
98         end = quicly_encodev(end, 0);
99         end = quicly_encodev(end, QUICLY_ACK_MAX_GAPS + 30); // with excess ranges
100         end = quicly_encodev(end, 8);
101         for (i = 0; i < QUICLY_ACK_MAX_GAPS + 30; ++i) {
102             end = quicly_encodev(end, i);      // gap
103             end = quicly_encodev(end, i % 10); // ack-range
104         }
105 
106         ok(quicly_decode_ack_frame(&src, end, &decoded, 0) == 0);
107         ok(decoded.largest_acknowledged == 0xFA00);
108         ok(decoded.ack_delay == 0);
109         ok(decoded.num_gaps == QUICLY_ACK_MAX_GAPS);
110         ok(decoded.ack_block_lengths[0] == 8 + 1); // first ack-range
111         range_sum = decoded.ack_block_lengths[0];
112         for (i = 0; i < decoded.num_gaps; ++i) {
113             ok(decoded.gaps[i] == i + 1);
114             ok(decoded.ack_block_lengths[i + 1] == (i % 10) + 1);
115             range_sum += decoded.gaps[i] + decoded.ack_block_lengths[i + 1];
116         }
117         ok(src == end); // decoded the entire frame
118         ok(decoded.smallest_acknowledged == 0xFA00 - range_sum + 1);
119     }
120 
121     subtest("underflow", test_ack_decode_underflow);
122 }
123 
test_ack_encode(void)124 static void test_ack_encode(void)
125 {
126     quicly_ranges_t ranges;
127     uint8_t buf[256], *end;
128     const uint8_t *src;
129     quicly_ack_frame_t decoded;
130 
131     quicly_ranges_init(&ranges);
132     quicly_ranges_add(&ranges, 0x12, 0x14);
133 
134     /* encode */
135     end = quicly_encode_ack_frame(buf, buf + sizeof(buf), &ranges, 63);
136     ok(end - buf == 5);
137     /* decode */
138     src = buf + 1;
139     ok(quicly_decode_ack_frame(&src, end, &decoded, 0) == 0);
140     ok(src == end);
141     ok(decoded.ack_delay == 63);
142     ok(decoded.num_gaps == 0);
143     ok(decoded.largest_acknowledged == 0x13);
144     ok(decoded.ack_block_lengths[0] == 2);
145 
146     quicly_ranges_add(&ranges, 0x10, 0x11);
147 
148     /* encode */
149     end = quicly_encode_ack_frame(buf, buf + sizeof(buf), &ranges, 63);
150     ok(end - buf == 7);
151     /* decode */
152     src = buf + 1;
153     ok(quicly_decode_ack_frame(&src, end, &decoded, 0) == 0);
154     ok(src == end);
155     ok(decoded.ack_delay == 63);
156     ok(decoded.num_gaps == 1);
157     ok(decoded.largest_acknowledged == 0x13);
158     ok(decoded.ack_block_lengths[0] == 2);
159     ok(decoded.gaps[0] == 1);
160     ok(decoded.ack_block_lengths[1] == 1);
161 
162     quicly_ranges_clear(&ranges);
163 }
164 
test_mozquic(void)165 static void test_mozquic(void)
166 {
167     quicly_stream_frame_t frame;
168     static const char *mess = "\xc5\0\0\0\0\0\0\xb6\x16\x03";
169     const uint8_t *p = (void *)mess, type_flags = *p++;
170     quicly_decode_stream_frame(type_flags, &p, p + 9, &frame);
171 }
172 
test_frame(void)173 void test_frame(void)
174 {
175     subtest("ack-decode", test_ack_decode);
176     subtest("ack-encode", test_ack_encode);
177     subtest("mozquic", test_mozquic);
178 }
179