From b8330c08b59ae0af7a85ded8449f4a38c681a8e1 Mon Sep 17 00:00:00 2001 From: digaus Date: Fri, 17 Jan 2020 19:32:42 +0100 Subject: [PATCH 1/2] Prevent iOS crash on NetService.dictionary call Decode the TXT record as a string dictionary, or [:] if the data is malformed: https://stackoverflow.com/a/52220739 --- src/ios/ZeroConf.swift | 38 ++++++++++++++++++++++++++++++++++---- 1 file changed, 34 insertions(+), 4 deletions(-) diff --git a/src/ios/ZeroConf.swift b/src/ios/ZeroConf.swift index 573e85c..318010e 100644 --- a/src/ios/ZeroConf.swift +++ b/src/ios/ZeroConf.swift @@ -1,3 +1,4 @@ +import Cordova import Foundation @objc(ZeroConf) public class ZeroConf : CDVPlugin { @@ -395,10 +396,7 @@ import Foundation var txtRecord: [String: String] = [:] if let txtRecordData = netService.txtRecordData() { - let dict = NetService.dictionary(fromTXTRecord: txtRecordData) - for (key, data) in dict { - txtRecord[key] = String(data: data, encoding:String.Encoding.utf8) - } + txtRecord = dictionary(fromTXTRecord: txtRecordData) } var hostName:String = "" @@ -436,4 +434,36 @@ import Foundation return nil } + fileprivate static func dictionary(fromTXTRecord txtData: Data) -> [String: String] { + + var result = [String: String]() + var data = txtData + + while !data.isEmpty { + // The first byte of each record is its length, so prefix that much data + let recordLength = Int(data.removeFirst()) + guard data.count >= recordLength else { return [:] } + let recordData = data[..<(data.startIndex + recordLength)] + data = data.dropFirst(recordLength) + + guard let record = String(bytes: recordData, encoding: .utf8) else { return [:] } + // The format of the entry is "key=value" + // (According to the reference implementation, = is optional if there is no value, + // and any equals signs after the first are part of the value.) + // `ommittingEmptySubsequences` is necessary otherwise an empty string will crash the next line + let keyValue = record.split(separator: "=", maxSplits: 1, omittingEmptySubsequences: false) + let key = String(keyValue[0]) + // If there's no value, make the value the empty string + switch keyValue.count { + case 1: + result[key] = "" + case 2: + result[key] = String(keyValue[1]) + default: + fatalError() + } + } + + return result + } } From 3f00f8f007c4fe122d11ea43454f8c6ba0be2f77 Mon Sep 17 00:00:00 2001 From: digaus Date: Fri, 17 Jan 2020 19:36:00 +0100 Subject: [PATCH 2/2] Update ZeroConf.swift Remove import --- src/ios/ZeroConf.swift | 1 - 1 file changed, 1 deletion(-) diff --git a/src/ios/ZeroConf.swift b/src/ios/ZeroConf.swift index 318010e..088ee5c 100644 --- a/src/ios/ZeroConf.swift +++ b/src/ios/ZeroConf.swift @@ -1,4 +1,3 @@ -import Cordova import Foundation @objc(ZeroConf) public class ZeroConf : CDVPlugin {