1 /*
2
3 Copyright (c) 2008, Arvid Norberg
4 All rights reserved.
5
6 Redistribution and use in source and binary forms, with or without
7 modification, are permitted provided that the following conditions
8 are met:
9
10 * Redistributions of source code must retain the above copyright
11 notice, this list of conditions and the following disclaimer.
12 * Redistributions in binary form must reproduce the above copyright
13 notice, this list of conditions and the following disclaimer in
14 the documentation and/or other materials provided with the distribution.
15 * Neither the name of the author nor the names of its
16 contributors may be used to endorse or promote products derived
17 from this software without specific prior written permission.
18
19 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
20 AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
23 LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
24 CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
25 SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
26 INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
27 CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
28 ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
29 POSSIBILITY OF SUCH DAMAGE.
30
31 */
32
33 #include "libtorrent/bencode.hpp"
34 #include "libtorrent/bdecode.hpp"
35
36 #include <iostream>
37 #include <cstring>
38 #include <utility>
39
40 #if TORRENT_ABI_VERSION == 1
41 #include "libtorrent/lazy_entry.hpp"
42 #endif
43
44 #include "test.hpp"
45
46 using namespace lt;
47
48 // test vectors from bittorrent protocol description
49 // http://www.bittorrent.com/protocol.html
50
51 namespace {
52
encode(entry const & e)53 std::string encode(entry const& e)
54 {
55 std::string ret;
56 bencode(std::back_inserter(ret), e);
57 return ret;
58 }
59
60 } // anonymous namespace
61
TORRENT_TEST(strings)62 TORRENT_TEST(strings)
63 {
64 entry e("spam");
65 TEST_CHECK(encode(e) == "4:spam");
66 TEST_CHECK(bdecode(encode(e)) == e);
67 }
68
TORRENT_TEST(integers)69 TORRENT_TEST(integers)
70 {
71 entry e(3);
72 TEST_CHECK(encode(e) == "i3e");
73 TEST_CHECK(bdecode(encode(e)) == e);
74 }
75
TORRENT_TEST(integers2)76 TORRENT_TEST(integers2)
77 {
78 entry e(-3);
79 TEST_CHECK(encode(e) == "i-3e");
80 TEST_CHECK(bdecode(encode(e)) == e);
81 }
82
TORRENT_TEST(integers3)83 TORRENT_TEST(integers3)
84 {
85 entry e(int(0));
86 TEST_CHECK(encode(e) == "i0e");
87 TEST_CHECK(bdecode(encode(e)) == e);
88 }
89
TORRENT_TEST(lists)90 TORRENT_TEST(lists)
91 {
92 entry::list_type l;
93 l.push_back(entry("spam"));
94 l.push_back(entry("eggs"));
95 entry e(l);
96 TEST_CHECK(encode(e) == "l4:spam4:eggse");
97 TEST_CHECK(bdecode(encode(e)) == e);
98 }
99
TORRENT_TEST(dictionaries)100 TORRENT_TEST(dictionaries)
101 {
102 entry e(entry::dictionary_t);
103 e["spam"] = entry("eggs");
104 e["cow"] = entry("moo");
105 TEST_CHECK(encode(e) == "d3:cow3:moo4:spam4:eggse");
106 TEST_CHECK(bdecode(encode(e)) == e);
107 }
108
TORRENT_TEST(preformatted)109 TORRENT_TEST(preformatted)
110 {
111 entry e(entry::preformatted_t);
112 char const str[] = "foobar";
113 e.preformatted().assign(str, str + sizeof(str)-1);
114 TEST_EQUAL(encode(e), "foobar");
115 }
116
TORRENT_TEST(preformatted_node)117 TORRENT_TEST(preformatted_node)
118 {
119 entry e(entry::dictionary_t);
120 char const str[] = "foobar";
121 e["info"] = entry::preformatted_type(str, str + sizeof(str)-1);
122 TEST_EQUAL(encode(e), "d4:infofoobare");
123 }
124
TORRENT_TEST(undefined_node)125 TORRENT_TEST(undefined_node)
126 {
127 entry e(entry::undefined_t);
128 TEST_EQUAL(encode(e), "0:");
129 }
130
TORRENT_TEST(undefined_node2)131 TORRENT_TEST(undefined_node2)
132 {
133 entry e(entry::dictionary_t);
134 e["info"] = entry(entry::undefined_t);
135 TEST_EQUAL(encode(e), "d4:info0:e");
136 }
137
TORRENT_TEST(implicit_construct)138 TORRENT_TEST(implicit_construct)
139 {
140 entry e(entry::list_t);
141 e.list().push_back(entry::list_t);
142 TEST_EQUAL(e.list().back().type(), entry::list_t);
143 }
144
TORRENT_TEST(print_dict_single_line)145 TORRENT_TEST(print_dict_single_line)
146 {
147 entry e;
148 e["foo"] = "bar";
149 e["bar"] = "foo";
150 TEST_EQUAL(e.to_string(true), "{ 'bar': 'foo', 'foo': 'bar' }");
151 }
152
TORRENT_TEST(print_dict)153 TORRENT_TEST(print_dict)
154 {
155 entry e;
156 e["foo"] = "bar";
157 e["bar"] = "foo";
158 TEST_EQUAL(e.to_string(), "{\n 'bar': 'foo',\n 'foo': 'bar' }");
159 }
160
TORRENT_TEST(print_list_single_line)161 TORRENT_TEST(print_list_single_line)
162 {
163 entry e;
164 e.list().push_back(entry("foo"));
165 e.list().push_back(entry("bar"));
166 TEST_EQUAL(e.to_string(true), "[ 'foo', 'bar' ]");
167 }
168
169
TORRENT_TEST(print_list)170 TORRENT_TEST(print_list)
171 {
172 entry e;
173 e.list().push_back(entry("foo"));
174 e.list().push_back(entry("bar"));
175 TEST_EQUAL(e.to_string(), "[\n 'foo',\n 'bar' ]");
176 }
177
TORRENT_TEST(print_int_single_line)178 TORRENT_TEST(print_int_single_line)
179 {
180 entry e(1337);
181 TEST_EQUAL(e.to_string(true), "1337");
182 }
183
TORRENT_TEST(print_int)184 TORRENT_TEST(print_int)
185 {
186 entry e(1337);
187 TEST_EQUAL(e.to_string(), "1337");
188 }
189
TORRENT_TEST(print_string_single_line)190 TORRENT_TEST(print_string_single_line)
191 {
192 entry e("foobar");
193 TEST_EQUAL(e.to_string(true), "'foobar'");
194 }
195
TORRENT_TEST(print_string)196 TORRENT_TEST(print_string)
197 {
198 entry e("foobar");
199 TEST_EQUAL(e.to_string(), "'foobar'");
200 }
201
TORRENT_TEST(print_deep_dict_single_line)202 TORRENT_TEST(print_deep_dict_single_line)
203 {
204 entry e;
205 e["strings"].list().push_back(entry("foo"));
206 e["strings"].list().push_back(entry("bar"));
207 e["ints"].list().push_back(entry(1));
208 e["ints"].list().push_back(entry(2));
209 e["ints"].list().push_back(entry(3));
210 e["a"] = "foobar";
211 TEST_EQUAL(e.to_string(true), "{ 'a': 'foobar', 'ints': [ 1, 2, 3 ], 'strings': [ 'foo', 'bar' ] }");
212 }
213
TORRENT_TEST(print_deep_dict)214 TORRENT_TEST(print_deep_dict)
215 {
216 entry e;
217 e["strings"].list().push_back(entry("foo"));
218 e["strings"].list().push_back(entry("bar"));
219 e["ints"].list().push_back(entry(1));
220 e["ints"].list().push_back(entry(2));
221 e["ints"].list().push_back(entry(3));
222 e["a"] = "foobar";
223 TEST_EQUAL(e.to_string(), "{\n 'a': 'foobar',\n 'ints': [\n 1,\n 2,\n 3 ],\n 'strings': [\n 'foo',\n 'bar' ] }");
224 }
225
TORRENT_TEST(dict_constructor)226 TORRENT_TEST(dict_constructor)
227 {
228 entry::dictionary_type e{{std::string("foo"), std::string("bar")},
229 {std::string("bar"), 1234}};
230
231 TEST_EQUAL(entry(e).to_string(), "{\n 'bar': 1234,\n 'foo': 'bar' }");
232 }
233
TORRENT_TEST(integer_to_str)234 TORRENT_TEST(integer_to_str)
235 {
236 using lt::detail::integer_to_str;
237
238 char buf[30];
239 TEST_CHECK(integer_to_str(buf, 0) == "0"_sv);
240 TEST_CHECK(integer_to_str(buf, 1234) == "1234"_sv);
241 TEST_CHECK(integer_to_str(buf, -1234) == "-1234"_sv);
242 TEST_CHECK(integer_to_str(buf, 123456789012345678LL) == "123456789012345678"_sv);
243 TEST_CHECK(integer_to_str(buf, -123456789012345678LL) == "-123456789012345678"_sv);
244 }
245
246 #if TORRENT_ABI_VERSION == 1
TORRENT_TEST(lazy_entry)247 TORRENT_TEST(lazy_entry)
248 {
249 {
250 char b[] = "i12453e";
251 lazy_entry e;
252 error_code ec;
253 int ret = lazy_bdecode(b, b + sizeof(b)-1, e, ec);
254 TEST_CHECK(ret == 0);
255 std::printf("%s\n", print_entry(e).c_str());
256 std::pair<const char*, int> section = e.data_section();
257 TEST_CHECK(std::memcmp(b, section.first, std::size_t(section.second)) == 0);
258 TEST_CHECK(section.second == sizeof(b) - 1);
259 TEST_CHECK(e.type() == lazy_entry::int_t);
260 TEST_CHECK(e.int_value() == 12453);
261 }
262
263 {
264 char b[] = "26:abcdefghijklmnopqrstuvwxyz";
265 lazy_entry e;
266 error_code ec;
267 int ret = lazy_bdecode(b, b + sizeof(b)-1, e, ec);
268 TEST_CHECK(ret == 0);
269 std::printf("%s\n", print_entry(e).c_str());
270 std::pair<const char*, int> section = e.data_section();
271 TEST_CHECK(std::memcmp(b, section.first, std::size_t(section.second)) == 0);
272 TEST_CHECK(section.second == sizeof(b) - 1);
273 TEST_CHECK(e.type() == lazy_entry::string_t);
274 TEST_CHECK(e.string_value() == std::string("abcdefghijklmnopqrstuvwxyz"));
275 TEST_CHECK(e.string_length() == 26);
276 }
277
278 {
279 char b[] = "li12453e3:aaae";
280 lazy_entry e;
281 error_code ec;
282 int ret = lazy_bdecode(b, b + sizeof(b)-1, e, ec);
283 TEST_CHECK(ret == 0);
284 std::printf("%s\n", print_entry(e).c_str());
285 std::pair<const char*, int> section = e.data_section();
286 TEST_CHECK(std::memcmp(b, section.first, std::size_t(section.second)) == 0);
287 TEST_CHECK(section.second == sizeof(b) - 1);
288 TEST_CHECK(e.type() == lazy_entry::list_t);
289 TEST_CHECK(e.list_size() == 2);
290 TEST_CHECK(e.list_at(0)->type() == lazy_entry::int_t);
291 TEST_CHECK(e.list_at(1)->type() == lazy_entry::string_t);
292 TEST_CHECK(e.list_at(0)->int_value() == 12453);
293 TEST_CHECK(e.list_at(1)->string_value() == std::string("aaa"));
294 TEST_CHECK(e.list_at(1)->string_length() == 3);
295 section = e.list_at(1)->data_section();
296 TEST_CHECK(std::memcmp("3:aaa", section.first, std::size_t(section.second)) == 0);
297 TEST_CHECK(section.second == 5);
298 }
299
300 {
301 char b[] = "d1:ai12453e1:b3:aaa1:c3:bbb1:X10:0123456789e";
302 lazy_entry e;
303 error_code ec;
304 int ret = lazy_bdecode(b, b + sizeof(b)-1, e, ec);
305 TEST_CHECK(ret == 0);
306 std::printf("%s\n", print_entry(e).c_str());
307 std::pair<const char*, int> section = e.data_section();
308 TEST_CHECK(std::memcmp(b, section.first, std::size_t(section.second)) == 0);
309 TEST_CHECK(section.second == sizeof(b) - 1);
310 TEST_CHECK(e.type() == lazy_entry::dict_t);
311 TEST_CHECK(e.dict_size() == 4);
312 TEST_CHECK(e.dict_find("a")->type() == lazy_entry::int_t);
313 TEST_CHECK(e.dict_find("a")->int_value() == 12453);
314 TEST_CHECK(e.dict_find("b")->type() == lazy_entry::string_t);
315 TEST_CHECK(e.dict_find("b")->string_value() == std::string("aaa"));
316 TEST_CHECK(e.dict_find("b")->string_length() == 3);
317 TEST_CHECK(e.dict_find("c")->type() == lazy_entry::string_t);
318 TEST_CHECK(e.dict_find("c")->string_value() == std::string("bbb"));
319 TEST_CHECK(e.dict_find("c")->string_length() == 3);
320 TEST_CHECK(e.dict_find_string_value("X") == "0123456789");
321 }
322
323 // dictionary key with \0
324 {
325 char b[] = "d3:a\0bi1ee";
326 lazy_entry e;
327 error_code ec;
328 int ret = lazy_bdecode(b, b + sizeof(b)-1, e, ec);
329 TEST_CHECK(ret == 0);
330 TEST_CHECK(e.dict_size() == 1);
331 lazy_entry* d = e.dict_find({"a\0b", 3});
332 TEST_CHECK(d);
333 TEST_EQUAL(d->type(), lazy_entry::int_t);
334 TEST_EQUAL(d->int_value(), 1);
335 }
336
337 // test strings with negative length-prefix
338 {
339 char b[] = "-10:foobar";
340 lazy_entry e;
341 error_code ec;
342 int ret = lazy_bdecode(b, b + sizeof(b)-1, e, ec);
343 TEST_CHECK(ret != 0);
344 std::printf("%s\n", print_entry(e).c_str());
345 TEST_EQUAL(ec, error_code(bdecode_errors::expected_value));
346 }
347
348 // test strings with overflow length-prefix
349 {
350 char b[] = "18446744073709551615:foobar";
351 lazy_entry e;
352 error_code ec;
353 int ret = lazy_bdecode(b, b + sizeof(b)-1, e, ec);
354 TEST_CHECK(ret != 0);
355 std::printf("%s\n", print_entry(e).c_str());
356 TEST_EQUAL(ec, error_code(bdecode_errors::overflow));
357 }
358
359 // test integers that don't fit in 64 bits
360 {
361 char b[] = "i18446744073709551615e";
362 lazy_entry e;
363 error_code ec;
364 int ret = lazy_bdecode(b, b + sizeof(b)-1, e, ec);
365 TEST_CHECK(ret == 0);
366 std::printf("%s\n", print_entry(e).c_str());
367 // the lazy aspect makes this overflow when asking for
368 // the value. turning it to zero.
369 TEST_CHECK(e.int_value() == 0);
370 }
371
372 // test integers that just exactly fit in 64 bits
373 {
374 char b[] = "i9223372036854775807e";
375 lazy_entry e;
376 error_code ec;
377 int ret = lazy_bdecode(b, b + sizeof(b)-1, e, ec);
378 TEST_CHECK(ret == 0);
379 std::printf("%s\n", print_entry(e).c_str());
380 TEST_CHECK(e.int_value() == 9223372036854775807LL);
381 }
382
383 // test integers that just exactly fit in 64 bits
384 {
385 char b[] = "i-9223372036854775807e";
386 lazy_entry e;
387 error_code ec;
388 int ret = lazy_bdecode(b, b + sizeof(b)-1, e, ec);
389 TEST_CHECK(ret == 0);
390 std::printf("%s\n", print_entry(e).c_str());
391 TEST_CHECK(e.int_value() == -9223372036854775807LL);
392 }
393
394 // test invalid encoding
395 {
396 unsigned char buf[] =
397 { 0x64, 0x31, 0x3a, 0x61, 0x64, 0x32, 0x3a, 0x69
398 , 0x64, 0x32, 0x30, 0x3a, 0x2a, 0x21, 0x19, 0x89
399 , 0x9f, 0xcd, 0x5f, 0xc9, 0xbc, 0x80, 0xc1, 0x76
400 , 0xfe, 0xe0, 0xc6, 0x84, 0x2d, 0xf6, 0xfc, 0xb8
401 , 0x39, 0x3a, 0x69, 0x6e, 0x66, 0x6f, 0x5f, 0x68
402 , 0x61, 0xae, 0x68, 0x32, 0x30, 0x3a, 0x14, 0x78
403 , 0xd5, 0xb0, 0xdc, 0xf6, 0x82, 0x42, 0x32, 0xa0
404 , 0xd6, 0x88, 0xeb, 0x48, 0x57, 0x01, 0x89, 0x40
405 , 0x4e, 0xbc, 0x65, 0x31, 0x3a, 0x71, 0x39, 0x3a
406 , 0x67, 0x65, 0x74, 0x5f, 0x70, 0x65, 0x65, 0x72
407 , 0x78, 0xff, 0x3a, 0x74, 0x38, 0x3a, 0xaa, 0xd4
408 , 0xa1, 0x88, 0x7a, 0x8d, 0xc3, 0xd6, 0x31, 0x3a
409 , 0x79, 0x31, 0xae, 0x71, 0x65, 0};
410
411 std::printf("%s\n", buf);
412 lazy_entry e;
413 error_code ec;
414 int ret = lazy_bdecode(reinterpret_cast<char*>(buf), reinterpret_cast<char*>(buf) + sizeof(buf), e, ec);
415 TEST_CHECK(ret == -1);
416 }
417
418 // test the depth limit
419 {
420 char b[2048];
421 for (int i = 0; i < 1024; ++i)
422 b[i]= 'l';
423
424 for (int i = 1024; i < 2048; ++i)
425 b[i]= 'e';
426
427 // 1024 levels nested lists
428
429 lazy_entry e;
430 error_code ec;
431 int ret = lazy_bdecode(b, b + sizeof(b), e, ec);
432 TEST_CHECK(ret != 0);
433 TEST_EQUAL(ec, error_code(bdecode_errors::depth_exceeded));
434 }
435
436 // test the item limit
437 {
438 char b[10240];
439 b[0] = 'l';
440 int i = 1;
441 for (i = 1; i < 10239; i += 2)
442 memcpy(&b[i], "0:", 2);
443 b[i] = 'e';
444
445 lazy_entry e;
446 error_code ec;
447 int ret = lazy_bdecode(b, b + i + 1, e, ec, nullptr, 1000, 1000);
448 TEST_CHECK(ret != 0);
449 TEST_EQUAL(ec, error_code(bdecode_errors::limit_exceeded));
450 }
451
452 // test unexpected EOF
453 {
454 char b[] = "l2:.."; // expected terminating 'e'
455
456 lazy_entry e;
457 error_code ec;
458 int ret = lazy_bdecode(b, b + sizeof(b)-1, e, ec, nullptr);
459 TEST_CHECK(ret != 0);
460 std::printf("%s\n", print_entry(e).c_str());
461 TEST_EQUAL(ec, error_code(bdecode_errors::unexpected_eof));
462 }
463
464 // test unexpected EOF (really expected terminator)
465 {
466 char b[] = "l2:..0"; // expected terminating 'e' instead of '0'
467
468 lazy_entry e;
469 error_code ec;
470 int ret = lazy_bdecode(b, b + sizeof(b)-1, e, ec, nullptr);
471 TEST_CHECK(ret != 0);
472 std::printf("%s\n", print_entry(e).c_str());
473 TEST_EQUAL(ec, error_code(bdecode_errors::unexpected_eof));
474 }
475
476 // test expected string
477 {
478 char b[] = "di2ei0ee";
479 // expected string (dict keys must be strings)
480
481 lazy_entry e;
482 error_code ec;
483 int ret = lazy_bdecode(b, b + sizeof(b)-1, e, ec, nullptr);
484 TEST_CHECK(ret != 0);
485 std::printf("%s\n", print_entry(e).c_str());
486 TEST_EQUAL(ec, error_code(bdecode_errors::expected_digit));
487 }
488
489 // test unexpected EOF while parsing dict key
490 {
491 char b[] = "d1000:..e";
492
493 lazy_entry e;
494 error_code ec;
495 int ret = lazy_bdecode(b, b + sizeof(b)-1, e, ec, nullptr);
496 TEST_CHECK(ret != 0);
497 std::printf("%s\n", print_entry(e).c_str());
498 TEST_EQUAL(ec, error_code(bdecode_errors::unexpected_eof));
499 }
500
501 // test unexpected EOF while parsing dict key
502 {
503 char b[] = "d1000:";
504
505 lazy_entry e;
506 error_code ec;
507 int ret = lazy_bdecode(b, b + sizeof(b)-1, e, ec, nullptr);
508 TEST_CHECK(ret != 0);
509 std::printf("%s\n", print_entry(e).c_str());
510 TEST_EQUAL(ec, error_code(bdecode_errors::unexpected_eof));
511 }
512
513 // test expected string while parsing dict key
514 {
515 char b[] = "df00:";
516
517 lazy_entry e;
518 error_code ec;
519 int ret = lazy_bdecode(b, b + sizeof(b)-1, e, ec, nullptr);
520 TEST_CHECK(ret != 0);
521 std::printf("%s\n", print_entry(e).c_str());
522 TEST_EQUAL(ec, error_code(bdecode_errors::expected_digit));
523 }
524
525 // test unexpected EOF while parsing int
526 {
527 char b[] = "i";
528
529 lazy_entry e;
530 error_code ec;
531 int ret = lazy_bdecode(b, b + sizeof(b)-1, e, ec, nullptr);
532 TEST_CHECK(ret != 0);
533 std::printf("%s\n", print_entry(e).c_str());
534 TEST_EQUAL(ec, error_code(bdecode_errors::unexpected_eof));
535 }
536
537 // test unexpected EOF while parsing int
538 {
539 char b[] = "i10";
540
541 lazy_entry e;
542 error_code ec;
543 int ret = lazy_bdecode(b, b + sizeof(b)-1, e, ec, nullptr);
544 TEST_CHECK(ret != 0);
545 std::printf("%s\n", print_entry(e).c_str());
546 TEST_EQUAL(ec, error_code(bdecode_errors::unexpected_eof));
547 }
548
549
550 // test expected colon
551 {
552 char b[] = "d1000";
553
554 lazy_entry e;
555 error_code ec;
556 int ret = lazy_bdecode(b, b + sizeof(b)-1, e, ec, nullptr);
557 TEST_CHECK(ret != 0);
558 std::printf("%s\n", print_entry(e).c_str());
559 TEST_EQUAL(ec, error_code(bdecode_errors::expected_colon));
560 }
561
562 // test empty string
563 {
564 char b[] = "";
565
566 lazy_entry e;
567 error_code ec;
568 int ret = lazy_bdecode(b, b + sizeof(b)-1, e, ec, nullptr);
569 TEST_EQUAL(ret, -1);
570 TEST_EQUAL(ec, error_code(bdecode_errors::unexpected_eof));
571 std::printf("%s\n", print_entry(e).c_str());
572 }
573
574 // test partial string
575 {
576 char b[] = "100:..";
577
578 lazy_entry e;
579 error_code ec;
580 int ret = lazy_bdecode(b, b + sizeof(b)-1, e, ec, nullptr);
581 TEST_CHECK(ret != 0);
582 std::printf("%s\n", print_entry(e).c_str());
583 TEST_EQUAL(ec, error_code(bdecode_errors::unexpected_eof));
584 }
585
586 // test pascal string dict
587 {
588 char b[] = "d6:foobar6:barfooe";
589
590 lazy_entry e;
591 error_code ec;
592 int ret = lazy_bdecode(b, b + sizeof(b)-1, e, ec, nullptr);
593 TEST_EQUAL(ret, 0);
594 std::printf("%s\n", print_entry(e).c_str());
595
596 pascal_string ps = e.dict_find_pstr("foobar");
597 TEST_EQUAL(std::memcmp(ps.ptr, "barfoo", std::size_t(ps.len)), 0);
598 TEST_EQUAL(ps.len, 6);
599
600 ps = e.dict_find_pstr("foobar2");
601 TEST_EQUAL(ps.ptr, static_cast<char const*>(nullptr));
602 TEST_EQUAL(ps.len, 0);
603 }
604
605 // test pascal string in list
606 {
607 char b[] = "l6:foobari4ee";
608
609 lazy_entry e;
610 error_code ec;
611 int ret = lazy_bdecode(b, b + sizeof(b)-1, e, ec, nullptr);
612 TEST_EQUAL(ret, 0);
613 std::printf("%s\n", print_entry(e).c_str());
614
615 TEST_EQUAL(e.list_size(), 2);
616 pascal_string ps = e.list_pstr_at(0);
617 TEST_EQUAL(std::memcmp(ps.ptr, "foobar", std::size_t(ps.len)), 0);
618 TEST_EQUAL(ps.len, 6);
619
620 ps = e.list_pstr_at(1);
621 TEST_EQUAL(ps.ptr, static_cast<char const*>(nullptr));
622 TEST_EQUAL(ps.len, 0);
623 }
624
625 {
626 unsigned char buf[] = { 0x44, 0x91, 0x3a };
627 error_code ec;
628 entry ent = bdecode({reinterpret_cast<char*>(buf), int(sizeof(buf))}, ec);
629 TEST_CHECK(ent == entry());
630 }
631
632 {
633 std::string buf;
634 buf += "l";
635 for (int i = 0; i < 1000; ++i)
636 {
637 char tmp[20];
638 std::snprintf(tmp, sizeof(tmp), "i%de", i);
639 buf += tmp;
640 }
641 buf += "e";
642
643 lazy_entry e;
644 error_code ec;
645 int ret = lazy_bdecode(buf.data(), buf.data() + buf.size(), e, ec);
646 TEST_EQUAL(ret, 0);
647 TEST_EQUAL(e.type(), lazy_entry::list_t);
648 TEST_EQUAL(e.list_size(), 1000);
649 for (int i = 0; i < 1000; ++i)
650 {
651 TEST_EQUAL(e.list_int_value_at(i), i);
652 }
653 }
654
655 {
656 std::string buf;
657 buf += "d";
658 for (int i = 0; i < 1000; ++i)
659 {
660 char tmp[30];
661 std::snprintf(tmp, sizeof(tmp), "4:%04di%de", i, i);
662 buf += tmp;
663 }
664 buf += "e";
665
666 std::printf("%s\n", buf.c_str());
667 lazy_entry e;
668 error_code ec;
669 int ret = lazy_bdecode(buf.data(), buf.data() + buf.size(), e, ec);
670 TEST_EQUAL(ret, 0);
671 TEST_EQUAL(e.type(), lazy_entry::dict_t);
672 TEST_EQUAL(e.dict_size(), 1000);
673 for (int i = 0; i < 1000; ++i)
674 {
675 char tmp[30];
676 std::snprintf(tmp, sizeof(tmp), "%04d", i);
677 TEST_EQUAL(e.dict_find_int_value(tmp), i);
678 }
679 }
680
681 // test parse_int
682 {
683 char b[] = "1234567890e";
684 std::int64_t val = 0;
685 bdecode_errors::error_code_enum ec = bdecode_errors::no_error;
686 char const* e = parse_int(b, b + sizeof(b)-1, 'e', val, ec);
687 TEST_CHECK(ec == bdecode_errors::no_error);
688 TEST_EQUAL(val, 1234567890);
689 TEST_EQUAL(e, b + sizeof(b) - 2);
690 }
691
692 // test invalid digit
693 {
694 char b[] = "0o";
695 std::int64_t val = 0;
696 bdecode_errors::error_code_enum ec;
697 char const* e = parse_int(b, b + sizeof(b)-1, 'e', val, ec);
698 TEST_EQUAL(ec, bdecode_errors::expected_digit);
699 TEST_EQUAL(e, b + 1);
700 }
701
702 {
703 char b[] = "9223372036854775808:";
704 std::int64_t val = 0;
705 bdecode_errors::error_code_enum ec;
706 char const* e = parse_int(b, b + sizeof(b)-1, ':', val, ec);
707 TEST_CHECK(ec == bdecode_errors::overflow);
708 TEST_EQUAL(e, b + 18);
709 }
710
711 {
712 char b[] = "928";
713 std::int64_t val = 0;
714 bdecode_errors::error_code_enum ec = bdecode_errors::no_error;
715 char const* e = parse_int(b, b + sizeof(b)-1, ':', val, ec);
716 TEST_CHECK(ec == bdecode_errors::no_error);
717 TEST_EQUAL(e, b + 3);
718 }
719
720 {
721 char const* b[] = {
722 "d1:a1919191010:11111",
723 "d2143289344:a4:aaaae",
724 "d214328934114:a4:aaaae",
725 "d9205357638345293824:a4:aaaae",
726 "d1:a9205357638345293824:11111",
727 };
728
729 for (int i = 0; i < int(sizeof(b)/sizeof(b[0])); ++i)
730 {
731 lazy_entry tmp;
732 error_code ec;
733 int ret = lazy_bdecode(b[i], b[i] + strlen(b[i]), tmp, ec, nullptr);
734 lazy_entry e;
735 e = std::move(tmp);
736 TEST_EQUAL(ret, -1);
737 TEST_CHECK(ec == error_code(bdecode_errors::unexpected_eof));
738 std::printf("%s\n", print_entry(e).c_str());
739
740 lazy_entry* moved = new lazy_entry(std::move(e));
741 delete moved;
742 }
743 }
744 }
745 #endif // TORRENT_ABI_VERSION
746