From ecdc42978c6c120fabec417d20fd56caecd0ebab Mon Sep 17 00:00:00 2001 From: Tim Kientzle Date: Thu, 9 Nov 2023 14:53:53 -0800 Subject: [PATCH 1/2] A performance-oriented test decoding 1 million messages from a stream Checking this in to help aid in future performance optimization for AsyncMessageSequence --- ...AsyncMessageSequence_debug-5217919734513664 | Bin 0 -> 910019 bytes .../Test_AsyncMessageSequence.swift | 17 +++++++++++++++++ .../Test_BinaryDelimited.swift | 16 ++++++++++++++++ 3 files changed, 33 insertions(+) create mode 100644 FuzzTesting/FailCases/clusterfuzz-testcase-minimized-FuzzAsyncMessageSequence_debug-5217919734513664 diff --git a/FuzzTesting/FailCases/clusterfuzz-testcase-minimized-FuzzAsyncMessageSequence_debug-5217919734513664 b/FuzzTesting/FailCases/clusterfuzz-testcase-minimized-FuzzAsyncMessageSequence_debug-5217919734513664 new file mode 100644 index 0000000000000000000000000000000000000000..a95e33e0915a28fb8d8a0884ab91310036f6285e GIT binary patch literal 910019 zcmeIu!3h8%6hpxvf?ySvy*2zQ1;xwOFu6R)aWZQ4* AsyncStream { AsyncStream(UInt8.self) { continuation in diff --git a/Tests/SwiftProtobufTests/Test_BinaryDelimited.swift b/Tests/SwiftProtobufTests/Test_BinaryDelimited.swift index cc87c7311..d78fc72a7 100644 --- a/Tests/SwiftProtobufTests/Test_BinaryDelimited.swift +++ b/Tests/SwiftProtobufTests/Test_BinaryDelimited.swift @@ -145,4 +145,20 @@ final class Test_BinaryDelimited: XCTestCase { assertParseFails(atEndOfStream: stream2) } + // oss-fuzz found this case that runs slowly for AsyncMessageSequence + // Copied here as well for comparison. + func testLargeExample() throws { + let bytes = [UInt8](repeating: 0, count: 1000000) + let istream = openInputStream(bytes) + + for _ in 0..<1000000 { + let msg = try BinaryDelimited.parse( + messageType: SwiftProtoTesting_TestAllTypes.self, + from: istream) + XCTAssertEqual(msg, SwiftProtoTesting_TestAllTypes()) + } + XCTAssertThrowsError(try BinaryDelimited.parse( + messageType: SwiftProtoTesting_TestAllTypes.self, + from: istream)) + } } From 692d45a365ba18cc5cc904d403afad96f4fb0dd7 Mon Sep 17 00:00:00 2001 From: Tim Kientzle Date: Thu, 9 Nov 2023 15:21:05 -0800 Subject: [PATCH 2/2] Reduce the number of iterations to 100,000 Also factor out the number of iterations so future tinkerers have a way to experiment. --- Tests/SwiftProtobufTests/Test_AsyncMessageSequence.swift | 9 ++++++--- Tests/SwiftProtobufTests/Test_BinaryDelimited.swift | 5 +++-- 2 files changed, 9 insertions(+), 5 deletions(-) diff --git a/Tests/SwiftProtobufTests/Test_AsyncMessageSequence.swift b/Tests/SwiftProtobufTests/Test_AsyncMessageSequence.swift index 734394153..9304ab310 100644 --- a/Tests/SwiftProtobufTests/Test_AsyncMessageSequence.swift +++ b/Tests/SwiftProtobufTests/Test_AsyncMessageSequence.swift @@ -202,9 +202,12 @@ final class Test_AsyncMessageSequence: XCTestCase { // Slow test case found by oss-fuzz: 1 million zero-sized messages // A similar test with BinaryDelimited is about 4x faster, showing - // that we have some room for improvement here: + // that we have some room for improvement here. + // (Note this currently only tests 100,000 zero-sized messages, + // but the constant below is easy to edit if you want to experiment.) func testLargeExample() async throws { - let bytes = [UInt8](repeating: 0, count: 1000000) + let messageCount = 100_000 + let bytes = [UInt8](repeating: 0, count: messageCount) let byteStream = asyncByteStream(bytes: bytes) let decodedStream = byteStream.binaryProtobufDelimitedMessages( of: SwiftProtoTesting_TestAllTypes.self, @@ -214,7 +217,7 @@ final class Test_AsyncMessageSequence: XCTestCase { XCTAssertEqual(message, SwiftProtoTesting_TestAllTypes()) count += 1 } - XCTAssertEqual(count, 1000000) + XCTAssertEqual(count, messageCount) } fileprivate func asyncByteStream(bytes: [UInt8]) -> AsyncStream { diff --git a/Tests/SwiftProtobufTests/Test_BinaryDelimited.swift b/Tests/SwiftProtobufTests/Test_BinaryDelimited.swift index d78fc72a7..f65947eec 100644 --- a/Tests/SwiftProtobufTests/Test_BinaryDelimited.swift +++ b/Tests/SwiftProtobufTests/Test_BinaryDelimited.swift @@ -148,10 +148,11 @@ final class Test_BinaryDelimited: XCTestCase { // oss-fuzz found this case that runs slowly for AsyncMessageSequence // Copied here as well for comparison. func testLargeExample() throws { - let bytes = [UInt8](repeating: 0, count: 1000000) + let messageCount = 100_000 + let bytes = [UInt8](repeating: 0, count: messageCount) let istream = openInputStream(bytes) - for _ in 0..<1000000 { + for _ in 0..