Mac OS X 10.10.0: Unexpected new exception thrown by NSString method

Originator:google
Number:rdar://18814753 Date Originated:29-Oct-2014 08:47 PM
Status:Open Resolved:
Product:OS X Product Version:Mac OS X 10.10.0 (14A389)
Classification:Crash/Hang/Data Loss Reproducible:Always
 
Summary:
The NSString method “-dataUsingEncoding:allowLossyConversion:” throws and exception on 10.10.0 when called on a valid string.

Steps to Reproduce:
1. Create a new “Command Line Tool”
2. Replace the code with the attached main.m file
3. Build & Run

Expected Results:
The test code should run without any output.

Actual Results:
The test code runs with output like this (always the same):
Exception for character: ‘°’…

Regression:
Works without exceptions on Mac OS X 10.9.5 (13F34).

Notes:
Both NSString and NSMutableString are affected.
It works fine, when the method is called on codePointString (see test code).
So there needs to be a prefix to trigger this.

Comments

test code

#import <Foundation/Foundation.h>

static CFStringRef jx_CFStringCreateWithCodePoint(UTF32Char codePoint) {
    UniChar surrogates[2];
    Boolean isSurrogatePair = CFStringGetSurrogatePairForLongCharacter(codePoint, (UniChar *)&surrogates);
    const CFIndex validSurrogatesSize = (isSurrogatePair) ? sizeof(surrogates) : sizeof(UniChar);

    CFStringRef string = CFStringCreateWithBytes(kCFAllocatorDefault,
                                                 (const UInt8 *)&surrogates,
                                                 validSurrogatesSize,
                                                 kCFStringEncodingUTF16,
                                                 false);

    return string;
}

int main(int argc, const char * argv[]) {

    BOOL simpleTest = NO;
    BOOL exhaustiveTest = YES;

    @autoreleasepool {

        if (simpleTest) {
            NSString *testString = @"Test °";

            // This will cause an exception to be thrown when run on 10.10.0.
            NSData *asciiData = [testString dataUsingEncoding:NSASCIIStringEncoding
                                         allowLossyConversion:YES];

            //NSLog(@"%@", asciiData);

            NSString *asciiString = [[NSString alloc] initWithData:asciiData
                                                          encoding:NSASCIIStringEncoding];
            NSLog(@"%@", asciiString);
        }

        if (exhaustiveTest) {
            // We are checking all possible Unicode code points.
            UTF32Char firstCodePoint = 0x000000;
            UTF32Char lastCodePoint = 0x10FFFF;

            for (UTF32Char codePoint = firstCodePoint; codePoint <= lastCodePoint; codePoint++) {
                @autoreleasepool {
                    CFStringRef codePointStringCF = jx_CFStringCreateWithCodePoint(codePoint);
                    if (codePointStringCF == NULL) {
                        // Skip over invalid code points.
                        continue;
                    }

                    NSString *codePointString = CFBridgingRelease(codePointStringCF);
                    NSMutableString *testString = [@"Test " mutableCopy];
                    [testString appendString:codePointString];

                    @try {
                        // This will cause an exception to be thrown when run on 10.10.0.
                        // Both NSString and NSMutableString are affected.
                        // It works fine, when the method is called on codePointString.
                        // So there needs to be a prefix to trigger this.
                        NSData *asciiData = [testString dataUsingEncoding:NSASCIIStringEncoding
                                                     allowLossyConversion:YES];

                        NSString *asciiString = nil;
                        asciiString = [[NSString alloc] initWithData:asciiData
                                                            encoding:NSASCIIStringEncoding];
                    }
                    @catch (NSException *exception) {
                        NSLog(@"Exception for character: ‘%@’ (0x%06X)",
                              codePointString,
                              codePoint);
                        //NSLog(@"%@", exception);
                    }
                }
            }
        }

    }

    return EXIT_SUCCESS;
}

Please note: Reports posted here will not necessarily be seen by Apple. All problems should be submitted at bugreport.apple.com before they are posted here. Please only post information for Radars that you have filed yourself, and please do not include Apple confidential information in your posts. Thank you!