Skip to content

Commit

Permalink
Fix buffer overflow and data corruption when a type has more than 5 l…
Browse files Browse the repository at this point in the history
…ayers of nesting
  • Loading branch information
amorde committed Dec 6, 2024
1 parent 67b73b5 commit d498d08
Show file tree
Hide file tree
Showing 5 changed files with 100 additions and 1 deletion.
Original file line number Diff line number Diff line change
Expand Up @@ -778,7 +778,7 @@ public final class ProtoWriter {
let newCapacity = messageStackCapacity * 2

let newMessageStack = UnsafeMutablePointer<MessageFrame>.allocate(capacity: newCapacity)
newMessageStack.moveInitialize(from: messageStack, count: messageStackIndex + 1)
newMessageStack.moveInitialize(from: messageStack, count: messageStackCapacity)
messageStack.deallocate()

messageStack = newMessageStack
Expand Down
3 changes: 3 additions & 0 deletions wire-runtime-swift/src/test/proto/nested4.proto
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,11 @@
* limitations under the License.
*/
syntax = "proto2";
import "nested5.proto";

message Nested4 {
required string name = 1;

optional Nested5 nested = 2;
}

25 changes: 25 additions & 0 deletions wire-runtime-swift/src/test/proto/nested5.proto
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
/*
* Copyright 2020 Square Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
syntax = "proto2";

import "nested6.proto";

message Nested5 {
required string name = 1;

optional Nested6 nested = 2;
}

21 changes: 21 additions & 0 deletions wire-runtime-swift/src/test/proto/nested6.proto
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
/*
* Copyright 2020 Square Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
syntax = "proto2";

message Nested6 {
required string name = 1;
}

50 changes: 50 additions & 0 deletions wire-runtime-swift/src/test/swift/ProtoWriterTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -255,6 +255,56 @@ final class ProtoWriterTests: XCTestCase {
""")
}

func testEncodeMessageWithStackExpansion() throws {
let writer = ProtoWriter()
let message = Nested1(name: "name1") { v1 in
v1.nested = Nested2(name: "name2") { v2 in
v2.nested = Nested3(name: "name3") { v3 in
v3.nested = Nested4(name: "name4") { v4 in
v4.nested = Nested5(name: "name5") { v5 in
v5.nested = Nested6(name: "name6")
}
}
}
}
}

try writer.encode(tag: 1, value: message)

assertBufferEqual(writer, """
0A // (Tag 1 | Length Delimited)
34 // Length 52 for Nested1
0A // (Tag 1 | Length Delimited)
05 // Length 5 for name1
6E616D6531 // UTF-8 Value "name1"
12 // (Tag 2 | Length Delimited)
2B // Length 43
0A // (Tag 1 | Length Delimited)
05 // Length 5 for name2
6E616D6532 // UTF-8 Value "name2"
12 // (Tag 2 | Length Delimited)
22 // Length 34
0A // (Tag 1 | Length Delimited)
05 // Length 5 for name3
6E616D6533 // UTF-8 Value "name3"
12 // (Tag 2 | Length Delimited)
19 // Length 25
0A // (Tag 1 | Length Delimited)
05 // Length 5 for name4
6E616D6534 // UTF-8 Value "name4"
12 // (Tag 2 | Length Delimited)
10 // Length 16
0A // (Tag 1 | Length Delimited)
05 // Length 5 for name5
6E616D6535 // UTF-8 Value "name5"
12 // (Tag 2 | Length Delimited)
07 // Length 7
0A // (Tag 1 | Length Delimited)
05 // Length 5 for name6
6E616D6536 // UTF-8 Value "name6"
""")
}

func testEncodeString() throws {
let writer = ProtoWriter()
try writer.encode(tag: 1, value: "foo")
Expand Down

0 comments on commit d498d08

Please sign in to comment.