TypeScript Compiler (tsc) — CWE-407 Analysis
============================================

.. contents:: :local:

Overview
--------

``tsc`` is the TypeScript compiler, which performs type checking, symbol resolution, and
export-star graph traversal. Three CWE-407 defect sites were found in ``checker.ts``, the
largest single source file in the compiler (54,000+ lines). **All three are now patched
in a single 120-line diff** (``defects/typescript/patch/ts-checker-set-visited.patch``).
The defects affect cycle detection in resolution chains, export-star symbol merging, and
symbol-table inheritance traversal.

Defect Sites
------------

ts-0001
~~~~~~~

**File:** ``src/compiler/checker.ts:11503``

**Pattern:**

.. code-block:: typescript

   // Resolution cycle detection — linear scan of resolutionTargets array
   function findResolutionCycleStartIndex(target: object, propertyName: TypeSystemPropertyName): number {
       for (let i = resolutionTargets.length - 1; i >= 0; i--) {
           if (resolutionTargets[i] === target &&
               resolutionPropertyNames[i] === propertyName) {
               return i;   // O(depth) linear scan every call
           }
       }
       return -1;
   }

**Why this is O(n):** ``resolutionTargets`` is a plain array; finding a target requires scanning
from the end. Called once per symbol resolution: O(depth²) total for a chain of depth ``depth``.

**Complexity:** ``O(depth²)`` where depth = resolution stack depth

**Patch:**

.. code-block:: typescript

   // Use a Map<object, Map<TypeSystemPropertyName, number>> for O(1) lookup
   const resolutionTargetIndex = new Map<object, Map<TypeSystemPropertyName, number>>();

   function findResolutionCycleStartIndex(target: object, propertyName: TypeSystemPropertyName): number {
       return resolutionTargetIndex.get(target)?.get(propertyName) ?? -1;
   }

**Data structure change:** ``object[]`` array + linear scan → ``Map<object, Map<...>>``

**Status:** **PATCHED** — ``defects/typescript/patch/ts-checker-set-visited.patch``

Benchmark Results
-----------------

.. TODO: benchmark pending patch

Complexity Proof
----------------

Let depth = maximum resolution stack depth. Each call to ``findResolutionCycleStartIndex``
scans an array of up to ``depth`` entries: O(depth). With O(depth) calls total during a
resolution chain: O(depth²). Map lookup is O(1) amortized: O(depth) total. QED.

References
----------

* Defect ticket: ``tools/tickets/defects/ts-0001.md``

ts-0002
~~~~~~~

**File:** ``src/compiler/checker.ts:5256``

**Pattern:**

.. code-block:: typescript

   // Export-star symbol merging — pushIfUnique on visitedSymbols array
   function getExportsOfModuleWorker(moduleSymbol: Symbol): Symbol[] {
       const visitedSymbols: Symbol[] = [];
       // ...
       function visit(symbol: Symbol) {
           if (!pushIfUnique(visitedSymbols, symbol)) return;  // O(V) per call
           // ... traverse exports
       }
   }

   function pushIfUnique<T>(array: T[], toAdd: T): boolean {
       if (array.includes(toAdd)) return false;   // O(V) linear scan
       array.push(toAdd);
       return true;
   }

**Why this is O(n):** ``array.includes()`` is O(|array|); called once per symbol in the
export-star graph; total is O(V²) where V = number of exported symbols.

**Complexity:** ``O(V²)`` where V = number of symbols in the export-star graph

**Patch:**

.. code-block:: typescript

   function getExportsOfModuleWorker(moduleSymbol: Symbol): Symbol[] {
       const visitedSymbols = new Set<Symbol>();
       function visit(symbol: Symbol) {
           if (visitedSymbols.has(symbol)) return;   // O(1)
           visitedSymbols.add(symbol);
           // ... traverse exports
       }
   }

**Data structure change:** ``Symbol[]`` array + ``pushIfUnique`` → ``Set<Symbol>`` + ``has/add``

**Status:** **PATCHED** — ``defects/typescript/patch/ts-checker-set-visited.patch``

Benchmark Results
-----------------

.. TODO: benchmark pending patch

Complexity Proof
----------------

Let V = number of unique symbols in the export graph. ``pushIfUnique`` scans an array of up to V
elements: O(V) per call. With V calls total: O(V²). ``Set.has()`` is O(1): O(V) total. QED.

References
----------

* Defect ticket: ``tools/tickets/defects/ts-0002.md``

ts-0003
~~~~~~~

**File:** ``src/compiler/checker.ts:5763``

**Pattern:**

.. code-block:: typescript

   // Symbol-table inheritance traversal — pushIfUnique on visitedSymbolTables
   const visitedSymbolTables: SymbolTable[] = [];

   function visit(symbolTable: SymbolTable) {
       if (!pushIfUnique(visitedSymbolTables, symbolTable)) return;  // O(depth) per call
       // ... inherit symbols
   }

**Why this is O(n):** Same ``pushIfUnique`` pattern as ts-0002; ``visitedSymbolTables`` is a
plain array scanned linearly on every call.

**Complexity:** ``O(depth²)`` where depth = symbol-table inheritance depth

**Patch:**

.. code-block:: typescript

   const visitedSymbolTables = new Set<SymbolTable>();

   function visit(symbolTable: SymbolTable) {
       if (visitedSymbolTables.has(symbolTable)) return;   // O(1)
       visitedSymbolTables.add(symbolTable);
       // ... inherit symbols
   }

**Data structure change:** ``SymbolTable[]`` array + ``pushIfUnique`` → ``Set<SymbolTable>``

**Status:** **PATCHED** — ``defects/typescript/patch/ts-checker-set-visited.patch``

Benchmark Results
-----------------

.. TODO: benchmark pending patch

Complexity Proof
----------------

Identical argument to ts-0002. Let depth = inheritance chain depth. ``pushIfUnique`` costs
O(depth) per call; O(depth²) total. ``Set.has()`` costs O(1) per call; O(depth) total. QED.

References
----------

* Defect ticket: ``tools/tickets/defects/ts-0003.md``
