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