From 7e3babc9b366ca9d1869ade395407363d94052e2 Mon Sep 17 00:00:00 2001 From: sashaweiss-signal Date: Wed, 24 Jul 2024 10:25:34 -0700 Subject: [PATCH 1/2] Add test demonstrating fatalError --- .../src/test/swift/ProtoReaderTests.swift | 44 +++++++++++++++++++ 1 file changed, 44 insertions(+) diff --git a/wire-runtime-swift/src/test/swift/ProtoReaderTests.swift b/wire-runtime-swift/src/test/swift/ProtoReaderTests.swift index 58be8f6918..4708cea4b0 100644 --- a/wire-runtime-swift/src/test/swift/ProtoReaderTests.swift +++ b/wire-runtime-swift/src/test/swift/ProtoReaderTests.swift @@ -646,6 +646,50 @@ final class ProtoReaderTests: XCTestCase { } } + func testDecodePackedRepeatedFixedUInt32Empty() throws { + let data = Foundation.Data(hexEncoded: """ + 0A // (Tag 1 | Length Delimited) + 00 // Length 0 + """)! + + try test(data: data) { reader in + var values: [UInt64] = [] + try reader.decode(tag: 1) { try reader.decode(into: &values, encoding: .fixed) } + + XCTAssertEqual(values, []) + } + } + + func testDecodePackedRepeatedFixedUInt64() throws { + let data = Foundation.Data(hexEncoded: """ + 0A // (Tag 1 | Length Delimited) + 10 // Length 16 + 0100000000000000 // Value 1 + FFFFFFFFFFFFFFFF // Value UInt64.max + """)! + + try test(data: data) { reader in + var values: [UInt64] = [] + try reader.decode(tag: 1) { try reader.decode(into: &values, encoding: .fixed) } + + XCTAssertEqual(values, [1, .max]) + } + } + + func testDecodePackedRepeatedFixedUInt64Empty() throws { + let data = Foundation.Data(hexEncoded: """ + 0A // (Tag 1 | Length Delimited) + 00 // Length 0 + """)! + + try test(data: data) { reader in + var values: [UInt64] = [] + try reader.decode(tag: 1) { try reader.decode(into: &values, encoding: .fixed) } + + XCTAssertEqual(values, []) + } + } + func testDecodeRepeatedVarintUInt32() throws { let data = Foundation.Data(hexEncoded: """ 08 // (Tag 1 | Varint) From 48a2567e1de80be18110f50deff62c4cdece3063 Mon Sep 17 00:00:00 2001 From: sashaweiss-signal Date: Wed, 24 Jul 2024 10:27:45 -0700 Subject: [PATCH 2/2] Add patch to ProtoReader.swift to avoid crash --- .../src/main/swift/ProtoCodable/ProtoReader.swift | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/wire-runtime-swift/src/main/swift/ProtoCodable/ProtoReader.swift b/wire-runtime-swift/src/main/swift/ProtoCodable/ProtoReader.swift index 203c16c5ae..d6cca5c5bb 100644 --- a/wire-runtime-swift/src/main/swift/ProtoCodable/ProtoReader.swift +++ b/wire-runtime-swift/src/main/swift/ProtoCodable/ProtoReader.swift @@ -861,6 +861,12 @@ public final class ProtoReader { private func decode(into array: inout [T], decode: () throws -> T?) throws { switch state { case let .lengthDelimited(length): + guard length > 0 else { + // If the array is empty, there's nothing to do. + state = .tag + return + } + // Preallocate space for the unpacked data. // It's allowable to have a packed field spread across multiple places // in the buffer, so add to the existing capacity.