From bbd64de0e8c528097aef0768c038ebeee81974f5 Mon Sep 17 00:00:00 2001 From: blacktop Date: Tue, 23 Apr 2024 13:29:04 -0600 Subject: [PATCH] fix: swift protocol typeref ptr == 0 bind parsing --- swift.go | 94 +++++++++++++++++++++++++++++++++++++++----------------- 1 file changed, 66 insertions(+), 28 deletions(-) diff --git a/swift.go b/swift.go index 2d8f4dc..79475a7 100644 --- a/swift.go +++ b/swift.go @@ -1112,17 +1112,27 @@ func (f *File) parseProtocol(r io.ReadSeeker, typ *swift.Type) (prot *swift.Prot if err != nil { return nil, fmt.Errorf("failed to read signature requirement protocol pointer: %v", err) } - prot.SignatureRequirements[idx].Kind, err = f.GetBindName(ptr) - if err != nil { - f.cr.SeekToAddr(ptr) - pc, err := f.getContextDesc(ptr) - if err != nil { - return nil, fmt.Errorf("failed to read signature requirement protocol: %v", err) + if ptr == 0 { + ptr = req.TypeOrProtocolOrConformanceOrLayoutOff.GetRelPtrAddress() + if (ptr & 1) == 1 { + ptr = ptr &^ 1 } - if pc.Parent != "" { - prot.SignatureRequirements[idx].Kind = fmt.Sprintf("%s.%s", pc.Parent, pc.Name) - } else { - prot.SignatureRequirements[idx].Kind = pc.Name + if bind, err := f.GetBindName(ptr); err == nil { + prot.SignatureRequirements[idx].Kind = bind + } + } else { + prot.SignatureRequirements[idx].Kind, err = f.GetBindName(ptr) + if err != nil { + f.cr.SeekToAddr(ptr) + pc, err := f.getContextDesc(ptr) + if err != nil { + return nil, fmt.Errorf("failed to read signature requirement protocol: %v", err) + } + if pc.Parent != "" { + prot.SignatureRequirements[idx].Kind = fmt.Sprintf("%s.%s", pc.Parent, pc.Name) + } else { + prot.SignatureRequirements[idx].Kind = pc.Name + } } } } @@ -1262,25 +1272,37 @@ func (f *File) readProtocolConformance(r io.ReadSeeker, addr uint64) (pcd *swift return nil, fmt.Errorf("failed to get indirect type descriptor pointer: %v", err) } ptr = f.vma.Convert(ptr) - if bind, err := f.GetBindName(ptr); err == nil { - pcd.TypeRef = &swift.Type{ - Address: ptr, - Name: bind, - } - } else { - f.cr.SeekToAddr(ptr) - ctx, err := f.getContextDesc(ptr) - if err != nil { - return nil, fmt.Errorf("failed to get parent: %v", err) + if ptr == 0 { + if (addr & 1) == 1 { + addr = addr &^ 1 } - pcd.TypeRef = &swift.Type{ - Address: ptr, - Name: ctx.Name, - Parent: &swift.Type{ - Name: ctx.Parent, - }, + if bind, err := f.GetBindName(addr); err == nil { + pcd.TypeRef = &swift.Type{ + Address: addr, + Name: bind, + } } + } else { + if bind, err := f.GetBindName(ptr); err == nil { + pcd.TypeRef = &swift.Type{ + Address: ptr, + Name: bind, + } + } else { + f.cr.SeekToAddr(ptr) + ctx, err := f.getContextDesc(ptr) + if err != nil { + return nil, fmt.Errorf("failed to get parent: %v", err) + } + pcd.TypeRef = &swift.Type{ + Address: ptr, + Name: ctx.Name, + Parent: &swift.Type{ + Name: ctx.Parent, + }, + } + } } case swift.DirectObjCClassName: name, err := f.GetCString(pcd.TypeRefOffsest.GetRelPtrAddress()) @@ -1345,7 +1367,15 @@ func (f *File) readProtocolConformance(r io.ReadSeeker, addr uint64) (pcd *swift return nil, fmt.Errorf("failed to read conditional requirement protocol pointer: %v", err) } ptr = f.vma.Convert(ptr) - if bind, err := f.GetBindName(ptr); err == nil { + if ptr == 0 { + ptr = req.TypeOrProtocolOrConformanceOrLayoutOff.GetRelPtrAddress() + if (ptr & 1) == 1 { + ptr = ptr &^ 1 + } + if bind, err := f.GetBindName(ptr); err == nil { + pcd.ConditionalRequirements[idx].Kind = bind + } + } else if bind, err := f.GetBindName(ptr); err == nil { pcd.ConditionalRequirements[idx].Kind = bind } else { f.cr.SeekToAddr(ptr) @@ -2220,7 +2250,15 @@ func (f *File) parseGenericContext(ctx *swift.TypeGenericContext) (err error) { return fmt.Errorf("failed to read generic requirement param protocol pointer: %v", err) } ptr = f.vma.Convert(ptr) - if bind, err := f.GetBindName(ptr); err == nil { + if ptr == 0 { + ptr = req.TypeOrProtocolOrConformanceOrLayoutOff.GetRelPtrAddress() + if (ptr & 1) == 1 { + ptr = ptr &^ 1 + } + if bind, err := f.GetBindName(ptr); err == nil { + ctx.Requirements[idx].Kind = bind + } + } else if bind, err := f.GetBindName(ptr); err == nil { ctx.Requirements[idx].Kind = bind } else { f.cr.SeekToAddr(ptr)