diff --git a/Signal/src/Models/CompareSafetyNumbersActivity.swift b/Signal/src/Models/CompareSafetyNumbersActivity.swift
index d89be5c87..7fdeefc90 100644
--- a/Signal/src/Models/CompareSafetyNumbersActivity.swift
+++ b/Signal/src/Models/CompareSafetyNumbersActivity.swift
@@ -1,5 +1,5 @@
//
-// Copyright (c) 2018 Open Whisper Systems. All rights reserved.
+// Copyright (c) 2019 Open Whisper Systems. All rights reserved.
//
import Foundation
@@ -85,13 +85,13 @@ class CompareSafetyNumbersActivity: UIActivity {
// MARK: Helpers
func numericOnly(string: String?) -> String? {
- guard (string != nil) else {
+ guard let string = string else {
return nil
}
var numericOnly: String?
if let regex = try? NSRegularExpression(pattern: "\\D", options: .caseInsensitive) {
- numericOnly = regex.stringByReplacingMatches(in: string!, options: .withTransparentBounds, range: NSRange(location: 0, length: string!.count), withTemplate: "")
+ numericOnly = regex.stringByReplacingMatches(in: string, options: .withTransparentBounds, range: NSRange(location: 0, length: string.utf16.count), withTemplate: "")
}
return numericOnly
diff --git a/Signal/src/call/PeerConnectionClient.swift b/Signal/src/call/PeerConnectionClient.swift
index b2f5db84b..15d85c73f 100644
--- a/Signal/src/call/PeerConnectionClient.swift
+++ b/Signal/src/call/PeerConnectionClient.swift
@@ -1,5 +1,5 @@
//
-// Copyright (c) 2018 Open Whisper Systems. All rights reserved.
+// Copyright (c) 2019 Open Whisper Systems. All rights reserved.
//
import Foundation
@@ -1107,12 +1107,12 @@ class HardenedRTCSessionDescription {
// Enforce Constant bit rate.
let cbrRegex = try! NSRegularExpression(pattern: "(a=fmtp:111 ((?!cbr=).)*)\r?\n", options: .caseInsensitive)
- description = cbrRegex.stringByReplacingMatches(in: description, options: [], range: NSRange(location: 0, length: description.count), withTemplate: "$1;cbr=1\r\n")
+ description = cbrRegex.stringByReplacingMatches(in: description, options: [], range: NSRange(location: 0, length: description.utf16.count), withTemplate: "$1;cbr=1\r\n")
// Strip plaintext audio-level details
// https://tools.ietf.org/html/rfc6464
let audioLevelRegex = try! NSRegularExpression(pattern: ".+urn:ietf:params:rtp-hdrext:ssrc-audio-level.*\r?\n", options: .caseInsensitive)
- description = audioLevelRegex.stringByReplacingMatches(in: description, options: [], range: NSRange(location: 0, length: description.count), withTemplate: "")
+ description = audioLevelRegex.stringByReplacingMatches(in: description, options: [], range: NSRange(location: 0, length: description.utf16.count), withTemplate: "")
return RTCSessionDescription.init(type: rtcSessionDescription.type, sdp: description)
}
@@ -1161,7 +1161,7 @@ class HardenedRTCSessionDescription {
do {
let regex = try NSRegularExpression(pattern: "[\\da-f]*:[\\da-f]*:[\\da-f:\\.]*",
options: .caseInsensitive)
- return regex.stringByReplacingMatches(in: sdp, options: [], range: NSRange(location: 0, length: sdp.count), withTemplate: "[ REDACTED_IPV6_ADDRESS ]")
+ return regex.stringByReplacingMatches(in: sdp, options: [], range: NSRange(location: 0, length: sdp.utf16.count), withTemplate: "[ REDACTED_IPV6_ADDRESS ]")
} catch {
owsFailDebug("Could not redact IPv6 addresses.")
return "[Could not redact IPv6 addresses.]"
diff --git a/Signal/src/util/Backup/OWSBackupAPI.swift b/Signal/src/util/Backup/OWSBackupAPI.swift
index 27bf5aeea..aceea9ab5 100644
--- a/Signal/src/util/Backup/OWSBackupAPI.swift
+++ b/Signal/src/util/Backup/OWSBackupAPI.swift
@@ -1,5 +1,5 @@
//
-// Copyright (c) 2018 Open Whisper Systems. All rights reserved.
+// Copyright (c) 2019 Open Whisper Systems. All rights reserved.
//
import Foundation
@@ -94,7 +94,7 @@ import PromiseKit
var recipientIds = [String]()
for recordName in recordNames {
let regex = recordNamePrefixRegex
- guard let match: NSTextCheckingResult = regex.firstMatch(in: recordName, options: [], range: NSRange(location: 0, length: recordName.count)) else {
+ guard let match: NSTextCheckingResult = regex.firstMatch(in: recordName, options: [], range: NSRange(location: 0, length: recordName.utf16.count)) else {
Logger.warn("no match: \(recordName)")
continue
}
diff --git a/SignalServiceKit/src/Messages/Interactions/OWSLinkPreview.swift b/SignalServiceKit/src/Messages/Interactions/OWSLinkPreview.swift
index 784ba87d0..80c1515fa 100644
--- a/SignalServiceKit/src/Messages/Interactions/OWSLinkPreview.swift
+++ b/SignalServiceKit/src/Messages/Interactions/OWSLinkPreview.swift
@@ -751,7 +751,9 @@ public class OWSLinkPreview: MTLModel {
}
var title: String?
- if let rawTitle = NSRegularExpression.parseFirstMatch(pattern: "", text: linkText) {
+ if let rawTitle = NSRegularExpression.parseFirstMatch(pattern: "",
+ text: linkText,
+ options: .dotMatchesLineSeparators) {
if let decodedTitle = decodeHTMLEntities(inString: rawTitle) {
let normalizedTitle = OWSLinkPreview.normalizeTitle(title: decodedTitle)
if normalizedTitle.count > 0 {
diff --git a/SignalServiceKit/src/Util/NSRegularExpression+SSK.swift b/SignalServiceKit/src/Util/NSRegularExpression+SSK.swift
index b8e2fda49..e9b398d38 100644
--- a/SignalServiceKit/src/Util/NSRegularExpression+SSK.swift
+++ b/SignalServiceKit/src/Util/NSRegularExpression+SSK.swift
@@ -14,12 +14,13 @@ public extension NSRegularExpression {
@objc
public class func parseFirstMatch(pattern: String,
- text: String) -> String? {
+ text: String,
+ options: NSRegularExpression.Options = []) -> String? {
do {
- let regex = try NSRegularExpression(pattern: pattern)
+ let regex = try NSRegularExpression(pattern: pattern, options: options)
guard let match = regex.firstMatch(in: text,
options: [],
- range: NSRange(location: 0, length: text.count)) else {
+ range: NSRange(location: 0, length: text.utf16.count)) else {
return nil
}
let matchRange = match.range(at: 1)
diff --git a/SignalServiceKit/tests/Messages/OWSLinkPreviewTest.swift b/SignalServiceKit/tests/Messages/OWSLinkPreviewTest.swift
index 979dbaca8..db5a1743c 100644
--- a/SignalServiceKit/tests/Messages/OWSLinkPreviewTest.swift
+++ b/SignalServiceKit/tests/Messages/OWSLinkPreviewTest.swift
@@ -434,4 +434,24 @@ class OWSLinkPreviewTest: SSKBaseTestSwift {
self.waitForExpectations(timeout: 5.0, handler: nil)
}
+
+ // When using regular expressions to parse link titles, we need to use
+ // String.utf16.count, not String.count in the range.
+ func testRegexRanges() {
+ let regex = try! NSRegularExpression(pattern: "bob", options: [])
+ var text = "bob"
+ XCTAssertNotNil(regex.firstMatch(in: text,
+ options: [],
+ range: NSRange(location: 0, length: text.count)))
+ XCTAssertNotNil(regex.firstMatch(in: text,
+ options: [],
+ range: NSRange(location: 0, length: text.utf16.count)))
+ text = "😂😘🙂 bob"
+ XCTAssertNil(regex.firstMatch(in: text,
+ options: [],
+ range: NSRange(location: 0, length: text.count)))
+ XCTAssertNotNil(regex.firstMatch(in: text,
+ options: [],
+ range: NSRange(location: 0, length: text.utf16.count)))
+ }
}