kdenlive: all 5 MOADs scanned. - MOAD-0001: 8 pre-existing CWE-407 patches confirmed, no new sites found. - MOAD-0002: pCore god object (3704 refs) noted as Intertangle observation. - MOAD-0003: CLEAN (thread_local is execution guard, not request identity). - MOAD-0004: CLEAN (no credential logging). - MOAD-0005 NEW: buildLumaThumbs() called via QtConcurrent::run() writes to MainWindow::m_lumacache (QMap, not thread-safe) without mutex while UI widgets read/write the same map from the main thread — data race on project load. Patch: add QMutex, wrap all m_lumacache access sites. audacity: all 5 MOADs scanned. - MOAD-0001: 2 pre-existing CWE-407 patches confirmed, no new sites found. - MOAD-0002 through MOAD-0005: CLEAN. 9/9 KdenliveTest PASS (added kdenlive-0009 MOAD-0005 threading test).
130 lines
4.4 KiB
Java
130 lines
4.4 KiB
Java
package unit;
|
|
|
|
import java.util.ArrayList;
|
|
import java.util.HashSet;
|
|
import java.util.List;
|
|
import java.util.Set;
|
|
|
|
/**
|
|
* CWE-407 unit test: opencv-0003 — ifInt8Output() O(N*I*L) vs O(N*I)
|
|
*
|
|
* Models modules/dnn/src/onnx/onnx_importer.cpp ifInt8Output():
|
|
*
|
|
* slow() = static vector<String> + std::find, O(L) per lookup
|
|
* called N*I times during ONNX model import (N nodes, I inputs each)
|
|
* total: O(N * I * L)
|
|
*
|
|
* fast() = static unordered_set<String>, O(1) per lookup
|
|
* total: O(N * I)
|
|
*
|
|
* L=35 (size of input8output8 list), N=1000 nodes, I=3 inputs/node
|
|
* Expected ratio: >30x op-count reduction.
|
|
*/
|
|
public class OpenCVOnnxInt8OutputTest {
|
|
|
|
static long slowOps = 0;
|
|
static long fastOps = 0;
|
|
|
|
// The 35-entry list from op_timvx.cpp
|
|
static final List<String> INPUT8OUTPUT8_LIST = new ArrayList<>();
|
|
static final Set<String> INPUT8OUTPUT8_SET = new HashSet<>();
|
|
|
|
static {
|
|
String[] types = {
|
|
"QuantizeLinear", "QLinearAdd", "QLinearMul",
|
|
"QLinearAveragePool", "QLinearGlobalAveragePool",
|
|
"QLinearLeakyRelu", "QLinearSigmoid", "QLinearConcat",
|
|
"QGemm", "QLinearSoftmax", "QLinearConv", "QLinearMatMul",
|
|
"MaxPool", "ReduceMax", "ReduceMin", "Split", "Clip",
|
|
"Abs", "Transpose", "Squeeze", "Flatten", "Unsqueeze",
|
|
"Expand", "Reshape", "Pad", "Gather", "Concat", "Resize",
|
|
"SpaceToDepth", "DepthToSpace", "Pow", "Add", "Sub", "Mul", "Div"
|
|
};
|
|
for (String t : types) {
|
|
INPUT8OUTPUT8_LIST.add(t);
|
|
INPUT8OUTPUT8_SET.add(t);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Slow: O(L) linear scan per call — models std::find on static vector.
|
|
*/
|
|
static boolean ifInt8OutputSlow(String layerType) {
|
|
for (String s : INPUT8OUTPUT8_LIST) {
|
|
slowOps++;
|
|
if (s.equals(layerType)) return true;
|
|
}
|
|
return false;
|
|
}
|
|
|
|
/**
|
|
* Fast: O(1) hash lookup — models unordered_set::count.
|
|
*/
|
|
static boolean ifInt8OutputFast(String layerType) {
|
|
fastOps++;
|
|
return INPUT8OUTPUT8_SET.contains(layerType);
|
|
}
|
|
|
|
/**
|
|
* Simulate ONNX populateNet(): loop over N nodes, I inputs each,
|
|
* call ifInt8Output() per input.
|
|
*/
|
|
static void simulatePopulateNet(int nNodes, int inputsPerNode, boolean useSlow) {
|
|
// Mix of types: half match, half do not
|
|
String[] layerTypes = {"Conv", "Relu", "Add", "Reshape", "BatchNormalization"};
|
|
for (int n = 0; n < nNodes; n++) {
|
|
String layerType = layerTypes[n % layerTypes.length];
|
|
for (int i = 0; i < inputsPerNode; i++) {
|
|
if (useSlow) {
|
|
ifInt8OutputSlow(layerType);
|
|
} else {
|
|
ifInt8OutputFast(layerType);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
public static void main(String[] args) {
|
|
final int N_NODES = 1000;
|
|
final int INPUTS_PER_NODE = 3;
|
|
|
|
// Warm up
|
|
simulatePopulateNet(10, 3, true);
|
|
simulatePopulateNet(10, 3, false);
|
|
slowOps = 0;
|
|
fastOps = 0;
|
|
|
|
// Measure
|
|
simulatePopulateNet(N_NODES, INPUTS_PER_NODE, true);
|
|
long measuredSlowOps = slowOps;
|
|
slowOps = 0;
|
|
|
|
simulatePopulateNet(N_NODES, INPUTS_PER_NODE, false);
|
|
long measuredFastOps = fastOps;
|
|
|
|
double ratio = (double) measuredSlowOps / measuredFastOps;
|
|
|
|
System.out.printf("opencv-0003 ifInt8Output O(N*I*L) vs O(N*I)%n");
|
|
System.out.printf(" N=%d nodes, I=%d inputs, L=%d list entries%n",
|
|
N_NODES, INPUTS_PER_NODE, INPUT8OUTPUT8_LIST.size());
|
|
System.out.printf(" slow ops (vector+find): %d%n", measuredSlowOps);
|
|
System.out.printf(" fast ops (hash set): %d%n", measuredFastOps);
|
|
System.out.printf(" ratio: %.1fx%n", ratio);
|
|
|
|
// Verify correctness: both return same result
|
|
boolean slowResult = ifInt8OutputSlow("Add");
|
|
boolean fastResult = ifInt8OutputFast("Add");
|
|
boolean slowMiss = ifInt8OutputSlow("Conv");
|
|
boolean fastMiss = ifInt8OutputFast("Conv");
|
|
|
|
assert slowResult == fastResult : "hit mismatch";
|
|
assert slowMiss == fastMiss : "miss mismatch";
|
|
assert slowResult : "Add should be in int8output set";
|
|
assert !slowMiss : "Conv should not be in int8output set";
|
|
|
|
assert ratio > 10.0 :
|
|
"Expected >10x ratio, got " + ratio;
|
|
|
|
System.out.println("PASS");
|
|
}
|
|
}
|