[YoutubeDL] Protect from infinite recursion due to recursively nested playlists (closes #27833)
This commit is contained in:
parent
9d50f86232
commit
9c9b458145
|
@ -338,6 +338,8 @@ class YoutubeDL(object):
|
||||||
_pps = []
|
_pps = []
|
||||||
_download_retcode = None
|
_download_retcode = None
|
||||||
_num_downloads = None
|
_num_downloads = None
|
||||||
|
_playlist_level = 0
|
||||||
|
_playlist_urls = set()
|
||||||
_screen_file = None
|
_screen_file = None
|
||||||
|
|
||||||
def __init__(self, params=None, auto_init=True):
|
def __init__(self, params=None, auto_init=True):
|
||||||
|
@ -906,8 +908,51 @@ class YoutubeDL(object):
|
||||||
return self.process_ie_result(
|
return self.process_ie_result(
|
||||||
new_result, download=download, extra_info=extra_info)
|
new_result, download=download, extra_info=extra_info)
|
||||||
elif result_type in ('playlist', 'multi_video'):
|
elif result_type in ('playlist', 'multi_video'):
|
||||||
|
# Protect from infinite recursion due to recursively nested playlists
|
||||||
|
# (see https://github.com/ytdl-org/youtube-dl/issues/27833)
|
||||||
|
webpage_url = ie_result['webpage_url']
|
||||||
|
if webpage_url in self._playlist_urls:
|
||||||
|
self.to_screen(
|
||||||
|
'[download] Skipping already downloaded playlist: %s'
|
||||||
|
% ie_result.get('title') or ie_result.get('id'))
|
||||||
|
return
|
||||||
|
|
||||||
|
self._playlist_level += 1
|
||||||
|
self._playlist_urls.add(webpage_url)
|
||||||
|
try:
|
||||||
|
return self.__process_playlist(ie_result, download)
|
||||||
|
finally:
|
||||||
|
self._playlist_level -= 1
|
||||||
|
if not self._playlist_level:
|
||||||
|
self._playlist_urls.clear()
|
||||||
|
elif result_type == 'compat_list':
|
||||||
|
self.report_warning(
|
||||||
|
'Extractor %s returned a compat_list result. '
|
||||||
|
'It needs to be updated.' % ie_result.get('extractor'))
|
||||||
|
|
||||||
|
def _fixup(r):
|
||||||
|
self.add_extra_info(
|
||||||
|
r,
|
||||||
|
{
|
||||||
|
'extractor': ie_result['extractor'],
|
||||||
|
'webpage_url': ie_result['webpage_url'],
|
||||||
|
'webpage_url_basename': url_basename(ie_result['webpage_url']),
|
||||||
|
'extractor_key': ie_result['extractor_key'],
|
||||||
|
}
|
||||||
|
)
|
||||||
|
return r
|
||||||
|
ie_result['entries'] = [
|
||||||
|
self.process_ie_result(_fixup(r), download, extra_info)
|
||||||
|
for r in ie_result['entries']
|
||||||
|
]
|
||||||
|
return ie_result
|
||||||
|
else:
|
||||||
|
raise Exception('Invalid result type: %s' % result_type)
|
||||||
|
|
||||||
|
def __process_playlist(self, ie_result, download):
|
||||||
# We process each entry in the playlist
|
# We process each entry in the playlist
|
||||||
playlist = ie_result.get('title') or ie_result.get('id')
|
playlist = ie_result.get('title') or ie_result.get('id')
|
||||||
|
|
||||||
self.to_screen('[download] Downloading playlist: %s' % playlist)
|
self.to_screen('[download] Downloading playlist: %s' % playlist)
|
||||||
|
|
||||||
playlist_results = []
|
playlist_results = []
|
||||||
|
@ -1015,29 +1060,6 @@ class YoutubeDL(object):
|
||||||
ie_result['entries'] = playlist_results
|
ie_result['entries'] = playlist_results
|
||||||
self.to_screen('[download] Finished downloading playlist: %s' % playlist)
|
self.to_screen('[download] Finished downloading playlist: %s' % playlist)
|
||||||
return ie_result
|
return ie_result
|
||||||
elif result_type == 'compat_list':
|
|
||||||
self.report_warning(
|
|
||||||
'Extractor %s returned a compat_list result. '
|
|
||||||
'It needs to be updated.' % ie_result.get('extractor'))
|
|
||||||
|
|
||||||
def _fixup(r):
|
|
||||||
self.add_extra_info(
|
|
||||||
r,
|
|
||||||
{
|
|
||||||
'extractor': ie_result['extractor'],
|
|
||||||
'webpage_url': ie_result['webpage_url'],
|
|
||||||
'webpage_url_basename': url_basename(ie_result['webpage_url']),
|
|
||||||
'extractor_key': ie_result['extractor_key'],
|
|
||||||
}
|
|
||||||
)
|
|
||||||
return r
|
|
||||||
ie_result['entries'] = [
|
|
||||||
self.process_ie_result(_fixup(r), download, extra_info)
|
|
||||||
for r in ie_result['entries']
|
|
||||||
]
|
|
||||||
return ie_result
|
|
||||||
else:
|
|
||||||
raise Exception('Invalid result type: %s' % result_type)
|
|
||||||
|
|
||||||
@__handle_extraction_exceptions
|
@__handle_extraction_exceptions
|
||||||
def __process_iterable_entry(self, entry, download, extra_info):
|
def __process_iterable_entry(self, entry, download, extra_info):
|
||||||
|
|
Loading…
Reference in New Issue