Skip to content

[Autodiff] EXC_BAD_ACCESS when running a @differentiable function in the context of an XCTest. #69238

@fibrechannelscsi

Description

@fibrechannelscsi

Description
An EXC_BAD_ACCESS related to a null pointer (0x0) is encountered when attempting to run the unit test below.
Note that this only occurs via the command line; running this in Xcode will not generate a null pointer.

Steps to reproduce
This reproducer requires three files; the directory tree looks like this:

./Package.swift
./Sources/aTest/main.swift
./Tests/aTestTest/test.swift

Listing for Package.swift:

// swift-tools-version: 5.8
import PackageDescription; let package = Package(name: "aTest", targets: [.executableTarget(name: "aTest"), .testTarget(name: "aTestTest", dependencies: [])])

Listing for test.swift:

import _Differentiation; import Foundation; import XCTest
final class Z: XCTestCase {func testA() throws {print(valueWithPullback(at: 2.3, of: m))}}
@differentiable(reverse) private func m(a: Double) -> Double {var c = 0.0; for _ in 0 ... 0 {c = c + 2.4}; return c}

The main.swift file can be blank.

To run via command line, simply run:
swift test

This will generate output like this:

Test Case '-[aTestTest.Z testA]' started.
error: Exited with unexpected signal code 11

To run via lldb, use:

swift build --build-tests
lldb /Applications/Xcode.app/Contents/Developer/usr/bin/xctest ./.build/arm64-apple-macosx/debug/aTestPackageTests.xctest
(lldb) run

Expected behavior
The test should print
(value: 2.4, pullback: (Function))
and exit with an exit code of 0.

Environment

  • Swift compiler version info: 2023-10-08a, 2023-10-15a
  • Xcode version info: N/A
  • Deployment target: macOS 13.6

Additional context
If we remove the control flow in line 3, that is, we replace it with:
@differentiable(reverse) private func m(a: Double) -> Double {var c = 0.0; c = c + 2.4; return c}
then the program will run as expected.

Stack trace (via lldb):

* thread #1, queue = 'com.apple.main-thread', stop reason = EXC_BAD_ACCESS (code=1, address=0x0)
  * frame #0: 0x0000000000000000
    frame #1: 0x00000001006ba43c aTestPackageTests`reverse-mode derivative of m(a=0) at test.swift:3:39
    frame #2: 0x00000001006b9d6c aTestPackageTests`thunk for @callee_guaranteed (@unowned Double) -> (@unowned Double, @owned @escaping @callee_guaranteed (@unowned Double) -> (@unowned Double)) at <compiler-generated>:0
    frame #3: 0x0000000213753fd0 libswift_Differentiation.dylib`_Differentiation.valueWithPullback<τ_0_0, τ_0_1 where τ_0_0: _Differentiation.Differentiable, τ_0_1: _Differentiation.Differentiable>(at: τ_0_0, of: @differentiable(reverse) (τ_0_0) -> τ_0_1) -> (value: τ_0_1, pullback: (τ_0_1.TangentVector) -> τ_0_0.TangentVector) + 152
    frame #4: 0x00000001006b9af8 aTestPackageTests`Z.testA(self=0x0000000100a065d0) at test.swift:2:55
    frame #5: 0x00000001006ba064 aTestPackageTests`@objc Z.testA() at <compiler-generated>:0
    frame #6: 0x0000000186024784 CoreFoundation`__invoking___ + 148
    frame #7: 0x00000001860245f8 CoreFoundation`-[NSInvocation invoke] + 428
    frame #8: 0x000000010072d918 XCTestCore`+[XCTFailableInvocation invokeErrorConventionInvocation:completion:] + 96
    frame #9: 0x000000010072d8b0 XCTestCore`__90+[XCTFailableInvocation invokeInvocation:withTestMethodConvention:lastObservedErrorIssue:]_block_invoke + 28
    frame #10: 0x000000010072d40c XCTestCore`__81+[XCTFailableInvocation invokeWithAsynchronousWait:lastObservedErrorIssue:block:]_block_invoke + 356
    frame #11: 0x00000001006ec6d0 XCTestCore`__49+[XCTSwiftErrorObservation observeErrorsInBlock:]_block_invoke + 48
    frame #12: 0x0000000100e640d8 libXCTestSwiftSupport.dylib`function signature specialization <Arg[1] = [Closure Propagated : reabstraction thunk helper from @callee_unowned @convention(block) (@unowned @callee_unowned @convention(block) () -> ()) -> () to @escaping @callee_guaranteed (@unowned @callee_guaranteed () -> ()) -> (), Argument Types : [@callee_unowned @convention(block) (@unowned @callee_unowned @convention(block) () -> ()) -> ()]> of closure #1 () -> () in static __C.XCTSwiftErrorObservation._observeErrors(in: (() -> ()) -> ()) -> () -> Swift.Optional<XCTest.XCTIssue> + 208
    frame #13: 0x0000000100e641d4 libXCTestSwiftSupport.dylib`function signature specialization <Arg[5] = [Closure Propagated : reabstraction thunk helper from @callee_unowned @convention(block) (@unowned @callee_unowned @convention(block) () -> ()) -> () to @escaping @callee_guaranteed (@unowned @callee_guaranteed () -> ()) -> (), Argument Types : [@callee_unowned @convention(block) (@unowned @callee_unowned @convention(block) () -> ()) -> ()]> of function signature specialization <Arg[2] = [Closure Propagated : closure #1 () -> () in static (extension in XCTest):__C.XCTSwiftErrorObservation.(_observeErrors in _B0397D3B80CBC8D7FB9A5B33AB2A74B8)(in: (() -> ()) -> ()) -> () -> Swift.Optional<XCTest.XCTIssue>, Argument Types : [@callee_guaranteed (@unowned @callee_guaranteed () -> ()) -> ()]> of generic specialization <Swift.Optional<XCTest.LocalErrorTracker>, ()> of Swift.TaskLocal.withValue<τ_0_0>(_: τ_0_0, operation: () throws -> τ_1_0, file: Swift.String, line: Swift.UInt) throws -> τ_1_0 + 144
    frame #14: 0x0000000100e63e80 libXCTestSwiftSupport.dylib`function signature specialization <Arg[0] = [Closure Propagated : reabstraction thunk helper from @callee_unowned @convention(block) (@unowned @callee_unowned @convention(block) () -> ()) -> () to @escaping @callee_guaranteed (@unowned @callee_guaranteed () -> ()) -> (), Argument Types : [@callee_unowned @convention(block) (@unowned @callee_unowned @convention(block) () -> ()) -> ()]> of static __C.XCTSwiftErrorObservation._observeErrors(in: (() -> ()) -> ()) -> () -> Swift.Optional<XCTest.XCTIssue> + 916
    frame #15: 0x0000000100e642bc libXCTestSwiftSupport.dylib`@objc static __C.XCTSwiftErrorObservation._observeErrors(in: (() -> ()) -> ()) -> () -> Swift.Optional<XCTest.XCTIssue> + 52
    frame #16: 0x00000001006ec5d8 XCTestCore`+[XCTSwiftErrorObservation observeErrorsInBlock:] + 204
    frame #17: 0x000000010072d1cc XCTestCore`+[XCTFailableInvocation invokeWithAsynchronousWait:lastObservedErrorIssue:block:] + 228
    frame #18: 0x000000010072d84c XCTestCore`+[XCTFailableInvocation invokeInvocation:withTestMethodConvention:lastObservedErrorIssue:] + 372
    frame #19: 0x000000010072dbc8 XCTestCore`+[XCTFailableInvocation invokeInvocation:lastObservedErrorIssue:] + 72
    frame #20: 0x000000010071b748 XCTestCore`__24-[XCTestCase invokeTest]_block_invoke_2 + 88
    frame #21: 0x00000001006f9924 XCTestCore`-[XCTMemoryChecker _assertInvalidObjectsDeallocatedAfterScope:] + 84
    frame #22: 0x0000000100724984 XCTestCore`-[XCTestCase assertInvalidObjectsDeallocatedAfterScope:] + 92
    frame #23: 0x000000010071b6c8 XCTestCore`__24-[XCTestCase invokeTest]_block_invoke.98 + 172
    frame #24: 0x00000001006e51e8 XCTestCore`-[XCTestCase(XCTIssueHandling) _caughtUnhandledDeveloperExceptionPermittingControlFlowInterruptions:caughtInterruptionException:whileExecutingBlock:] + 168
    frame #25: 0x000000010071b24c XCTestCore`-[XCTestCase invokeTest] + 756
    frame #26: 0x000000010071c89c XCTestCore`__26-[XCTestCase performTest:]_block_invoke.154 + 36
    frame #27: 0x00000001006e51e8 XCTestCore`-[XCTestCase(XCTIssueHandling) _caughtUnhandledDeveloperExceptionPermittingControlFlowInterruptions:caughtInterruptionException:whileExecutingBlock:] + 168
    frame #28: 0x000000010071c3e8 XCTestCore`__26-[XCTestCase performTest:]_block_invoke.140 + 516
    frame #29: 0x0000000100702e8c XCTestCore`+[XCTContext _runInChildOfContext:forTestCase:markAsReportingBase:block:] + 180
    frame #30: 0x0000000100702da0 XCTestCore`+[XCTContext runInContextForTestCase:markAsReportingBase:block:] + 144
    frame #31: 0x000000010071c040 XCTestCore`-[XCTestCase performTest:] + 308
    frame #32: 0x00000001006d402c XCTestCore`-[XCTest runTest] + 48
    frame #33: 0x0000000100705a18 XCTestCore`-[XCTestSuite runTestBasedOnRepetitionPolicy:testRun:] + 68
    frame #34: 0x00000001007058f8 XCTestCore`__27-[XCTestSuite performTest:]_block_invoke + 164
    frame #35: 0x00000001007053f8 XCTestCore`__59-[XCTestSuite _performProtectedSectionForTest:testSection:]_block_invoke + 48
    frame #36: 0x0000000100702e8c XCTestCore`+[XCTContext _runInChildOfContext:forTestCase:markAsReportingBase:block:] + 180
    frame #37: 0x0000000100702da0 XCTestCore`+[XCTContext runInContextForTestCase:markAsReportingBase:block:] + 144
    frame #38: 0x0000000100705394 XCTestCore`-[XCTestSuite _performProtectedSectionForTest:testSection:] + 180
    frame #39: 0x0000000100705600 XCTestCore`-[XCTestSuite performTest:] + 216
    frame #40: 0x00000001006d402c XCTestCore`-[XCTest runTest] + 48
    frame #41: 0x0000000100705a18 XCTestCore`-[XCTestSuite runTestBasedOnRepetitionPolicy:testRun:] + 68
    frame #42: 0x00000001007058f8 XCTestCore`__27-[XCTestSuite performTest:]_block_invoke + 164
    frame #43: 0x00000001007053f8 XCTestCore`__59-[XCTestSuite _performProtectedSectionForTest:testSection:]_block_invoke + 48
    frame #44: 0x0000000100702e8c XCTestCore`+[XCTContext _runInChildOfContext:forTestCase:markAsReportingBase:block:] + 180
    frame #45: 0x0000000100702da0 XCTestCore`+[XCTContext runInContextForTestCase:markAsReportingBase:block:] + 144
    frame #46: 0x0000000100705394 XCTestCore`-[XCTestSuite _performProtectedSectionForTest:testSection:] + 180
    frame #47: 0x0000000100705600 XCTestCore`-[XCTestSuite performTest:] + 216
    frame #48: 0x00000001006d402c XCTestCore`-[XCTest runTest] + 48
    frame #49: 0x0000000100705a18 XCTestCore`-[XCTestSuite runTestBasedOnRepetitionPolicy:testRun:] + 68
    frame #50: 0x00000001007058f8 XCTestCore`__27-[XCTestSuite performTest:]_block_invoke + 164
    frame #51: 0x00000001007053f8 XCTestCore`__59-[XCTestSuite _performProtectedSectionForTest:testSection:]_block_invoke + 48
    frame #52: 0x0000000100702e8c XCTestCore`+[XCTContext _runInChildOfContext:forTestCase:markAsReportingBase:block:] + 180
    frame #53: 0x0000000100702da0 XCTestCore`+[XCTContext runInContextForTestCase:markAsReportingBase:block:] + 144
    frame #54: 0x0000000100705394 XCTestCore`-[XCTestSuite _performProtectedSectionForTest:testSection:] + 180
    frame #55: 0x0000000100705600 XCTestCore`-[XCTestSuite performTest:] + 216
    frame #56: 0x00000001006d402c XCTestCore`-[XCTest runTest] + 48
    frame #57: 0x00000001006d5b50 XCTestCore`__89-[XCTTestRunSession executeTestsWithIdentifiers:skippingTestsWithIdentifiers:completion:]_block_invoke + 104
    frame #58: 0x0000000100702e8c XCTestCore`+[XCTContext _runInChildOfContext:forTestCase:markAsReportingBase:block:] + 180
    frame #59: 0x0000000100702da0 XCTestCore`+[XCTContext runInContextForTestCase:markAsReportingBase:block:] + 144
    frame #60: 0x00000001006d5a44 XCTestCore`-[XCTTestRunSession executeTestsWithIdentifiers:skippingTestsWithIdentifiers:completion:] + 296
    frame #61: 0x000000010073a3b0 XCTestCore`__72-[XCTExecutionWorker enqueueTestIdentifiersToRun:testIdentifiersToSkip:]_block_invoke_2 + 136
    frame #62: 0x000000010073a500 XCTestCore`-[XCTExecutionWorker runWithError:] + 108
    frame #63: 0x00000001007000c8 XCTestCore`__25-[XCTestDriver _runTests]_block_invoke.272 + 56
    frame #64: 0x00000001006de460 XCTestCore`-[XCTestObservationCenter _observeTestExecutionForBlock:] + 288
    frame #65: 0x00000001006ffd24 XCTestCore`-[XCTestDriver _runTests] + 1092
    frame #66: 0x00000001006d461c XCTestCore`_XCTestMain + 88
    frame #67: 0x00000001000057d0 xctest`main + 172
    frame #68: 0x0000000185c0bf28 dyld`start + 2236
  thread #2
    frame #0: 0x0000000185f25be8 libsystem_kernel.dylib`__workq_kernreturn + 8
  thread #3
    frame #0: 0x0000000185f25be8 libsystem_kernel.dylib`__workq_kernreturn + 8

Metadata

Metadata

Assignees

No one assigned

    Labels

    AutoDiffbugA deviation from expected or documented behavior. Also: expected but undesirable behavior.

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions