fix invalid read in parse_int() in bdecode_node() and lazy_bdecode()
This commit is contained in:
parent
50c2aee8ec
commit
fcb9c7b6f3
|
@ -1,3 +1,4 @@
|
||||||
|
* fix invalid read in parse_int in bdecoder
|
||||||
* fix issue with very long tracker- and web seed URLs
|
* fix issue with very long tracker- and web seed URLs
|
||||||
* don't attempt to create empty files on startup, if they already exist
|
* don't attempt to create empty files on startup, if they already exist
|
||||||
* fix force-recheck issue (new files would not be picked up)
|
* fix force-recheck issue (new files would not be picked up)
|
||||||
|
|
|
@ -126,10 +126,12 @@ namespace libtorrent
|
||||||
} // anonymous namespace
|
} // anonymous namespace
|
||||||
|
|
||||||
|
|
||||||
// fills in 'val' with what the string between start and the
|
// reads the string between start and end, or up to the first occurrance of
|
||||||
// first occurance of the delimiter is interpreted as an int.
|
// 'delimiter', whichever comes first. This string is interpreted as an
|
||||||
// return the pointer to the delimiter, or 0 if there is a
|
// integer which is assigned to 'val'. If there's a non-delimiter and
|
||||||
// parse error. val should be initialized to zero
|
// non-digit in the range, a parse error is reported in 'ec'. If the value
|
||||||
|
// cannot be represented by the variable 'val' and overflow error is reported
|
||||||
|
// by 'ec'.
|
||||||
char const* parse_int(char const* start, char const* end, char delimiter
|
char const* parse_int(char const* start, char const* end, char delimiter
|
||||||
, boost::int64_t& val, bdecode_errors::error_code_enum& ec)
|
, boost::int64_t& val, bdecode_errors::error_code_enum& ec)
|
||||||
{
|
{
|
||||||
|
@ -155,8 +157,6 @@ namespace libtorrent
|
||||||
val += digit;
|
val += digit;
|
||||||
++start;
|
++start;
|
||||||
}
|
}
|
||||||
if (*start != delimiter)
|
|
||||||
ec = bdecode_errors::expected_colon;
|
|
||||||
return start;
|
return start;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -618,16 +618,18 @@ namespace libtorrent
|
||||||
bdecode_token const& t = m_root_tokens[m_token_idx];
|
bdecode_token const& t = m_root_tokens[m_token_idx];
|
||||||
int size = m_root_tokens[m_token_idx + 1].offset - t.offset;
|
int size = m_root_tokens[m_token_idx + 1].offset - t.offset;
|
||||||
TORRENT_ASSERT(t.type == bdecode_token::integer);
|
TORRENT_ASSERT(t.type == bdecode_token::integer);
|
||||||
|
|
||||||
// +1 is to skip the 'i'
|
// +1 is to skip the 'i'
|
||||||
char const* ptr = m_buffer + t.offset + 1;
|
char const* ptr = m_buffer + t.offset + 1;
|
||||||
boost::int64_t val = 0;
|
boost::int64_t val = 0;
|
||||||
bool negative = false;
|
bool negative = false;
|
||||||
if (*ptr == '-') negative = true;
|
if (*ptr == '-') negative = true;
|
||||||
bdecode_errors::error_code_enum ec = bdecode_errors::no_error;
|
bdecode_errors::error_code_enum ec = bdecode_errors::no_error;
|
||||||
parse_int(ptr + negative
|
char const* end = parse_int(ptr + negative
|
||||||
, ptr + size, 'e', val, ec);
|
, ptr + size, 'e', val, ec);
|
||||||
if (ec) return 0;
|
if (ec) return 0;
|
||||||
|
TORRENT_UNUSED(end);
|
||||||
|
TORRENT_ASSERT(end < ptr + size);
|
||||||
if (negative) val = -val;
|
if (negative) val = -val;
|
||||||
return val;
|
return val;
|
||||||
}
|
}
|
||||||
|
@ -844,6 +846,8 @@ namespace libtorrent
|
||||||
start = parse_int(start, end, ':', len, e);
|
start = parse_int(start, end, ':', len, e);
|
||||||
if (e)
|
if (e)
|
||||||
TORRENT_FAIL_BDECODE(e);
|
TORRENT_FAIL_BDECODE(e);
|
||||||
|
if (start == end)
|
||||||
|
TORRENT_FAIL_BDECODE(bdecode_errors::expected_colon);
|
||||||
|
|
||||||
// remaining buffer size excluding ':'
|
// remaining buffer size excluding ':'
|
||||||
const ptrdiff_t buff_size = end - start - 1;
|
const ptrdiff_t buff_size = end - start - 1;
|
||||||
|
|
|
@ -131,6 +131,8 @@ namespace libtorrent
|
||||||
start = parse_int(start, end, ':', len, e);
|
start = parse_int(start, end, ':', len, e);
|
||||||
if (e)
|
if (e)
|
||||||
TORRENT_FAIL_BDECODE(e);
|
TORRENT_FAIL_BDECODE(e);
|
||||||
|
if (start == end)
|
||||||
|
TORRENT_FAIL_BDECODE(bdecode_errors::expected_colon);
|
||||||
|
|
||||||
// remaining buffer size excluding ':'
|
// remaining buffer size excluding ':'
|
||||||
const ptrdiff_t buff_size = end - start - 1;
|
const ptrdiff_t buff_size = end - start - 1;
|
||||||
|
@ -203,6 +205,8 @@ namespace libtorrent
|
||||||
start = parse_int(start, end, ':', len, e);
|
start = parse_int(start, end, ':', len, e);
|
||||||
if (e)
|
if (e)
|
||||||
TORRENT_FAIL_BDECODE(e);
|
TORRENT_FAIL_BDECODE(e);
|
||||||
|
if (start == end)
|
||||||
|
TORRENT_FAIL_BDECODE(bdecode_errors::expected_colon);
|
||||||
|
|
||||||
// remaining buffer size excluding ':'
|
// remaining buffer size excluding ':'
|
||||||
const ptrdiff_t buff_size = end - start - 1;
|
const ptrdiff_t buff_size = end - start - 1;
|
||||||
|
|
|
@ -715,8 +715,9 @@ TORRENT_TEST(parse_int)
|
||||||
{
|
{
|
||||||
char b[] = "1234567890e";
|
char b[] = "1234567890e";
|
||||||
boost::int64_t val = 0;
|
boost::int64_t val = 0;
|
||||||
bdecode_errors::error_code_enum ec;
|
bdecode_errors::error_code_enum ec = bdecode_errors::no_error;
|
||||||
char const* e = parse_int(b, b + sizeof(b)-1, 'e', val, ec);
|
char const* e = parse_int(b, b + sizeof(b)-1, 'e', val, ec);
|
||||||
|
TEST_EQUAL(ec, bdecode_errors::no_error);
|
||||||
TEST_EQUAL(val, 1234567890);
|
TEST_EQUAL(val, 1234567890);
|
||||||
TEST_EQUAL(e, b + sizeof(b) - 2);
|
TEST_EQUAL(e, b + sizeof(b) - 2);
|
||||||
}
|
}
|
||||||
|
@ -759,7 +760,7 @@ TORRENT_TEST(parse_length_overflow)
|
||||||
bdecode_node e;
|
bdecode_node e;
|
||||||
int ret = bdecode(b[i], b[i] + strlen(b[i]), e, ec);
|
int ret = bdecode(b[i], b[i] + strlen(b[i]), e, ec);
|
||||||
TEST_EQUAL(ret, -1);
|
TEST_EQUAL(ret, -1);
|
||||||
TEST_CHECK(ec == error_code(bdecode_errors::unexpected_eof));
|
TEST_EQUAL(ec, error_code(bdecode_errors::unexpected_eof));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -768,9 +769,9 @@ TORRENT_TEST(expected_colon_string)
|
||||||
{
|
{
|
||||||
char b[] = "928";
|
char b[] = "928";
|
||||||
boost::int64_t val = 0;
|
boost::int64_t val = 0;
|
||||||
bdecode_errors::error_code_enum ec;
|
bdecode_errors::error_code_enum ec = bdecode_errors::no_error;
|
||||||
char const* e = parse_int(b, b + sizeof(b)-1, ':', val, ec);
|
char const* e = parse_int(b, b + sizeof(b)-1, ':', val, ec);
|
||||||
TEST_EQUAL(ec, bdecode_errors::expected_colon);
|
TEST_EQUAL(ec, bdecode_errors::no_error);
|
||||||
TEST_EQUAL(e, b + 3);
|
TEST_EQUAL(e, b + 3);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1253,6 +1254,21 @@ TORRENT_TEST(partial_parse4)
|
||||||
TEST_EQUAL(print_entry(e), "{ 'a': 1, 'b': 'foo', 'c': [ 1 ] }");
|
TEST_EQUAL(print_entry(e), "{ 'a': 1, 'b': 'foo', 'c': [ 1 ] }");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TORRENT_TEST(partial_parse_string)
|
||||||
|
{
|
||||||
|
// it's important to not have a null terminator here
|
||||||
|
// to allow address sanitizer to trigger in case the decoder reads past the
|
||||||
|
// end
|
||||||
|
char b[] = { '5', '5'};
|
||||||
|
|
||||||
|
bdecode_node e;
|
||||||
|
error_code ec;
|
||||||
|
int pos;
|
||||||
|
int ret = bdecode(b, b + sizeof(b), e, ec, &pos);
|
||||||
|
TEST_EQUAL(ret, -1);
|
||||||
|
TEST_EQUAL(pos, 2);
|
||||||
|
}
|
||||||
|
|
||||||
// test switch_underlying_buffer
|
// test switch_underlying_buffer
|
||||||
TORRENT_TEST(switch_buffer)
|
TORRENT_TEST(switch_buffer)
|
||||||
{
|
{
|
||||||
|
|
|
@ -587,8 +587,9 @@ TORRENT_TEST(lazy_entry)
|
||||||
{
|
{
|
||||||
char b[] = "1234567890e";
|
char b[] = "1234567890e";
|
||||||
boost::int64_t val = 0;
|
boost::int64_t val = 0;
|
||||||
bdecode_errors::error_code_enum ec;
|
bdecode_errors::error_code_enum ec = bdecode_errors::no_error;
|
||||||
char const* e = parse_int(b, b + sizeof(b)-1, 'e', val, ec);
|
char const* e = parse_int(b, b + sizeof(b)-1, 'e', val, ec);
|
||||||
|
TEST_CHECK(ec == bdecode_errors::no_error);
|
||||||
TEST_EQUAL(val, 1234567890);
|
TEST_EQUAL(val, 1234567890);
|
||||||
TEST_EQUAL(e, b + sizeof(b) - 2);
|
TEST_EQUAL(e, b + sizeof(b) - 2);
|
||||||
}
|
}
|
||||||
|
@ -615,9 +616,9 @@ TORRENT_TEST(lazy_entry)
|
||||||
{
|
{
|
||||||
char b[] = "928";
|
char b[] = "928";
|
||||||
boost::int64_t val = 0;
|
boost::int64_t val = 0;
|
||||||
bdecode_errors::error_code_enum ec;
|
bdecode_errors::error_code_enum ec = bdecode_errors::no_error;
|
||||||
char const* e = parse_int(b, b + sizeof(b)-1, ':', val, ec);
|
char const* e = parse_int(b, b + sizeof(b)-1, ':', val, ec);
|
||||||
TEST_CHECK(ec == bdecode_errors::expected_colon);
|
TEST_CHECK(ec == bdecode_errors::no_error);
|
||||||
TEST_EQUAL(e, b + 3);
|
TEST_EQUAL(e, b + 3);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue