[vlc-commits] qt: playlist: fix stack overflow
Romain Vimont
git at videolan.org
Tue Nov 7 14:25:14 CET 2017
vlc | branch: master | Romain Vimont <rom at rom1v.com> | Tue Nov 7 09:53:46 2017 +0100| [991ed989345c28d5fced32a9a5e60f0e793fcab1] | committer: Hugo Beauzée-Luyssen
qt: playlist: fix stack overflow
The playlist tree may be arbitrary deep, so traversing it recursively
may lead to stack overflow.
Traverse it iteratively instead.
Fixes #18376
Signed-off-by: Hugo Beauzée-Luyssen <hugo at beauzee.fr>
> http://git.videolan.org/gitweb.cgi/vlc.git/?a=commit;h=991ed989345c28d5fced32a9a5e60f0e793fcab1
---
.../gui/qt/components/playlist/playlist_model.cpp | 30 +++++++++++++++-------
1 file changed, 21 insertions(+), 9 deletions(-)
diff --git a/modules/gui/qt/components/playlist/playlist_model.cpp b/modules/gui/qt/components/playlist/playlist_model.cpp
index 2b6d0e1ccc..99e4c8f942 100644
--- a/modules/gui/qt/components/playlist/playlist_model.cpp
+++ b/modules/gui/qt/components/playlist/playlist_model.cpp
@@ -41,6 +41,7 @@
#include <assert.h>
#include <QFont>
#include <QAction>
+#include <QStack>
/*************************************************************************
* Playlist model implementation
@@ -518,20 +519,31 @@ PLItem *PLModel::findByPLId( PLItem *root, int i_id ) const
if( root->id() == i_id )
return root;
- QList<AbstractPLItem *>::iterator it = root->children.begin();
- while ( it != root->children.end() )
+ /* traverse the tree (in depth first) iteratively to avoid stack overflow */
+
+ struct RemainingChildren {
+ QList<AbstractPLItem *>::const_iterator next;
+ QList<AbstractPLItem *>::const_iterator end;
+ };
+
+ QStack<RemainingChildren> stack;
+ if( root->childCount() )
+ stack.push( {root->children.cbegin(), root->children.cend()} );
+
+ while ( !stack.isEmpty() )
{
- PLItem *item = static_cast<PLItem *>(*it);
+ RemainingChildren &remainingChildren = stack.top();
+
+ PLItem *item = static_cast<PLItem *>( *remainingChildren.next );
if( item->id() == i_id )
return item;
+ if( ++remainingChildren.next == remainingChildren.end )
+ /* there are no more children at this depth level */
+ stack.pop();
+
if( item->childCount() )
- {
- PLItem *childFound = findByPLId( item, i_id );
- if( childFound )
- return childFound;
- }
- ++it;
+ stack.push( {item->children.cbegin(), item->children.cend()} );
}
return NULL;
}
More information about the vlc-commits
mailing list