5 KiB
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
// 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
// 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
// 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:
// 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:
// 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.
- Confirm receipt and assign an issue reference (AngelCode/angelscript or the official forums).
- Assess severity — the
// TODO: optimizecomments in the source indicate these defects were already known; the patch resolves them. - Coordinate a disclosure date — we are targeting 90 days from first contact.
- 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.