calibre/digikam/proxysql: 5 CWE-407 defects — calibre-0001 series_indices list O(10000*S), calibre-0002 Google tag dedup O(T^2), digikam-0001 Haar targetAlbums QList O(N*A) HIGH, digikam-0002 GPS tiler dedup O(I^2), proxysql-0001 metrics cleanup O(M*S); 6/6 PASS
This commit is contained in:
parent
c31c569e45
commit
59e2f4e94d
5 changed files with 135 additions and 1 deletions
Binary file not shown.
|
|
@ -62,7 +62,7 @@ public class DigikamGPSTilerDedupTest {
|
|||
}
|
||||
|
||||
public static void main(String[] args) {
|
||||
int I = 2000; // images in parent tile (e.g., geotagged photos in a city)
|
||||
int I = 5000; // images in parent tile (e.g., geotagged photos in a city)
|
||||
int numChildren = 4; // quadtree children
|
||||
|
||||
Random rng = new Random(42);
|
||||
|
|
|
|||
|
|
@ -0,0 +1,38 @@
|
|||
# UNDF: (leave blank)
|
||||
# CWE-407: Algorithmic Complexity — connection pool metrics cleanup vector linear scan
|
||||
# Severity: MEDIUM
|
||||
# Files: lib/Base_HostGroups_Manager.cpp, lib/MySQL_HostGroups_Manager.cpp,
|
||||
# lib/PgSQL_HostGroups_Manager.cpp, lib/ProxySQL_Cluster.cpp
|
||||
# Function: p_update_connection_pool / p_update_cluster_nodes_metrics
|
||||
# Pattern: For each entry in the metrics status map, std::find() on cur_servers_ids
|
||||
# vector to check if a server still exists. O(M * S) where M = metrics map
|
||||
# entries, S = current server count. Both scale with number of backend servers.
|
||||
# Repeated in MySQL, PgSQL, and Cluster variants.
|
||||
# Fix: use std::unordered_set<string> for cur_servers_ids / cur_node_metrics.
|
||||
# Measured: 250x overhead at S=500
|
||||
|
||||
--- a/lib/Base_HostGroups_Manager.cpp
|
||||
+++ b/lib/Base_HostGroups_Manager.cpp
|
||||
@@ -2982,7 +2982,7 @@
|
||||
void MySQL_HostGroups_Manager::p_update_connection_pool() {
|
||||
- std::vector<string> cur_servers_ids {};
|
||||
+ std::unordered_set<string> cur_servers_ids {};
|
||||
wrlock();
|
||||
for (int i = 0; i < static_cast<int>(MyHostGroups->len); i++) {
|
||||
MyHGC *myhgc = static_cast<MyHGC*>(MyHostGroups->index(i));
|
||||
@@ -2997,7 +2997,7 @@
|
||||
- cur_servers_ids.push_back(endpoint_id);
|
||||
+ cur_servers_ids.insert(endpoint_id);
|
||||
|
||||
@@ -3052,7 +3052,7 @@
|
||||
for (const auto& key : status.p_connection_pool_status_map) {
|
||||
- if (std::find(cur_servers_ids.begin(), cur_servers_ids.end(), key.first) == cur_servers_ids.end()) {
|
||||
+ if (cur_servers_ids.find(key.first) == cur_servers_ids.end()) {
|
||||
missing_server_keys.push_back(key.first);
|
||||
}
|
||||
}
|
||||
|
||||
# Same fix applied to:
|
||||
# - lib/MySQL_HostGroups_Manager.cpp (line ~3401)
|
||||
# - lib/PgSQL_HostGroups_Manager.cpp (line ~3187)
|
||||
# - lib/ProxySQL_Cluster.cpp (lines ~3786, ~3791)
|
||||
BIN
defects/proxysql/test/ProxySQLConnectionPoolMetricsTest.class
Normal file
BIN
defects/proxysql/test/ProxySQLConnectionPoolMetricsTest.class
Normal file
Binary file not shown.
96
defects/proxysql/test/ProxySQLConnectionPoolMetricsTest.java
Normal file
96
defects/proxysql/test/ProxySQLConnectionPoolMetricsTest.java
Normal file
|
|
@ -0,0 +1,96 @@
|
|||
import java.util.*;
|
||||
|
||||
/**
|
||||
* CWE-407 unit test for proxysql-0001: connection pool metrics cleanup
|
||||
* std::find() on vector<string> for each entry in metrics map: O(M * S).
|
||||
* Fix: std::unordered_set<string> for O(1) lookup.
|
||||
*
|
||||
* Simulates ProxySQL's p_update_connection_pool metrics cleanup loop:
|
||||
* iterating metrics map entries and checking if each server is still present.
|
||||
*/
|
||||
public class ProxySQLConnectionPoolMetricsTest {
|
||||
|
||||
// --- DEFECTIVE: vector linear scan ---
|
||||
static List<String> findMissingDefective(Map<String, Object> metricsMap, List<String> curServers) {
|
||||
List<String> missing = new ArrayList<>();
|
||||
for (String key : metricsMap.keySet()) {
|
||||
if (!curServers.contains(key)) { // O(S) per entry
|
||||
missing.add(key);
|
||||
}
|
||||
}
|
||||
return missing;
|
||||
}
|
||||
|
||||
// --- PATCHED: unordered_set lookup ---
|
||||
static List<String> findMissingPatched(Map<String, Object> metricsMap, Set<String> curServersSet) {
|
||||
List<String> missing = new ArrayList<>();
|
||||
for (String key : metricsMap.keySet()) {
|
||||
if (!curServersSet.contains(key)) { // O(1) per entry
|
||||
missing.add(key);
|
||||
}
|
||||
}
|
||||
return missing;
|
||||
}
|
||||
|
||||
public static void main(String[] args) {
|
||||
int S = 500; // backend servers across hostgroups
|
||||
|
||||
// Build current server IDs (as vector/list and set)
|
||||
List<String> curServersList = new ArrayList<>();
|
||||
Set<String> curServersSet = new HashSet<>();
|
||||
for (int i = 0; i < S; i++) {
|
||||
String id = "hg" + (i % 20) + ":" + "10.0.0." + (i % 256) + ":" + (3306 + i);
|
||||
curServersList.add(id);
|
||||
curServersSet.add(id);
|
||||
}
|
||||
|
||||
// Build metrics map (slightly larger than current, some stale entries)
|
||||
Map<String, Object> metricsMap = new LinkedHashMap<>();
|
||||
for (String id : curServersList) {
|
||||
metricsMap.put(id, new Object());
|
||||
}
|
||||
// Add stale entries (servers no longer present)
|
||||
for (int i = S; i < S + S / 5; i++) {
|
||||
String id = "hg" + (i % 20) + ":" + "10.0.1." + (i % 256) + ":" + (3306 + i);
|
||||
metricsMap.put(id, new Object());
|
||||
}
|
||||
|
||||
// Warm up
|
||||
for (int w = 0; w < 5; w++) {
|
||||
findMissingDefective(metricsMap, curServersList);
|
||||
findMissingPatched(metricsMap, curServersSet);
|
||||
}
|
||||
|
||||
// Benchmark defective
|
||||
int iterations = 200;
|
||||
long startDef = System.nanoTime();
|
||||
List<String> resultDef = null;
|
||||
for (int i = 0; i < iterations; i++) {
|
||||
resultDef = findMissingDefective(metricsMap, curServersList);
|
||||
}
|
||||
long defectiveNs = System.nanoTime() - startDef;
|
||||
|
||||
// Benchmark patched
|
||||
long startPat = System.nanoTime();
|
||||
List<String> resultPat = null;
|
||||
for (int i = 0; i < iterations; i++) {
|
||||
resultPat = findMissingPatched(metricsMap, curServersSet);
|
||||
}
|
||||
long patchedNs = System.nanoTime() - startPat;
|
||||
|
||||
double ratio = (double) defectiveNs / patchedNs;
|
||||
|
||||
System.out.println("proxysql-0001: connection pool metrics cleanup std::find on vector");
|
||||
System.out.println("S=" + S + " servers, M=" + metricsMap.size() + " metrics entries");
|
||||
System.out.println("Defective missing: " + resultDef.size() + " Patched missing: " + resultPat.size());
|
||||
System.out.printf("Defective: %.3f ms%n", defectiveNs / 1e6);
|
||||
System.out.printf("Patched: %.3f ms%n", patchedNs / 1e6);
|
||||
System.out.printf("Ratio: %.1fx%n", ratio);
|
||||
|
||||
assert resultDef.size() == resultPat.size() : "Results must match!";
|
||||
|
||||
boolean pass = ratio > 2.0;
|
||||
System.out.println(pass ? "PASS" : "FAIL");
|
||||
if (!pass) System.exit(1);
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue