Runtime crash caused by (NS)CharacterSet.hasMember?


(Jens Persson) #1

The below program demonstrates a possible bug that I encountered.
Can anyone else reproduce my results (as explained in the comments)?
If so, is it a Swift or Cocoa bug (I haven't tried it in Objective C)?

import AppKit

extension NSFont {
    var planesWithMembers: [UInt8] {
        return (UInt8(0) ... UInt8(255)).filter {
            // The follwing line will crash (EXC_BAD_ACCESS) for some fonts:
            coveredCharacterSet.hasMember(inPlane: $0)
            // I have tested it with Xcode 8.3.3 and Xcode 9 beta 1, both
            // Swift 3 and 4, and they all reproduce the crash.
            // macOS 10.12.5
        }
    }
}

// Examples that will not cause the crash:
// let fontName = "AlBayan"
// let fontName = "AppleBraille"
// let fontName = "Chalkboard"
// let fontName = "Helvetica"
// let fontName = "Zapfino"

// Examples that will cause the crash:
// let fontName = "AppleColorEmoji"
// let fontName = "AppleSymbols"
let fontName = "Baskerville"
// let fontName = "Geneva"
// let fontName = "SnellRoundhand"

let font = NSFont(name: fontName, size: 12)!
let result = font.planesWithMembers
print("Planes that contains members:", result)


(Jens Persson) #2

PS
There are only 17 planes in the (current?) Unicode standard, but I'm
assuming that the CharacterSet.hasMember(inPlane:) shouldn't (randomly?)
crash for UInt8 values other than 0 ... 16?
It also seems strange that it reproducibly crashes or not depending on
which specific font I use.

···

On Tue, Jun 13, 2017 at 4:00 PM, Jens Persson <jens@bitcycle.com> wrote:

The below program demonstrates a possible bug that I encountered.
Can anyone else reproduce my results (as explained in the comments)?
If so, is it a Swift or Cocoa bug (I haven't tried it in Objective C)?

import AppKit

extension NSFont {
    var planesWithMembers: [UInt8] {
        return (UInt8(0) ... UInt8(255)).filter {
            // The follwing line will crash (EXC_BAD_ACCESS) for some
fonts:
            coveredCharacterSet.hasMember(inPlane: $0)
            // I have tested it with Xcode 8.3.3 and Xcode 9 beta 1, both
            // Swift 3 and 4, and they all reproduce the crash.
            // macOS 10.12.5
        }
    }
}

// Examples that will not cause the crash:
// let fontName = "AlBayan"
// let fontName = "AppleBraille"
// let fontName = "Chalkboard"
// let fontName = "Helvetica"
// let fontName = "Zapfino"

// Examples that will cause the crash:
// let fontName = "AppleColorEmoji"
// let fontName = "AppleSymbols"
let fontName = "Baskerville"
// let fontName = "Geneva"
// let fontName = "SnellRoundhand"

let font = NSFont(name: fontName, size: 12)!
let result = font.planesWithMembers
print("Planes that contains members:", result)


(Doug Hill) #3

I tried your calls to NSFont in Objective-C, and it also crashes. Looking at the stack trace, I see that it crashes in CFCharacterSetHasMemberInPlane. I see documentation for thePlane parameter of this function says:

The valid value range is from 0 to 16. If the value is outside of the valid plane number range, the behavior is undefined.

I guess randomly crashing counts as undefined behavior.
While it would be great if this function was more robust, Apple is definitely saying Don’t Do That.

Doug Hill
https://github.com/djfitz/SFFontFeatures

···

On Jun 13, 2017, at 9:42 AM, Jens Persson via swift-users <swift-users@swift.org> wrote:

PS
There are only 17 planes in the (current?) Unicode standard, but I'm assuming that the CharacterSet.hasMember(inPlane:) shouldn't (randomly?) crash for UInt8 values other than 0 ... 16?
It also seems strange that it reproducibly crashes or not depending on which specific font I use.

On Tue, Jun 13, 2017 at 4:00 PM, Jens Persson <jens@bitcycle.com <mailto:jens@bitcycle.com>> wrote:
The below program demonstrates a possible bug that I encountered.
Can anyone else reproduce my results (as explained in the comments)?
If so, is it a Swift or Cocoa bug (I haven't tried it in Objective C)?

import AppKit

extension NSFont {
    var planesWithMembers: [UInt8] {
        return (UInt8(0) ... UInt8(255)).filter {
            // The follwing line will crash (EXC_BAD_ACCESS) for some fonts:
            coveredCharacterSet.hasMember(inPlane: $0)
            // I have tested it with Xcode 8.3.3 and Xcode 9 beta 1, both
            // Swift 3 and 4, and they all reproduce the crash.
            // macOS 10.12.5
        }
    }
}

// Examples that will not cause the crash:
// let fontName = "AlBayan"
// let fontName = "AppleBraille"
// let fontName = "Chalkboard"
// let fontName = "Helvetica"
// let fontName = "Zapfino"

// Examples that will cause the crash:
// let fontName = "AppleColorEmoji"
// let fontName = "AppleSymbols"
let fontName = "Baskerville"
// let fontName = "Geneva"
// let fontName = "SnellRoundhand"

let font = NSFont(name: fontName, size: 12)!
let result = font.planesWithMembers
print("Planes that contains members:", result)

_______________________________________________
swift-users mailing list
swift-users@swift.org
https://lists.swift.org/mailman/listinfo/swift-users


(Jens Persson) #4

Thanks!

The documentation that Xcode displays (for CharacterSet's hasMember(inPlane
plane:)) is as follows:

Declaration:
func hasMember(inPlane plane: UInt8) -> Bool

Description:
Returns true if the `CharacterSet` has a member in the specified plane.
This method makes it easier to find the plane containing the members of the
current character set.
The Basic Multilingual Plane (BMP) is plane 0.

Parameters:
plane - No description

Which is about the same as here:
https://developer.apple.com/documentation/foundation/characterset/1779728-hasmember
and here:
https://developer.apple.com/documentation/foundation/nscharacterset/1412406-hasmemberinplane

No where does it mention anything about undefined behavior for some values
of plane.

In order to find that crucial info, I'd have to do what you did, write it
in Objective C and dig through the stack trace, or just guess that it
calls CFCharacterSetHasMemberInPlane
and that its documentation contains very valuable pieces of information
that for some reason got lost on the way to NSCharacterSet's method
hasMemberInPlane ...

Kind of makes one wonder what other undocumented undefined behavior might
hide in Foundation and other places.

/Jens

···

On Tue, Jun 13, 2017 at 7:14 PM, Doug Hill via swift-users < swift-users@swift.org> wrote:

I tried your calls to NSFont in Objective-C, and it also crashes. Looking
at the stack trace, I see that it crashes in CFCharacterSetHasMemberInPlane. > I see documentation for thePlane parameter of this function says:

The valid value range is from 0 to 16. If the value is outside of the
valid plane number range, the behavior is undefined.

I guess randomly crashing counts as undefined behavior.
While it would be great if this function was more robust, Apple is
definitely saying Don’t Do That.

Doug Hill
https://github.com/djfitz/SFFontFeatures

On Jun 13, 2017, at 9:42 AM, Jens Persson via swift-users < > swift-users@swift.org> wrote:

PS
There are only 17 planes in the (current?) Unicode standard, but I'm
assuming that the CharacterSet.hasMember(inPlane:) shouldn't (randomly?)
crash for UInt8 values other than 0 ... 16?
It also seems strange that it reproducibly crashes or not depending on
which specific font I use.

On Tue, Jun 13, 2017 at 4:00 PM, Jens Persson <jens@bitcycle.com> wrote:

The below program demonstrates a possible bug that I encountered.
Can anyone else reproduce my results (as explained in the comments)?
If so, is it a Swift or Cocoa bug (I haven't tried it in Objective C)?

import AppKit

extension NSFont {
    var planesWithMembers: [UInt8] {
        return (UInt8(0) ... UInt8(255)).filter {
            // The follwing line will crash (EXC_BAD_ACCESS) for some
fonts:
            coveredCharacterSet.hasMember(inPlane: $0)
            // I have tested it with Xcode 8.3.3 and Xcode 9 beta 1, both
            // Swift 3 and 4, and they all reproduce the crash.
            // macOS 10.12.5
        }
    }
}

// Examples that will not cause the crash:
// let fontName = "AlBayan"
// let fontName = "AppleBraille"
// let fontName = "Chalkboard"
// let fontName = "Helvetica"
// let fontName = "Zapfino"

// Examples that will cause the crash:
// let fontName = "AppleColorEmoji"
// let fontName = "AppleSymbols"
let fontName = "Baskerville"
// let fontName = "Geneva"
// let fontName = "SnellRoundhand"

let font = NSFont(name: fontName, size: 12)!
let result = font.planesWithMembers
print("Planes that contains members:", result)

_______________________________________________
swift-users mailing list
swift-users@swift.org
https://lists.swift.org/mailman/listinfo/swift-users

_______________________________________________
swift-users mailing list
swift-users@swift.org
https://lists.swift.org/mailman/listinfo/swift-users


(David Hart) #5

Worth a radar to improve docs.

···

On 13 Jun 2017, at 22:12, Jens Persson via swift-users <swift-users@swift.org> wrote:

Thanks!

The documentation that Xcode displays (for CharacterSet's hasMember(inPlane plane:)) is as follows:

Declaration:
func hasMember(inPlane plane: UInt8) -> Bool

Description:
Returns true if the `CharacterSet` has a member in the specified plane.
This method makes it easier to find the plane containing the members of the current character set.
The Basic Multilingual Plane (BMP) is plane 0.

Parameters:
plane - No description

Which is about the same as here:
https://developer.apple.com/documentation/foundation/characterset/1779728-hasmember
and here:
https://developer.apple.com/documentation/foundation/nscharacterset/1412406-hasmemberinplane

No where does it mention anything about undefined behavior for some values of plane.

In order to find that crucial info, I'd have to do what you did, write it in Objective C and dig through the stack trace, or just guess that it calls CFCharacterSetHasMemberInPlane and that its documentation contains very valuable pieces of information that for some reason got lost on the way to NSCharacterSet's method hasMemberInPlane ...

Kind of makes one wonder what other undocumented undefined behavior might hide in Foundation and other places.

/Jens

On Tue, Jun 13, 2017 at 7:14 PM, Doug Hill via swift-users <swift-users@swift.org <mailto:swift-users@swift.org>> wrote:
I tried your calls to NSFont in Objective-C, and it also crashes. Looking at the stack trace, I see that it crashes in CFCharacterSetHasMemberInPlane. I see documentation for thePlane parameter of this function says:

The valid value range is from 0 to 16. If the value is outside of the valid plane number range, the behavior is undefined.

I guess randomly crashing counts as undefined behavior.
While it would be great if this function was more robust, Apple is definitely saying Don’t Do That.

Doug Hill
https://github.com/djfitz/SFFontFeatures

On Jun 13, 2017, at 9:42 AM, Jens Persson via swift-users <swift-users@swift.org <mailto:swift-users@swift.org>> wrote:

PS
There are only 17 planes in the (current?) Unicode standard, but I'm assuming that the CharacterSet.hasMember(inPlane:) shouldn't (randomly?) crash for UInt8 values other than 0 ... 16?
It also seems strange that it reproducibly crashes or not depending on which specific font I use.

On Tue, Jun 13, 2017 at 4:00 PM, Jens Persson <jens@bitcycle.com <mailto:jens@bitcycle.com>> wrote:
The below program demonstrates a possible bug that I encountered.
Can anyone else reproduce my results (as explained in the comments)?
If so, is it a Swift or Cocoa bug (I haven't tried it in Objective C)?

import AppKit

extension NSFont {
    var planesWithMembers: [UInt8] {
        return (UInt8(0) ... UInt8(255)).filter {
            // The follwing line will crash (EXC_BAD_ACCESS) for some fonts:
            coveredCharacterSet.hasMember(inPlane: $0)
            // I have tested it with Xcode 8.3.3 and Xcode 9 beta 1, both
            // Swift 3 and 4, and they all reproduce the crash.
            // macOS 10.12.5
        }
    }
}

// Examples that will not cause the crash:
// let fontName = "AlBayan"
// let fontName = "AppleBraille"
// let fontName = "Chalkboard"
// let fontName = "Helvetica"
// let fontName = "Zapfino"

// Examples that will cause the crash:
// let fontName = "AppleColorEmoji"
// let fontName = "AppleSymbols"
let fontName = "Baskerville"
// let fontName = "Geneva"
// let fontName = "SnellRoundhand"

let font = NSFont(name: fontName, size: 12)!
let result = font.planesWithMembers
print("Planes that contains members:", result)

_______________________________________________
swift-users mailing list
swift-users@swift.org <mailto:swift-users@swift.org>
https://lists.swift.org/mailman/listinfo/swift-users

_______________________________________________
swift-users mailing list
swift-users@swift.org <mailto:swift-users@swift.org>
https://lists.swift.org/mailman/listinfo/swift-users

_______________________________________________
swift-users mailing list
swift-users@swift.org
https://lists.swift.org/mailman/listinfo/swift-users


(Jens Persson) #6

Filed 32748795

···

On Tue, Jun 13, 2017 at 10:55 PM, David Hart <david@hartbit.com> wrote:

Worth a radar to improve docs.

On 13 Jun 2017, at 22:12, Jens Persson via swift-users < > swift-users@swift.org> wrote:

Thanks!

The documentation that Xcode displays (for CharacterSet's
hasMember(inPlane plane:)) is as follows:

Declaration:
func hasMember(inPlane plane: UInt8) -> Bool

Description:
Returns true if the `CharacterSet` has a member in the specified plane.
This method makes it easier to find the plane containing the members of
the current character set.
The Basic Multilingual Plane (BMP) is plane 0.

Parameters:
plane - No description

Which is about the same as here:
https://developer.apple.com/documentation/foundation/
characterset/1779728-hasmember
and here:
https://developer.apple.com/documentation/foundation/
nscharacterset/1412406-hasmemberinplane

No where does it mention anything about undefined behavior for some values
of plane.

In order to find that crucial info, I'd have to do what you did, write it
in Objective C and dig through the stack trace, or just guess that it calls
CFCharacterSetHasMemberInPlane and that its documentation contains very
valuable pieces of information that for some reason got lost on the way to
NSCharacterSet's method hasMemberInPlane ...

Kind of makes one wonder what other undocumented undefined behavior might
hide in Foundation and other places.

/Jens

On Tue, Jun 13, 2017 at 7:14 PM, Doug Hill via swift-users < > swift-users@swift.org> wrote:

I tried your calls to NSFont in Objective-C, and it also crashes. Looking
at the stack trace, I see that it crashes in CFCharacterSetHasMemberInPlane. >> I see documentation for thePlane parameter of this function says:

The valid value range is from 0 to 16. If the value is outside of the
valid plane number range, the behavior is undefined.

I guess randomly crashing counts as undefined behavior.
While it would be great if this function was more robust, Apple is
definitely saying Don’t Do That.

Doug Hill
https://github.com/djfitz/SFFontFeatures

On Jun 13, 2017, at 9:42 AM, Jens Persson via swift-users < >> swift-users@swift.org> wrote:

PS
There are only 17 planes in the (current?) Unicode standard, but I'm
assuming that the CharacterSet.hasMember(inPlane:) shouldn't (randomly?)
crash for UInt8 values other than 0 ... 16?
It also seems strange that it reproducibly crashes or not depending on
which specific font I use.

On Tue, Jun 13, 2017 at 4:00 PM, Jens Persson <jens@bitcycle.com> wrote:

The below program demonstrates a possible bug that I encountered.
Can anyone else reproduce my results (as explained in the comments)?
If so, is it a Swift or Cocoa bug (I haven't tried it in Objective C)?

import AppKit

extension NSFont {
    var planesWithMembers: [UInt8] {
        return (UInt8(0) ... UInt8(255)).filter {
            // The follwing line will crash (EXC_BAD_ACCESS) for some
fonts:
            coveredCharacterSet.hasMember(inPlane: $0)
            // I have tested it with Xcode 8.3.3 and Xcode 9 beta 1, both
            // Swift 3 and 4, and they all reproduce the crash.
            // macOS 10.12.5
        }
    }
}

// Examples that will not cause the crash:
// let fontName = "AlBayan"
// let fontName = "AppleBraille"
// let fontName = "Chalkboard"
// let fontName = "Helvetica"
// let fontName = "Zapfino"

// Examples that will cause the crash:
// let fontName = "AppleColorEmoji"
// let fontName = "AppleSymbols"
let fontName = "Baskerville"
// let fontName = "Geneva"
// let fontName = "SnellRoundhand"

let font = NSFont(name: fontName, size: 12)!
let result = font.planesWithMembers
print("Planes that contains members:", result)

_______________________________________________
swift-users mailing list
swift-users@swift.org
https://lists.swift.org/mailman/listinfo/swift-users

_______________________________________________
swift-users mailing list
swift-users@swift.org
https://lists.swift.org/mailman/listinfo/swift-users

_______________________________________________
swift-users mailing list
swift-users@swift.org
https://lists.swift.org/mailman/listinfo/swift-users