From 012711007560579c4df72b5ea5a7e7749f70ee7a Mon Sep 17 00:00:00 2001 From: Huw Rowlands Date: Fri, 17 Mar 2023 11:49:13 +1100 Subject: [PATCH 1/2] Protect against overflows in BoxedFlagValues MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Previously, attempting to unwrap an Int from a BoxedFlagValue into an FlagValue that was not wide enough would cause a runtime error. Now, we unwrap the Int from the BoxedFlagValue and convert it into the Int type’s fallible initialiser. That way, we know it will not be too big when we do the assignment. --- Sources/Vexil/Value.swift | 36 ++++++++--------- Tests/VexilTests/FlagValueUnboxingTests.swift | 39 +++++++++++++++++++ 2 files changed, 57 insertions(+), 18 deletions(-) diff --git a/Sources/Vexil/Value.swift b/Sources/Vexil/Value.swift index ec8c383b..398ed38b 100644 --- a/Sources/Vexil/Value.swift +++ b/Sources/Vexil/Value.swift @@ -208,8 +208,8 @@ extension Int8: FlagValue { public typealias BoxedValueType = Int public init? (boxedFlagValue: BoxedFlagValue) { - guard let value = Int(boxedFlagValue: boxedFlagValue) else { return nil } - self = Int8(value) + guard let value = Int(boxedFlagValue: boxedFlagValue).flatMap(Int8.init(exactly:)) else { return nil } + self = value } public var boxedFlagValue: BoxedFlagValue { @@ -221,8 +221,8 @@ extension Int16: FlagValue { public typealias BoxedValueType = Int public init? (boxedFlagValue: BoxedFlagValue) { - guard let value = Int(boxedFlagValue: boxedFlagValue) else { return nil } - self = Int16(value) + guard let value = Int(boxedFlagValue: boxedFlagValue).flatMap(Int16.init(exactly:)) else { return nil } + self = value } public var boxedFlagValue: BoxedFlagValue { @@ -234,8 +234,8 @@ extension Int32: FlagValue { public typealias BoxedValueType = Int public init? (boxedFlagValue: BoxedFlagValue) { - guard let value = Int(boxedFlagValue: boxedFlagValue) else { return nil } - self = Int32(value) + guard let value = Int(boxedFlagValue: boxedFlagValue).flatMap(Int32.init(exactly:)) else { return nil } + self = value } public var boxedFlagValue: BoxedFlagValue { @@ -247,8 +247,8 @@ extension Int64: FlagValue { public typealias BoxedValueType = Int public init? (boxedFlagValue: BoxedFlagValue) { - guard let value = Int(boxedFlagValue: boxedFlagValue) else { return nil } - self = Int64(value) + guard let value = Int(boxedFlagValue: boxedFlagValue).flatMap(Int64.init(exactly:)) else { return nil } + self = value } public var boxedFlagValue: BoxedFlagValue { @@ -260,8 +260,8 @@ extension UInt: FlagValue { public typealias BoxedValueType = Int public init? (boxedFlagValue: BoxedFlagValue) { - guard let value = Int(boxedFlagValue: boxedFlagValue) else { return nil } - self = UInt(value) + guard let value = Int(boxedFlagValue: boxedFlagValue).flatMap(UInt.init(exactly:)) else { return nil } + self = value } public var boxedFlagValue: BoxedFlagValue { @@ -273,8 +273,8 @@ extension UInt8: FlagValue { public typealias BoxedValueType = Int public init? (boxedFlagValue: BoxedFlagValue) { - guard let value = Int(boxedFlagValue: boxedFlagValue) else { return nil } - self = UInt8(value) + guard let value = Int(boxedFlagValue: boxedFlagValue).flatMap(UInt8.init(exactly:)) else { return nil } + self = value } public var boxedFlagValue: BoxedFlagValue { @@ -286,8 +286,8 @@ extension UInt16: FlagValue { public typealias BoxedValueType = Int public init? (boxedFlagValue: BoxedFlagValue) { - guard let value = Int(boxedFlagValue: boxedFlagValue) else { return nil } - self = UInt16(value) + guard let value = Int(boxedFlagValue: boxedFlagValue).flatMap(UInt16.init(exactly:)) else { return nil } + self = value } public var boxedFlagValue: BoxedFlagValue { @@ -299,8 +299,8 @@ extension UInt32: FlagValue { public typealias BoxedValueType = Int public init? (boxedFlagValue: BoxedFlagValue) { - guard let value = Int(boxedFlagValue: boxedFlagValue) else { return nil } - self = UInt32(value) + guard let value = Int(boxedFlagValue: boxedFlagValue).flatMap(UInt32.init(exactly:)) else { return nil } + self = value } public var boxedFlagValue: BoxedFlagValue { @@ -312,8 +312,8 @@ extension UInt64: FlagValue { public typealias BoxedValueType = Int public init? (boxedFlagValue: BoxedFlagValue) { - guard let value = Int(boxedFlagValue: boxedFlagValue) else { return nil } - self = UInt64(value) + guard let value = Int(boxedFlagValue: boxedFlagValue).flatMap(UInt64.init(exactly:)) else { return nil } + self = value } public var boxedFlagValue: BoxedFlagValue { diff --git a/Tests/VexilTests/FlagValueUnboxingTests.swift b/Tests/VexilTests/FlagValueUnboxingTests.swift index 430d78ed..979dc4a8 100644 --- a/Tests/VexilTests/FlagValueUnboxingTests.swift +++ b/Tests/VexilTests/FlagValueUnboxingTests.swift @@ -161,6 +161,45 @@ final class FlagValueUnboxingTests: XCTestCase { } + // MARK: - Integer overflows + + func testInt8FlagValueWithOverflow () { + let boxed = BoxedFlagValue.integer(Int(Int8.max)+1) + + XCTAssertNil(Int8(boxedFlagValue: boxed)) + } + + func testInt16FlagValueWithOverflow () { + let boxed = BoxedFlagValue.integer(Int(Int16.max)+1) + + XCTAssertNil(Int16(boxedFlagValue: boxed)) + } + + func testInt32FlagValueWithOverflow () { + let boxed = BoxedFlagValue.integer(Int(Int32.max)+1) + + XCTAssertNil(Int32(boxedFlagValue: boxed)) + } + + func testUInt8FlagValueWithOverflow () { + let boxed = BoxedFlagValue.integer(Int(UInt8.max)+1) + + XCTAssertNil(UInt8(boxedFlagValue: boxed)) + } + + func testUInt16FlagValueWithOverflow () { + let boxed = BoxedFlagValue.integer(Int(UInt16.max)+1) + + XCTAssertNil(UInt16(boxedFlagValue: boxed)) + } + + func testUInt32FlagValueWithOverflow () { + let boxed = BoxedFlagValue.integer(Int(UInt32.max)+1) + + XCTAssertNil(UInt32(boxedFlagValue: boxed)) + } + + // MARK: - Floating Point Flag Values func testFloatFlagValue () { From dbfb6dd8f44483599e4001d96ba12c04b81ad546 Mon Sep 17 00:00:00 2001 From: Huw Rowlands Date: Fri, 17 Mar 2023 12:38:12 +1100 Subject: [PATCH 2/2] Fix SwiftLint --- Tests/VexilTests/FlagValueUnboxingTests.swift | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/Tests/VexilTests/FlagValueUnboxingTests.swift b/Tests/VexilTests/FlagValueUnboxingTests.swift index 979dc4a8..92716c31 100644 --- a/Tests/VexilTests/FlagValueUnboxingTests.swift +++ b/Tests/VexilTests/FlagValueUnboxingTests.swift @@ -164,37 +164,37 @@ final class FlagValueUnboxingTests: XCTestCase { // MARK: - Integer overflows func testInt8FlagValueWithOverflow () { - let boxed = BoxedFlagValue.integer(Int(Int8.max)+1) + let boxed = BoxedFlagValue.integer(Int(Int8.max) + 1) XCTAssertNil(Int8(boxedFlagValue: boxed)) } func testInt16FlagValueWithOverflow () { - let boxed = BoxedFlagValue.integer(Int(Int16.max)+1) + let boxed = BoxedFlagValue.integer(Int(Int16.max) + 1) XCTAssertNil(Int16(boxedFlagValue: boxed)) } func testInt32FlagValueWithOverflow () { - let boxed = BoxedFlagValue.integer(Int(Int32.max)+1) + let boxed = BoxedFlagValue.integer(Int(Int32.max) + 1) XCTAssertNil(Int32(boxedFlagValue: boxed)) } func testUInt8FlagValueWithOverflow () { - let boxed = BoxedFlagValue.integer(Int(UInt8.max)+1) + let boxed = BoxedFlagValue.integer(Int(UInt8.max) + 1) XCTAssertNil(UInt8(boxedFlagValue: boxed)) } func testUInt16FlagValueWithOverflow () { - let boxed = BoxedFlagValue.integer(Int(UInt16.max)+1) + let boxed = BoxedFlagValue.integer(Int(UInt16.max) + 1) XCTAssertNil(UInt16(boxedFlagValue: boxed)) } func testUInt32FlagValueWithOverflow () { - let boxed = BoxedFlagValue.integer(Int(UInt32.max)+1) + let boxed = BoxedFlagValue.integer(Int(UInt32.max) + 1) XCTAssertNil(UInt32(boxedFlagValue: boxed)) }