@@ -320,34 +320,22 @@ func SecCopyErrorMessageString(status C.OSStatus) *cf.StringRef {
320320
321321func GetSecAttrApplicationLabel (v * cf.DictionaryRef ) []byte {
322322 data := C .CFDataRef (C .CFDictionaryGetValue (C .CFDictionaryRef (v .Value ), unsafe .Pointer (C .kSecAttrApplicationLabel )))
323- return C .GoBytes (
324- unsafe .Pointer (C .CFDataGetBytePtr (data )),
325- C .int (C .CFDataGetLength (data )),
326- )
323+ return goBytes (data )
327324}
328325
329326func GetSecAttrApplicationTag (v * cf.DictionaryRef ) string {
330327 data := C .CFDataRef (C .CFDictionaryGetValue (C .CFDictionaryRef (v .Value ), unsafe .Pointer (C .kSecAttrApplicationTag )))
331- return string (C .GoBytes (
332- unsafe .Pointer (C .CFDataGetBytePtr (data )),
333- C .int (C .CFDataGetLength (data )),
334- ))
328+ return string (goBytes (data ))
335329}
336330
337- func GetSecAttrLabel (v * cf.DictionaryRef ) ( label string ) {
331+ func GetSecAttrLabel (v * cf.DictionaryRef ) string {
338332 ref := C .CFStringRef (C .CFDictionaryGetValue (C .CFDictionaryRef (v .Value ), unsafe .Pointer (C .kSecAttrLabel )))
339- if cstr := C .CFStringGetCStringPtr (ref , C .kCFStringEncodingUTF8 ); cstr != nil {
340- label = C .GoString (cstr )
341- }
342- return label
333+ return goString (ref )
343334}
344335
345- func GetSecAttrTokenID (v * cf.DictionaryRef ) ( tokenID string ) {
336+ func GetSecAttrTokenID (v * cf.DictionaryRef ) string {
346337 ref := C .CFStringRef (C .CFDictionaryGetValue (C .CFDictionaryRef (v .Value ), unsafe .Pointer (C .kSecAttrTokenID )))
347- if cstr := C .CFStringGetCStringPtr (ref , C .kCFStringEncodingUTF8 ); cstr != nil {
348- tokenID = C .GoString (cstr )
349- }
350- return tokenID
338+ return goString (ref )
351339}
352340
353341func GetSecAttrAccessControl (v * cf.DictionaryRef ) * SecAccessControlRef {
@@ -376,10 +364,7 @@ func GetSecAttrAccessControl(v *cf.DictionaryRef) *SecAccessControlRef {
376364
377365func GetSecValueData (v * cf.DictionaryRef ) []byte {
378366 data := C .CFDataRef (C .CFDictionaryGetValue (C .CFDictionaryRef (v .Value ), unsafe .Pointer (C .kSecValueData )))
379- return C .GoBytes (
380- unsafe .Pointer (C .CFDataGetBytePtr (data )),
381- C .int (C .CFDataGetLength (data )),
382- )
367+ return goBytes (data )
383368}
384369
385370type osStatusError struct {
@@ -406,9 +391,7 @@ func goOSStatus(status C.OSStatus) error {
406391
407392 var message string
408393 if ref := SecCopyErrorMessageString (status ); ref .Value != 0 {
409- if cstr := C .CFStringGetCStringPtr (C .CFStringRef (ref .Value ), C .kCFStringEncodingUTF8 ); cstr != nil {
410- message = C .GoString (cstr )
411- }
394+ message = goString (C .CFStringRef (ref .Value ))
412395 defer ref .Release ()
413396 }
414397 return osStatusError {
@@ -417,6 +400,41 @@ func goOSStatus(status C.OSStatus) error {
417400 }
418401}
419402
403+ func goBytes (data C.CFDataRef ) []byte {
404+ if data == 0 {
405+ return nil
406+ }
407+ return C .GoBytes (
408+ unsafe .Pointer (C .CFDataGetBytePtr (data )),
409+ C .int (C .CFDataGetLength (data )),
410+ )
411+ }
412+
413+ func goString (ref C.CFStringRef ) string {
414+ if ref == 0 {
415+ return ""
416+ }
417+
418+ // CFStringGetCStringPtr either returns the requested pointer immediately,
419+ // with no memory allocations and no copying, in constant time, or returns
420+ // NULL.
421+ if cstr := C .CFStringGetCStringPtr (ref , C .kCFStringEncodingUTF8 ); cstr != nil {
422+ return C .GoString (cstr )
423+ }
424+
425+ // The documentation recommends using CFStringGetCString if the previous one
426+ // fails.
427+ length := C .CFStringGetLength (ref )
428+ buf := (* C .char )(C .malloc (C .size_t (length ) + 1 ))
429+ defer C .free (unsafe .Pointer (buf ))
430+
431+ if C .CFStringGetCString (ref , buf , length + 1 , C .kCFStringEncodingUTF8 ) == 0 {
432+ return ""
433+ }
434+
435+ return C .GoString (buf )
436+ }
437+
420438type cfError struct {
421439 code int
422440 message string
0 commit comments