From 4018ea8a9f55470c725e6c238ec727219538e8ba Mon Sep 17 00:00:00 2001 From: fumoboy007 Date: Thu, 16 Feb 2023 23:24:08 -0800 Subject: [PATCH] Verify the first byte when decoding `Double`/`Float`. Currently, the decoding code for `Double`/`Float` parses the data without first verifying that the data represents a `Double`/`Float`. This is unsafe. For example, a value of type `UInt64` could be decoded as a `Double` with the same bit pattern (but not the same semantic value). Instead, the decoding code should always check the first byte before continuing to parse the data. --- Sources/MessagePackTypes/MessagePackType+DoubleType.swift | 3 +++ Sources/MessagePackTypes/MessagePackType+FloatType.swift | 3 +++ Tests/MessagePackerTests/DoubleUnpackedTests.swift | 5 +++++ Tests/MessagePackerTests/FloatUnpackedTests.swift | 5 +++++ 4 files changed, 16 insertions(+) diff --git a/Sources/MessagePackTypes/MessagePackType+DoubleType.swift b/Sources/MessagePackTypes/MessagePackType+DoubleType.swift index ccbd103..872c70c 100644 --- a/Sources/MessagePackTypes/MessagePackType+DoubleType.swift +++ b/Sources/MessagePackTypes/MessagePackType+DoubleType.swift @@ -32,6 +32,9 @@ extension MessagePackType.DoubleType { } static func unpack(for value: Data) throws -> Double { + guard let firstByte = value.first else { throw MessagePackError.emptyData } + guard firstByte == self.firstByte else { throw MessagePackError.invalidData } + let unpacked: UInt64 = try unpackInteger(try value.subdata(dataRange)) return Double(bitPattern: UInt64(bigEndian: unpacked)) } diff --git a/Sources/MessagePackTypes/MessagePackType+FloatType.swift b/Sources/MessagePackTypes/MessagePackType+FloatType.swift index bb63def..56b2e9e 100644 --- a/Sources/MessagePackTypes/MessagePackType+FloatType.swift +++ b/Sources/MessagePackTypes/MessagePackType+FloatType.swift @@ -32,6 +32,9 @@ extension MessagePackType.FloatType { } static func unpack(for value: Data) throws -> Float { + guard let firstByte = value.first else { throw MessagePackError.emptyData } + guard firstByte == self.firstByte else { throw MessagePackError.invalidData } + let unpacked: UInt32 = try unpackInteger(try value.subdata(dataRange)) return Float(bitPattern: UInt32(bigEndian: unpacked)) } diff --git a/Tests/MessagePackerTests/DoubleUnpackedTests.swift b/Tests/MessagePackerTests/DoubleUnpackedTests.swift index 6e3933a..70cc6c3 100644 --- a/Tests/MessagePackerTests/DoubleUnpackedTests.swift +++ b/Tests/MessagePackerTests/DoubleUnpackedTests.swift @@ -25,4 +25,9 @@ class DoubleUnpackedTests: XCTestCase { let output = 3.14 XCTAssertEqual(try decoder.decode(Double.self, from: input), output) } + + func testMismatchedType() { + let input = Data([207, 255, 255, 255, 255, 255, 255, 255, 255]) + XCTAssertThrowsError(try decoder.decode(Double.self, from: input)) + } } diff --git a/Tests/MessagePackerTests/FloatUnpackedTests.swift b/Tests/MessagePackerTests/FloatUnpackedTests.swift index a6a5450..394bfde 100644 --- a/Tests/MessagePackerTests/FloatUnpackedTests.swift +++ b/Tests/MessagePackerTests/FloatUnpackedTests.swift @@ -25,4 +25,9 @@ class FloatUnpackedTests: XCTestCase { let output: Float = 3.14 XCTAssertEqual(try decoder.decode(Float.self, from: input), output) } + + func testMismatchedType() { + let input = Data([207, 255, 255, 255, 255, 255, 255, 255, 255]) + XCTAssertThrowsError(try decoder.decode(Float.self, from: input)) + } }