// return 0 = success int lazy_bdecode(char const* start, char const* end, lazy_entry& ret , error_code& ec, int* error_pos, int depth_limit, int item_limit) { char const* const orig_start = start; ret.clear(); std::vector<lazy_entry*> stack; if (start == end) TORRENT_FAIL_BDECODE(bdecode_errors::unexpected_eof); stack.push_back(&ret); while (start <= end) { if (stack.empty()) break; // done! lazy_entry* top = stack.back(); if (int(stack.size()) > depth_limit) TORRENT_FAIL_BDECODE(bdecode_errors::depth_exceeded); if (start >= end) TORRENT_FAIL_BDECODE(bdecode_errors::unexpected_eof); char t = *start; ++start; if (start >= end && t != 'e') TORRENT_FAIL_BDECODE(bdecode_errors::unexpected_eof); switch (top->type()) { case lazy_entry::dict_t: { if (t == 'e') { top->set_end(start); stack.pop_back(); continue; } if (!numeric(t)) TORRENT_FAIL_BDECODE(bdecode_errors::expected_digit); std::int64_t len = t - '0'; bdecode_errors::error_code_enum e = bdecode_errors::no_error; start = parse_int(start, end, ':', len, e); if (e) TORRENT_FAIL_BDECODE(e); // remaining buffer size excluding ':' const ptrdiff_t buff_size = end - start - 1; if (len > buff_size) TORRENT_FAIL_BDECODE(bdecode_errors::unexpected_eof); if (len < 0) TORRENT_FAIL_BDECODE(bdecode_errors::overflow); ++start; if (start == end) TORRENT_FAIL_BDECODE(bdecode_errors::unexpected_eof); lazy_entry* ent = top->dict_append(start); if (ent == nullptr) TORRENT_FAIL_BDECODE(boost::system::errc::not_enough_memory); start += len; if (start >= end) TORRENT_FAIL_BDECODE(bdecode_errors::unexpected_eof); stack.push_back(ent); t = *start; ++start; break; } case lazy_entry::list_t: { if (t == 'e') { top->set_end(start); stack.pop_back(); continue; } lazy_entry* ent = top->list_append(); if (ent == nullptr) TORRENT_FAIL_BDECODE(boost::system::errc::not_enough_memory); stack.push_back(ent); break; } case lazy_entry::int_t: case lazy_entry::string_t: case lazy_entry::none_t: break; } --item_limit; if (item_limit <= 0) TORRENT_FAIL_BDECODE(bdecode_errors::limit_exceeded); top = stack.back(); switch (t) { case 'd': top->construct_dict(start - 1); break; case 'l': top->construct_list(start - 1); break; case 'i': { char const* int_start = start; start = find_char(start, end, 'e'); top->construct_int(int_start, start - int_start); if (start == end) TORRENT_FAIL_BDECODE(bdecode_errors::unexpected_eof); TORRENT_ASSERT(*start == 'e'); ++start; stack.pop_back(); break; } default: { if (!numeric(t)) TORRENT_FAIL_BDECODE(bdecode_errors::expected_value); std::int64_t len = t - '0'; bdecode_errors::error_code_enum e = bdecode_errors::no_error; start = parse_int(start, end, ':', len, e); if (e) TORRENT_FAIL_BDECODE(e); // remaining buffer size excluding ':' const ptrdiff_t buff_size = end - start - 1; if (len > buff_size) TORRENT_FAIL_BDECODE(bdecode_errors::unexpected_eof); if (len < 0) TORRENT_FAIL_BDECODE(bdecode_errors::overflow); ++start; if (start == end) TORRENT_FAIL_BDECODE(bdecode_errors::unexpected_eof); top->construct_string(start, int(len)); start += len; stack.pop_back(); break; } } } return 0; }
// return 0 = success int lazy_bdecode(char const* start, char const* end, lazy_entry& ret , error_code& ec, int* error_pos, int depth_limit, int item_limit) { char const* const orig_start = start; ret.clear(); if (start == end) return 0; std::vector<lazy_entry*> stack; stack.push_back(&ret); while (start < end) { if (stack.empty()) break; // done! lazy_entry* top = stack.back(); if (int(stack.size()) > depth_limit) TORRENT_FAIL_BDECODE(errors::depth_exceeded); if (start >= end) TORRENT_FAIL_BDECODE(errors::unexpected_eof); char t = *start; ++start; if (start >= end && t != 'e') TORRENT_FAIL_BDECODE(errors::unexpected_eof); switch (top->type()) { case lazy_entry::dict_t: { if (t == 'e') { top->set_end(start); stack.pop_back(); continue; } if (!is_digit(t)) TORRENT_FAIL_BDECODE(errors::expected_string); boost::int64_t len = t - '0'; start = parse_int(start, end, ':', len); if (start == 0 || start + len + 3 > end || *start != ':') TORRENT_FAIL_BDECODE(errors::expected_colon); ++start; if (start == end) TORRENT_FAIL_BDECODE(errors::unexpected_eof); lazy_entry* ent = top->dict_append(start); if (ent == 0) TORRENT_FAIL_BDECODE(errors::no_memory); start += len; if (start >= end) TORRENT_FAIL_BDECODE(errors::unexpected_eof); stack.push_back(ent); t = *start; ++start; break; } case lazy_entry::list_t: { if (t == 'e') { top->set_end(start); stack.pop_back(); continue; } lazy_entry* ent = top->list_append(); if (ent == 0) TORRENT_FAIL_BDECODE(errors::no_memory); stack.push_back(ent); break; } default: break; } --item_limit; if (item_limit <= 0) TORRENT_FAIL_BDECODE(errors::limit_exceeded); top = stack.back(); switch (t) { case 'd': top->construct_dict(start - 1); continue; case 'l': top->construct_list(start - 1); continue; case 'i': { char const* int_start = start; start = find_char(start, end, 'e'); top->construct_int(int_start, start - int_start); if (start == end) TORRENT_FAIL_BDECODE(errors::unexpected_eof); TORRENT_ASSERT(*start == 'e'); ++start; stack.pop_back(); continue; } default: { if (!is_digit(t)) TORRENT_FAIL_BDECODE(errors::expected_value); boost::int64_t len = t - '0'; start = parse_int(start, end, ':', len); if (start == 0 || start + len + 1 > end || *start != ':') TORRENT_FAIL_BDECODE(errors::expected_colon); ++start; top->construct_string(start, int(len)); stack.pop_back(); start += len; continue; } } return 0; } return 0; }
// return 0 = success int lazy_bdecode(char const* start, char const* end, lazy_entry& ret, int depth_limit) { ret.clear(); if (start == end) return 0; std::vector<lazy_entry*> stack; stack.push_back(&ret); while (start < end) { if (stack.empty()) break; // done! lazy_entry* top = stack.back(); if (int(stack.size()) > depth_limit) return fail_bdecode(ret); if (start >= end) return fail_bdecode(ret); char t = *start; ++start; if (start >= end && t != 'e') return fail_bdecode(ret); switch (top->type()) { case lazy_entry::dict_t: { if (t == 'e') { top->set_end(start); stack.pop_back(); continue; } boost::int64_t len = t - '0'; start = parse_int(start, end, ':', len); if (start == 0 || start + len + 3 > end || *start != ':') return fail_bdecode(ret); ++start; if (start == end) fail_bdecode(ret); lazy_entry* ent = top->dict_append(start); start += len; if (start >= end) fail_bdecode(ret); stack.push_back(ent); t = *start; ++start; break; } case lazy_entry::list_t: { if (t == 'e') { top->set_end(start); stack.pop_back(); continue; } lazy_entry* ent = top->list_append(); stack.push_back(ent); break; } default: break; } top = stack.back(); switch (t) { case 'd': top->construct_dict(start - 1); continue; case 'l': top->construct_list(start - 1); continue; case 'i': { char const* int_start = start; start = find_char(start, end, 'e'); top->construct_int(int_start, start - int_start); if (start == end) return fail_bdecode(ret); TORRENT_ASSERT(*start == 'e'); ++start; stack.pop_back(); continue; } default: { if (!is_digit(t)) return fail_bdecode(ret); boost::int64_t len = t - '0'; start = parse_int(start, end, ':', len); if (start == 0 || start + len + 1 > end || *start != ':') return fail_bdecode(ret); ++start; top->construct_string(start, int(len)); stack.pop_back(); start += len; continue; } } return 0; } return 0; }