From 70ba1720d913acb3d15f1620a919f981dee3e0a0 Mon Sep 17 00:00:00 2001 From: Matthew Chen Date: Tue, 20 Feb 2018 20:35:40 -0500 Subject: [PATCH] Filter unicode ordering letters. --- Signal/test/util/UtilTest.m | 16 +++++++++- SignalServiceKit/src/Util/NSString+SSK.m | 40 +++++++++++++++++++++--- 2 files changed, 50 insertions(+), 6 deletions(-) diff --git a/Signal/test/util/UtilTest.m b/Signal/test/util/UtilTest.m index 1e193f9fa..7ebcf79e1 100644 --- a/Signal/test/util/UtilTest.m +++ b/Signal/test/util/UtilTest.m @@ -1,5 +1,5 @@ // -// Copyright (c) 2017 Open Whisper Systems. All rights reserved. +// Copyright (c) 2018 Open Whisper Systems. All rights reserved. // #import "UtilTest.h" @@ -11,6 +11,8 @@ - (NSString *)removeAllCharactersIn:(NSCharacterSet *)characterSet; +- (NSString *)filterUnsafeCharacters; + @end #pragma mark - @@ -69,4 +71,16 @@ test([@"(555) 235-7111".digitsOnly isEqual:@"5552357111"]); } +- (void)testFilterUnsafeCharacters +{ + XCTAssertEqualObjects(@"1".filterUnsafeCharacters, @"1"); + XCTAssertEqualObjects(@"alice\u202Dbob".filterUnsafeCharacters, @"alice\uFFFDbob"); + XCTAssertEqualObjects(@"\u202Dalicebob".filterUnsafeCharacters, @"\uFFFDalicebob"); + XCTAssertEqualObjects(@"alicebob\u202D".filterUnsafeCharacters, @"alicebob\uFFFD"); + XCTAssertEqualObjects(@"alice\u202Ebob".filterUnsafeCharacters, @"alice\uFFFDbob"); + XCTAssertEqualObjects(@"\u202Ealicebob".filterUnsafeCharacters, @"\uFFFDalicebob"); + XCTAssertEqualObjects(@"alicebob\u202E".filterUnsafeCharacters, @"alicebob\uFFFD"); + XCTAssertEqualObjects(@"alice\u202Dbobalice\u202Ebob".filterUnsafeCharacters, @"alice\uFFFDbobalice\uFFFDbob"); +} + @end diff --git a/SignalServiceKit/src/Util/NSString+SSK.m b/SignalServiceKit/src/Util/NSString+SSK.m index ad2ad4eb7..d00de7109 100644 --- a/SignalServiceKit/src/Util/NSString+SSK.m +++ b/SignalServiceKit/src/Util/NSString+SSK.m @@ -103,10 +103,7 @@ NS_ASSUME_NONNULL_BEGIN static NSCharacterSet *characterSet; static dispatch_once_t onceToken; dispatch_once(&onceToken, ^{ - UniChar chars[] = { 0x200C }; - NSString *characterSetString = - [[NSString alloc] initWithCharacters:chars length:sizeof(chars) / sizeof(UniChar)]; - characterSet = [NSCharacterSet characterSetWithCharactersInString:characterSetString]; + characterSet = [NSCharacterSet characterSetWithCharactersInString:@"\u200C"]; }); return characterSet; @@ -147,9 +144,42 @@ NS_ASSUME_NONNULL_BEGIN return [filteredForIndic copy]; } ++ (NSCharacterSet *)unsafeCharacterSet +{ + static NSCharacterSet *characterSet; + static dispatch_once_t onceToken; + dispatch_once(&onceToken, ^{ + characterSet = [NSCharacterSet characterSetWithCharactersInString:@"\u202D\u202E"]; + }); + + return characterSet; +} + +- (NSString *)filterUnsafeCharacters +{ + NSCharacterSet *unsafeCharacterSet = [[self class] unsafeCharacterSet]; + NSRange range = [self rangeOfCharacterFromSet:unsafeCharacterSet]; + if (range.location == NSNotFound) { + return self; + } + NSMutableString *filtered = [NSMutableString new]; + NSString *remainder = [self copy]; + while (range.location != NSNotFound) { + if (range.location > 0) { + [filtered appendString:[remainder substringToIndex:range.location]]; + } + // The "replacement" code point. + [filtered appendString:@"\uFFFD"]; + remainder = [remainder substringFromIndex:range.location + range.length]; + range = [remainder rangeOfCharacterFromSet:unsafeCharacterSet]; + } + [filtered appendString:remainder]; + return filtered; +} + - (NSString *)filterStringForDisplay { - return self.ows_stripped.filterForIndicScripts.filterForExcessiveDiacriticals; + return self.ows_stripped.filterForIndicScripts.filterForExcessiveDiacriticals.filterUnsafeCharacters; } - (NSString *)filterForExcessiveDiacriticals