cpython/ruby: CWE-407 scan — 2 CPython defects, 1 Ruby defect
This commit is contained in:
parent
76ffba4a60
commit
44d513d045
5 changed files with 548 additions and 0 deletions
112
defects/ruby/unit/RubyTest.java
Normal file
112
defects/ruby/unit/RubyTest.java
Normal file
|
|
@ -0,0 +1,112 @@
|
|||
import java.util.*;
|
||||
|
||||
/**
|
||||
* Java simulation of Ruby MRI CWE-407 defect.
|
||||
*
|
||||
* ruby-0001: class.c do_include_modules_at super chain linear scan O(M*S)
|
||||
* For each module to include, walks entire super chain to check if
|
||||
* module's method table is already present. O(M * S) total.
|
||||
* Fix: st_table (hash set) of method table pointers for O(1) lookup.
|
||||
*/
|
||||
public class RubyTest {
|
||||
|
||||
/**
|
||||
* Simulate module include with linear super chain scan.
|
||||
* DEFECTIVE: O(M * S) — for each of M modules, scan S super entries.
|
||||
*/
|
||||
static long includeModulesDefective(int numModules, int superChainLen) {
|
||||
// Simulate super chain as list of "method table pointers" (ints)
|
||||
List<Integer> superChain = new ArrayList<>();
|
||||
for (int i = 0; i < superChainLen; i++) {
|
||||
superChain.add(i); // existing iclass method tables
|
||||
}
|
||||
|
||||
long ops = 0;
|
||||
|
||||
// Include M new modules
|
||||
for (int m = 0; m < numModules; m++) {
|
||||
int moduleMTbl = superChainLen + m; // new module's method table
|
||||
boolean found = false;
|
||||
|
||||
// Linear scan of super chain — O(S)
|
||||
for (int s = 0; s < superChain.size(); s++) {
|
||||
ops++;
|
||||
if (superChain.get(s) == moduleMTbl) {
|
||||
found = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!found) {
|
||||
superChain.add(moduleMTbl); // Insert new iclass
|
||||
}
|
||||
}
|
||||
return ops;
|
||||
}
|
||||
|
||||
/**
|
||||
* FIXED: O(M) — hash set for method table membership check.
|
||||
*/
|
||||
static long includeModulesFixed(int numModules, int superChainLen) {
|
||||
List<Integer> superChain = new ArrayList<>();
|
||||
Set<Integer> mtblSet = new HashSet<>();
|
||||
for (int i = 0; i < superChainLen; i++) {
|
||||
superChain.add(i);
|
||||
mtblSet.add(i);
|
||||
}
|
||||
|
||||
long ops = 0;
|
||||
|
||||
for (int m = 0; m < numModules; m++) {
|
||||
int moduleMTbl = superChainLen + m;
|
||||
ops++; // O(1) hash lookup
|
||||
boolean found = mtblSet.contains(moduleMTbl);
|
||||
|
||||
if (!found) {
|
||||
superChain.add(moduleMTbl);
|
||||
mtblSet.add(moduleMTbl);
|
||||
}
|
||||
}
|
||||
return ops;
|
||||
}
|
||||
|
||||
static void test0001() {
|
||||
System.out.println("=== ruby-0001: do_include_modules_at super chain scan ===");
|
||||
|
||||
int[][] params = {
|
||||
{10, 20}, // M=10 modules, S=20 super chain
|
||||
{20, 50}, // M=20, S=50 (typical Rails)
|
||||
{30, 80}, // M=30, S=80 (heavy Rails)
|
||||
{50, 100}, // M=50, S=100 (extreme)
|
||||
};
|
||||
|
||||
for (int[] p : params) {
|
||||
int M = p[0], S = p[1];
|
||||
long defOps = includeModulesDefective(M, S);
|
||||
long fixOps = includeModulesFixed(M, S);
|
||||
double ratio = (double) defOps / fixOps;
|
||||
System.out.printf(" M=%2d S=%3d: defective=%6d fixed=%3d ratio=%.1fx%n",
|
||||
M, S, defOps, fixOps, ratio);
|
||||
if (M >= 20 && ratio < 5.0) {
|
||||
throw new AssertionError("Expected ratio >= 5x at M=" + M
|
||||
+ " S=" + S + ", got " + ratio);
|
||||
}
|
||||
}
|
||||
|
||||
// Verify growth is proportional to M*S
|
||||
long ops_20_50 = includeModulesDefective(20, 50);
|
||||
long ops_50_100 = includeModulesDefective(50, 100);
|
||||
double growth = (double) ops_50_100 / ops_20_50;
|
||||
System.out.printf(" Growth (20,50)->(50,100): %.1fx (expect ~5x for O(M*S))%n", growth);
|
||||
if (growth < 3.0) {
|
||||
throw new AssertionError("Expected M*S growth, got " + growth + "x");
|
||||
}
|
||||
|
||||
System.out.println(" PASS");
|
||||
}
|
||||
|
||||
public static void main(String[] args) {
|
||||
test0001();
|
||||
System.out.println("\nAll Ruby CWE-407 tests PASSED");
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue