arvidn / libtorrent

an efficient feature complete C++ bittorrent implementation

Home Page:http://libtorrent.org

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Force-check of a completed torrent with broken files sometimes causes nullptr dereference

grechnik opened this issue · comments

libtorrent version (or branch): 2.0.5.0 [part of qBittorrent v4.4.1]

platform/architecture: Windows 64-bit

compiler and compiler version: [whatever qBittorrent uses]

  1. Create a 100M file filled with zeroes head -c 104857600 /dev/zero > zero (it seems that the content does not actually matter, zeroes are easy to generate).
  2. Create a v1 torrent for this file. I have attached my torrent for the reference: zero.torrent.zip
  3. "Download" it to verify against the local file to obtain .fastresume marking it as complete.
  4. Break the local file by changing the first byte to 1 (while keeping the size).
  5. Force-check the torrent.
    Expected behaviour: the torrent should be marked as incomplete with first block missing.
    Actual behaviour: the code crashes
(3b88.2184): Access violation - code c0000005 (first chance)
First chance exceptions are reported before any exception handling.
This exception may be expected and handled.
qbittorrent!std::vector<libtorrent::piece_picker::piece_pos,std::allocator<libtorrent::piece_picker::piece_pos> >::operator[] [inlined in qbittorrent!libtorrent::torrent::on_piece_hashed+0x6f4]:
00007ff6`a11b9634 488b00          mov     rax,qword ptr [rax] ds:00000000`00000000=????????????????
 # Child-SP          RetAddr               Call Site
00 (Inline Function) --------`--------     qbittorrent!std::vector<libtorrent::piece_picker::piece_pos,std::allocator<libtorrent::piece_picker::piece_pos> >::operator[](void) [c:\program files (x86)\microsoft visual studio\2017\community\vc\tools\msvc\14.16.27023\include\vector @ 1736] 
01 (Inline Function) --------`--------     qbittorrent!libtorrent::aux::container_wrapper<libtorrent::piece_picker::piece_pos,libtorrent::aux::strong_typedef<int,libtorrent::aux::piece_index_tag,void>,std::vector<libtorrent::piece_picker::piece_pos,std::allocator<libtorrent::piece_picker::piece_pos> > >::operator[](void) [g:\qbittorrent\libtorrent\include\libtorrent\aux_\container_wrapper.hpp @ 75] 
02 (Inline Function) --------`--------     qbittorrent!libtorrent::torrent::on_piece_hashed(void)+0x6f4 [g:\qbittorrent\libtorrent\src\piece_picker.cpp @ 2544] 
03 000000c1`661ff2e0 00007ff6`a11e4e42     qbittorrent!libtorrent::torrent::on_piece_hashed(struct libtorrent::aux::container_wrapper<libtorrent::digest32<256>,int,std::vector<libtorrent::digest32<256>,std::allocator<libtorrent::digest32<256> > > > * block_hashes = 0x000000c1`661ff570, struct libtorrent::aux::strong_typedef<int,libtorrent::aux::piece_index_tag,void> piece = struct libtorrent::aux::strong_typedef<int,libtorrent::aux::piece_index_tag,void>, class libtorrent::digest32<160> * piece_hash = 0x000001d2`0608f1f8, struct libtorrent::storage_error * error = 0x000001d2`0608f1d8)+0x6f4 [g:\qbittorrent\libtorrent\src\torrent.cpp @ 2481] 
04 (Inline Function) --------`--------     qbittorrent!libtorrent::torrent::start_checking::__l14::<lambda_613e5e3954c0b09f5b594b162c6c2e6b>::operator()(void)+0x45 [g:\qbittorrent\libtorrent\src\torrent.cpp @ 2346] 
05 (Inline Function) --------`--------     qbittorrent!std::_Invoker_functor::_Call(void)+0x45
06 (Inline Function) --------`--------     qbittorrent!std::invoke(void)+0x45
07 (Inline Function) --------`--------     qbittorrent!std::_Invoker_ret<void,1>::_Call(void)+0x45
08 000000c1`661ff540 00007ff6`a12a62e5     qbittorrent!std::_Func_impl_no_alloc<<lambda_613e5e3954c0b09f5b594b162c6c2e6b>,void,libtorrent::aux::strong_typedef<int,libtorrent::aux::piece_index_tag,void>,libtorrent::digest32<160> const &,libtorrent::storage_error const &>::_Do_call(struct libtorrent::aux::strong_typedef<int,libtorrent::aux::piece_index_tag,void> * <_Args_0> = <Value unavailable error>, class libtorrent::digest32<160> * <_Args_1> = <Value unavailable error>, struct libtorrent::storage_error * <_Args_2> = <Value unavailable error>)+0x52
09 000000c1`661ff5a0 00007ff6`a11a8d5c     qbittorrent!boost::variant<std::function<void __cdecl(struct libtorrent::aux::`anonymous-namespace'::caller_visitor * visitor = 0x000000c1`661ff8e0)+0x135 [g:\qbittorrent\boost_1_78_0\boost\variant\variant.hpp @ 2394] 
0a (Inline Function) --------`--------     qbittorrent!boost::apply_visitor(void)+0xd [g:\qbittorrent\boost_1_78_0\boost\variant\detail\apply_visitor_unary.hpp @ 68] 
0b (Inline Function) --------`--------     qbittorrent!libtorrent::aux::mmap_disk_job::call_callback(void)+0x19 [g:\qbittorrent\libtorrent\src\mmap_disk_job.cpp @ 133] 
0c 000000c1`661ff630 00007ff6`a11ac71f     qbittorrent!libtorrent::mmap_disk_io::call_job_handlers(void)+0xec [g:\qbittorrent\libtorrent\src\mmap_disk_io.cpp @ 1833] 
0d (Inline Function) --------`--------     qbittorrent!libtorrent::mmap_disk_io::job_fail_add::__l5::<lambda_ed543268652c4975f02558337c7c75f2>::operator()(void)+0x8 [g:\qbittorrent\libtorrent\src\mmap_disk_io.cpp @ 1342] 
0e (Inline Function) --------`--------     qbittorrent!boost::asio::detail::binder0<<lambda_ed543268652c4975f02558337c7c75f2> >::operator()(void)+0x8 [g:\qbittorrent\boost_1_78_0\boost\asio\detail\bind_handler.hpp @ 60] 
0f (Inline Function) --------`--------     qbittorrent!boost_asio_handler_invoke_helpers::invoke(void)+0x8 [g:\qbittorrent\boost_1_78_0\boost\asio\detail\handler_invoke_helpers.hpp @ 51] 
10 000000c1`661ff8e0 00007ff6`a10f14c8     qbittorrent!boost::asio::detail::executor_op<boost::asio::detail::binder0<<lambda_ed543268652c4975f02558337c7c75f2> >,std::allocator<void>,boost::asio::detail::win_iocp_operation>::do_complete(void * owner = 0x000001d2`679d6bd0, class boost::asio::detail::win_iocp_operation * base = <Value unavailable error>, class boost::system::error_code * __formal = 0x00000000`00000000, unsigned int64 __formal = 0x000001d2`0972f250)+0x4f [g:\qbittorrent\boost_1_78_0\boost\asio\detail\executor_op.hpp @ 70] 
11 (Inline Function) --------`--------     qbittorrent!boost::asio::detail::win_iocp_operation::complete(unsigned int64 bytes_transferred = <Value unavailable error>)+0x15 [g:\qbittorrent\boost_1_78_0\boost\asio\detail\win_iocp_operation.hpp @ 47] 
12 000000c1`661ff940 00007ff6`a10f0cff     qbittorrent!boost::asio::detail::win_iocp_io_context::do_one(struct boost::asio::detail::win_iocp_thread_info * this_thread = 0x000000c1`661ffb10, class boost::system::error_code * ec = 0x000000c1`661ffbc0)+0x418 [g:\qbittorrent\boost_1_78_0\boost\asio\detail\impl\win_iocp_io_context.ipp @ 474] 
13 000000c1`661ffac0 00007ff6`a10f186c     qbittorrent!boost::asio::detail::win_iocp_io_context::run(class boost::system::error_code * ec = 0x000000c1`661ffbc0)+0x10f [g:\qbittorrent\boost_1_78_0\boost\asio\detail\impl\win_iocp_io_context.ipp @ 204] 
14 000000c1`661ffba0 00007ff6`a10f3067     qbittorrent!boost::asio::io_context::run(void)+0x2c [g:\qbittorrent\boost_1_78_0\boost\asio\impl\io_context.ipp @ 64] 
15 (Inline Function) --------`--------     qbittorrent!libtorrent::session::start::__l17::<lambda_fbeb383e937d466d9daca3d775268279>::operator()(void)+0x14 [g:\qbittorrent\libtorrent\src\session.cpp @ 344] 
16 (Inline Function) --------`--------     qbittorrent!std::_Invoker_functor::_Call(void)+0x14 [c:\program files (x86)\microsoft visual studio\2017\community\vc\tools\msvc\14.16.27023\include\thr\xthread @ 230] 
17 (Inline Function) --------`--------     qbittorrent!std::invoke(void)+0x14 [c:\program files (x86)\microsoft visual studio\2017\community\vc\tools\msvc\14.16.27023\include\thr\xthread @ 230] 
18 (Inline Function) --------`--------     qbittorrent!std::_LaunchPad<std::unique_ptr<std::tuple<<lambda_fbeb383e937d466d9daca3d775268279> >,std::default_delete<std::tuple<<lambda_fbeb383e937d466d9daca3d775268279> > > > >::_Execute(void)+0x14 [c:\program files (x86)\microsoft visual studio\2017\community\vc\tools\msvc\14.16.27023\include\thr\xthread @ 238] 
19 (Inline Function) --------`--------     qbittorrent!std::_LaunchPad<std::unique_ptr<std::tuple<<lambda_fbeb383e937d466d9daca3d775268279> >,std::default_delete<std::tuple<<lambda_fbeb383e937d466d9daca3d775268279> > > > >::_Run(void)+0x25 [c:\program files (x86)\microsoft visual studio\2017\community\vc\tools\msvc\14.16.27023\include\thr\xthread @ 245] 
1a 000000c1`661ffbf0 00007ff6`a10efd99     qbittorrent!std::_LaunchPad<std::unique_ptr<std::tuple<<lambda_fbeb383e937d466d9daca3d775268279> >,std::default_delete<std::tuple<<lambda_fbeb383e937d466d9daca3d775268279> > > > >::_Go(void)+0x47 [c:\program files (x86)\microsoft visual studio\2017\community\vc\tools\msvc\14.16.27023\include\thr\xthread @ 230] 
1b 000000c1`661ffc30 00007ff6`a1c63e00     qbittorrent!std::_Pad::_Call_func(void * _Data = <Value unavailable error>)+0x19 [c:\program files (x86)\microsoft visual studio\2017\community\vc\tools\msvc\14.16.27023\include\thr\xthread @ 209] 
1c (Inline Function) --------`--------     qbittorrent!invoke_thread_procedure(void)+0xd [minkernel\crts\ucrt\src\appcrt\startup\thread.cpp @ 91] 
1d 000000c1`661ffc60 00007ffc`269e7034     qbittorrent!thread_start<unsigned int (void * parameter = 0x000001d2`67a08ba0)+0x50 [minkernel\crts\ucrt\src\appcrt\startup\thread.cpp @ 115] 
1e 000000c1`661ffc90 00007ffc`27a62651     KERNEL32!BaseThreadInitThunk+0x14
1f 000000c1`661ffcc0 00000000`00000000     ntdll!RtlUserThreadStart+0x21

thanks for the report! I believe this fixes it: #6852