swiftlang / swiftlang/swift-corelibs-libdispatch

[SR-3097] Empty DispatchData returns a nil pointer in withUnsafeBytes

Open
#713 0 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

bug libdispatch RunTimeCrash
Dominant language
C
Stars
2.6k
Forks
496
Avg merge
2d 6h
Merged PRs (30d)
3

Description

Previous ID SR-3097
Radar None
Original Reporter @karwa
Type Bug
Environment

Swift 3

Additional Detail from JIRA
Votes 0
Component/s libdispatch
Labels Bug, RunTimeCrash
Assignee mww (JIRA)
Priority Medium

md5: b81d63c73d62a0030cc60459e73a98fc

relates to:

  • SR-2976 [Swift 4] Add an UnsafeBufferPointer.empty API

Issue Description:

I have an API which accepts a Foundation Data, and I'm trying to feed it the bytes I read from DispatchIO.read (which come packaged as a DispatchData). The following code (which is the best solution I could find to bridge from DispatchData to Foundation's Data without copying) crashes in Swift 3 when the data is empty:

let dispatchData = DispatchData.empty
dispatchData.withUnsafeBytes { (ptr: UnsafePointer<Int8>) -> Void in
    // We make the pointer mutating, but the Data is a `let` so we won't mutate the bytes
    let foundationData = Data(bytesNoCopy: UnsafeMutableRawPointer(mutating: ptr), count: dispatchData.count, deallocator: .none)
    print("\(foundationData)")
}

The root of the problem seems to be that the Swift dispatch overlay is returning a null-pointer as non-optional, and it gets dereferenced somewhere.

* thread #&#8203;1: tid = 0xda386b, 0x000000010067c557 libswiftDispatch.dylib`Dispatch.DispatchData.withUnsafeBytes <A, B> (body : (Swift.UnsafePointer<B>) throws -> A) throws -> A + 215, queue = 'com.apple.main-thread', stop reason = EXC_BAD_INSTRUCTION (code=EXC_I386_INVOP, subcode=0x0)
  * frame #&#8203;0: 0x000000010067c557 libswiftDispatch.dylib`Dispatch.DispatchData.withUnsafeBytes <A, B> (body : (Swift.UnsafePointer<B>) throws -> A) throws -> A + 215
    frame #&#8203;1: 0x00000001006f80f2 $__lldb_expr38`main + 242 at repl.swift:42
    frame #&#8203;2: 0x0000000100001420 repl_swift`_mh_execute_header + 5152
    frame #&#8203;3: 0x00000001000014c8 repl_swift`main + 168 at main.swift:46
    frame #&#8203;4: 0x00007fffea293255 libdyld.dylib`start + 1
    frame #&#8203;5: 0x00007fffea293255 libdyld.dylib`start + 1

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start at the Dispatch.DispatchData.withUnsafeBytes entry point shown in the stack trace and run the empty DispatchData reproducer under Swift 3. Trace how the empty buffer pointer is passed to the callback. Done means the reproducer no longer crashes and an empty DispatchData can be bridged to Data successfully.

Written by the indexing model from the issue text.

Assessment

Tech stack
swift
Domain
operating-systems
Issue type
Bug
Difficulty
3/5
Estimated time
1-2 days
Activity status
Stale
Clarity
Mostly clear
Newbie friendliness
48/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.