@@ -86,13 +86,10 @@ impl CFString {
8686 ///
8787 /// Warning: This is very difficult to ensure in generic contexts, e.g. it
8888 /// cannot even be used inside `Debug::fmt`, since `Formatter` uses `dyn`
89- /// internally, and can thus mutate the string inside there.
89+ /// internally, and could thus mutate the string inside there.
9090 #[ doc( alias = "CFStringGetCStringPtr" ) ]
91- // NOTE: This is NOT public, since it's completely broken for differently
92- // encoded strings, see the `as_str_broken` test below. See also:
93- // <https://github.com/swiftlang/swift-corelibs-foundation/issues/5164>.
94- #[ allow( dead_code) ]
95- unsafe fn as_str_unchecked ( & self ) -> Option < & str > {
91+ pub unsafe fn as_str_unchecked ( & self ) -> Option < & str > {
92+ // NOTE: The encoding is an 8-bit encoding.
9693 let bytes = CFStringGetCStringPtr ( self , CFStringBuiltInEncodings :: EncodingUTF8 . 0 ) ;
9794 NonNull :: new ( bytes as * mut c_char ) . map ( |bytes| {
9895 // SAFETY: The pointer is valid for as long as the CFString is not
@@ -102,8 +99,6 @@ impl CFString {
10299 // We won't accidentally truncate the string here, since
103100 // `CFStringGetCStringPtr` makes sure that there are no internal
104101 // NUL bytes in the string.
105- //
106- // TODO: Verify this claim with a test.
107102 let cstr = unsafe { CStr :: from_ptr ( bytes. as_ptr ( ) ) } ;
108103 // SAFETY: `CFStringGetCStringPtr` is (very likely) implemented
109104 // correctly, and won't return non-UTF8 strings.
@@ -255,6 +250,8 @@ mod tests {
255250 let s = CFString :: from_str ( "a\0 b\0 c\0 d" ) ;
256251 // Works with `CFStringGetBytes`.
257252 assert_eq ! ( s. to_string( ) , "a\0 b\0 c\0 d" ) ;
253+ // Expectedly does not work `CFStringGetCStringPtr`.
254+ assert_eq ! ( unsafe { s. as_str_unchecked( ) } , None ) ;
258255
259256 // Test `CFStringGetCString`.
260257 let mut buf = [ 0u8 ; 10 ] ;
@@ -287,9 +284,15 @@ mod tests {
287284 }
288285
289286 #[ test]
290- fn as_str_broken ( ) {
287+ fn create_with_cstring_broken_on_non_8_bit ( ) {
291288 // A CFString that is supposed to contain a "♥" (the UTF-8 encoding of
292289 // that is the vastly different b"\xE2\x99\xA5").
290+ //
291+ // This line is wrong, because `CFStringCreateWithCString` expects an
292+ // 8-bit encoding.
293+ //
294+ // See also:
295+ // https://github.com/swiftlang/swift-corelibs-foundation/issues/5164
293296 let s = unsafe {
294297 CFStringCreateWithCString (
295298 None ,
@@ -315,8 +318,7 @@ mod tests {
315318 let cstr = CStr :: from_bytes_until_nul ( & buf) . unwrap ( ) ;
316319 assert_eq ! ( cstr. to_bytes( ) , "♥" . as_bytes( ) ) ;
317320
318- // But `CFStringGetCStringPtr` completely ignores the UTF-8 conversion
319- // we asked it to do, i.e. a huge correctness footgun!
321+ // `CFStringGetCStringPtr` completely ignores the UTF-8 conversion.
320322 assert_eq ! ( unsafe { s. as_str_unchecked( ) } , Some ( "e&" ) ) ;
321323 }
322324
0 commit comments