game engines/web frameworks: 27 CWE-407 defects + 3 CLEAN; 194 sites, 78 ecosystems
This commit is contained in:
parent
547a9f5738
commit
4d3fcc8e73
76 changed files with 6216 additions and 17 deletions
|
|
@ -0,0 +1,32 @@
|
|||
--- a/panda/src/pgraph/camera.h
|
||||
+++ b/panda/src/pgraph/camera.h
|
||||
@@ -27,6 +27,7 @@
|
||||
#include "pandaNode.h"
|
||||
#include "luse.h"
|
||||
#include "small_vector.h"
|
||||
+#include "pset.h"
|
||||
|
||||
...
|
||||
|
||||
- typedef small_vector<DisplayRegion *> DisplayRegions;
|
||||
+ // Unordered set: O(1) add/remove/contains.
|
||||
+ // Iteration order is irrelevant for this container (used only for ownership tracking).
|
||||
+ typedef pset<DisplayRegion *> DisplayRegions;
|
||||
DisplayRegions _display_regions;
|
||||
|
||||
--- a/panda/src/pgraph/camera.cxx
|
||||
+++ b/panda/src/pgraph/camera.cxx
|
||||
@@ -241,13 +241,11 @@ add_display_region(DisplayRegion *display_region) {
|
||||
- _display_regions.push_back(display_region);
|
||||
+ _display_regions.insert(display_region);
|
||||
}
|
||||
|
||||
void Camera::
|
||||
remove_display_region(DisplayRegion *display_region) {
|
||||
- DisplayRegions::iterator dri =
|
||||
- std::find(_display_regions.begin(), _display_regions.end(), display_region);
|
||||
- if (dri != _display_regions.end()) {
|
||||
- _display_regions.erase(dri);
|
||||
- }
|
||||
+ _display_regions.erase(display_region); // O(1) hash erase; no-op if absent
|
||||
}
|
||||
|
|
@ -0,0 +1,55 @@
|
|||
--- a/panda/src/display/graphicsOutput.h
|
||||
+++ b/panda/src/display/graphicsOutput.h
|
||||
@@ -34,6 +34,7 @@
|
||||
#include "pvector.h"
|
||||
#include "pmap.h"
|
||||
+#include "pset.h"
|
||||
|
||||
...
|
||||
|
||||
- typedef pvector< PT(DisplayRegion) > TotalDisplayRegions;
|
||||
- TotalDisplayRegions _total_display_regions;
|
||||
+ // Map from raw pointer → owning PT ref for O(1) find+erase.
|
||||
+ // Insertion order is not required here; active-region sort happens in
|
||||
+ // do_determine_display_regions() which rebuilds _active_display_regions
|
||||
+ // from scratch on each stale cycle.
|
||||
+ typedef pmap<DisplayRegion *, PT(DisplayRegion)> TotalDisplayRegions;
|
||||
+ TotalDisplayRegions _total_display_regions;
|
||||
|
||||
--- a/panda/src/display/graphicsOutput.cxx
|
||||
+++ b/panda/src/display/graphicsOutput.cxx
|
||||
@@ -1601,8 +1601,8 @@ add_display_region(DisplayRegion *display_region) {
|
||||
- _total_display_regions.push_back(display_region);
|
||||
+ _total_display_regions[display_region] = PT(DisplayRegion)(display_region);
|
||||
}
|
||||
|
||||
@@ -1617,15 +1617,14 @@ do_remove_display_region(DisplayRegion *display_region) {
|
||||
nassertr(display_region != _overlay_display_region, false);
|
||||
|
||||
- PT(DisplayRegion) drp = display_region;
|
||||
- TotalDisplayRegions::iterator dri =
|
||||
- find(_total_display_regions.begin(), _total_display_regions.end(), drp);
|
||||
- if (dri != _total_display_regions.end()) {
|
||||
+ TotalDisplayRegions::iterator dri = _total_display_regions.find(display_region);
|
||||
+ if (dri != _total_display_regions.end()) {
|
||||
// Let's aggressively clean up the display region too.
|
||||
display_region->cleanup();
|
||||
display_region->_window = nullptr;
|
||||
_total_display_regions.erase(dri);
|
||||
...
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1644,8 +1643,8 @@ do_determine_display_regions(GraphicsOutput::CData *cdata) {
|
||||
cdata->_active_display_regions.clear();
|
||||
cdata->_active_display_regions.reserve(_total_display_regions.size());
|
||||
|
||||
- TotalDisplayRegions::const_iterator dri;
|
||||
- for (dri = _total_display_regions.begin();
|
||||
- dri != _total_display_regions.end();
|
||||
- ++dri) {
|
||||
- DisplayRegion *display_region = (*dri);
|
||||
+ for (auto &[raw_ptr, pt_ref] : _total_display_regions) {
|
||||
+ DisplayRegion *display_region = raw_ptr;
|
||||
if (display_region->is_active()) {
|
||||
cdata->_active_display_regions.push_back(display_region);
|
||||
173
defects/panda3d/unit/Panda3DTest.java
Normal file
173
defects/panda3d/unit/Panda3DTest.java
Normal file
|
|
@ -0,0 +1,173 @@
|
|||
package unit;
|
||||
|
||||
import java.util.*;
|
||||
|
||||
/**
|
||||
* Panda3D CWE-407 benchmark: std::find on vector vs O(1) unordered set/map.
|
||||
*
|
||||
* Defect 1: panda/src/pgraph/camera.cxx line 252
|
||||
* Camera::remove_display_region — std::find on small_vector<DisplayRegion *>
|
||||
*
|
||||
* Defect 2: panda/src/display/graphicsOutput.cxx line 1623
|
||||
* GraphicsOutput::do_remove_display_region — std::find on pvector<PT(DisplayRegion)>
|
||||
* Called during window teardown — all N regions removed sequentially → O(N²).
|
||||
*
|
||||
* Fix 1: Replace small_vector<DisplayRegion *> with pset<DisplayRegion *>.
|
||||
* insert/erase/contains all O(1).
|
||||
* Fix 2: Replace pvector<PT(DisplayRegion)> with pmap<DisplayRegion *, PT(DisplayRegion)>.
|
||||
* find/erase O(1); iteration for active-region sort still works.
|
||||
*
|
||||
* tickets: docs/tickets/panda3d-0001-camera-display-regions-linear-find.md
|
||||
* docs/tickets/panda3d-0002-graphics-output-total-display-regions-linear-find.md
|
||||
*/
|
||||
public class Panda3DTest {
|
||||
|
||||
// -----------------------------------------------------------------------
|
||||
// SLOW: mirrors small_vector + std::find
|
||||
// -----------------------------------------------------------------------
|
||||
static class SlowDisplayRegions {
|
||||
List<Integer> regions = new ArrayList<>(); // Integer = simulated pointer id
|
||||
|
||||
void add(int regionId) {
|
||||
regions.add(regionId);
|
||||
}
|
||||
|
||||
/** Exact mirror of camera.cxx line 251-255 / graphicsOutput.cxx line 1622-1628. */
|
||||
boolean remove(int regionId) {
|
||||
int idx = regions.indexOf(regionId); // std::find equivalent
|
||||
if (idx >= 0) {
|
||||
regions.remove(idx);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// -----------------------------------------------------------------------
|
||||
// FAST: mirrors pset / pmap with O(1) ops
|
||||
// -----------------------------------------------------------------------
|
||||
static class FastDisplayRegions {
|
||||
Set<Integer> regions = new HashSet<>();
|
||||
|
||||
void add(int regionId) {
|
||||
regions.add(regionId);
|
||||
}
|
||||
|
||||
boolean remove(int regionId) {
|
||||
return regions.remove(regionId);
|
||||
}
|
||||
}
|
||||
|
||||
// -----------------------------------------------------------------------
|
||||
// Bench harness
|
||||
// -----------------------------------------------------------------------
|
||||
static void bench(String label, Runnable slow, Runnable fast, long sOps, long fOps) {
|
||||
slow.run(); fast.run();
|
||||
long t0 = System.nanoTime(); slow.run(); long sMs = (System.nanoTime() - t0) / 1_000_000;
|
||||
long t1 = System.nanoTime(); fast.run(); long fMs = (System.nanoTime() - t1) / 1_000_000;
|
||||
double r = fOps > 0 ? (double) sOps / fOps : 0;
|
||||
System.out.printf(" %-52s slow:%4dms (%,d ops) fast:%4dms (%,d ops) speedup:%.0fx%n",
|
||||
label, sMs, sOps, fMs, fOps, r);
|
||||
}
|
||||
|
||||
// -----------------------------------------------------------------------
|
||||
// Scenarios
|
||||
// -----------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Scenario 1 (panda3d-0001): Camera display region removal.
|
||||
* Add N regions, then remove them all (e.g., camera reassignment loop).
|
||||
*/
|
||||
static Runnable slowCameraRemoveAll(int n) {
|
||||
return () -> {
|
||||
SlowDisplayRegions dr = new SlowDisplayRegions();
|
||||
for (int i = 0; i < n; i++) dr.add(i);
|
||||
for (int i = 0; i < n; i++) dr.remove(i);
|
||||
};
|
||||
}
|
||||
|
||||
static Runnable fastCameraRemoveAll(int n) {
|
||||
return () -> {
|
||||
FastDisplayRegions dr = new FastDisplayRegions();
|
||||
for (int i = 0; i < n; i++) dr.add(i);
|
||||
for (int i = 0; i < n; i++) dr.remove(i);
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Scenario 2 (panda3d-0002): Window teardown — all display regions destroyed.
|
||||
* Deferred shading pipeline: N = render passes (shadow maps + g-buffer + post).
|
||||
* Each DisplayRegion destructor calls do_remove_display_region.
|
||||
*/
|
||||
static Runnable slowWindowTeardown(int n) {
|
||||
return () -> {
|
||||
SlowDisplayRegions total = new SlowDisplayRegions();
|
||||
for (int i = 0; i < n; i++) total.add(i);
|
||||
// Teardown: regions destroyed in reverse-creation order (typical destructor order)
|
||||
for (int i = n - 1; i >= 0; i--) total.remove(i);
|
||||
};
|
||||
}
|
||||
|
||||
static Runnable fastWindowTeardown(int n) {
|
||||
return () -> {
|
||||
FastDisplayRegions total = new FastDisplayRegions();
|
||||
for (int i = 0; i < n; i++) total.add(i);
|
||||
for (int i = n - 1; i >= 0; i--) total.remove(i);
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Scenario 3: VR multi-eye with repeated camera reassignment.
|
||||
* Each eye reassignment removes from old camera and adds to new — repeated K times
|
||||
* across N display regions.
|
||||
*/
|
||||
static Runnable slowVRReassign(int n, int k) {
|
||||
return () -> {
|
||||
SlowDisplayRegions cam = new SlowDisplayRegions();
|
||||
for (int i = 0; i < n; i++) cam.add(i);
|
||||
for (int iter = 0; iter < k; iter++) {
|
||||
for (int i = 0; i < n; i++) {
|
||||
cam.remove(i);
|
||||
cam.add(i);
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
static Runnable fastVRReassign(int n, int k) {
|
||||
return () -> {
|
||||
FastDisplayRegions cam = new FastDisplayRegions();
|
||||
for (int i = 0; i < n; i++) cam.add(i);
|
||||
for (int iter = 0; iter < k; iter++) {
|
||||
for (int i = 0; i < n; i++) {
|
||||
cam.remove(i);
|
||||
cam.add(i);
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
public static void main(String[] args) {
|
||||
System.out.println("Panda3D CWE-407: std::find on vector vs O(1) hash set/map");
|
||||
System.out.println(" defect 1: panda/src/pgraph/camera.cxx line 252");
|
||||
System.out.println(" defect 2: panda/src/display/graphicsOutput.cxx line 1623");
|
||||
System.out.println();
|
||||
|
||||
int N = 800;
|
||||
long slowOps = (long) N * N / 2;
|
||||
|
||||
bench(String.format("camera remove-all N=%d (panda3d-0001)", N),
|
||||
slowCameraRemoveAll(N), fastCameraRemoveAll(N), slowOps, N);
|
||||
|
||||
bench(String.format("window teardown N=%d (panda3d-0002)", N),
|
||||
slowWindowTeardown(N), fastWindowTeardown(N), slowOps, N);
|
||||
|
||||
bench(String.format("VR reassign N=%d x K=10 (panda3d-0001)", N),
|
||||
slowVRReassign(N, 10), fastVRReassign(N, 10), slowOps * 10, (long) N * 10);
|
||||
|
||||
System.out.println();
|
||||
System.out.println("Fix 1 (camera.cxx): pset<DisplayRegion *> — insert/erase O(1).");
|
||||
System.out.println("Fix 2 (graphicsOutput.cxx): pmap<DisplayRegion *, PT(...)> — find/erase O(1).");
|
||||
System.out.println("See patches panda3d-0001-* and panda3d-0002-*");
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue