// 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; }