wave6a/6b: elasticsearch/opensearch/solr/llvm-0004-5/linux-0005-6/gcc-0002/tokio/actix-web + love2d/raylib new defects
This commit is contained in:
parent
a4b0cf4edd
commit
3eebda37e1
38 changed files with 3651 additions and 0 deletions
156
defects/elasticsearch/unit/IngestDocumentAppendContains.java
Normal file
156
defects/elasticsearch/unit/IngestDocumentAppendContains.java
Normal file
|
|
@ -0,0 +1,156 @@
|
|||
package unit;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
* CWE-407 unit test: elasticsearch-002
|
||||
* IngestDocument.java:960 — list.contains(val) (ArrayList) inside append loop
|
||||
* when allowDuplicates=false — O(n²) deduplication.
|
||||
*
|
||||
* Slow path: ArrayList.contains() per item — O(existing_size) each.
|
||||
* Fast path: HashSet.add() — returns false if duplicate, O(1) amortized.
|
||||
*
|
||||
* Compile: javac -d . IngestDocumentAppendContains.java
|
||||
* Run: java -ea unit.IngestDocumentAppendContains
|
||||
*/
|
||||
public class IngestDocumentAppendContains {
|
||||
|
||||
/**
|
||||
* Simulates the defective appendValues logic.
|
||||
* Returns total comparison count across all contains() calls.
|
||||
*/
|
||||
static long slowAppend(List<Object> list, List<Object> valuesToAppend) {
|
||||
long comparisons = 0;
|
||||
for (Object val : valuesToAppend) {
|
||||
// Charge the cost of a linear scan through `list` at current size
|
||||
comparisons += list.size();
|
||||
if (!list.contains(val)) {
|
||||
list.add(val);
|
||||
}
|
||||
}
|
||||
return comparisons;
|
||||
}
|
||||
|
||||
/**
|
||||
* Simulates the fixed appendValues using HashSet for O(1) dedup.
|
||||
* Returns number of hash operations performed.
|
||||
*/
|
||||
static long fastAppend(List<Object> list, List<Object> valuesToAppend) {
|
||||
long operations = 0;
|
||||
Set<Object> seen = new HashSet<>(list);
|
||||
for (Object val : valuesToAppend) {
|
||||
operations++; // O(1) set.add()
|
||||
if (seen.add(val)) {
|
||||
list.add(val);
|
||||
}
|
||||
}
|
||||
return operations;
|
||||
}
|
||||
|
||||
public static void main(String[] args) {
|
||||
int passed = 0;
|
||||
int total = 0;
|
||||
|
||||
// Test 1: correctness — dedup behavior matches between paths
|
||||
{
|
||||
total++;
|
||||
List<Object> baseItems = new ArrayList<>();
|
||||
baseItems.add("a");
|
||||
baseItems.add("b");
|
||||
baseItems.add("c");
|
||||
|
||||
List<Object> slowList = new ArrayList<>(baseItems);
|
||||
List<Object> fastList = new ArrayList<>(baseItems);
|
||||
|
||||
List<Object> toAppend = new ArrayList<>();
|
||||
toAppend.add("b"); // duplicate
|
||||
toAppend.add("d"); // new
|
||||
toAppend.add("a"); // duplicate
|
||||
toAppend.add("e"); // new
|
||||
|
||||
slowAppend(slowList, toAppend);
|
||||
fastAppend(fastList, toAppend);
|
||||
|
||||
assert slowList.equals(fastList) :
|
||||
"Dedup results differ: slow=" + slowList + " fast=" + fastList;
|
||||
assert slowList.size() == 5 :
|
||||
"Expected 5 elements (a,b,c,d,e), got " + slowList.size();
|
||||
System.out.printf("Test 1 (correctness): both produced %s%n", slowList);
|
||||
passed++;
|
||||
}
|
||||
|
||||
// Test 2: cost comparison — small N
|
||||
{
|
||||
total++;
|
||||
int existingN = 50;
|
||||
int appendM = 50;
|
||||
|
||||
List<Object> existing = new ArrayList<>();
|
||||
for (int i = 0; i < existingN; i++) existing.add("item" + i);
|
||||
|
||||
// New unique values to append
|
||||
List<Object> toAppend = new ArrayList<>();
|
||||
for (int i = existingN; i < existingN + appendM; i++) toAppend.add("item" + i);
|
||||
|
||||
List<Object> slowList = new ArrayList<>(existing);
|
||||
List<Object> fastList = new ArrayList<>(existing);
|
||||
|
||||
long slowCost = slowAppend(slowList, toAppend);
|
||||
long fastCost = fastAppend(fastList, toAppend);
|
||||
|
||||
assert slowCost > fastCost :
|
||||
String.format("Expected slow > fast: slow=%d fast=%d", slowCost, fastCost);
|
||||
System.out.printf("Test 2 (N=%d M=%d): slow=%d, fast=%d, ratio=%.1fx%n",
|
||||
existingN, appendM, slowCost, fastCost, (double) slowCost / fastCost);
|
||||
passed++;
|
||||
}
|
||||
|
||||
// Test 3: large duplicate-heavy case — worst case for the defect
|
||||
{
|
||||
total++;
|
||||
int n = 2000;
|
||||
List<Object> existing = new ArrayList<>();
|
||||
for (int i = 0; i < n; i++) existing.add(Integer.valueOf(i));
|
||||
|
||||
// All duplicates — existing list never grows, but contains() still scans
|
||||
List<Object> toAppend = new ArrayList<>();
|
||||
for (int i = 0; i < n; i++) toAppend.add(Integer.valueOf(i));
|
||||
|
||||
List<Object> slowList = new ArrayList<>(existing);
|
||||
List<Object> fastList = new ArrayList<>(existing);
|
||||
|
||||
long slowCost = slowAppend(slowList, toAppend);
|
||||
long fastCost = fastAppend(fastList, toAppend);
|
||||
|
||||
double ratio = (double) slowCost / fastCost;
|
||||
assert ratio > 50.0 :
|
||||
String.format("Expected >50x speedup at n=%d, got %.1fx (slow=%d fast=%d)",
|
||||
n, ratio, slowCost, fastCost);
|
||||
System.out.printf("Test 3 (N=%d all-dupes): slow=%d, fast=%d, speedup=%.1fx%n",
|
||||
n, slowCost, fastCost, ratio);
|
||||
passed++;
|
||||
}
|
||||
|
||||
// Test 4: empty existing list
|
||||
{
|
||||
total++;
|
||||
List<Object> slowList = new ArrayList<>();
|
||||
List<Object> fastList = new ArrayList<>();
|
||||
List<Object> toAppend = new ArrayList<>();
|
||||
for (int i = 0; i < 10; i++) toAppend.add("v" + i);
|
||||
|
||||
slowAppend(slowList, toAppend);
|
||||
fastAppend(fastList, toAppend);
|
||||
|
||||
assert slowList.equals(fastList) :
|
||||
"Empty-base results differ: slow=" + slowList + " fast=" + fastList;
|
||||
System.out.printf("Test 4 (empty base): both produced %d items%n", slowList.size());
|
||||
passed++;
|
||||
}
|
||||
|
||||
System.out.printf("%n%d/%d PASS%n", passed, total);
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue