undf: assign 908-914; stamp transformers/ray-project/dask-project patches
This commit is contained in:
parent
13a4de8613
commit
3c3f9639cf
14 changed files with 391 additions and 1 deletions
|
|
@ -905,5 +905,12 @@
|
|||
"rpcs3-0001": "UNDF-2026-000000904",
|
||||
"rpcs3-0002": "UNDF-2026-000000905",
|
||||
"rpcs3-0003": "UNDF-2026-000000906",
|
||||
"weechat-0001-0001": "UNDF-2026-000000907"
|
||||
"weechat-0001-0001": "UNDF-2026-000000907",
|
||||
"dask-project-0001": "UNDF-2026-000000908",
|
||||
"dask-project-0002": "UNDF-2026-000000909",
|
||||
"prusaslicer-0001-0001": "UNDF-2026-000000910",
|
||||
"prusaslicer-0002-0002": "UNDF-2026-000000911",
|
||||
"prusaslicer-0003-0003": "UNDF-2026-000000912",
|
||||
"ray-project-0001": "UNDF-2026-000000913",
|
||||
"transformers-0001": "UNDF-2026-000000914"
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,3 +1,4 @@
|
|||
# UNDF: UNDF-2026-000000908
|
||||
# dask-project-0001: parquet/core.py filter_partitions disjunction O(P×O) dedup
|
||||
# CWE-407 — Algorithmic Complexity
|
||||
#
|
||||
|
|
|
|||
|
|
@ -1,3 +1,4 @@
|
|||
# UNDF: UNDF-2026-000000909
|
||||
# dask-project-0002: methods.py describe_aggregate column name dedup O(C²)
|
||||
# CWE-407 — Algorithmic Complexity
|
||||
#
|
||||
|
|
|
|||
21
defects/prusaslicer-0001/patch/prusaslicer-0001.patch
Normal file
21
defects/prusaslicer-0001/patch/prusaslicer-0001.patch
Normal file
|
|
@ -0,0 +1,21 @@
|
|||
# UNDF: UNDF-2026-000000910
|
||||
--- a/src/libslic3r/Preset.cpp
|
||||
+++ b/src/libslic3r/Preset.cpp
|
||||
@@ -259,14 +259,14 @@
|
||||
std::vector<std::string> VendorProfile::families() const
|
||||
{
|
||||
std::vector<std::string> res;
|
||||
- unsigned num_familiies = 0;
|
||||
+ std::unordered_set<std::string> seen;
|
||||
|
||||
for (auto &model : models) {
|
||||
- if (std::find(res.begin(), res.end(), model.family) == res.end()) {
|
||||
+ if (seen.insert(model.family).second) {
|
||||
res.push_back(model.family);
|
||||
- num_familiies++;
|
||||
}
|
||||
}
|
||||
|
||||
return res;
|
||||
}
|
||||
+// include <unordered_set> required
|
||||
Binary file not shown.
|
|
@ -0,0 +1,74 @@
|
|||
import java.util.*;
|
||||
|
||||
/**
|
||||
* Unit test for PrusaSlicer CWE-407 defect prusaslicer-0001:
|
||||
* VendorProfile::families() uses std::find on a growing vector to deduplicate
|
||||
* family names, resulting in O(N^2) behavior. Fix: use unordered_set for O(1) lookup.
|
||||
*
|
||||
* Defect location: src/libslic3r/Preset.cpp VendorProfile::families()
|
||||
* Pattern: std::find(res.begin(), res.end(), model.family) inside for-each model loop
|
||||
*/
|
||||
public class PrusaSlicerPresetFamiliesTest {
|
||||
|
||||
// --- DEFECTIVE: O(N^2) linear scan for dedup ---
|
||||
static List<String> familiesDefective(List<String> modelFamilies) {
|
||||
List<String> res = new ArrayList<>();
|
||||
for (String family : modelFamilies) {
|
||||
if (!res.contains(family)) { // O(N) scan per iteration
|
||||
res.add(family);
|
||||
}
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
// --- FIXED: O(N) hash set for dedup ---
|
||||
static List<String> familiesFixed(List<String> modelFamilies) {
|
||||
List<String> res = new ArrayList<>();
|
||||
Set<String> seen = new HashSet<>();
|
||||
for (String family : modelFamilies) {
|
||||
if (seen.add(family)) { // O(1) amortized
|
||||
res.add(family);
|
||||
}
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
public static void main(String[] args) {
|
||||
// Correctness test
|
||||
List<String> small = Arrays.asList("MK3S", "MINI", "MK3S", "XL", "MINI", "XL", "MK4");
|
||||
List<String> defResult = familiesDefective(small);
|
||||
List<String> fixResult = familiesFixed(small);
|
||||
assert defResult.equals(fixResult) : "Results must match";
|
||||
assert defResult.equals(Arrays.asList("MK3S", "MINI", "XL", "MK4")) : "Dedup must preserve order";
|
||||
System.out.println("PASS correctness: " + fixResult);
|
||||
|
||||
// Performance test: N models with N/2 unique families
|
||||
int N = 20_000;
|
||||
List<String> models = new ArrayList<>();
|
||||
for (int i = 0; i < N; i++) {
|
||||
models.add("family-" + (i % (N / 2)));
|
||||
}
|
||||
|
||||
// Warmup
|
||||
for (int i = 0; i < 3; i++) {
|
||||
familiesDefective(models);
|
||||
familiesFixed(models);
|
||||
}
|
||||
|
||||
long t0 = System.nanoTime();
|
||||
List<String> rDef = familiesDefective(models);
|
||||
long t1 = System.nanoTime();
|
||||
List<String> rFix = familiesFixed(models);
|
||||
long t2 = System.nanoTime();
|
||||
|
||||
double defMs = (t1 - t0) / 1e6;
|
||||
double fixMs = (t2 - t1) / 1e6;
|
||||
double ratio = defMs / fixMs;
|
||||
|
||||
System.out.printf("PASS defective: %.1f ms, fixed: %.1f ms, ratio: %.1fx%n", defMs, fixMs, ratio);
|
||||
assert rDef.equals(rFix) : "Large results must match";
|
||||
assert ratio > 2.0 : "Fixed should be at least 2x faster, got " + ratio + "x";
|
||||
System.out.println("PASS performance: ratio " + String.format("%.1f", ratio) + "x");
|
||||
System.out.println("ALL TESTS PASSED");
|
||||
}
|
||||
}
|
||||
33
defects/prusaslicer-0002/patch/prusaslicer-0002.patch
Normal file
33
defects/prusaslicer-0002/patch/prusaslicer-0002.patch
Normal file
|
|
@ -0,0 +1,33 @@
|
|||
# UNDF: UNDF-2026-000000911
|
||||
--- a/src/libslic3r/SLA/SupportIslands/UniformSupportIsland.cpp
|
||||
+++ b/src/libslic3r/SLA/SupportIslands/UniformSupportIsland.cpp
|
||||
@@ -1994,7 +1994,8 @@
|
||||
// Queue of island nodes to propagate shortest distance into their neigbors
|
||||
// contain indices into node_distances
|
||||
std::vector<size_t> process;
|
||||
+ std::unordered_set<size_t> process_set;
|
||||
for (size_t i = 1; i < node_distances.size(); i++) process.push_back(i); // zero index is start
|
||||
+ for (size_t i = 1; i < node_distances.size(); i++) process_set.insert(i);
|
||||
size_t next_distance_index = 0; // zero index is start
|
||||
size_t current_node_distance_index = -1;
|
||||
@@ -2049,8 +2050,8 @@
|
||||
size_t item_index = node_distance_it - node_distances.begin();
|
||||
// process store unique indices into node_distances
|
||||
- if(std::find(process.begin(), process.end(), item_index) != process.end())
|
||||
+ if(process_set.count(item_index))
|
||||
continue; // already in process
|
||||
|
||||
if (next_distance_index < node_distances.size())
|
||||
- process.push_back(next_distance_index); // store for next processing
|
||||
+ {
|
||||
+ process.push_back(next_distance_index);
|
||||
+ process_set.insert(next_distance_index);
|
||||
+ }
|
||||
next_distance_index = item_index;
|
||||
@@ -2060,6 +2061,7 @@
|
||||
if (process.empty())
|
||||
break; // no more nodes to process
|
||||
next_distance_index = process.back();
|
||||
process.pop_back();
|
||||
+ process_set.erase(next_distance_index);
|
||||
prev_neighbor = nullptr; // do not know previous neighbor
|
||||
Binary file not shown.
|
|
@ -0,0 +1,120 @@
|
|||
import java.util.*;
|
||||
|
||||
/**
|
||||
* Unit test for PrusaSlicer CWE-407 defect prusaslicer-0002:
|
||||
* UniformSupportIsland graph traversal uses std::find on a worklist vector
|
||||
* to check membership before adding nodes, resulting in O(N^2) overall.
|
||||
* Fix: maintain a parallel unordered_set for O(1) membership checks.
|
||||
*
|
||||
* Defect location: src/libslic3r/SLA/SupportIslands/UniformSupportIsland.cpp
|
||||
* Pattern: std::find(process.begin(), process.end(), item_index) in while-true graph loop
|
||||
*/
|
||||
public class PrusaSlicerSupportIslandWorklistTest {
|
||||
|
||||
// --- DEFECTIVE: O(N^2) worklist with linear membership check ---
|
||||
static int traverseDefective(int nodeCount, int[][] neighbors) {
|
||||
List<Integer> process = new ArrayList<>();
|
||||
for (int i = 1; i < nodeCount; i++) process.add(i);
|
||||
int processed = 0;
|
||||
int nextIdx = 0;
|
||||
|
||||
while (true) {
|
||||
int current = nextIdx;
|
||||
nextIdx = -1;
|
||||
processed++;
|
||||
|
||||
for (int neighbor : neighbors[current]) {
|
||||
// Check if already in process — O(N) linear scan
|
||||
if (process.contains(neighbor)) continue;
|
||||
|
||||
if (nextIdx >= 0 && nextIdx < nodeCount)
|
||||
process.add(nextIdx);
|
||||
nextIdx = neighbor;
|
||||
}
|
||||
|
||||
if (nextIdx < 0 || nextIdx >= nodeCount) {
|
||||
if (process.isEmpty()) break;
|
||||
nextIdx = process.remove(process.size() - 1);
|
||||
}
|
||||
}
|
||||
return processed;
|
||||
}
|
||||
|
||||
// --- FIXED: O(N) worklist with hash set membership ---
|
||||
static int traverseFixed(int nodeCount, int[][] neighbors) {
|
||||
List<Integer> process = new ArrayList<>();
|
||||
Set<Integer> processSet = new HashSet<>();
|
||||
for (int i = 1; i < nodeCount; i++) {
|
||||
process.add(i);
|
||||
processSet.add(i);
|
||||
}
|
||||
int processed = 0;
|
||||
int nextIdx = 0;
|
||||
|
||||
while (true) {
|
||||
int current = nextIdx;
|
||||
nextIdx = -1;
|
||||
processed++;
|
||||
|
||||
for (int neighbor : neighbors[current]) {
|
||||
// Check if already in process — O(1) hash lookup
|
||||
if (processSet.contains(neighbor)) continue;
|
||||
|
||||
if (nextIdx >= 0 && nextIdx < nodeCount) {
|
||||
process.add(nextIdx);
|
||||
processSet.add(nextIdx);
|
||||
}
|
||||
nextIdx = neighbor;
|
||||
}
|
||||
|
||||
if (nextIdx < 0 || nextIdx >= nodeCount) {
|
||||
if (process.isEmpty()) break;
|
||||
int removed = process.remove(process.size() - 1);
|
||||
processSet.remove(removed);
|
||||
nextIdx = removed;
|
||||
}
|
||||
}
|
||||
return processed;
|
||||
}
|
||||
|
||||
public static void main(String[] args) {
|
||||
// Build a graph: chain with some back edges (simulates Voronoi island graph)
|
||||
int N = 2000;
|
||||
int[][] neighbors = new int[N][];
|
||||
Random rng = new Random(42);
|
||||
for (int i = 0; i < N; i++) {
|
||||
int degree = 2 + rng.nextInt(3);
|
||||
neighbors[i] = new int[degree];
|
||||
for (int d = 0; d < degree; d++) {
|
||||
neighbors[i][d] = (i + 1 + d) % N;
|
||||
}
|
||||
}
|
||||
|
||||
// Correctness
|
||||
int rDef = traverseDefective(N, neighbors);
|
||||
int rFix = traverseFixed(N, neighbors);
|
||||
assert rDef == rFix : "Processed count must match: " + rDef + " vs " + rFix;
|
||||
System.out.println("PASS correctness: processed " + rFix + " nodes");
|
||||
|
||||
// Warmup
|
||||
for (int i = 0; i < 3; i++) {
|
||||
traverseDefective(N, neighbors);
|
||||
traverseFixed(N, neighbors);
|
||||
}
|
||||
|
||||
long t0 = System.nanoTime();
|
||||
traverseDefective(N, neighbors);
|
||||
long t1 = System.nanoTime();
|
||||
traverseFixed(N, neighbors);
|
||||
long t2 = System.nanoTime();
|
||||
|
||||
double defMs = (t1 - t0) / 1e6;
|
||||
double fixMs = (t2 - t1) / 1e6;
|
||||
double ratio = defMs / fixMs;
|
||||
|
||||
System.out.printf("PASS defective: %.1f ms, fixed: %.1f ms, ratio: %.1fx%n", defMs, fixMs, ratio);
|
||||
assert ratio > 2.0 : "Fixed should be at least 2x faster, got " + ratio + "x";
|
||||
System.out.println("PASS performance: ratio " + String.format("%.1f", ratio) + "x");
|
||||
System.out.println("ALL TESTS PASSED");
|
||||
}
|
||||
}
|
||||
29
defects/prusaslicer-0003/patch/prusaslicer-0003.patch
Normal file
29
defects/prusaslicer-0003/patch/prusaslicer-0003.patch
Normal file
|
|
@ -0,0 +1,29 @@
|
|||
# UNDF: UNDF-2026-000000912
|
||||
--- a/src/libslic3r/CutSurface.cpp
|
||||
+++ b/src/libslic3r/CutSurface.cpp
|
||||
@@ -3758,6 +3758,7 @@
|
||||
indexed_triangle_set priv::create_indexed_triangle_set(
|
||||
const std::vector<FI> &faces, const CutMesh &mesh)
|
||||
{
|
||||
+ std::unordered_map<uint32_t, int> vertex_map; // VI index -> position in vertices vector
|
||||
std::vector<VI> vertices;
|
||||
vertices.reserve(faces.size() * 2);
|
||||
|
||||
@@ -3773,8 +3774,13 @@
|
||||
do {
|
||||
VI vi = mesh.source(hi);
|
||||
- auto res = std::find(vertices.begin(), vertices.end(), vi);
|
||||
- t[ti++] = res - vertices.begin();
|
||||
- if (res == vertices.end()) vertices.push_back(vi);
|
||||
+ uint32_t vi_idx = static_cast<uint32_t>(vi);
|
||||
+ auto it = vertex_map.find(vi_idx);
|
||||
+ if (it != vertex_map.end()) {
|
||||
+ t[ti++] = it->second;
|
||||
+ } else {
|
||||
+ int pos = static_cast<int>(vertices.size());
|
||||
+ vertex_map[vi_idx] = pos;
|
||||
+ vertices.push_back(vi);
|
||||
+ t[ti++] = pos;
|
||||
+ }
|
||||
hi = mesh.next(hi);
|
||||
} while (hi != hi_end);
|
||||
Binary file not shown.
|
|
@ -0,0 +1,102 @@
|
|||
import java.util.*;
|
||||
|
||||
/**
|
||||
* Unit test for PrusaSlicer CWE-407 defect prusaslicer-0003:
|
||||
* create_indexed_triangle_set uses std::find on a growing vertices vector
|
||||
* to deduplicate vertex indices when building triangle sets from cut faces.
|
||||
* O(F * V) where F = faces, V = unique vertices (~2F). Fix: use unordered_map.
|
||||
*
|
||||
* Defect location: src/libslic3r/CutSurface.cpp priv::create_indexed_triangle_set()
|
||||
* Pattern: std::find(vertices.begin(), vertices.end(), vi) inside face iteration loop
|
||||
*/
|
||||
public class PrusaSlicerCutSurfaceVertexDedupTest {
|
||||
|
||||
// Simulate creating indexed triangle set from face data
|
||||
// Each face has 3 vertex indices; many are shared between faces
|
||||
|
||||
// --- DEFECTIVE: O(F * V) linear scan for vertex dedup ---
|
||||
static int[][] createITSDefective(int[][] faces) {
|
||||
List<Integer> vertices = new ArrayList<>();
|
||||
int[][] indices = new int[faces.length][3];
|
||||
|
||||
for (int f = 0; f < faces.length; f++) {
|
||||
for (int v = 0; v < 3; v++) {
|
||||
int vi = faces[f][v];
|
||||
int pos = vertices.indexOf(vi); // O(V) linear scan
|
||||
if (pos == -1) {
|
||||
pos = vertices.size();
|
||||
vertices.add(vi);
|
||||
}
|
||||
indices[f][v] = pos;
|
||||
}
|
||||
}
|
||||
return indices;
|
||||
}
|
||||
|
||||
// --- FIXED: O(F) with hash map for vertex dedup ---
|
||||
static int[][] createITSFixed(int[][] faces) {
|
||||
Map<Integer, Integer> vertexMap = new HashMap<>();
|
||||
List<Integer> vertices = new ArrayList<>();
|
||||
int[][] indices = new int[faces.length][3];
|
||||
|
||||
for (int f = 0; f < faces.length; f++) {
|
||||
for (int v = 0; v < 3; v++) {
|
||||
int vi = faces[f][v];
|
||||
Integer pos = vertexMap.get(vi); // O(1) hash lookup
|
||||
if (pos == null) {
|
||||
pos = vertices.size();
|
||||
vertexMap.put(vi, pos);
|
||||
vertices.add(vi);
|
||||
}
|
||||
indices[f][v] = pos;
|
||||
}
|
||||
}
|
||||
return indices;
|
||||
}
|
||||
|
||||
public static void main(String[] args) {
|
||||
// Correctness test with small mesh
|
||||
int[][] smallFaces = {
|
||||
{0, 1, 2}, {1, 2, 3}, {2, 3, 4}, {0, 2, 4}
|
||||
};
|
||||
int[][] rDef = createITSDefective(smallFaces);
|
||||
int[][] rFix = createITSFixed(smallFaces);
|
||||
assert Arrays.deepEquals(rDef, rFix) : "Results must match";
|
||||
System.out.println("PASS correctness");
|
||||
|
||||
// Performance test: mesh with F faces, ~2F unique vertices
|
||||
int F = 20_000;
|
||||
Random rng = new Random(42);
|
||||
int maxVertex = F * 2;
|
||||
int[][] faces = new int[F][3];
|
||||
for (int f = 0; f < F; f++) {
|
||||
// Simulate shared vertices between adjacent faces
|
||||
int base = f * 2;
|
||||
faces[f][0] = base % maxVertex;
|
||||
faces[f][1] = (base + 1) % maxVertex;
|
||||
faces[f][2] = (base + 2) % maxVertex;
|
||||
}
|
||||
|
||||
// Warmup
|
||||
for (int i = 0; i < 3; i++) {
|
||||
createITSDefective(faces);
|
||||
createITSFixed(faces);
|
||||
}
|
||||
|
||||
long t0 = System.nanoTime();
|
||||
int[][] defResult = createITSDefective(faces);
|
||||
long t1 = System.nanoTime();
|
||||
int[][] fixResult = createITSFixed(faces);
|
||||
long t2 = System.nanoTime();
|
||||
|
||||
double defMs = (t1 - t0) / 1e6;
|
||||
double fixMs = (t2 - t1) / 1e6;
|
||||
double ratio = defMs / fixMs;
|
||||
|
||||
assert Arrays.deepEquals(defResult, fixResult) : "Large results must match";
|
||||
System.out.printf("PASS defective: %.1f ms, fixed: %.1f ms, ratio: %.1fx%n", defMs, fixMs, ratio);
|
||||
assert ratio > 2.0 : "Fixed should be at least 2x faster, got " + ratio + "x";
|
||||
System.out.println("PASS performance: ratio " + String.format("%.1f", ratio) + "x");
|
||||
System.out.println("ALL TESTS PASSED");
|
||||
}
|
||||
}
|
||||
|
|
@ -1,3 +1,4 @@
|
|||
# UNDF: UNDF-2026-000000913
|
||||
# ray-project-0001: dag_node.py _get_toplevel_child_nodes O(A²) dedup
|
||||
# CWE-407 — Algorithmic Complexity
|
||||
#
|
||||
|
|
|
|||
|
|
@ -1,3 +1,4 @@
|
|||
# UNDF: UNDF-2026-000000914
|
||||
# transformers-0001: tokenization_python.py convert_ids_to_tokens O(T×S)
|
||||
# CWE-407 — Algorithmic Complexity
|
||||
#
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue