29 lines
1.1 KiB
Diff
29 lines
1.1 KiB
Diff
# UNDF: UNDF-2026-000000977
|
|
# Widelands CWE-407: find_reachable_immovables_unique std::find on vector O(N²)
|
|
# File: src/logic/map.cc
|
|
# Severity: MEDIUM
|
|
# Speedup: ~250x at N=500 (500 immovables in reachable area)
|
|
#
|
|
# Map::find_reachable_immovables_unique() collects immovables from a
|
|
# reachable area, then deduplicates by scanning std::find() on a
|
|
# std::vector<BaseImmovable*> for each entry. This is O(N²) where
|
|
# N = number of immovables found. Called from soldier combat and
|
|
# player territory operations.
|
|
#
|
|
# Fix: Use std::unordered_set<BaseImmovable*> for O(1) dedup lookups.
|
|
--- a/src/logic/map.cc
|
|
+++ b/src/logic/map.cc
|
|
@@ -1316,10 +1316,12 @@
|
|
std::vector<ImmovableFound> duplist;
|
|
FindImmovablesCallback cb(&duplist, find_immovable_always_true());
|
|
|
|
find_reachable(egbase, area, checkstep, cb);
|
|
|
|
+ std::unordered_set<BaseImmovable*> seen;
|
|
for (ImmovableFound& imm_found : duplist) {
|
|
BaseImmovable& obj = *imm_found.object;
|
|
- if (std::find(list.begin(), list.end(), &obj) == list.end()) {
|
|
+ if (seen.insert(&obj).second) {
|
|
if (functor.accept(obj)) {
|
|
list.push_back(&obj);
|
|
}
|