Fix crash when using Pathspec in StatusOptions

Using `StatusOptions.Pathspec` results in a fatal error panic with
the message 'unexpected signal during runtime execution'.

This is because the `&cpathspec` C.git_strarray gets freed in
`*StatusOptions.toC()` before being passed to
`C.git_status_init_options()` in `*Repository.StatusList()`
(see b3e7705c48/status.go (L138))

The relevant panic trace is:

```
fatal error: unexpected signal during runtime execution
[signal 0xb code=0x1 addr=0xb01dfacedebac1e pc=0x4062609]

runtime stack:
runtime.throw(0x469a080, 0x2a)
    /usr/local/Cellar/go/1.5.1/libexec/src/runtime/panic.go:527 +0x90
runtime.sigpanic()
    /usr/local/Cellar/go/1.5.1/libexec/src/runtime/sigpanic_unix.go:12
+0x5a

goroutine 71 [syscall, locked to thread]:
runtime.cgocall(0x400a720, 0xc8204e9998, 0x0)
    /usr/local/Cellar/go/1.5.1/libexec/src/runtime/cgocall.go:120 +0x11b
fp=0xc8204e9968 sp=0xc8204e9938
github.com/libgit2/git2go._Cfunc_git_status_list_new(0xc8204c39c8,
0x5e17780, 0xc820478c40, 0xc800000000)
    ??:0 +0x39 fp=0xc8204e9998 sp=0xc8204e9968
github.com/libgit2/git2go.(*Repository).StatusList(0xc820013290,
0xc8204e9b58, 0x0, 0x0, 0x0)
    /Users/calin/go/src/github.com/libgit2/git2go/status.go:168 +0x11d
fp=0xc8204e99e8 sp=0xc8204e9998
```
This commit is contained in:
Calin Seciu 2015-09-17 17:07:34 +03:00 committed by Carlos Martín Nieto
parent 6d3a3499f1
commit 34fb7e03ec
1 changed files with 13 additions and 23 deletions

View File

@ -126,34 +126,24 @@ type StatusOptions struct {
Pathspec []string
}
func (opts *StatusOptions) toC() *C.git_status_options {
if opts == nil {
return nil
}
cpathspec := C.git_strarray{}
if opts.Pathspec != nil {
cpathspec.count = C.size_t(len(opts.Pathspec))
cpathspec.strings = makeCStringsFromStrings(opts.Pathspec)
defer freeStrarray(&cpathspec)
}
copts := &C.git_status_options{
version: C.GIT_STATUS_OPTIONS_VERSION,
show: C.git_status_show_t(opts.Show),
flags: C.uint(opts.Flags),
pathspec: cpathspec,
}
return copts
}
func (v *Repository) StatusList(opts *StatusOptions) (*StatusList, error) {
var ptr *C.git_status_list
var copts *C.git_status_options
if opts != nil {
copts = opts.toC()
cpathspec := C.git_strarray{}
if opts.Pathspec != nil {
cpathspec.count = C.size_t(len(opts.Pathspec))
cpathspec.strings = makeCStringsFromStrings(opts.Pathspec)
defer freeStrarray(&cpathspec)
}
copts = &C.git_status_options{
version: C.GIT_STATUS_OPTIONS_VERSION,
show: C.git_status_show_t(opts.Show),
flags: C.uint(opts.Flags),
pathspec: cpathspec,
}
} else {
copts = &C.git_status_options{}
ret := C.git_status_init_options(copts, C.GIT_STATUS_OPTIONS_VERSION)