diff --git a/lib/swift/Sources/TCompactProtocol.swift b/lib/swift/Sources/TCompactProtocol.swift index 812df25c1a..acdb91b79c 100644 --- a/lib/swift/Sources/TCompactProtocol.swift +++ b/lib/swift/Sources/TCompactProtocol.swift @@ -313,6 +313,10 @@ public class TCompactProtocol: TProtocol { booleanValue = type == .boolean_TRUE } + guard fieldId >= 0 && fieldId <= Int16(UInt8.max) else { + throw TProtocolError(error: .invalidData, + message: "Field id out of range: \(fieldId)") + } // push the new field onto the field stack so we can keep the deltas going lastFieldId = UInt8(fieldId) return ("", fieldType, Int32(fieldId)) diff --git a/lib/swift/Sources/TProtocol.swift b/lib/swift/Sources/TProtocol.swift index ed6db6fa3e..e3a7a0ec40 100644 --- a/lib/swift/Sources/TProtocol.swift +++ b/lib/swift/Sources/TProtocol.swift @@ -133,6 +133,14 @@ public extension TProtocol { } func skip(type: TType) throws { + try skip(type: type, depth: 0) + } + + private func skip(type: TType, depth: Int) throws { + let nextDepth = depth + 1 + if nextDepth > 64 { + throw TProtocolError(error: .depthLimit, message: "Maximum skip depth exceeded") + } switch type { case .bool: _ = try read() as Bool case .i8: _ = try read() as Int8 @@ -142,7 +150,7 @@ public extension TProtocol { case .double: _ = try read() as Double case .string: _ = try read() as String case .uuid: _ = try read() as UUID - + case .struct: _ = try readStructBegin() while true { @@ -150,35 +158,44 @@ public extension TProtocol { if fieldType == .stop { break } - try skip(type: fieldType) + try skip(type: fieldType, depth: nextDepth) try readFieldEnd() } try readStructEnd() - - + + case .map: let (keyType, valueType, size) = try readMapBegin() + if size < 0 { + throw TProtocolError(error: .negativeSize, message: "Negative map size: \(size)") + } for _ in 0..