← Back to team overview

linuxdcpp-team team mailing list archive

[Branch ~dcplusplus-team/dcplusplus/trunk] Rev 2452: Prevent a stack overflow when searching within too big file lists

 

------------------------------------------------------------
revno: 2452
committer: poy <poy@xxxxxxxxxx>
branch nick: trunk
timestamp: Thu 2011-03-10 19:29:54 +0100
message:
  Prevent a stack overflow when searching within too big file lists
modified:
  changelog.txt
  win32/DirectoryListingFrame.cpp
  win32/DirectoryListingFrame.h


--
lp:dcplusplus
https://code.launchpad.net/~dcplusplus-team/dcplusplus/trunk

Your team Dcplusplus-team is subscribed to branch lp:dcplusplus.
To unsubscribe from this branch go to https://code.launchpad.net/~dcplusplus-team/dcplusplus/trunk/+edit-subscription
=== modified file 'changelog.txt'
--- changelog.txt	2011-03-05 21:13:48 +0000
+++ changelog.txt	2011-03-10 18:29:54 +0000
@@ -7,6 +7,7 @@
 * Report the progress of file list searches in the status bar (poy)
 * Repurpose Ctrl+F to in-place searches in chat windows & file lists (poy)
 * Better splitter resizing
+* [L#730828] Prevent a stack overflow when searching within too big file lists (poy)
 
 -- 0.782 2011-03-05 --
 * Prevent a remote crash triggered via malformed user commands (poy)

=== modified file 'win32/DirectoryListingFrame.cpp'
--- win32/DirectoryListingFrame.cpp	2011-03-09 19:44:02 +0000
+++ win32/DirectoryListingFrame.cpp	2011-03-10 18:29:54 +0000
@@ -959,47 +959,6 @@
 	}
 }
 
-pair<HTREEITEM, int> DirectoryListingFrame::findFile(const StringSearch& str, bool reverse, HTREEITEM item, int pos,
-	HTREEITEM const start, vector<HTREEITEM>& collapse, bool& cycle)
-{
-	// try to match the names currently in the list pane
-	const int n = files->size();
-	if(reverse && pos == -1)
-		pos = n;
-	for(reverse ? --pos : ++pos; reverse ? (pos >= 0) : (pos < n); reverse ? --pos : ++pos) {
-		const ItemInfo& ii = *files->getData(pos);
-		const string& name = (ii.type == ItemInfo::FILE) ? ii.file->getName() : ii.dir->getName();
-		if(str.match(name))
-			return make_pair(item, pos);
-	}
-
-	// flow to the next directory
-	if(!reverse && dirs->getChild(item) && !dirs->isExpanded(item)) {
-		dirs->expand(item);
-		collapse.push_back(item);
-	}
-	HTREEITEM next = dirs->getNext(item, reverse ? TVGN_PREVIOUSVISIBLE : TVGN_NEXTVISIBLE);
-	if(!next) {
-		next = reverse ? dirs->getLast() : treeRoot;
-		cycle = true;
-	}
-	if(next && next != start) {
-		if(reverse && dirs->getChild(next) && !dirs->isExpanded(next)) {
-			dirs->expand(next);
-			collapse.push_back(next);
-			if(!(next = dirs->getNext(item, TVGN_PREVIOUSVISIBLE)))
-				next = dirs->getLast();
-		}
-
-		// refresh the list pane to respect sorting etc
-		changeDir(dirs->getData(next)->dir);
-
-		return findFile(str, reverse, next, -1, start, collapse, cycle);
-	}
-
-	return make_pair(nullptr, 0);
-}
-
 void DirectoryListingFrame::findFile(bool reverse) {
 	const tstring findStr = searchBox->getText();
 	if(findStr.empty())
@@ -1051,24 +1010,70 @@
 		}
 	};
 
+	StringSearch search(Text::fromT(findStr));
 	vector<HTREEITEM> collapse;
 	bool cycle = false;
 	const auto fileSel = files->getSelected();
 
-	auto search = findFile(StringSearch(Text::fromT(findStr)), reverse, start, fileSel, start, collapse, cycle);
+	HTREEITEM item = start;
+	auto pos = fileSel;
+
+	while(true) {
+		// try to match the names currently in the list pane
+		const int n = files->size();
+		if(reverse && pos == -1)
+			pos = n;
+		bool found = false;
+		for(reverse ? --pos : ++pos; reverse ? (pos >= 0) : (pos < n); reverse ? --pos : ++pos) {
+			const ItemInfo& ii = *files->getData(pos);
+			if(search.match((ii.type == ItemInfo::FILE) ? ii.file->getName() : ii.dir->getName())) {
+				found = true;
+				break;
+			}
+		}
+		if(found)
+			break;
+
+		// flow to the next directory
+		if(!reverse && dirs->getChild(item) && !dirs->isExpanded(item)) {
+			dirs->expand(item);
+			collapse.push_back(item);
+		}
+		HTREEITEM next = dirs->getNext(item, reverse ? TVGN_PREVIOUSVISIBLE : TVGN_NEXTVISIBLE);
+		if(!next) {
+			next = reverse ? dirs->getLast() : treeRoot;
+			if(!next || next == start) {
+				item = nullptr;
+				break;
+			}
+			cycle = true;
+		}
+		if(reverse && dirs->getChild(next) && !dirs->isExpanded(next)) {
+			dirs->expand(next);
+			collapse.push_back(next);
+			if(!(next = dirs->getNext(item, TVGN_PREVIOUSVISIBLE)))
+				next = dirs->getLast();
+		}
+
+		// refresh the list pane to respect sorting etc
+		changeDir(dirs->getData(next)->dir);
+
+		item = next;
+		pos = -1;
+	}
 
 	for(auto i = collapse.cbegin(), iend = collapse.cend(); i != iend; ++i)
 		dirs->collapse(*i);
 
-	if(search.first) {
-		selectDir(search.first);
+	if(item) {
+		selectDir(item);
 
 		// Remove prev. selection from file list
 		files->clearSelection();
 
 		// Highlight the file
-		files->setSelected(search.second);
-		files->ensureVisible(search.second);
+		files->setSelected(pos);
+		files->ensureVisible(pos);
 
 		if(cycle) {
 			auto s_b(T_("beginning")), s_e(T_("end"));

=== modified file 'win32/DirectoryListingFrame.h'
--- win32/DirectoryListingFrame.h	2011-02-21 19:48:45 +0000
+++ win32/DirectoryListingFrame.h	2011-03-10 18:29:54 +0000
@@ -266,8 +266,6 @@
 	void updateStatus();
 
 	void findFile(bool reverse);
-	pair<HTREEITEM, int> findFile(const StringSearch& str, bool reverse, HTREEITEM item, int pos,
-		HTREEITEM const start, vector<HTREEITEM>& collapse, bool& cycle);
 
 	// MDIChildFrame
 	void tabMenuImpl(dwt::MenuPtr& menu);