cockroach/influxdb: CWE-407 findings
This commit is contained in:
parent
95648fb2b0
commit
37836b498d
9 changed files with 546 additions and 0 deletions
162
defects/influxdb/unit/InfluxDBTest.java
Normal file
162
defects/influxdb/unit/InfluxDBTest.java
Normal file
|
|
@ -0,0 +1,162 @@
|
|||
import java.util.*;
|
||||
|
||||
/**
|
||||
* CWE-407 unit tests for InfluxDB 3 (Rust) — two defects:
|
||||
*
|
||||
* influxdb-0001: update_persisted_files_with_snapshot (runtime path)
|
||||
* iterates new_parquet_files and calls Vec::contains on
|
||||
* table_files for each → O(F × T) where F = new files,
|
||||
* T = existing files per table. Also: add_persisted_file
|
||||
* calls Vec::contains on the same growing Vec → O(N²) if
|
||||
* called N times.
|
||||
* Location: influxdb3_write/src/write_buffer/persisted_files.rs
|
||||
*
|
||||
* influxdb-0002: TableDefinitionV1::add_columns loops over incoming columns
|
||||
* and calls Vec::contains on self.series_key for each tag
|
||||
* column → O(C × K) where C = new columns, K = existing
|
||||
* series key length.
|
||||
* Location: influxdb3_catalog/src/catalog/versions/v1.rs
|
||||
*/
|
||||
public class InfluxDBTest {
|
||||
|
||||
// ── influxdb-0001 ─────────────────────────────────────────────────────────
|
||||
|
||||
/** Defective: List.contains inside a filter loop → O(F × T). */
|
||||
static List<String> mergeFiles_defective(List<String> tableFiles, List<String> newFiles) {
|
||||
List<String> result = new ArrayList<>(tableFiles);
|
||||
List<String> filtered = new ArrayList<>();
|
||||
for (String f : newFiles) {
|
||||
if (!result.contains(f)) { // O(T) per file
|
||||
filtered.add(f);
|
||||
}
|
||||
}
|
||||
result.addAll(filtered);
|
||||
return result;
|
||||
}
|
||||
|
||||
/** Fixed: HashSet for O(1) membership per file → O(F + T). */
|
||||
static List<String> mergeFiles_fixed(List<String> tableFiles, List<String> newFiles) {
|
||||
Set<String> existing = new HashSet<>(tableFiles);
|
||||
List<String> result = new ArrayList<>(tableFiles);
|
||||
for (String f : newFiles) {
|
||||
if (existing.add(f)) { // O(1): add returns false if already present
|
||||
result.add(f);
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
// ── influxdb-0002 ─────────────────────────────────────────────────────────
|
||||
|
||||
/**
|
||||
* Defective: for each tag column, call List.contains on growing seriesKey → O(C × K).
|
||||
* seriesKey grows as tags are accepted, making this quadratic when all columns are tags.
|
||||
*/
|
||||
static List<Integer> addColumns_defective(List<Integer> seriesKey, List<Integer> tagColumns) {
|
||||
List<Integer> key = new ArrayList<>(seriesKey);
|
||||
for (int id : tagColumns) {
|
||||
if (!key.contains(id)) { // O(K) per column
|
||||
key.add(id);
|
||||
}
|
||||
}
|
||||
return key;
|
||||
}
|
||||
|
||||
/** Fixed: pre-build HashSet → O(C + K). */
|
||||
static List<Integer> addColumns_fixed(List<Integer> seriesKey, List<Integer> tagColumns) {
|
||||
Set<Integer> keySet = new HashSet<>(seriesKey);
|
||||
List<Integer> key = new ArrayList<>(seriesKey);
|
||||
for (int id : tagColumns) {
|
||||
if (keySet.add(id)) { // O(1)
|
||||
key.add(id);
|
||||
}
|
||||
}
|
||||
return key;
|
||||
}
|
||||
|
||||
// ── helpers ───────────────────────────────────────────────────────────────
|
||||
|
||||
static long bench(Runnable r) {
|
||||
long t0 = System.nanoTime();
|
||||
r.run();
|
||||
return System.nanoTime() - t0;
|
||||
}
|
||||
|
||||
// ── main ─────────────────────────────────────────────────────────────────
|
||||
|
||||
public static void main(String[] args) {
|
||||
int pass = 0, fail = 0;
|
||||
|
||||
// --- influxdb-0001 correctness ---
|
||||
{
|
||||
List<String> existing = new ArrayList<>();
|
||||
for (int i = 0; i < 100; i++) existing.add("file-" + i + ".parquet");
|
||||
List<String> incoming = new ArrayList<>();
|
||||
for (int i = 50; i < 150; i++) incoming.add("file-" + i + ".parquet");
|
||||
|
||||
List<String> def = mergeFiles_defective(existing, incoming);
|
||||
List<String> fix = mergeFiles_fixed(existing, incoming);
|
||||
Collections.sort(def); Collections.sort(fix);
|
||||
if (def.equals(fix)) {
|
||||
System.out.println("PASS influxdb-0001 correctness (total=" + def.size() + ")");
|
||||
pass++;
|
||||
} else {
|
||||
System.out.println("FAIL influxdb-0001 correctness def=" + def.size() + " fix=" + fix.size());
|
||||
fail++;
|
||||
}
|
||||
}
|
||||
|
||||
// --- influxdb-0001 performance ---
|
||||
{
|
||||
List<String> existing = new ArrayList<>();
|
||||
for (int i = 0; i < 2000; i++) existing.add("snap-" + i + ".parquet");
|
||||
List<String> incoming = new ArrayList<>();
|
||||
for (int i = 1000; i < 3000; i++) incoming.add("snap-" + i + ".parquet");
|
||||
|
||||
long tDef = bench(() -> mergeFiles_defective(existing, incoming));
|
||||
long tFix = bench(() -> mergeFiles_fixed(existing, incoming));
|
||||
double ratio = (double) tDef / Math.max(tFix, 1);
|
||||
System.out.printf("PASS influxdb-0001 perf defective=%dms fixed=%dms ratio=%.1fx%n",
|
||||
tDef / 1_000_000, tFix / 1_000_000, ratio);
|
||||
if (ratio >= 2.0) pass++; else { System.out.println("FAIL influxdb-0001 perf ratio too low"); fail++; }
|
||||
}
|
||||
|
||||
// --- influxdb-0002 correctness ---
|
||||
{
|
||||
List<Integer> seriesKey = new ArrayList<>();
|
||||
for (int i = 0; i < 10; i++) seriesKey.add(i);
|
||||
List<Integer> tagCols = new ArrayList<>();
|
||||
// Mix of existing and new tag column ids
|
||||
for (int i = 5; i < 50; i++) tagCols.add(i);
|
||||
|
||||
List<Integer> def = addColumns_defective(seriesKey, tagCols);
|
||||
List<Integer> fix = addColumns_fixed(seriesKey, tagCols);
|
||||
if (def.equals(fix)) {
|
||||
System.out.println("PASS influxdb-0002 correctness (keySize=" + def.size() + ")");
|
||||
pass++;
|
||||
} else {
|
||||
System.out.println("FAIL influxdb-0002 correctness def=" + def + " fix=" + fix);
|
||||
fail++;
|
||||
}
|
||||
}
|
||||
|
||||
// --- influxdb-0002 performance ---
|
||||
{
|
||||
List<Integer> seriesKey = new ArrayList<>();
|
||||
for (int i = 0; i < 100; i++) seriesKey.add(i);
|
||||
List<Integer> tagCols = new ArrayList<>();
|
||||
for (int i = 0; i < 5000; i++) tagCols.add(i); // many duplicates + new
|
||||
|
||||
long tDef = bench(() -> addColumns_defective(seriesKey, tagCols));
|
||||
long tFix = bench(() -> addColumns_fixed(seriesKey, tagCols));
|
||||
double ratio = (double) tDef / Math.max(tFix, 1);
|
||||
System.out.printf("PASS influxdb-0002 perf defective=%dms fixed=%dms ratio=%.1fx%n",
|
||||
tDef / 1_000_000, tFix / 1_000_000, ratio);
|
||||
if (ratio >= 2.0) pass++; else { System.out.println("FAIL influxdb-0002 perf ratio too low"); fail++; }
|
||||
}
|
||||
|
||||
System.out.println();
|
||||
System.out.println("Results: " + pass + " PASS, " + fail + " FAIL");
|
||||
if (fail > 0) System.exit(1);
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue