From b5c7468f3a6603ee2f707417181c60a4fbd00995 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pedro=20T=C3=B4rres?= Date: Sat, 1 Jun 2024 20:20:15 -0700 Subject: [PATCH] fix: decoding struct and union fields with ambiguous types (#59) --- types/objc/type_encoding.go | 9 +++++++++ types/objc/type_encoding_test.go | 14 ++++++++++++++ 2 files changed, 23 insertions(+) diff --git a/types/objc/type_encoding.go b/types/objc/type_encoding.go index 3e64c5c..1384c11 100644 --- a/types/objc/type_encoding.go +++ b/types/objc/type_encoding.go @@ -446,6 +446,15 @@ func decodeStructOrUnion(typ, kind string) string { field, rest, ok := CutType(rest) for ok { + // Although technically possible, binaries produced by clang never have a + // mix of named and unnamed fields in the same struct. This assumption is + // necessary to disambiguate {"x0"@"x1"c}. + if fieldName != "" && rest != "" && strings.HasSuffix(field, `"`) && !strings.HasPrefix(rest, `"`) { + penultQuoteIdx := strings.LastIndex(strings.TrimRight(field, `"`), `"`) + rest = field[penultQuoteIdx:] + rest + field = field[:penultQuoteIdx] + } + if fieldName == "" { fieldName = fmt.Sprintf("x%d", idx) } diff --git a/types/objc/type_encoding_test.go b/types/objc/type_encoding_test.go index 01b94be..6c4f6fd 100644 --- a/types/objc/type_encoding_test.go +++ b/types/objc/type_encoding_test.go @@ -74,6 +74,13 @@ func Test_decodeType(t *testing.T) { }, want: "struct __CFRuntimeBase { unsigned long long x0; _Atomic unsigned long long x1; }", }, + { + name: "Test struct 4", + args: args{ + encType: "{__cfobservers_t=\"slot\"@\"next\"^{__cfobservers_t}}", + }, + want: "struct __cfobservers_t { id slot; struct __cfobservers_t *next; }", + }, { name: "Test union 0", args: args{ @@ -95,6 +102,13 @@ func Test_decodeType(t *testing.T) { }, want: "void * /* union */", }, + { + name: "Test union 3", + args: args{ + encType: "(?=\"xpc\"@\"NSObject\"\"remote\"@\"OS_xpc_remote_connection\")", + }, + want: "union { NSObject *xpc; OS_xpc_remote_connection *remote; }", + }, { name: "Test block", args: args{