# 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.
