50 lines
2.4 KiB
Diff
50 lines
2.4 KiB
Diff
# UNDF: UNDF-2026-000001168
|
|
--- a/mail/base/content/about3Pane.js
|
|
+++ b/mail/base/content/about3Pane.js
|
|
@@ -1241,20 +1241,21 @@ MOAD-0001 CWE-407: about3Pane.js SmartServerPane.initServer() O(N²) folder dedup
|
|
# Severity: MEDIUM-HIGH
|
|
# Ratio: O(F²) where F = number of folders in a server (e.g. 500 IMAP folders → 250,000 ops)
|
|
#
|
|
# Root cause: initServer() builds existingURIs as an Array, then calls existingURIs.includes()
|
|
# inside a do-while loop over remainingFolderURIs. After each addFolder() call the array is
|
|
# fully rebuilt from DOM (Array.from(existingRows, li => li.uri)). Every includes() call is
|
|
# O(F) and there are F iterations → O(F²) total.
|
|
#
|
|
# Fix: use a Set<string> for existingURIs. Seed it once from DOM; when addFolder() adds a row
|
|
# update the Set directly instead of re-scanning the entire live NodeList.
|
|
|
|
initServer(server) {
|
|
// Find all folders in this server, and display the ones that aren't
|
|
// currently displayed.
|
|
const descendants = new Map(
|
|
server.rootFolder.descendants.map(d => [d.URI, d])
|
|
);
|
|
if (!descendants.size) {
|
|
return;
|
|
}
|
|
const remainingFolderURIs = Array.from(descendants.keys());
|
|
|
|
// Get a list of folders that already exist in the folder tree.
|
|
const existingRows = this.containerList.getElementsByTagName("li");
|
|
- let existingURIs = Array.from(existingRows, li => li.uri);
|
|
+ // PATCH thunderbird-0007: use a Set so membership checks are O(1).
|
|
+ const existingURIs = new Set(Array.from(existingRows, li => li.uri));
|
|
do {
|
|
const folderURI = remainingFolderURIs.shift();
|
|
- if (existingURIs.includes(folderURI)) {
|
|
+ if (existingURIs.has(folderURI)) {
|
|
continue;
|
|
}
|
|
const folder = descendants.get(folderURI);
|
|
if (folderPane._isGmailFolder(folder)) {
|
|
continue;
|
|
}
|
|
this.addFolder(folderPane._getNonGmailParent(folder), folder);
|
|
- // Update the list of existing folders. `existingRows` is a live
|
|
- // list, so we don't need to call `getElementsByTagName` again.
|
|
- existingURIs = Array.from(existingRows, li => li.uri);
|
|
+ // Update the Set so subsequent iterations see the newly added row.
|
|
+ // `existingRows` is a live NodeList — we just add the new URI.
|
|
+ existingURIs.add(folderURI);
|
|
} while (remainingFolderURIs.length);
|
|
},
|