progrium/darwinkit

NSArray_withObjects() causing segmentation violation

Closed this issue · 4 comments

I was doing a test of NSArray. Using this program below causes a segmentation violation at the NSArray_WithObjects() function:

package main

import "github.com/progrium/macdriver/core"
import "fmt"

func main() {
	oneString := core.NSString_FromString("One")
	myArray := core.NSArray_WithObjects(oneString, nil)
	fmt.Println("array:", myArray)
}

I made a very similar program in objective-c and it worked correctly. This is it:

#import <Foundation/Foundation.h>

void main()
{
    NSString *oneString = @"One";
    NSArray *myArray = [NSArray arrayWithObjects: oneString, nil];
    NSLog(@"array: %@", myArray);
}

I am using Mac OS 12.3.1 on an M1 chip.

Here is the error:

fatal error: unexpected signal during runtime execution
[signal SIGSEGV: segmentation violation code=0x2 addr=0x20 pc=0x183d004b0]

runtime stack:
runtime.throw({0x102be9fe1?, 0x16d2c7390?})
/usr/local/go/src/runtime/panic.go:1047 +0x40 fp=0x16d2c7350 sp=0x16d2c7320 pc=0x102b6bac0
runtime.sigpanic()
/usr/local/go/src/runtime/signal_unix.go:821 +0x240 fp=0x16d2c7390 sp=0x16d2c7350 pc=0x102b80550

goroutine 1 [syscall]:
runtime.cgocall(0x102be2920, 0x14000115c18)
/usr/local/go/src/runtime/cgocall.go:157 +0x50 fp=0x14000115be0 sp=0x14000115ba0 pc=0x102b3e040
github.com/progrium/macdriver/misc/variadic._Cfunc_VariadicCall(0x1400010e750)
_cgo_gotypes.go:105 +0x34 fp=0x14000115c10 sp=0x14000115be0 pc=0x102bd0664
github.com/progrium/macdriver/misc/variadic.(*FunctionCall).Call.func1(0x14000115c68?)
/Users/user/go/pkg/mod/github.com/progrium/macdriver@v0.3.0/misc/variadic/variadic_arm64.go:77 +0x40 fp=0x14000115c50 sp=0x14000115c10 pc=0x102bd0810
github.com/progrium/macdriver/misc/variadic.(*FunctionCall).Call(0x1400010e750)
/Users/user/go/pkg/mod/github.com/progrium/macdriver@v0.3.0/misc/variadic/variadic_arm64.go:77 +0x20 fp=0x14000115c70 sp=0x14000115c50 pc=0x102bd07a0
github.com/progrium/macdriver/objc.sendMsg({0x102c2a160, 0x1400001c0d0}, 0x0, {0x102be4f82, 0x11}, {0x1400006c020, 0x2, 0x102c2a2e0?})
/Users/user/go/pkg/mod/github.com/progrium/macdriver@v0.3.0/objc/msg_arm64.go:202 +0x13a4 fp=0x14000115e10 sp=0x14000115c70 pc=0x102bd5604
github.com/progrium/macdriver/objc.object.Send(...)
/Users/user/go/pkg/mod/github.com/progrium/macdriver@v0.3.0/objc/msg_arm64.go:206
github.com/progrium/macdriver/objc.(*object).Send(0x102be355d?, {0x102be4f82?, 0x11?}, {0x1400006c020?, 0x2?, 0x2?})
:1 +0x78 fp=0x14000115e70 sp=0x14000115e10 pc=0x102bd6d48
github.com/progrium/macdriver/core.NSArray_WithObjects({0x14000115f28, 0x2, 0x14000115f28?})
/Users/user/go/pkg/mod/github.com/progrium/macdriver@v0.3.0/core/NSArray.go:22 +0xd4 fp=0x14000115ed0 sp=0x14000115e70 pc=0x102bd72f4
main.main()
/Users/user/desktop/my go app/main.go:8 +0x70 fp=0x14000115f70 sp=0x14000115ed0 pc=0x102bd98a0
runtime.main()
/usr/local/go/src/runtime/proc.go:250 +0x200 fp=0x14000115fd0 sp=0x14000115f70 pc=0x102b6e080
runtime.goexit()
/usr/local/go/src/runtime/asm_arm64.s:1172 +0x4 fp=0x14000115fd0 sp=0x14000115fd0 pc=0x102b98834

Good find, it looks like nil breaks it if you want to confirm (trying without nil). Do you know if NSNull is an equivalent for this? It could be we just can't use nil for the obj-c equivalent, but I haven't looked into it. Unfortunately there are like 4 variants of nil in Objective-C and I don't know how interchangeable they are, but I'm hoping we can do something similar to what we do for core.True and core.False

I removed the nil so the call looks like this: myArray := core.NSArray_WithObjects(oneString).
The program still segment faulted.

NSNull did not work in the objective-c file, so I don't think it will work with MacDriver.

Please let me know if you need anything else.

This should work now with the same caveat as with the similar Dictionary method. There is now a test case in foundation for arrays also showing the custom helpers:

func TestFoundationArray(t *testing.T) {
	s := String_StringWithString("one")
	a1 := Array_ArrayWithObjects(s, "two", "three", nil)
	s1 := ArrayToSlice[string](a1)
	a2 := ArrayOf(s1)
	s2 := ArrayToSlice[string](a2)
	if !reflect.DeepEqual(s2, []string{
		"one",
		"two",
		"three",
	}) {
		t.Fatal("unexpected final slice from array")
	}
}

Closing since there are tests passing that satisfy the original issue. Please open another issue or discussion if there is still a problem or question.