Skip to content

Commit 60fc9f8

Browse files
committed
fix: prevent exponential type re-traversal in SwiftCxxBridgedType
`getRequiredImports()` and `getExtraFiles()` in nitrogen's `SwiftCxxBridgedType` (the TypeScript class that generates the Swift <-> C++ bridge code) have no protection against re-traversing the same type from multiple paths in the type graph, causing exponential blowup and a "Maximum call stack size exceeded" crash for projects with many interconnected struct types. mrousavy#1247 added a visited-set guard to the equivalent `KotlinCxxBridgedType`; this applies the same per-call-tree visited-set guard to `SwiftCxxBridgedType`, which still crashes on large specs. Fixes mrousavy#1079
1 parent 12756ea commit 60fc9f8

1 file changed

Lines changed: 14 additions & 5 deletions

File tree

packages/nitrogen/src/syntax/swift/SwiftCxxBridgedType.ts

Lines changed: 14 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -128,7 +128,13 @@ export class SwiftCxxBridgedType implements BridgedType<'swift', 'c++'> {
128128
return bridge
129129
}
130130

131-
getRequiredImports(language: Language): SourceImport[] {
131+
getRequiredImports(
132+
language: Language,
133+
visited = new Set<Type>()
134+
): SourceImport[] {
135+
if (visited.has(this.type)) return []
136+
visited.add(this.type)
137+
132138
const imports = this.type.getRequiredImports(language)
133139

134140
if (language === 'c++') {
@@ -154,13 +160,16 @@ export class SwiftCxxBridgedType implements BridgedType<'swift', 'c++'> {
154160
return
155161
}
156162
const bridged = new SwiftCxxBridgedType(t)
157-
imports.push(...bridged.getRequiredImports(language))
163+
imports.push(...bridged.getRequiredImports(language, visited))
158164
})
159165

160166
return imports
161167
}
162168

163-
getExtraFiles(): SourceFile[] {
169+
getExtraFiles(visited = new Set<Type>()): SourceFile[] {
170+
if (visited.has(this.type)) return []
171+
visited.add(this.type)
172+
164173
const files: SourceFile[] = []
165174

166175
switch (this.type.kind) {
@@ -170,7 +179,7 @@ export class SwiftCxxBridgedType implements BridgedType<'swift', 'c++'> {
170179
files.push(extensionFile)
171180
extensionFile.referencedTypes.forEach((t) => {
172181
const bridge = new SwiftCxxBridgedType(t)
173-
files.push(...bridge.getExtraFiles())
182+
files.push(...bridge.getExtraFiles(visited))
174183
})
175184
break
176185
}
@@ -209,7 +218,7 @@ export class SwiftCxxBridgedType implements BridgedType<'swift', 'c++'> {
209218
return
210219
}
211220
const bridged = new SwiftCxxBridgedType(t)
212-
files.push(...bridged.getExtraFiles())
221+
files.push(...bridged.getExtraFiles(visited))
213222
})
214223

215224
return files

0 commit comments

Comments
 (0)