Skip to content

Commit 90b2ba0

Browse files
isaacclaude
andcommitted
SwiftTL: avoid trap when flags field fails to parse
Generated parse_<ctor>(...) for constructors with conditional fields used to emit 'if Int(_N!) & Int(1 << K) != 0 { ... }' as the gate, and 'let _cM = (Int(_N!) & Int(1 << K) == 0) || _M != nil' as the per-field validation. Both force-unwrap _N (the flags field read) before the bottom-of-function '_cN = _N != nil' validation runs, so a buffer short enough to fail the flags read traps deterministically instead of returning nil. Replace the force-unwraps with (_N ?? 0). Missing flags then reads as "all bits off": every gated branch is skipped, each flag-gated _cM short-circuits to true via the '== 0' clause, and the flags field's own _cN = _N != nil still fails so the overall constructor validation falls through to return nil — matching the intended "return nil on truncated buffer" contract. Touches both generator emit paths (flat generateImplFile and layered emitLayeredType). Regenerated Api*/SecretApiLayer*.swift follow in a separate commit. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
1 parent 3559ee9 commit 90b2ba0

1 file changed

Lines changed: 4 additions & 4 deletions

File tree

‎build-system/SwiftTL/Sources/SwiftTL/CodeGeneration.swift‎

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -462,7 +462,7 @@ enum CodeGenerator {
462462
guard let fieldIndex = constructor.arguments.filter({ if case .boolTrue = $0.type { return false } else { return true } }).firstIndex(where: { $0.name == condition.fieldName }) else {
463463
throw CodeGenerationError(text: "Condition field \(condition.fieldName) not found")
464464
}
465-
writer.line("if Int(_\(fieldIndex + 1)!) & Int(1 << \(condition.bitIndex)) != 0 {")
465+
writer.line("if Int(_\(fieldIndex + 1) ?? 0) & Int(1 << \(condition.bitIndex)) != 0 {")
466466
writer.indent()
467467
try generateFieldParsing(apiPrefix: structName, writer: &writer, typeMap: typeMap, argument: argument, argumentAccessor: "_\(argumentIndex + 1)")
468468
writer.dedent()
@@ -488,7 +488,7 @@ enum CodeGenerator {
488488
guard let fieldIndex = constructor.arguments.filter({ if case .boolTrue = $0.type { return false } else { return true } }).firstIndex(where: { $0.name == condition.fieldName }) else {
489489
throw CodeGenerationError(text: "Condition field \(condition.fieldName) not found")
490490
}
491-
writer.line("let _c\(checkIndex + 1) = (Int(_\(fieldIndex + 1)!) & Int(1 << \(condition.bitIndex)) == 0) || _\(checkIndex + 1) != nil")
491+
writer.line("let _c\(checkIndex + 1) = (Int(_\(fieldIndex + 1) ?? 0) & Int(1 << \(condition.bitIndex)) == 0) || _\(checkIndex + 1) != nil")
492492
} else {
493493
writer.line("let _c\(checkIndex + 1) = _\(checkIndex + 1) != nil")
494494
}
@@ -1000,7 +1000,7 @@ enum CodeGenerator {
10001000
throw CodeGenerationError(text: "Condition field \(condition.fieldName) not found")
10011001
}
10021002

1003-
writer.line("if Int(_\(fieldIndex + 1)!) & Int(1 << \(condition.bitIndex)) != 0 {")
1003+
writer.line("if Int(_\(fieldIndex + 1) ?? 0) & Int(1 << \(condition.bitIndex)) != 0 {")
10041004
writer.indent()
10051005
try generateFieldParsing(apiPrefix: apiPrefix, writer: &writer, typeMap: typeMap, argument: argument, argumentAccessor: "_\(argumentIndex + 1)")
10061006
writer.dedent()
@@ -1036,7 +1036,7 @@ enum CodeGenerator {
10361036
throw CodeGenerationError(text: "Condition field \(condition.fieldName) not found")
10371037
}
10381038

1039-
writer.line("let _c\(checkIndex + 1) = (Int(_\(fieldIndex + 1)!) & Int(1 << \(condition.bitIndex)) == 0) || _\(checkIndex + 1) != nil")
1039+
writer.line("let _c\(checkIndex + 1) = (Int(_\(fieldIndex + 1) ?? 0) & Int(1 << \(condition.bitIndex)) == 0) || _\(checkIndex + 1) != nil")
10401040
} else {
10411041
writer.line("let _c\(checkIndex + 1) = _\(checkIndex + 1) != nil")
10421042
}

0 commit comments

Comments
 (0)