make bdecoder more robust when encountering errors (leave the resulting tree consistent)
This commit is contained in:
parent
be339c244f
commit
c384d00dbf
|
@ -155,6 +155,7 @@ namespace libtorrent
|
|||
}
|
||||
|
||||
lazy_entry* dict_append(char const* name);
|
||||
void pop();
|
||||
lazy_entry* dict_find(char const* name);
|
||||
lazy_entry const* dict_find(char const* name) const
|
||||
{ return const_cast<lazy_entry*>(this)->dict_find(name); }
|
||||
|
|
|
@ -51,6 +51,12 @@ namespace libtorrent
|
|||
#define TORRENT_FAIL_BDECODE(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; \
|
||||
return -1; \
|
||||
}
|
||||
|
@ -176,7 +182,11 @@ namespace libtorrent
|
|||
}
|
||||
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';
|
||||
start = parse_int(start, end, ':', len);
|
||||
|
@ -234,6 +244,11 @@ namespace libtorrent
|
|||
return &ret.val;
|
||||
}
|
||||
|
||||
void lazy_entry::pop()
|
||||
{
|
||||
if (m_size > 0) --m_size;
|
||||
}
|
||||
|
||||
namespace
|
||||
{
|
||||
// the number of decimal digits needed
|
||||
|
|
|
@ -499,6 +499,21 @@ int test_main()
|
|||
fprintf(stderr, "%s\n", error_string);
|
||||
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
|
||||
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
|
||||
|
|
Loading…
Reference in New Issue