withUnsafeBytes Data API confusion

I'm struggling with this whole memory management stuff …

That’s understandable. Swift makes this challenging because:

  • The API details have changed quite a lot over the years.

  • Recent versions have strict rules about aliasing (in this sense of the word). These will yield long-term benefits, but they do take some getting used to.


With regards your specific issue, I’m a big fan of moving up a level of abstraction. In your case, I’d rethink this as a parsing problem rather than a structure access problem. The fact that Data exposes its contents as a collection of bytes means you can take advantage of lots of functionality that’s available on collections. For example:

func isIcns(data icnsData: Data) -> Bool {
    guard
        icnsData.count >= 8,
        icnsData.starts(with: "icns".utf8)
    else {
        return false
    }
    let embeddedCount32 = icnsData.dropFirst(4).prefix(4).reduce(0) { $0 << 8 | UInt32($1) }
    return Int(exactly: embeddedCount32) == icnsData.count
}

One thing to note about this code it that, on a 32-bit machine, it avoids the trap you might encounter converting the length bytes of a maliciously crafted icns to Int.

Share and Enjoy

Quinn “The Eskimo!” @ DTS @ Apple

5 Likes