Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[SR-13439] Swift is memory unsafe when escaping a fully initialised self in a fallible initialiser that returns nil. #55880

Closed
weissi opened this issue Aug 24, 2020 · 7 comments
Assignees
Labels
bug A deviation from expected or documented behavior. Also: expected but undesirable behavior. compiler The Swift compiler in itself crash Bug: A crash, i.e., an abnormal termination of software run-time crash Bug → crash: Swift code crashed during execution

Comments

@weissi
Copy link
Member

weissi commented Aug 24, 2020

Previous ID SR-13439
Radar rdar://problem/67746791
Original Reporter @weissi
Type Bug
Status Resolved
Resolution Done

Attachment: Download

Additional Detail from JIRA
Votes 0
Component/s Compiler
Labels Bug, RunTimeCrash
Assignee @slavapestov
Priority Medium

md5: bd71160abded35bdcd864e042d815a3a

Issue Description:

Consider this program

import Dispatch

class Foo: CustomStringConvertible {
    var x: Optional<Int>

    init?(_ x: Int) {
        print("Foo init   \(x)")
        if x == 0 {
            return nil
        }
        self.x = x
        if x == 1 {
            DispatchQueue(label: "Foo").async {
                print(self)
            }
            return nil
        }
    }

    var description: String {
        return "I exist!"
    }

    deinit {
        print("Foo deinit \(self.x.debugDescription)")
    }
}

print(Foo(1).debugDescription)
sleep(1)

it prints for me

$ swiftc test.swift && ./test
Foo init   1
nil
Segmentation fault: 11
-SEGV-

in

$ swift -version
Apple Swift version 5.2.4 (swiftlang-1103.0.32.9 clang-1103.0.32.53)
Target: x86_64-apple-darwin19.6.0
@jckarter
Copy link
Member

This ought to be safe; returning nil from the initializer after self has been escaped should cause the initializer to return nil, and let the escaped object live its life normally.

@slavapestov
Copy link
Member

Here is a reduced test case that crashes on my machine without using Dispatch:

var escaped: Foo? = nil

func escape(_ foo: Foo) {
  escaped = foo
}

class Foo {
    var x: Optional<Int>

    init?(_ x: Int) {
        if x == 0 {
            return nil
        }
        self.x = x
        if x == 1 {
            escape(self)
            return nil
        }
    }
}

_ = Foo(1)
print(escaped)

@slavapestov
Copy link
Member

One interesting thing is that if you remove the 'if x == 0' block, the crash goes away.

@slavapestov
Copy link
Member

Here is the failure exit block in the constructor:

bb7:                                              // Preds: bb4 bb1
  destroy_value %4 : $Foo                         // id: %42
  %43 = enum $Optional<Foo>, #Optional.none!enumelt // user: %44
  br bb8(%43 : $Optional<Foo>)    

DI lowers this to:

bb7:                                              // Preds: bb6
  %25 = metatype $@thick Foo.Type                 // user: %26
  dealloc_partial_ref %1 : $Foo, %25 : $@thick Foo.Type // id: %26
  %27 = enum $Optional<Foo>, #Optional.none!enumelt // user: %28
  br bb8(%27 : $Optional<Foo>)                    // id: %28

@typesanitizer
Copy link

@swift-ci create

@jckarter
Copy link
Member

Interesting. It sounds like maybe DI is failing to notice that the `if x == 0` case always exits, and so we still treat the initialization of `x` as conditional.

@slavapestov
Copy link
Member

#33743

@swift-ci swift-ci transferred this issue from apple/swift-issues Apr 25, 2022
@AnthonyLatsis AnthonyLatsis added the crash Bug: A crash, i.e., an abnormal termination of software label Dec 12, 2022
This issue was closed.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug A deviation from expected or documented behavior. Also: expected but undesirable behavior. compiler The Swift compiler in itself crash Bug: A crash, i.e., an abnormal termination of software run-time crash Bug → crash: Swift code crashed during execution
Projects
None yet
Development

No branches or pull requests

5 participants