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-8758] empty implementation of RandomNumberGenerator compiles and overflows stack #51266

Open
mayoff opened this issue Sep 15, 2018 · 5 comments
Assignees
Labels
bug A deviation from expected or documented behavior. Also: expected but undesirable behavior. standard library Area: Standard library umbrella

Comments

@mayoff
Copy link

mayoff commented Sep 15, 2018

Previous ID SR-8758
Radar rdar://problem/44605023
Original Reporter @mayoff
Type Bug
Environment

Xcode 10 GM Seed
Version 10.0 (10A254a)

Additional Detail from JIRA
Votes 1
Component/s Standard Library
Labels Bug
Assignee @Azoy
Priority Medium

md5: e7216ce650b084d0193678acab1893b4

Issue Description:

Paste the following into the Swift REPL:

struct MyRNG: RandomNumberGenerator {
}

var rng = MyRNG()
let x: UInt64 = rng.next()

It seems like it should not be possible to conform to RandomNumberGenerator without implementing something. But the code compiles and then (after a bit) crashes:

  1>  
  2. struct MyRNG: RandomNumberGenerator { 
  3. } 
  4.  
  5. var rng = MyRNG() 
  6. let x: UInt64 = rng.next()
rng: MyRNG = {}
x: UInt64 = <extracting data from value failed>

Execution interrupted. Enter code to recover and continue.
Enter LLDB commands to investigate (type :help for assistance.)
Process 47817 stopped
* thread #&#8203;1, queue = 'com.apple.main-thread', stop reason = EXC_BAD_ACCESS (code=2, address=0x7ffeef3ffff8)
    frame #&#8203;0: sp=0x00007ffeef400000 fp=0x00007ffeef400010 pc=0x0000000101116906 libswiftCore.dylib`(extension in Swift):Swift.RandomNumberGenerator.next<A where A1: Swift.FixedWidthInteger, A1: Swift.UnsignedInteger>() -> A1 + 22
libswiftCore.dylib`(extension in Swift):Swift.RandomNumberGenerator.next<A where A1: Swift.FixedWidthInteger, A1: Swift.UnsignedInteger>() -> A1:
->  0x101116906 <+22>: call   qword ptr [r8 + 0xf0]
    0x10111690d <+29>: add    rsp, 0x8
    0x101116911 <+33>: pop    r13
    0x101116913 <+35>: pop    rbp
Target 0: (repl_swift) stopped.
  7> :bht
error: 'bht' is not a valid command.
error: Unrecognized command 'bht'.
  7> :bt
* thread #&#8203;1, queue = 'com.apple.main-thread', stop reason = EXC_BAD_ACCESS (code=2, address=0x7ffeef3ffff8)
  * frame #&#8203;0: sp=0x00007ffeef400000 fp=0x00007ffeef400010 pc=0x0000000101116906 libswiftCore.dylib`(extension in Swift):Swift.RandomNumberGenerator.next<A where A1: Swift.FixedWidthInteger, A1: Swift.UnsignedInteger>() -> A1 + 22
    frame #&#8203;1: sp=0x00007ffeef400020 fp=0x00007ffeef400030 pc=0x00000001000e2134 $__lldb_expr2`protocol witness for RandomNumberGenerator.next() in conformance MyRNG + 84 at <compiler-generated>:0
    frame #&#8203;2: sp=0x00007ffeef400040 fp=0x00007ffeef400080 pc=0x00000001012a5cf0 libswiftCore.dylib`function signature specialization <Arg[0] = Exploded> of (extension in Swift):Swift.RandomNumberGenerator._fill(bytes: Swift.UnsafeMutableRawBufferPointer) -> () + 96
    frame #&#8203;3: sp=0x00007ffeef400090 fp=0x00007ffeef400090 pc=0x000000010117aa99 libswiftCore.dylib`(extension in Swift):Swift.RandomNumberGenerator._fill(bytes: Swift.UnsafeMutableRawBufferPointer) -> () + 9
    frame #&#8203;4: sp=0x00007ffeef4000a0 fp=0x00007ffeef4000b0 pc=0x00000001000e217d $__lldb_expr2`protocol witness for RandomNumberGenerator._fill(bytes:) in conformance MyRNG + 61 at <compiler-generated>:0
    frame #&#8203;5: sp=0x00007ffeef4000c0 fp=0x00007ffeef4000d0 pc=0x0000000101156d1c libswiftCore.dylib`static Swift.Int._random<A where A: Swift.RandomNumberGenerator>(using: inout A) -> Swift.Int + 44
    frame #&#8203;6: sp=0x00007ffeef4000e0 fp=0x00007ffeef4000f0 pc=0x000000010115528e libswiftCore.dylib`protocol witness for static Swift.FixedWidthInteger._random<A where A1: Swift.RandomNumberGenerator>(using: inout A1) -> A in conformance Swift.UInt : Swift.FixedWidthInteger in Swift + 14
    frame #&#8203;7: sp=0x00007ffeef400100 fp=0x00007ffeef400100 pc=0x00000001012fe509 libswiftCore.dylib`protocol witness for static Swift.FixedWidthInteger._random<A where A1: Swift.RandomNumberGenerator>(using: inout A1) -> A in conformance Swift.UInt64 : Swift.FixedWidthInteger in Swift + 9
    frame #&#8203;8: sp=0x00007ffeef400110 fp=0x00007ffeef400120 pc=0x000000010111690d libswiftCore.dylib`(extension in Swift):Swift.RandomNumberGenerator.next<A where A1: Swift.FixedWidthInteger, A1: Swift.UnsignedInteger>() -> A1 + 29
    frame #&#8203;9: sp=0x00007ffeef400130 fp=0x00007ffeef400140 pc=0x00000001000e2134 $__lldb_expr2`protocol witness for RandomNumberGenerator.next() in conformance MyRNG + 84 at <compiler-generated>:0
    frame #&#8203;10: sp=0x00007ffeef400150 fp=0x00007ffeef400190 pc=0x00000001012a5cf0 libswiftCore.dylib`function signature specialization <Arg[0] = Exploded> of (extension in Swift):Swift.RandomNumberGenerator._fill(bytes: Swift.UnsafeMutableRawBufferPointer) -> () + 96
    frame #&#8203;11: sp=0x00007ffeef4001a0 fp=0x00007ffeef4001a0 pc=0x000000010117aa99 libswiftCore.dylib`(extension in Swift):Swift.RandomNumberGenerator._fill(bytes: Swift.UnsafeMutableRawBufferPointer) -> () + 9
    frame #&#8203;12: sp=0x00007ffeef4001b0 fp=0x00007ffeef4001c0 pc=0x00000001000e217d $__lldb_expr2`protocol witness for RandomNumberGenerator._fill(bytes:) in conformance MyRNG + 61 at <compiler-generated>:0
    frame #&#8203;13: sp=0x00007ffeef4001d0 fp=0x00007ffeef4001e0 pc=0x0000000101156d1c libswiftCore.dylib`static Swift.Int._random<A where A: Swift.RandomNumberGenerator>(using: inout A) -> Swift.Int + 44

(approximately 247,000 stack frames omitted)

@Azoy
Copy link
Member

Azoy commented Sep 15, 2018

@belkadan
Copy link
Contributor

cc @lorentey

@lorentey
Copy link
Member

@swift-ci create

@airspeedswift
Copy link
Member

Is this another case of accidentally-recursive default implementations?

@Azoy
Copy link
Member

Azoy commented Sep 20, 2018

Unfortunately yes.

// Protocol requirement
mutating func next() -> UInt64

// Extension Method
mutating func next<T: FixedWidthInteger & UnsignedInteger>() -> T {
  // We call next() -> UInt64 somewhere in here
}

IMO the best solution here is to simply rename next() -> UInt64 to something like nextWord() -> UInt64 or nextValue() -> UInt64. Since 4.2 is out, this is somewhat of a compatibility issue where users who adopted this protocol would have implemented next() -> UInt64. This shouldn't be a huge issue because as Joe puts it, "In this case doing so wouldn't even really impact the user interface for next(), since the generic form would continue to work with UInt64 by calling down to the base case." Can we consider this a bug and simply rename the requirement w/o going through evolution? I imagine if we can't do that that we can simply make a small amendment for 0202?

@swift-ci swift-ci transferred this issue from apple/swift-issues Apr 25, 2022
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. standard library Area: Standard library umbrella
Projects
None yet
Development

No branches or pull requests

5 participants