Skip to content

Commit

Permalink
Fix crash in BinaryDataDecoder when decoding float values from misali…
Browse files Browse the repository at this point in the history
…gned memory. (#59)

The crash error was "load from misaligned raw pointer".
  • Loading branch information
featherless authored Jul 6, 2020
1 parent 1ebfddc commit 14820cd
Show file tree
Hide file tree
Showing 2 changed files with 30 additions and 6 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -111,10 +111,13 @@ private class BinaryDataDecodingContainer: BinaryDecodingContainer {
throw BinaryDecodingError.dataCorrupted(.init(debugDescription:
"Not enough data to create a a type of \(type). Needed: \(byteWidth). Received: \(bytes.count)."))
}
let value = bytes.withUnsafeBytes { ptr -> T in
return ptr.load(as: T.self)
return bytes.withUnsafeBytes { ptr in
var value: T = 0
withUnsafeMutableBytes(of: &value) { valuePtr in
valuePtr.copyMemory(from: UnsafeRawBufferPointer(rebasing: ptr[0..<ptr.count]))
}
return value
}
return value
}

func decode<T: FixedWidthInteger>(_ type: T.Type) throws -> T {
Expand Down
27 changes: 24 additions & 3 deletions Tests/BinaryCodableTests/MisalignedDecoderTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@
import BinaryCodable
import XCTest

private struct MisalignedPacket: BinaryDecodable {
private struct MisalignedUInt16Packet: BinaryDecodable {
let twoByteInt: UInt16
init(from decoder: BinaryDecoder) throws {
var container = decoder.container(maxLength: nil)
Expand All @@ -24,17 +24,38 @@ private struct MisalignedPacket: BinaryDecodable {
}
}

private struct MisalignedFloatPacket: BinaryDecodable {
let fourByteFloat: Float
init(from decoder: BinaryDecoder) throws {
var container = decoder.container(maxLength: nil)
_ = try container.decode(length: 1)
self.fourByteFloat = try container.decode(Float.self)
}
}

final class MisalignedDecoderTests: XCTestCase {

func testEmpty() throws {
func testUInt16() throws {
// Given
let packetData: [UInt8] = [0, 3, 0]
let decoder = BinaryDataDecoder()

// When
let packet = try decoder.decode(MisalignedPacket.self, from: packetData)
let packet = try decoder.decode(MisalignedUInt16Packet.self, from: packetData)

// Then
XCTAssertEqual(packet.twoByteInt, 3)
}

func testFloat() throws {
// Given
let packetData: [UInt8] = [0, 0, 0, 0x80, 0x3f]
let decoder = BinaryDataDecoder()

// When
let packet = try decoder.decode(MisalignedFloatPacket.self, from: packetData)

// Then
XCTAssertEqual(packet.fourByteFloat, 1.0, accuracy: 0.001)
}
}

0 comments on commit 14820cd

Please sign in to comment.