Skip to content

Commit b3d8875

Browse files
committed
Iterate on the long tagged string test
1 parent e0dd80f commit b3d8875

File tree

2 files changed

+87
-25
lines changed

2 files changed

+87
-25
lines changed

test/stdlib/Inputs/NSSlowTaggedLocalizedString/NSSlowTaggedLocalizedString.m

Lines changed: 70 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,25 +1,53 @@
11
#import <string.h>
22
#import "NSSlowTaggedLocalizedString.h"
33
#import <dlfcn.h>
4+
#import <objc/runtime.h>
5+
6+
//If and when CF starts linking Swift we may need to rethink this
7+
#import <CoreFoundation/CoreFoundation.h>
48

59
@implementation NSSlowTaggedLocalizedString
610

7-
uintptr_t *obfuscator;
8-
void (*_objc_registerTaggedPointerClass)(uint16_t tag, Class cls);
11+
typedef struct _NSRange {
12+
uint64_t location;
13+
uint64_t length;
14+
} NSRange;
915

1016
+ (instancetype) createTestString {
1117
#if __LP64__
12-
if (obfuscator == NULL) {
13-
obfuscator = dlsym(RTLD_DEFAULT, "objc_debug_taggedpointer_obfuscator");
14-
*obfuscator = 0;
15-
_objc_registerTaggedPointerClass = dlsym(RTLD_DEFAULT, "_objc_registerTaggedPointerClass");
16-
(*_objc_registerTaggedPointerClass)(0, self); //0 would be unsafe if we loaded Foundation, but we aren't doing that
17-
}
18-
#if __x86_64__
19-
return (id)(void *)(uintptr_t)1; //x86_64 uses the LSB as the tag bit, and we want tag 0
20-
#else
21-
return (id)(void *)(uintptr_t)(1llu << 63); //MSB everywhere else
22-
#endif
18+
static dispatch_once_t onceToken;
19+
dispatch_once(&onceToken, ^{
20+
Class tagClass = objc_lookUpClass("NSTaggedPointerString");
21+
Class ourClass = [NSSlowTaggedLocalizedString class];
22+
23+
Method fastCString = class_getInstanceMethod(ourClass, @selector(_fastCStringContents:));
24+
class_replaceMethod(tagClass, @selector(_fastCStringContents:), method_getImplementation(fastCString), method_getTypeEncoding(fastCString));
25+
26+
Method length = class_getInstanceMethod(ourClass, @selector(length));
27+
class_replaceMethod(tagClass, @selector(length), method_getImplementation(length), method_getTypeEncoding(length));
28+
29+
Method charIndex = class_getInstanceMethod(ourClass, @selector(characterAtIndex:));
30+
class_replaceMethod(tagClass, @selector(characterAtIndex:), method_getImplementation(charIndex), method_getTypeEncoding(charIndex));
31+
32+
Method fastChars = class_getInstanceMethod(ourClass, @selector(_fastCharacterContents));
33+
class_replaceMethod(tagClass, @selector(_fastCharacterContents), method_getImplementation(fastChars), method_getTypeEncoding(fastChars));
34+
35+
Method retain = class_getInstanceMethod(ourClass, @selector(retain));
36+
class_replaceMethod(tagClass, @selector(retain), method_getImplementation(retain), method_getTypeEncoding(retain));
37+
38+
Method release = class_getInstanceMethod(ourClass, @selector(release));
39+
class_replaceMethod(tagClass, @selector(release), method_getImplementation(release), method_getTypeEncoding(release));
40+
41+
Method typeID = class_getInstanceMethod(ourClass, @selector(_cfTypeID));
42+
class_replaceMethod(tagClass, @selector(_cfTypeID), method_getImplementation(typeID), method_getTypeEncoding(typeID));
43+
44+
Method description = class_getInstanceMethod(ourClass, @selector(description));
45+
class_replaceMethod(tagClass, @selector(description), method_getImplementation(description), method_getTypeEncoding(description));
46+
47+
Method getBytes = class_getInstanceMethod(ourClass, @selector(getBytes:maxLength:usedLength:encoding:options:range:remainingRange:));
48+
class_replaceMethod(tagClass, @selector(getBytes:maxLength:usedLength:encoding:options:range:remainingRange:), method_getImplementation(getBytes), method_getTypeEncoding(getBytes));
49+
});
50+
return (NSSlowTaggedLocalizedString *)(void *)CFStringCreateWithCString(NULL, "a", kCFStringEncodingASCII); //make a tagged pointer string
2351
#else
2452
return nil;
2553
#endif
@@ -29,7 +57,11 @@ + (instancetype) createTestString {
2957

3058
+ (void) setContents: (const char *)newContents {
3159
const char *oldContents = contents;
32-
contents = strdup(newContents);
60+
if (newContents) {
61+
contents = strdup(newContents);
62+
} else {
63+
contents = NULL;
64+
}
3365
free((void *)oldContents);
3466
}
3567

@@ -46,6 +78,7 @@ - (id)copyWithZone:(id)unused {
4678
}
4779

4880
- (uint16_t)characterAtIndex:(NSUInteger)index {
81+
abort();
4982
if (index >= [self length]) {
5083
//throw the appropriate exception
5184
abort();
@@ -57,4 +90,27 @@ - (void *) _fastCharacterContents {
5790
return nil;
5891
}
5992

93+
- (id) retain { return self; }
94+
- (oneway void) release {}
95+
96+
- (uint64_t)_cfTypeID {
97+
return 7; //CFString
98+
}
99+
100+
- (id) description {
101+
return self;
102+
}
103+
104+
- (BOOL)getBytes:(void *)buffer maxLength:(uint64_t)max usedLength:(uint64_t *)used encoding:(uint64_t)encoding options:(uint64_t)options range:(NSRange)range remainingRange:(NSRange *)leftover {
105+
strncpy(buffer, contents, max);
106+
if (strlen(contents) > max) {
107+
leftover->location = max;
108+
leftover->length = strlen(contents) - max;
109+
return false;
110+
}
111+
leftover->location = 0;
112+
leftover->length = 0;
113+
return true;
114+
}
115+
60116
@end

test/stdlib/NSSlowTaggedLocalizedString.swift

Lines changed: 17 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
// RUN: mkdir -p %t
2-
// RUN: %target-clang -fobjc-arc %S/Inputs/NSSlowTaggedLocalizedString/NSSlowTaggedLocalizedString.m -fno-objc-arc -c -o %t/NSSlowTaggedLocalizedString.o
3-
// RUN: %target-build-swift -Xfrontend -disable-access-control -I %S/Inputs/NSSlowTaggedLocalizedString/ %t/NSSlowTaggedLocalizedString.o %s -o %t/a.out
2+
// RUN: %target-clang %S/Inputs/NSSlowTaggedLocalizedString/NSSlowTaggedLocalizedString.m -fno-objc-arc -c -o %t/NSSlowTaggedLocalizedString.o
3+
// RUN: %target-build-swift -g -parse-stdlib -Xfrontend -disable-access-control -I %S/Inputs/NSSlowTaggedLocalizedString/ %t/NSSlowTaggedLocalizedString.o %s -o %t/a.out
44
// RUN: %target-codesign %t/a.out
55
// RUN: %target-run %t/a.out
66

@@ -13,19 +13,25 @@ import Swift
1313
import StdlibUnittest
1414

1515
let longTaggedTests = TestSuite("NonContiguousTaggedStrings")
16+
var constant = "Send Message to different Team"
1617

17-
longTaggedTests.test("EqualLongTagged") {
18-
var native = "Send Message to different Team"
19-
let longTagged = NSSlowTaggedLocalizedString.createTestString()
20-
NSSlowTaggedLocalizedString.setContents(&native)
18+
func runEqualLongTagged() {
19+
let native = constant.withUTF8 { String(decoding: $0, as: UTF8.self) }
20+
let longTagged = NSSlowTaggedLocalizedString.createTest()!
21+
constant.withCString {
22+
NSSlowTaggedLocalizedString.setContents($0)
23+
}
2124
defer {
2225
NSSlowTaggedLocalizedString.setContents(nil)
2326
}
24-
let reverseBridged = native._guts._object.objCBridgeableObject
25-
expectEqual(
26-
reverseBridged.isEqual(to: longTagged),
27-
longTagged.isEqual(to: reverseBridged)
28-
)
27+
let reverseBridged = unsafeBitCast(native._guts._object.largeAddressBits, to: AnyObject.self)
28+
let eq = reverseBridged.isEqual(to: longTagged)
29+
expectEqual(eq, 1)
30+
_fixLifetime(native)
31+
}
32+
33+
longTaggedTests.test("EqualLongTagged") {
34+
runEqualLongTagged()
2935
}
3036

3137
runAllTests()

0 commit comments

Comments
 (0)