From 4ec5f00b1dec8220c1e458d852eecd602dd56b8f Mon Sep 17 00:00:00 2001 From: rsgowman Date: Thu, 30 Nov 2017 13:41:26 -0500 Subject: Fix StringView to properly convert NSStrings (#509) NSStrings are utf16, so NSString::length returns the number of utf16 characters present in the string. When the string is entirely made up of US-ASCII characters, everything's fine. But when characters requiring 16 bits are present, the size calculations were incorrect. Fixed by calculating the length based on the destination character set (i.e. UTF8). --- Firestore/CHANGELOG.md | 2 + .../Example/Firestore.xcodeproj/project.pbxproj | 4 ++ Firestore/Example/Tests/Local/StringViewTests.mm | 47 ++++++++++++++++++++++ Firestore/Source/Local/StringView.h | 3 +- 4 files changed, 55 insertions(+), 1 deletion(-) create mode 100644 Firestore/Example/Tests/Local/StringViewTests.mm (limited to 'Firestore') diff --git a/Firestore/CHANGELOG.md b/Firestore/CHANGELOG.md index 884af45..f1cd832 100644 --- a/Firestore/CHANGELOG.md +++ b/Firestore/CHANGELOG.md @@ -1,5 +1,7 @@ # Unreleased - [changed] Firestore no longer has a direct dependency on FirebaseAuth. +- [fixed] Fixed a crash when using path names with international characters + with persistence enabled. # v0.9.3 - [changed] Improved performance loading documents matching a query. diff --git a/Firestore/Example/Firestore.xcodeproj/project.pbxproj b/Firestore/Example/Firestore.xcodeproj/project.pbxproj index f56af4c..ea9ae44 100644 --- a/Firestore/Example/Firestore.xcodeproj/project.pbxproj +++ b/Firestore/Example/Firestore.xcodeproj/project.pbxproj @@ -57,6 +57,7 @@ 6003F5B1195388D20070C39A /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 6003F58D195388D20070C39A /* Foundation.framework */; }; 6003F5B2195388D20070C39A /* UIKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 6003F591195388D20070C39A /* UIKit.framework */; }; 6003F5BA195388D20070C39A /* InfoPlist.strings in Resources */ = {isa = PBXBuildFile; fileRef = 6003F5B8195388D20070C39A /* InfoPlist.strings */; }; + 61E1D8B11FCF6C5700753285 /* StringViewTests.mm in Sources */ = {isa = PBXBuildFile; fileRef = 61E1D8AF1FCF6AF500753285 /* StringViewTests.mm */; }; 6ED54761B845349D43DB6B78 /* Pods_Firestore_Example.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 75A6FE51C1A02DF38F62FAAD /* Pods_Firestore_Example.framework */; }; 71719F9F1E33DC2100824A3D /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 71719F9D1E33DC2100824A3D /* LaunchScreen.storyboard */; }; 873B8AEB1B1F5CCA007FD442 /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 873B8AEA1B1F5CCA007FD442 /* Main.storyboard */; }; @@ -221,6 +222,7 @@ 6003F5AF195388D20070C39A /* XCTest.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = XCTest.framework; path = Library/Frameworks/XCTest.framework; sourceTree = DEVELOPER_DIR; }; 6003F5B7195388D20070C39A /* Tests-Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = "Tests-Info.plist"; sourceTree = ""; }; 6003F5B9195388D20070C39A /* en */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = en; path = en.lproj/InfoPlist.strings; sourceTree = ""; }; + 61E1D8AF1FCF6AF500753285 /* StringViewTests.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = StringViewTests.mm; sourceTree = ""; }; 69F6A10DBD6187489481CD76 /* Pods_Firestore_Tests.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_Firestore_Tests.framework; sourceTree = BUILT_PRODUCTS_DIR; }; 71719F9E1E33DC2100824A3D /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = ""; }; 75A6FE51C1A02DF38F62FAAD /* Pods_Firestore_Example.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_Firestore_Example.framework; sourceTree = BUILT_PRODUCTS_DIR; }; @@ -551,6 +553,7 @@ DE51B1621F0D48AC0013853F /* Local */ = { isa = PBXGroup; children = ( + 61E1D8AF1FCF6AF500753285 /* StringViewTests.mm */, DE51B16A1F0D48AC0013853F /* FSTLocalStoreTests.h */, DE51B1701F0D48AC0013853F /* FSTMutationQueueTests.h */, DE51B1721F0D48AC0013853F /* FSTPersistenceTestHelpers.h */, @@ -1216,6 +1219,7 @@ DE51B1E91F0D490D0013853F /* FSTLevelDBMutationQueueTests.mm in Sources */, 54764FAF1FAA21B90085E60A /* FSTGoogleTestTests.mm in Sources */, DE51B1E61F0D490D0013853F /* FSTRemoteDocumentCacheTests.m in Sources */, + 61E1D8B11FCF6C5700753285 /* StringViewTests.mm in Sources */, DE51B1D91F0D490D0013853F /* FSTEagerGarbageCollectorTests.m in Sources */, DE51B1E21F0D490D0013853F /* FSTMutationQueueTests.m in Sources */, DE51B1E81F0D490D0013853F /* FSTLevelDBKeyTests.mm in Sources */, diff --git a/Firestore/Example/Tests/Local/StringViewTests.mm b/Firestore/Example/Tests/Local/StringViewTests.mm new file mode 100644 index 0000000..fd97c13 --- /dev/null +++ b/Firestore/Example/Tests/Local/StringViewTests.mm @@ -0,0 +1,47 @@ +/* + * Copyright 2017 Google + * + * 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. + */ + +#import "Firestore/Source/Local/StringView.h" + +#import +#include + +using Firestore::StringView; + +#define ASSERT_NSSTRING_TO_STRINGVIEW_AND_BACK_OK( nsstr ) \ + StringView sv(nsstr); \ + leveldb::Slice slice = sv; \ + NSString *afterConversion = [[NSString alloc] initWithBytes:slice.data() \ + length:slice.size() \ + encoding:NSUTF8StringEncoding]; \ + XCTAssertEqualObjects(afterConversion, nsstr); + +@interface StringViewTests : XCTestCase +@end + +@implementation StringViewTests + +- (void)testStringViewNSStringToSliceWithUSAscii { + NSString *usAsciiChars = @"abcdefg ABCDEFG 12345 !@#$%"; + ASSERT_NSSTRING_TO_STRINGVIEW_AND_BACK_OK(usAsciiChars); +} + +- (void)testStringViewNSStringToSliceWithNonUSAscii { + NSString *nonUsAsciiChars = @"ó¹"; + ASSERT_NSSTRING_TO_STRINGVIEW_AND_BACK_OK(nonUsAsciiChars); +} + +@end diff --git a/Firestore/Source/Local/StringView.h b/Firestore/Source/Local/StringView.h index 799baf8..b81b7b5 100644 --- a/Firestore/Source/Local/StringView.h +++ b/Firestore/Source/Local/StringView.h @@ -46,7 +46,8 @@ class StringView { // Creates a StringView from an NSString. When StringView is an argument type // into which an NSString* is passed, the caller should ensure that the // NSString is retained. - StringView(NSString *str) : data_([str UTF8String]), size_(str.length) { + StringView(NSString *str) + : data_([str UTF8String]), size_([str lengthOfBytesUsingEncoding:NSUTF8StringEncoding]) { } // Creates a StringView from the given char* pointer with an explicit size. -- cgit v1.2.3