java-topology/defects/rawtherapee-0001/patch/rawtherapee-0001-batchqueue-cancel-linear-find.patch

62 lines
2.3 KiB
Diff

# UNDF: UNDF-2026-000001147
# Defect: rawtherapee-0001
# Component: rtgui/batchqueue.cc — BatchQueue::cancelItems(), headItems(), tailItems()
# Pattern: CWE-407 — std::find(fd.begin(), fd.end(), entry) inside loop over items
# Severity: MEDIUM — O(I*Q) where I=items to cancel/move, Q=total queue size
# Fix: Build unordered_set<> from fd for O(1) lookup in cancelItems; for headItems/tailItems
# the erase+reinsert is O(Q) per item by nature, but skip items not in fd quickly
--- a/rtgui/batchqueue.cc
+++ b/rtgui/batchqueue.cc
@@ -484,24 +484,22 @@
void BatchQueue::cancelItems (const std::vector<ThumbBrowserEntryBase*>& items)
{
std::set<BatchQueueEntry*> removable_bqes;
{
MYWRITERLOCK(l, entryRW);
- for (const auto item : items) {
-
- const auto entry = static_cast<BatchQueueEntry*> (item);
-
- if (entry->processing)
- continue;
-
- const auto pos = std::find (fd.begin (), fd.end (), entry);
-
- if (pos == fd.end ())
- continue;
-
- fd.erase (pos);
-
- rtengine::ProcessingJob::destroy (entry->job);
-
- if (entry->thumbnail)
- entry->thumbnail->imageRemovedFromQueue ();
-
- removable_bqes.insert(entry);
- }
+ // Build a set of items to cancel for O(1) lookup during fd iteration
+ std::unordered_set<ThumbBrowserEntryBase*> to_cancel;
+ for (const auto item : items) {
+ const auto entry = static_cast<BatchQueueEntry*> (item);
+ if (!entry->processing)
+ to_cancel.insert(entry);
+ }
+
+ // Single-pass removal: iterate fd once, remove matched entries
+ auto new_end = std::remove_if(fd.begin(), fd.end(), [&](ThumbBrowserEntryBase* e) {
+ if (to_cancel.count(e)) {
+ auto* entry = static_cast<BatchQueueEntry*>(e);
+ rtengine::ProcessingJob::destroy(entry->job);
+ if (entry->thumbnail)
+ entry->thumbnail->imageRemovedFromQueue();
+ removable_bqes.insert(entry);
+ return true;
+ }
+ return false;
+ });
+ fd.erase(new_end, fd.end());
for (const auto entry : fd)
entry->selected = false;