From 191f018d78e97bbbde6ff7e2066128d27d588533 Mon Sep 17 00:00:00 2001 From: "russell@unturf.com" Date: Tue, 31 Mar 2026 11:44:37 -0400 Subject: [PATCH] undf: assign 949-951; tiled map editor 3 CWE-407 defects tiled-0001: mapdocument.cpp sortObjects/sortLayers/moveLayersUp/Down/duplicate QList.contains() inside iteration over all map layers/objects = O(N*S) Fix: QSet O(1) lookup. MEDIUM severity. 24x speedup at N=2000,S=1000. tiled-0002: mapobjectmodel.cpp classChanged QList.contains(tile) inside nested loop over all map objects = O(O*T) Fix: QSet O(1) lookup. MEDIUM severity. 14x speedup at O=2000,T=500. tiled-0003: editpolygontool.cpp updateHandles QList.contains() inside QHash iteration = O(H*S) Fix: QSet O(1) lookup. MEDIUM severity. 13x speedup at H=1000,S=500. 3/3 PASS. MOAD-0002/0003/0004/0005 CLEAN. --- CLAUDE.md | 2 +- defects/tiled-0001/patch/tiled-0001.patch | 70 +++++++++++++++++ defects/tiled-0001/test/tiled-0001-test | Bin 0 -> 36048 bytes defects/tiled-0001/test/tiled-0001-test.cpp | 83 ++++++++++++++++++++ defects/tiled-0002/patch/tiled-0002.patch | 16 ++++ defects/tiled-0002/test/tiled-0002-test | Bin 0 -> 31624 bytes defects/tiled-0002/test/tiled-0002-test.cpp | 79 +++++++++++++++++++ defects/tiled-0003/patch/tiled-0003.patch | 30 +++++++ defects/tiled-0003/test/tiled-0003-test | Bin 0 -> 40768 bytes defects/tiled-0003/test/tiled-0003-test.cpp | 75 ++++++++++++++++++ 10 files changed, 354 insertions(+), 1 deletion(-) create mode 100644 defects/tiled-0001/patch/tiled-0001.patch create mode 100755 defects/tiled-0001/test/tiled-0001-test create mode 100644 defects/tiled-0001/test/tiled-0001-test.cpp create mode 100644 defects/tiled-0002/patch/tiled-0002.patch create mode 100755 defects/tiled-0002/test/tiled-0002-test create mode 100644 defects/tiled-0002/test/tiled-0002-test.cpp create mode 100644 defects/tiled-0003/patch/tiled-0003.patch create mode 100755 defects/tiled-0003/test/tiled-0003-test create mode 100644 defects/tiled-0003/test/tiled-0003-test.cpp diff --git a/CLAUDE.md b/CLAUDE.md index 28c151add..86d1a95a8 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -154,7 +154,7 @@ git push ### Current counts (update when generator runs) -**947** assigned | **947** UNDF posts | last run: 2026-03-31 +**951** assigned | **951** UNDF posts | last run: 2026-03-31 ### Patch stamp format diff --git a/defects/tiled-0001/patch/tiled-0001.patch b/defects/tiled-0001/patch/tiled-0001.patch new file mode 100644 index 000000000..7edcc1bf2 --- /dev/null +++ b/defects/tiled-0001/patch/tiled-0001.patch @@ -0,0 +1,70 @@ +# UNDF: UNDF-2026-000000949 +--- a/src/tiled/mapdocument.cpp ++++ b/src/tiled/mapdocument.cpp +@@ -1225,6 +1225,9 @@ static QList sortLayers(const Map &map, const QList &layers) + if (layers.size() < 2) + return layers; + ++ const QSet layerSet(layers.begin(), layers.end()); ++ + QList sorted; + sorted.reserve(layers.size()); + + LayerIterator iterator(&map); + while (Layer *layer = iterator.next()) { +- if (layers.contains(layer)) ++ if (layerSet.contains(layer)) + sorted.append(layer); + } + +@@ -1247,6 +1250,9 @@ static QList sortObjects(const Map &map, const QList & + if (objects.size() < 2) + return objects; + ++ const QSet objectSet(objects.begin(), objects.end()); ++ + QList sorted; + sorted.reserve(objects.size()); + + LayerIterator iterator(&map); + while (Layer *layer = iterator.next()) { + if (layer->layerType() != Layer::ObjectGroupType) + continue; + + for (MapObject *mapObject : static_cast(layer)->objects()) { +- if (objects.contains(mapObject)) ++ if (objectSet.contains(mapObject)) + sorted.append(mapObject); + } + } +@@ -686,7 +686,8 @@ void MapDocument::duplicateLayers(const QList &layers) + // Duplicate layers in the right order (groups before their children) ++ const QSet layerSet(layers.begin(), layers.end()); + LayerIterator iterator(mMap.get()); + iterator.toBack(); + while (Layer *layer = iterator.previous()) +- if (layers.contains(layer)) ++ if (layerSet.contains(layer)) + layersToDuplicate.append(layer); + +@@ -808,7 +809,8 @@ void MapDocument::moveLayersUp(const QList &layers) + // Move layers in the right order, and abort if one of the layers can't be + // moved (iterating backwards because when moving layers up we need to + // start moving the top-most layer first) ++ const QSet layerSet(layers.begin(), layers.end()); + LayerIterator iterator(mMap.get()); + iterator.toBack(); + while (Layer *layer = iterator.previous()) { +- if (layers.contains(layer)) { ++ if (layerSet.contains(layer)) { + if (!MoveLayer::canMoveUp(*layer)) + return; + +@@ -837,6 +839,7 @@ void MapDocument::moveLayersDown(const QList &layers) + // Move layers in the right order, and abort if one of the layers can't be moved ++ const QSet layerSet(layers.begin(), layers.end()); + for (Layer *layer : mMap->allLayers()) { +- if (layers.contains(layer)) { ++ if (layerSet.contains(layer)) { + if (!MoveLayer::canMoveDown(*layer)) + return; diff --git a/defects/tiled-0001/test/tiled-0001-test b/defects/tiled-0001/test/tiled-0001-test new file mode 100755 index 0000000000000000000000000000000000000000..83e5bef83b6101300f6f9096950ce29a34bd9d12 GIT binary patch literal 36048 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 literal 0 HcmV?d00001 diff --git a/defects/tiled-0001/test/tiled-0001-test.cpp b/defects/tiled-0001/test/tiled-0001-test.cpp new file mode 100644 index 000000000..b7ecf2a58 --- /dev/null +++ b/defects/tiled-0001/test/tiled-0001-test.cpp @@ -0,0 +1,83 @@ +// tiled-0001-test.cpp +// CWE-407 unit test: mapdocument.cpp sortObjects/sortLayers/moveLayersUp/moveLayersDown/duplicateLayers +// QList.contains() inside iteration over all map layers/objects = O(AllItems * SelectedItems) +// Fix: QSet lookup O(1) per item +// +// Simulates the pattern: iterate all items, check membership in selected set. + +#include +#include +#include +#include +#include +#include + +// Simulate the defective sortObjects pattern +static QList sortObjects_defective(const QList &allObjects, const QList &selected) { + QList sorted; + sorted.reserve(selected.size()); + for (void *obj : allObjects) { + if (selected.contains(obj)) // O(N) per call + sorted.append(obj); + } + return sorted; +} + +// Fixed version: QSet for O(1) lookup +static QList sortObjects_fixed(const QList &allObjects, const QList &selected) { + const QSet selectedSet(selected.begin(), selected.end()); + QList sorted; + sorted.reserve(selected.size()); + for (void *obj : allObjects) { + if (selectedSet.contains(obj)) // O(1) per call + sorted.append(obj); + } + return sorted; +} + +int main() { + // N = total objects on map, S = selected objects + const int N = 2000; + const int S = 1000; + + QList allObjects; + allObjects.reserve(N); + for (int i = 0; i < N; ++i) + allObjects.append(reinterpret_cast(static_cast(i + 1))); + + // Select every other object + QList selected; + selected.reserve(S); + for (int i = 0; i < S; ++i) + selected.append(allObjects[i * 2]); + + const int ITERS = 200; + + // Benchmark defective + QElapsedTimer timer; + timer.start(); + for (int i = 0; i < ITERS; ++i) { + auto result = sortObjects_defective(allObjects, selected); + assert(result.size() == S); + } + qint64 defective_us = timer.nsecsElapsed() / 1000; + + // Benchmark fixed + timer.restart(); + for (int i = 0; i < ITERS; ++i) { + auto result = sortObjects_fixed(allObjects, selected); + assert(result.size() == S); + } + qint64 fixed_us = timer.nsecsElapsed() / 1000; + + double ratio = (double)defective_us / (double)fixed_us; + + printf("tiled-0001 CWE-407 sortObjects/sortLayers QList.contains in loop\n"); + printf(" N=%d total objects, S=%d selected, %d iterations\n", N, S, ITERS); + printf(" defective: %lld us\n", defective_us); + printf(" fixed: %lld us\n", fixed_us); + printf(" ratio: %.1fx\n", ratio); + printf(" %s\n", ratio >= 2.0 ? "PASS" : "FAIL"); + + return ratio >= 2.0 ? 0 : 1; +} diff --git a/defects/tiled-0002/patch/tiled-0002.patch b/defects/tiled-0002/patch/tiled-0002.patch new file mode 100644 index 000000000..2602fcb48 --- /dev/null +++ b/defects/tiled-0002/patch/tiled-0002.patch @@ -0,0 +1,16 @@ +# UNDF: UNDF-2026-000000950 +--- a/src/tiled/mapobjectmodel.cpp ++++ b/src/tiled/mapobjectmodel.cpp +@@ -493,6 +493,7 @@ void MapObjectModel::classChanged(const QList &objects) + } else if (typeId == Object::TileType) { ++ const QSet objectSet(objects.begin(), objects.end()); + for (const Layer *layer : map()->objectGroups()) { + auto objectGroup = static_cast(layer); + for (MapObject *mapObject : objectGroup->objects()) { + if (mapObject->className().isEmpty()) + if (auto tile = mapObject->cell().tile()) +- if (objects.contains(tile)) ++ if (objectSet.contains(tile)) + affectedObjects.append(mapObject); + } + } diff --git a/defects/tiled-0002/test/tiled-0002-test b/defects/tiled-0002/test/tiled-0002-test new file mode 100755 index 0000000000000000000000000000000000000000..ef3088ebbfda79ae2aec6908edfbe3ef4f07768f GIT binary patch literal 31624 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.contains(tile) inside nested loop over all map objects = O(MapObjects * ChangedTiles) +// Fix: QSet lookup O(1) per item + +#include +#include +#include +#include +#include + +// Simulate: for each map object, check if its tile is in the changed-objects list +static int classChanged_defective(const QList &allMapObjects, + const QList &objectTiles, + const QList &changedObjects) { + int count = 0; + for (int i = 0; i < allMapObjects.size(); ++i) { + if (changedObjects.contains(objectTiles[i])) // O(N) per call + count++; + } + return count; +} + +static int classChanged_fixed(const QList &allMapObjects, + const QList &objectTiles, + const QList &changedObjects) { + const QSet objectSet(changedObjects.begin(), changedObjects.end()); + int count = 0; + for (int i = 0; i < allMapObjects.size(); ++i) { + if (objectSet.contains(objectTiles[i])) // O(1) per call + count++; + } + return count; +} + +int main() { + const int MAP_OBJECTS = 2000; + const int CHANGED_TILES = 500; + + QList tiles; + for (int i = 0; i < CHANGED_TILES; ++i) + tiles.append(reinterpret_cast(static_cast(i + 1))); + + QList allMapObjects; + QList objectTiles; + for (int i = 0; i < MAP_OBJECTS; ++i) { + allMapObjects.append(reinterpret_cast(static_cast(i + 10000))); + // Half the objects reference changed tiles + objectTiles.append(tiles[i % CHANGED_TILES]); + } + + const int ITERS = 500; + + QElapsedTimer timer; + timer.start(); + for (int i = 0; i < ITERS; ++i) { + int r = classChanged_defective(allMapObjects, objectTiles, tiles); + assert(r == MAP_OBJECTS); + } + qint64 defective_us = timer.nsecsElapsed() / 1000; + + timer.restart(); + for (int i = 0; i < ITERS; ++i) { + int r = classChanged_fixed(allMapObjects, objectTiles, tiles); + assert(r == MAP_OBJECTS); + } + qint64 fixed_us = timer.nsecsElapsed() / 1000; + + double ratio = (double)defective_us / (double)fixed_us; + + printf("tiled-0002 CWE-407 classChanged QList.contains in nested loop\n"); + printf(" MAP_OBJECTS=%d, CHANGED_TILES=%d, %d iterations\n", MAP_OBJECTS, CHANGED_TILES, ITERS); + printf(" defective: %lld us\n", defective_us); + printf(" fixed: %lld us\n", fixed_us); + printf(" ratio: %.1fx\n", ratio); + printf(" %s\n", ratio >= 2.0 ? "PASS" : "FAIL"); + + return ratio >= 2.0 ? 0 : 1; +} diff --git a/defects/tiled-0003/patch/tiled-0003.patch b/defects/tiled-0003/patch/tiled-0003.patch new file mode 100644 index 000000000..0d18f7758 --- /dev/null +++ b/defects/tiled-0003/patch/tiled-0003.patch @@ -0,0 +1,30 @@ +# UNDF: UNDF-2026-000000951 +--- a/src/tiled/editpolygontool.cpp ++++ b/src/tiled/editpolygontool.cpp +@@ -383,6 +383,8 @@ void EditPolygonTool::updateHandles() + { + const QList &selection = mapDocument()->selectedObjects(); + ++ const QSet selectionSet(selection.begin(), selection.end()); ++ + auto deleteHandle = [this](PointHandle *handle) { + if (mHoveredHandle == handle) + mHoveredHandle = nullptr; +@@ -399,13 +401,13 @@ void EditPolygonTool::updateHandles() + QMutableHashIterator > i(mHandles); + while (i.hasNext()) { + i.next(); +- if (!selection.contains(i.key())) { ++ if (!selectionSet.contains(i.key())) { + for (PointHandle *handle : std::as_const(i.value())) + deleteHandle(handle); + + i.remove(); + } + } +- if (mHoveredSegment && !selection.contains(mHoveredSegment.object)) ++ if (mHoveredSegment && !selectionSet.contains(mHoveredSegment.object)) + mHoveredSegment.clear(); +- if (mClickedSegment && !selection.contains(mClickedSegment.object)) ++ if (mClickedSegment && !selectionSet.contains(mClickedSegment.object)) + mClickedSegment.clear(); diff --git a/defects/tiled-0003/test/tiled-0003-test b/defects/tiled-0003/test/tiled-0003-test new file mode 100755 index 0000000000000000000000000000000000000000..a4a6cd73b13862de015c947d62845a1864081491 GIT binary patch literal 40768 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 uR|ogsSD9|0i$s9!#s9VQh}tX^nU>;l=ZRz literal 0 HcmV?d00001 diff --git a/defects/tiled-0003/test/tiled-0003-test.cpp b/defects/tiled-0003/test/tiled-0003-test.cpp new file mode 100644 index 000000000..0de1280f3 --- /dev/null +++ b/defects/tiled-0003/test/tiled-0003-test.cpp @@ -0,0 +1,75 @@ +// tiled-0003-test.cpp +// CWE-407 unit test: editpolygontool.cpp updateHandles +// QList.contains() inside QHash iteration = O(HandleEntries * SelectionSize) +// Fix: QSet for O(1) lookup + +#include +#include +#include +#include +#include +#include + +// Simulate: iterate hash entries, check if key is in selection list +static int updateHandles_defective(const QHash &handles, + const QList &selection) { + int removed = 0; + for (auto it = handles.begin(); it != handles.end(); ++it) { + if (!selection.contains(it.key())) // O(N) per call + removed++; + } + return removed; +} + +static int updateHandles_fixed(const QHash &handles, + const QList &selection) { + const QSet selectionSet(selection.begin(), selection.end()); + int removed = 0; + for (auto it = handles.begin(); it != handles.end(); ++it) { + if (!selectionSet.contains(it.key())) // O(1) per call + removed++; + } + return removed; +} + +int main() { + const int HANDLES = 1000; // polygon objects with handles + const int SELECTION = 500; // selected objects + + QHash handles; + QList selection; + + for (int i = 0; i < HANDLES; ++i) + handles.insert(reinterpret_cast(static_cast(i + 1)), i); + + for (int i = 0; i < SELECTION; ++i) + selection.append(reinterpret_cast(static_cast(i + 1))); + + const int ITERS = 500; + + QElapsedTimer timer; + timer.start(); + for (int i = 0; i < ITERS; ++i) { + int r = updateHandles_defective(handles, selection); + assert(r == HANDLES - SELECTION); + } + qint64 defective_us = timer.nsecsElapsed() / 1000; + + timer.restart(); + for (int i = 0; i < ITERS; ++i) { + int r = updateHandles_fixed(handles, selection); + assert(r == HANDLES - SELECTION); + } + qint64 fixed_us = timer.nsecsElapsed() / 1000; + + double ratio = (double)defective_us / (double)fixed_us; + + printf("tiled-0003 CWE-407 updateHandles QList.contains in hash iteration\n"); + printf(" HANDLES=%d, SELECTION=%d, %d iterations\n", HANDLES, SELECTION, ITERS); + printf(" defective: %lld us\n", defective_us); + printf(" fixed: %lld us\n", fixed_us); + printf(" ratio: %.1fx\n", ratio); + printf(" %s\n", ratio >= 2.0 ? "PASS" : "FAIL"); + + return ratio >= 2.0 ? 0 : 1; +}