java-topology/whitepaper/outreach/angelscript.md

117 lines
5 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# AngelScript — CWE-407 Disclosure Brief
**2026-03-27 · Patch available — awaiting upstream merge**
## Finding
Three O(n²) defects in AngelScript's module ownership transfer and switch-statement compiler. All patched. Patches ready for upstream review. Notably, the AngelScript source contains explicit `// TODO: optimize` comments at two of the defect sites, acknowledging the performance problem.
## The Defects
**angelscript-0001 (PATCHED — HIGH):** `sdk/angelscript/source/as_scriptengine.cpp:880`
```cpp
// In FindNewOwnerForSharedType() — called per shared type on module discard:
for (int n = 0; n < engine->modules.GetLength(); n++) {
asCModule *mod = engine->modules[n];
// 5 calls to IndexOf() per shared type transfer:
if (mod->sharedTypes.IndexOf(type) >= 0) { ... } // O(n) per call
}
// Engine comment at line 917:
// "TODO: optimize: If the modules already stored the shared types separately, this would be quicker"
```
`asCArray<T>::IndexOf()` is a linear scan. Called 5 times per shared type transfer for every remaining module.
**angelscript-0002 (PATCHED — HIGH):** `sdk/angelscript/source/as_scriptengine.cpp:953`
```cpp
// In FindNewOwnerForSharedFunc() — called per shared function on module discard:
if (mod->sharedFunctions.IndexOf(func) >= 0) { ... } // O(n) per call
```
Same root cause on shared functions. 5 linear scans per shared function transfer.
**angelscript-0003 (PATCHED — HIGH):** `sdk/angelscript/source/as_compiler.cpp`
```cpp
// In CompileSwitch() — per case value in while loop:
while (/* more cases */) {
if (caseValues.IndexOf(caseVal) >= 0) { // O(n) per case — duplicate check
Error(TXT_DUPLICATE_SWITCH_CASE);
}
caseValues.PushLast(caseVal);
}
// O(n²) duplicate case detection during switch compilation
```
`caseValues` is `asCArray<asDWORD>`. `IndexOf()` is O(n) per case. O(n²) total for n switch cases.
## Complexity Proof
**angelscript-0001/0002:** For T shared types/functions across M modules:
- Per module: 5 × O(T) `IndexOf()` calls
- Total: **O(M × T × 5)**
At T=200 types, M=100 modules: defective=3,980,000 comparisons, fixed=39,800 (`asCSet<>` shadow). **100× op reduction.**
**angelscript-0003:** For N case values in a switch statement:
- Per case: O(N) `IndexOf()` scan
- Total: **O(N²)**
At N=500 cases: defective=124,750 comparisons, fixed=500 (`asCSet<asDWORD>` shadow). **250× op reduction.**
## Impact
AngelScript is the scripting language embedded in many C++ game engines and applications, including Dry/Urho3D, and dozens of indie engines. It is used wherever C++ developers need a scripting layer that integrates tightly with C++ types.
angelscript-0001/0002 fire on every `module->Discard()` call — when a script module is unloaded and ownership of shared types/functions must be transferred. In applications that frequently reload scripts (modding systems, live editing workflows, hot-reload dev environments), this path runs repeatedly.
angelscript-0003 fires on every script compilation that includes a switch statement. Scripts with large switch statements (state machines, command parsers, opcode dispatchers) pay O(n²) at every compile. For switch statements with hundreds of cases (common in protocol implementations and scripted state machines), the overhead is significant.
## The Fix
**angelscript-0001/0002:** Add `asCSet<asCTypeInfo*>` and `asCSet<asCScriptFunction*>` shadow sets:
```cpp
// Before
if (mod->sharedTypes.IndexOf(type) >= 0) { ... }
// After
// CWE-407 fix: asCSet shadow for O(1) Exists() instead of O(n) IndexOf() scan.
if (mod->sharedTypeSet.Exists(type)) { ... }
```
Maintain `sharedTypeSet` and `sharedFuncSet` alongside the existing arrays. `asCSet` is already available in AngelScript's own container library.
**angelscript-0003:** Add `asCSet<asDWORD>` for case dedup:
```cpp
// Before
if (caseValues.IndexOf(caseVal) >= 0) { ... }
caseValues.PushLast(caseVal);
// After
// CWE-407 fix: asCSet for O(1) duplicate detection instead of O(n) IndexOf().
if (caseValueSet.Exists(caseVal)) { ... }
caseValueSet.Insert(caseVal);
caseValues.PushLast(caseVal); // preserved for downstream iteration
```
## Patch
Fix available: `defects/angelscript/patch/angelscript-0001-0003-ascset-shadow.patch`
Three-location patch across `as_scriptengine.cpp` (two sites) and `as_compiler.cpp`.
Unit test: `AngelScriptTest` 4/4 pass. angelscript-0001/0002: **100× speedup at T=200, M=100**. angelscript-0003: **250× speedup at N=500 cases**.
## What We Ask
A patch is ready for review.
1. Confirm receipt and assign an issue reference (AngelCode/angelscript or the official forums).
2. Assess severity — the `// TODO: optimize` comments in the source indicate these defects were already known; the patch resolves them.
3. Coordinate a disclosure date — we are targeting 90 days from first contact.
4. We will credit the AngelScript team in the public disclosure. Preferred acknowledgment format welcome.
Contact: see cover email. This brief is confidential until coordinated disclosure.