make bdecoder more robust when encountering errors (leave the resulting tree consistent)

This commit is contained in:
Arvid Norberg 2012-02-10 04:19:11 +00:00
parent be339c244f
commit c384d00dbf
3 changed files with 32 additions and 1 deletions

View File

@ -155,6 +155,7 @@ namespace libtorrent
} }
lazy_entry* dict_append(char const* name); lazy_entry* dict_append(char const* name);
void pop();
lazy_entry* dict_find(char const* name); lazy_entry* dict_find(char const* name);
lazy_entry const* dict_find(char const* name) const lazy_entry const* dict_find(char const* name) const
{ return const_cast<lazy_entry*>(this)->dict_find(name); } { return const_cast<lazy_entry*>(this)->dict_find(name); }

View File

@ -51,6 +51,12 @@ namespace libtorrent
#define TORRENT_FAIL_BDECODE(code) \ #define TORRENT_FAIL_BDECODE(code) \
{ \ { \
ec = code; \ ec = code; \
while (!stack.empty()) { \
top = stack.back(); \
fprintf(stderr, "top->type: %d\n", top->type()); \
if (top->type() == lazy_entry::dict_t || top->type() == lazy_entry::list_t) top->pop(); \
stack.pop_back(); \
} \
if (error_pos) *error_pos = start - orig_start; \ if (error_pos) *error_pos = start - orig_start; \
return -1; \ return -1; \
} }
@ -176,7 +182,11 @@ namespace libtorrent
} }
default: default:
{ {
if (!is_digit(t)) TORRENT_FAIL_BDECODE(errors::expected_value); if (!is_digit(t))
{
int a = 0;
TORRENT_FAIL_BDECODE(errors::expected_value);
}
boost::int64_t len = t - '0'; boost::int64_t len = t - '0';
start = parse_int(start, end, ':', len); start = parse_int(start, end, ':', len);
@ -234,6 +244,11 @@ namespace libtorrent
return &ret.val; return &ret.val;
} }
void lazy_entry::pop()
{
if (m_size > 0) --m_size;
}
namespace namespace
{ {
// the number of decimal digits needed // the number of decimal digits needed

View File

@ -499,6 +499,21 @@ int test_main()
fprintf(stderr, "%s\n", error_string); fprintf(stderr, "%s\n", error_string);
TEST_EQUAL(error_string, std::string("missing 'C2' key")); TEST_EQUAL(error_string, std::string("missing 'C2' key"));
// test empty strings [ { "":1 }, "" ]
char const test_msg6[] = "ld0:i1ee0:e";
lazy_bdecode(test_msg6, test_msg6 + sizeof(test_msg6)-1, ent, ec);
fprintf(stderr, "%s\n", print_entry(ent).c_str());
TEST_CHECK(ent.type() == lazy_entry::list_t);
if (ent.type() == lazy_entry::list_t)
{
TEST_CHECK(ent.list_size() == 2);
if (ent.list_size() == 2)
{
TEST_CHECK(ent.list_at(0)->dict_find_int_value("") == 1);
TEST_CHECK(ent.list_at(1)->string_value() == "");
}
}
// test external ip voting // test external ip voting
aux::session_impl* ses = new aux::session_impl(std::pair<int, int>(0,0) aux::session_impl* ses = new aux::session_impl(std::pair<int, int>(0,0)
, fingerprint("LT", 0, 0, 0, 0), "0.0.0.0", 0 , fingerprint("LT", 0, 0, 0, 0), "0.0.0.0", 0