Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

bencoded item count limit exceeded #3037

Closed
2 tasks done
pimlie opened this issue Jul 9, 2017 · 14 comments · Fixed by #7015
Closed
2 tasks done

bencoded item count limit exceeded #3037

pimlie opened this issue Jul 9, 2017 · 14 comments · Fixed by #7015
Assignees
Milestone

Comments

@pimlie
Copy link

pimlie commented Jul 9, 2017

  • I have read CONTRIBUTING.rst

  • I have tried with the latest pre-release version and I still can reproduce the issue.

Tribler version/branch+revision:

$ git status
On branch next
Your branch is up-to-date with 'origin/next'.
nothing to commit, working directory clean
$ git show
commit bc8991f
Merge: fe5e6be 521a0af
Date: Wed Jun 21 13:30:50 2017 +0200

Operating system and version:

Ubuntu 16.04

Could not find any issues yet with this message. I was adding a torrent and suddenly Tribler crashed with the following error. The torrent is from a private tracker which I cant share unfortunately, but it consists of a lot of small files (the torrent file is ~25MB in size).

Traceback (most recent call last):
  File "/opt/tribler/TriblerGUI/event_request_manager.py", line 99, in on_read_data
    raise RuntimeError(json_dict["event"]["text"])
RuntimeError: Unhandled Error
Traceback (most recent call last):
  File "/usr/lib/python2.7/multiprocessing/process.py", line 114, in run
    self._target(*self._args, **self._kwargs)
  File "/opt/tribler/TriblerGUI/core_manager.py", line 63, in start_tribler_core
    reactor.run()
  File "/usr/lib/python2.7/dist-packages/twisted/internet/base.py", line 1194, in run
    self.mainLoop()
  File "/usr/lib/python2.7/dist-packages/twisted/internet/base.py", line 1203, in mainLoop
    self.runUntilCurrent()
--- <exception caught here> ---
  File "/usr/lib/python2.7/dist-packages/twisted/internet/base.py", line 825, in runUntilCurrent
    call.func(*call.args, **call.kw)
  File "/opt/tribler/Tribler/Core/Libtorrent/LibtorrentDownloadImpl.py", line 240, in schedule_create_engine
    self.pstate_for_restart, share_mode=share_mode)
  File "/opt/tribler/Tribler/Core/Libtorrent/LibtorrentDownloadImpl.py", line 314, in network_create_engine_wrapper
    torrentinfo = lt.torrent_info(metainfo)
exceptions.RuntimeError: bencoded item count limit exceeded
@qstokkink qstokkink added this to the V7.0 milestone Jul 9, 2017
@qstokkink
Copy link
Contributor

qstokkink commented Aug 22, 2017

According to the libtorrent docs, the bencoded dict was too large to decode (ref http://www.rasterbar.com/products/libtorrent/manual.html#lazy-bdecode). Since this call is hidden in torrent_info, this might be a bit of a problematic fix.
UPDATE: Even worse, the lazy_bdecode fix seems to have been removed since libtorrent 1.1.0.

@qstokkink qstokkink modified the milestones: V7.1 anonymous seeding test, V7.0 Aug 22, 2017
@qstokkink
Copy link
Contributor

As it seems that the fix for this would be to write our own bdecode method (or switch torrent backend), we will postpone fixing this until after the 7.0 release.

@pimlie
Copy link
Author

pimlie commented Aug 22, 2017

It looks to me that this error is triggered by reaching item_limit (or depth_limit)? Wouldn't setting a larger item_limit solve the issue? Maybe configurable through a config file?

@qstokkink
Copy link
Contributor

@pimlie yes, but this is only available in the C++ backend: the Python binding to control this is no longer available. We would have to recompile libtorrent to expose this functionality (which is a fair bit of work and something we can't realistically support in the long run).

@pimlie
Copy link
Author

pimlie commented Aug 22, 2017

@qstokkink Ah right, sorry. Couldn't we just submit an upstream issue for this with libtorrent then? I would think if its possible in the C++ backend it should be possible in the Python binding, or is that too simple? ;)

@qstokkink
Copy link
Contributor

@pimlie Once again correct, but that would take months, if not years, to trickle down into the package managers of different platforms. Short term, we would still need a workaround for this.

@pimlie
Copy link
Author

pimlie commented Aug 22, 2017

@qstokkink unless you see more benefits from developing your own solution, I am not sure why you would go to all that trouble if this issue is the only reason for that. Probably that limit has been in libtorrent like forever and it seems nobody (also me) ever had problems with that limit before. So if I would need a specific lib version to be able to change that limit, I wouldnt regard that as a problem in this case. You just cant have it all ;)

That said, being dependent on package managers of different platforms is never a good solution. Probably one of the reasons why so many open source applications provide users with their own repositories (like ppa's for ubuntu). As an organisation it gives you full control and makes it easier to eg introduce new features also for (maybe) out-dated platforms.
A dependency on official package managers will most probably slow-down development as time needs to be spent on workarounds for old lib versions instead of new features (or bug fixes! ;)

Probably for this exact reason is why eg Deluge already has a ppa which includes their own libtorrent binary: https://launchpad.net/~deluge-team/+archive/ubuntu/develop/+packages

@qstokkink
Copy link
Contributor

@pimlie having a torrent which Tribler cannot handle, but other platforms can, is a thorn in my side. This hurts my pride. Nevertheless, I have been urged to delay fixing this until after the 7.0 release.

But, yes, you are probably right. Considering the issues we had in the past, just like Deluge, it would probably be best to start maintaining our own libtorrent binary as well.

@qstokkink qstokkink modified the milestones: V7.1: The token micro-economy, Backlog Mar 22, 2018
@qstokkink
Copy link
Contributor

I looked into this more. The only realistic option is to submit a PR to libtorrent to expose the bencoding limit.

@drew2a
Copy link
Contributor

drew2a commented Aug 17, 2022

Is this issue outdated?

In Tribler we use libtorrent version 1.2.15:

libtorrent==1.2.15

Also, I don't see this error in Sentry:

image

@qstokkink
Copy link
Contributor

This should still be an issue. Looking at the libtorrent source code, the default depth limit is 100 items and the token count is set to a max of 2000000. A ~25MB torrent file, as described in OP, should still trigger this issue.

Perhaps we can make our own huge torrent file for testing?

@qstokkink
Copy link
Contributor

qstokkink commented Aug 23, 2022

Reproduced using the following script:

# pip install bencode.py

import bencodepy

FILE_COUNT = 1000000

output = bencodepy.encode({
        'nodes': [],
        'info':
        {
            'files':
            [
                {'length': 1, 'path': [f'{i}.txt']} for i in range(FILE_COUNT)
            ],
            'name': 'longtorrent',
            'piece length': 1,
            'pieces': b"\x01" * 20 * FILE_COUNT
        }
    })

with open("longtorrent.torrent", "wb") as f:
    f.write(output)
    f.flush()

Output file: longtorrent.7z.gz

I confirmed that a FILE_COUNT of up to 100k works but 1M breaks with the following messages:

message

If you click "download" anyway, you get this:

box

@qstokkink
Copy link
Contributor

qstokkink commented Aug 23, 2022

The following is maybe even more interesting: torrent of death 😃. Tribler crashes and auto-closes before you can submit a report:

# pip install bencode.py

import bencodepy

PATH_DEPTH = 10000

output = bencodepy.encode({
        'nodes': [],
        'info':
        {
            'files':
            [
                {'length': 1, 'path': [f"{i}" for i in range(PATH_DEPTH)] + [f'file.txt']}
            ],
            'name': 'deeptorrent',
            'piece length': 1,
            'pieces': b"\x01" * 20
        }
    })

with open("deeptorrent.torrent", "wb") as f:
    f.write(output)
    f.flush()

Output file: deeptorrent.torrent.gz

Digging into the logs, this is causing it:

[PID:12868] 2022-08-23 13:37:35,455 - ERROR <error_handler:32> ErrorHandler.gui_error(): tribler.gui.utilities.CreationTraceback: 
  File "run_tribler.py", line 100, in <module>
  File "tribler\gui\start_gui.py", line 77, in run_gui
  File "tribler\gui\utilities.py", line 411, in trackback_wrapper
  File "tribler\gui\tribler_window.py", line 891, in on_add_torrent_browse_file
  File "tribler\gui\tribler_window.py", line 620, in process_uri_request
  File "tribler\gui\tribler_window.py", line 915, in start_download_from_uri
  File "tribler\gui\dialogs\startdownloaddialog.py", line 112, in __init__
  File "tribler\gui\dialogs\startdownloaddialog.py", line 148, in perform_files_request
  File "tribler\gui\tribler_request_manager.py", line 178, in __init__


The above exception was the direct cause of the following exception:

Traceback (most recent call last):
  File "tribler\gui\utilities.py", line 414, in trackback_wrapper
  File "tribler\gui\utilities.py", line 411, in trackback_wrapper
  File "tribler\gui\dialogs\startdownloaddialog.py", line 198, in on_received_metainfo
  File "tribler\gui\widgets\torrentfiletreewidget.py", line 210, in fill_entries
  File "tribler\gui\widgets\torrentfiletreewidget.py", line 82, in fill_directory_sizes
  File "tribler\gui\widgets\torrentfiletreewidget.py", line 82, in fill_directory_sizes
  File "tribler\gui\widgets\torrentfiletreewidget.py", line 82, in fill_directory_sizes
  [Previous line repeated 983 more times]
  File "tribler\gui\widgets\torrentfiletreewidget.py", line 81, in fill_directory_sizes
  File "tribler\gui\widgets\torrentfiletreewidget.py", line 67, in children
RecursionError: maximum recursion depth exceeded while calling a Python object

@drew2a drew2a self-assigned this Aug 24, 2022
@drew2a
Copy link
Contributor

drew2a commented Aug 24, 2022

@qstokkink great investigation! I think now I can fix the issue (at least the torrent of local death).

@drew2a drew2a modified the milestones: Backlog, 7.13.0 Aug 24, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Development

Successfully merging a pull request may close this issue.

4 participants