1 /*
2 * nghttp2 - HTTP/2 C Library
3 *
4 * Copyright (c) 2014 Tatsuhiro Tsujikawa
5 *
6 * Permission is hereby granted, free of charge, to any person obtaining
7 * a copy of this software and associated documentation files (the
8 * "Software"), to deal in the Software without restriction, including
9 * without limitation the rights to use, copy, modify, merge, publish,
10 * distribute, sublicense, and/or sell copies of the Software, and to
11 * permit persons to whom the Software is furnished to do so, subject to
12 * the following conditions:
13 *
14 * The above copyright notice and this permission notice shall be
15 * included in all copies or substantial portions of the Software.
16 *
17 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
18 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
19 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
20 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
21 * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
22 * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
23 * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
24 */
25 #include "nghttp2_buf_test.h"
26
27 #include <stdio.h>
28
29 #include "munit.h"
30
31 #include "nghttp2_buf.h"
32 #include "nghttp2_test_helper.h"
33
34 static const MunitTest tests[] = {
35 munit_void_test(test_nghttp2_bufs_add),
36 munit_void_test(test_nghttp2_bufs_add_stack_buffer_overflow_bug),
37 munit_void_test(test_nghttp2_bufs_addb),
38 munit_void_test(test_nghttp2_bufs_orb),
39 munit_void_test(test_nghttp2_bufs_remove),
40 munit_void_test(test_nghttp2_bufs_reset),
41 munit_void_test(test_nghttp2_bufs_advance),
42 munit_void_test(test_nghttp2_bufs_next_present),
43 munit_void_test(test_nghttp2_bufs_realloc),
44 munit_test_end(),
45 };
46
47 const MunitSuite buf_suite = {
48 "/buf", tests, NULL, 1, MUNIT_SUITE_OPTION_NONE,
49 };
50
test_nghttp2_bufs_add(void)51 void test_nghttp2_bufs_add(void) {
52 int rv;
53 nghttp2_bufs bufs;
54 uint8_t data[2048];
55 nghttp2_mem *mem;
56
57 mem = nghttp2_mem_default();
58
59 rv = nghttp2_bufs_init(&bufs, 1000, 3, mem);
60 assert_int(0, ==, rv);
61
62 assert_ptr_equal(bufs.cur->buf.pos, bufs.cur->buf.last);
63
64 rv = nghttp2_bufs_add(&bufs, data, 493);
65 assert_int(0, ==, rv);
66 assert_size(493, ==, nghttp2_buf_len(&bufs.cur->buf));
67 assert_size(493, ==, nghttp2_bufs_len(&bufs));
68 assert_size(507, ==, nghttp2_bufs_cur_avail(&bufs));
69
70 rv = nghttp2_bufs_add(&bufs, data, 507);
71 assert_int(0, ==, rv);
72 assert_size(1000, ==, nghttp2_buf_len(&bufs.cur->buf));
73 assert_size(1000, ==, nghttp2_bufs_len(&bufs));
74 assert_ptr_equal(bufs.cur, bufs.head);
75
76 rv = nghttp2_bufs_add(&bufs, data, 1);
77 assert_int(0, ==, rv);
78 assert_size(1, ==, nghttp2_buf_len(&bufs.cur->buf));
79 assert_size(1001, ==, nghttp2_bufs_len(&bufs));
80 assert_ptr_equal(bufs.cur, bufs.head->next);
81
82 nghttp2_bufs_free(&bufs);
83 }
84
85 /* Test for GH-232, stack-buffer-overflow */
test_nghttp2_bufs_add_stack_buffer_overflow_bug(void)86 void test_nghttp2_bufs_add_stack_buffer_overflow_bug(void) {
87 int rv;
88 nghttp2_bufs bufs;
89 uint8_t data[1024];
90 nghttp2_mem *mem;
91
92 mem = nghttp2_mem_default();
93
94 rv = nghttp2_bufs_init(&bufs, 100, 200, mem);
95 assert_int(0, ==, rv);
96
97 rv = nghttp2_bufs_add(&bufs, data, sizeof(data));
98
99 assert_int(0, ==, rv);
100 assert_size(sizeof(data), ==, nghttp2_bufs_len(&bufs));
101
102 nghttp2_bufs_free(&bufs);
103 }
104
test_nghttp2_bufs_addb(void)105 void test_nghttp2_bufs_addb(void) {
106 int rv;
107 nghttp2_bufs bufs;
108 size_t i;
109 nghttp2_mem *mem;
110
111 mem = nghttp2_mem_default();
112
113 rv = nghttp2_bufs_init(&bufs, 1000, 3, mem);
114 assert_int(0, ==, rv);
115
116 rv = nghttp2_bufs_addb(&bufs, 14);
117 assert_int(0, ==, rv);
118 assert_size(1, ==, nghttp2_buf_len(&bufs.cur->buf));
119 assert_size(1, ==, nghttp2_bufs_len(&bufs));
120 assert_uint8(14, ==, *bufs.cur->buf.pos);
121
122 for (i = 0; i < 999; ++i) {
123 rv = nghttp2_bufs_addb(&bufs, 254);
124
125 assert_int(0, ==, rv);
126 assert_size(i + 2, ==, nghttp2_buf_len(&bufs.cur->buf));
127 assert_size(i + 2, ==, nghttp2_bufs_len(&bufs));
128 assert_uint8(254, ==, *(bufs.cur->buf.last - 1));
129 assert_ptr_equal(bufs.cur, bufs.head);
130 }
131
132 rv = nghttp2_bufs_addb(&bufs, 253);
133 assert_int(0, ==, rv);
134 assert_size(1, ==, nghttp2_buf_len(&bufs.cur->buf));
135 assert_size(1001, ==, nghttp2_bufs_len(&bufs));
136 assert_uint8(253, ==, *(bufs.cur->buf.last - 1));
137 assert_ptr_equal(bufs.cur, bufs.head->next);
138
139 rv = nghttp2_bufs_addb_hold(&bufs, 15);
140 assert_int(0, ==, rv);
141 assert_size(1, ==, nghttp2_buf_len(&bufs.cur->buf));
142 assert_size(1001, ==, nghttp2_bufs_len(&bufs));
143 assert_uint8(15, ==, *(bufs.cur->buf.last));
144
145 /* test fast version */
146
147 nghttp2_bufs_fast_addb(&bufs, 240);
148
149 assert_size(2, ==, nghttp2_buf_len(&bufs.cur->buf));
150 assert_size(1002, ==, nghttp2_bufs_len(&bufs));
151 assert_uint8(240, ==, *(bufs.cur->buf.last - 1));
152
153 nghttp2_bufs_fast_addb_hold(&bufs, 113);
154
155 assert_size(2, ==, nghttp2_buf_len(&bufs.cur->buf));
156 assert_size(1002, ==, nghttp2_bufs_len(&bufs));
157 assert_uint8(113, ==, *(bufs.cur->buf.last));
158
159 /* addb_hold when last == end */
160 bufs.cur->buf.last = bufs.cur->buf.end;
161
162 rv = nghttp2_bufs_addb_hold(&bufs, 19);
163 assert_int(0, ==, rv);
164 assert_size(0, ==, nghttp2_buf_len(&bufs.cur->buf));
165 assert_size(2000, ==, nghttp2_bufs_len(&bufs));
166 assert_uint8(19, ==, *(bufs.cur->buf.last));
167
168 nghttp2_bufs_free(&bufs);
169 }
170
test_nghttp2_bufs_orb(void)171 void test_nghttp2_bufs_orb(void) {
172 int rv;
173 nghttp2_bufs bufs;
174 nghttp2_mem *mem;
175
176 mem = nghttp2_mem_default();
177
178 rv = nghttp2_bufs_init(&bufs, 1000, 3, mem);
179 assert_int(0, ==, rv);
180
181 *(bufs.cur->buf.last) = 0;
182
183 rv = nghttp2_bufs_orb_hold(&bufs, 15);
184 assert_int(0, ==, rv);
185 assert_size(0, ==, nghttp2_buf_len(&bufs.cur->buf));
186 assert_size(0, ==, nghttp2_bufs_len(&bufs));
187 assert_uint8(15, ==, *(bufs.cur->buf.last));
188
189 rv = nghttp2_bufs_orb(&bufs, 240);
190 assert_int(0, ==, rv);
191 assert_size(1, ==, nghttp2_buf_len(&bufs.cur->buf));
192 assert_size(1, ==, nghttp2_bufs_len(&bufs));
193 assert_uint8(255, ==, *(bufs.cur->buf.last - 1));
194
195 *(bufs.cur->buf.last) = 0;
196 nghttp2_bufs_fast_orb_hold(&bufs, 240);
197 assert_uint8(240, ==, *(bufs.cur->buf.last));
198
199 nghttp2_bufs_fast_orb(&bufs, 15);
200 assert_uint8(255, ==, *(bufs.cur->buf.last - 1));
201
202 nghttp2_bufs_free(&bufs);
203 }
204
test_nghttp2_bufs_remove(void)205 void test_nghttp2_bufs_remove(void) {
206 int rv;
207 nghttp2_bufs bufs;
208 nghttp2_buf_chain *chain;
209 int i;
210 uint8_t *out;
211 nghttp2_ssize outlen;
212 nghttp2_mem *mem;
213
214 mem = nghttp2_mem_default();
215
216 rv = nghttp2_bufs_init(&bufs, 1000, 3, mem);
217 assert_int(0, ==, rv);
218
219 nghttp2_buf_shift_right(&bufs.cur->buf, 10);
220
221 rv = nghttp2_bufs_add(&bufs, "hello ", 6);
222 assert_int(0, ==, rv);
223
224 for (i = 0; i < 2; ++i) {
225 chain = bufs.cur;
226
227 rv = nghttp2_bufs_advance(&bufs);
228 assert_int(0, ==, rv);
229
230 assert_ptr_equal(chain->next, bufs.cur);
231 }
232
233 rv = nghttp2_bufs_add(&bufs, "world", 5);
234 assert_int(0, ==, rv);
235
236 outlen = nghttp2_bufs_remove(&bufs, &out);
237 assert_ptrdiff(11, ==, outlen);
238
239 assert_memory_equal((size_t)outlen, "hello world", out);
240 assert_size(11, ==, nghttp2_bufs_len(&bufs));
241
242 mem->free(out, NULL);
243 nghttp2_bufs_free(&bufs);
244 }
245
test_nghttp2_bufs_reset(void)246 void test_nghttp2_bufs_reset(void) {
247 int rv;
248 nghttp2_bufs bufs;
249 nghttp2_buf_chain *ci;
250 size_t offset = 9;
251 nghttp2_mem *mem;
252
253 mem = nghttp2_mem_default();
254
255 rv = nghttp2_bufs_init3(&bufs, 250, 3, 1, offset, mem);
256 assert_int(0, ==, rv);
257
258 rv = nghttp2_bufs_add(&bufs, "foo", 3);
259 assert_int(0, ==, rv);
260
261 rv = nghttp2_bufs_advance(&bufs);
262 assert_int(0, ==, rv);
263
264 rv = nghttp2_bufs_add(&bufs, "bar", 3);
265 assert_int(0, ==, rv);
266
267 assert_size(6, ==, nghttp2_bufs_len(&bufs));
268
269 nghttp2_bufs_reset(&bufs);
270
271 assert_size(0, ==, nghttp2_bufs_len(&bufs));
272 assert_ptr_equal(bufs.cur, bufs.head);
273
274 for (ci = bufs.head; ci; ci = ci->next) {
275 assert_ptrdiff((ptrdiff_t)offset, ==, ci->buf.pos - ci->buf.begin);
276 assert_ptr_equal(ci->buf.pos, ci->buf.last);
277 }
278
279 assert_null(bufs.head->next);
280
281 nghttp2_bufs_free(&bufs);
282 }
283
test_nghttp2_bufs_advance(void)284 void test_nghttp2_bufs_advance(void) {
285 int rv;
286 nghttp2_bufs bufs;
287 int i;
288 nghttp2_mem *mem;
289
290 mem = nghttp2_mem_default();
291
292 rv = nghttp2_bufs_init(&bufs, 250, 3, mem);
293 assert_int(0, ==, rv);
294
295 for (i = 0; i < 2; ++i) {
296 rv = nghttp2_bufs_advance(&bufs);
297 assert_int(0, ==, rv);
298 }
299
300 rv = nghttp2_bufs_advance(&bufs);
301 assert_int(NGHTTP2_ERR_BUFFER_ERROR, ==, rv);
302
303 nghttp2_bufs_free(&bufs);
304 }
305
test_nghttp2_bufs_next_present(void)306 void test_nghttp2_bufs_next_present(void) {
307 int rv;
308 nghttp2_bufs bufs;
309 nghttp2_mem *mem;
310
311 mem = nghttp2_mem_default();
312
313 rv = nghttp2_bufs_init(&bufs, 250, 3, mem);
314 assert_int(0, ==, rv);
315
316 assert_false(nghttp2_bufs_next_present(&bufs));
317
318 rv = nghttp2_bufs_advance(&bufs);
319 assert_int(0, ==, rv);
320
321 nghttp2_bufs_rewind(&bufs);
322
323 assert_false(nghttp2_bufs_next_present(&bufs));
324
325 bufs.cur = bufs.head->next;
326
327 rv = nghttp2_bufs_addb(&bufs, 1);
328 assert_int(0, ==, rv);
329
330 nghttp2_bufs_rewind(&bufs);
331
332 assert_true(nghttp2_bufs_next_present(&bufs));
333
334 nghttp2_bufs_free(&bufs);
335 }
336
test_nghttp2_bufs_realloc(void)337 void test_nghttp2_bufs_realloc(void) {
338 int rv;
339 nghttp2_bufs bufs;
340 nghttp2_mem *mem;
341
342 mem = nghttp2_mem_default();
343
344 rv = nghttp2_bufs_init3(&bufs, 266, 3, 1, 10, mem);
345 assert_int(0, ==, rv);
346
347 /* Create new buffer to see that these buffers are deallocated on
348 realloc */
349 rv = nghttp2_bufs_advance(&bufs);
350 assert_int(0, ==, rv);
351
352 rv = nghttp2_bufs_realloc(&bufs, 522);
353 assert_int(0, ==, rv);
354
355 assert_size(512, ==, nghttp2_bufs_cur_avail(&bufs));
356
357 rv = nghttp2_bufs_realloc(&bufs, 9);
358 assert_int(NGHTTP2_ERR_INVALID_ARGUMENT, ==, rv);
359
360 nghttp2_bufs_free(&bufs);
361 }
362