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-6316] False-Positive Switch Exhaustiveness Check results in Bad Access / Bad Instruction at Runtime #48866

Closed
swift-ci opened this issue Nov 7, 2017 · 11 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

@swift-ci
Copy link
Collaborator

swift-ci commented Nov 7, 2017

Previous ID SR-6316
Radar rdar://problem/37749943
Original Reporter fabb (JIRA User)
Type Bug
Status Resolved
Resolution Done
Environment

Xcode 9.1.0

Additional Detail from JIRA
Votes 2
Component/s Compiler
Labels Bug, Miscompile, RunTimeCrash
Assignee @CodaFi
Priority Medium

md5: 812f6c41ea662cfe91de3e96db924ef7

is duplicated by:

  • SR-8891 Issues when checking that a switch is exhaustive

relates to:

  • SR-6652 "large space" heuristic might be too aggressive in certain cases.

Issue Description:

This is a serious issue that results in runtime crashes.
Seems like the compiler does not calculate exhaustiveness for nested tuples correctly.

let bool1 = false
let bool2 = false
let bool3 = false
let bool4 = true
let bool5 = false
let bool6 = true
let bool7 = true
let bool8 = false
let bool9 = false

// bad access, as compiler thinks switch is exhaustive, but it is not
switch (bool1, (bool2, bool4, bool6, bool8), (bool3, bool5, bool7, bool9)) {
case (true, (_, _, _, _), (_, true, true, _)):
    break
case (true, (_, _, _, _), (_, _, false, _)):
    break
case (_, (_, true, true, _), (_, _, false, _)):
    break
case (_, (_, _, false, _), (_, true, true, _)):
    break
case (_, (_, true, true, _), (_, true, true, _)):
    break
case (_, (_, _, false, _), (_, _, false, _)):
    break
case (_, (_, false, _, _), (_, false, _, _)):
    break
//default:
//  assertionFailure()
}
@belkadan
Copy link
Contributor

belkadan commented Nov 7, 2017

cc CodaFi (JIRA User)

@belkadan
Copy link
Contributor

belkadan commented Nov 7, 2017

@swift-ci create

@CodaFi
Copy link
Member

CodaFi commented Nov 8, 2017

Oh, I see. The reason it takes 9 bools is the generated space has size 2^9 = 512, which means the space engine falls back to a heuristic that checks to see if we've diagnosed any of the patterns as overlapping. This space built from this carefully-crafted set of cases is eluding that check and registering with size slightly greater than 512 which fools the heuristic.

@CodaFi
Copy link
Member

CodaFi commented Nov 8, 2017

Gotcha! #12818

@swift-ci
Copy link
Collaborator Author

swift-ci commented Nov 8, 2017

Comment by Fabian Ehrentraud (JIRA)

@CodaFi this is very interesting. Where is the threshold for the space engine?

@CodaFi
Copy link
Member

CodaFi commented Nov 8, 2017

I have it artificially limited to 2^7=128 to prevent foisting enormous fixits upon the user. It Would Be Nicer ™ from a QoI perspective to look into doing what GHC does here: Pop a diagnostic and suggest the first three or so missing cases with some ellipses to indicate the analysis is incomplete.

@swift-ci
Copy link
Collaborator Author

Comment by Fabian Ehrentraud (JIRA)

@CodaFi will associated values of enum cases count into that number, or are where clauses treated separately?

@CodaFi
Copy link
Member

CodaFi commented Dec 19, 2017

@belkadan
Copy link
Contributor

This got reverted, so I'm reopening the bug.

@belkadan
Copy link
Contributor

Here's another example from the new Radar:

enum Demo {
  case value1
  case value2
  case value3
  case value4
  case value5
  case value6
  case value7
  case value8
  case value9
  case value10
  case value11
  case value12
}

extension Demo {

  static func demoSwitch(_ lhs: Demo, _ rhs: Demo) -> Bool {
    switch (lhs, rhs) {
      case (.value1, .value1): return true
      case (.value2, .value2): return true
      case (.value3, .value3): return true
      case (.value4, .value4): return true
      case (.value5, .value5): return true
      case (.value6, .value6): return true
      case (.value7, .value7): return true
      case (.value8, .value8): return true
      case (.value9, .value9): return true
      case (.value10, .value10): return true
      case (.value11, .value11): return true
      case (.value12, .value12): return true

      // !!!
      //case (.value1, _): return false
      case (.value2, _): return false
      case (.value3, _): return false
      case (.value4, _): return false
      case (.value5, _): return false
      case (.value6, _): return false
      case (.value7, _): return false
      case (.value8, _): return false
      case (.value9, _): return false
      case (.value10, _): return false
      case (.value11, _): return false
      case (.value12, _): return false
    }
  }
}

@CodaFi
Copy link
Member

CodaFi commented Dec 12, 2018

#21230

@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

4 participants