unix: avoid index out of range in *setxattr on BSD

Passing an empty data []byte to Fsetxattr/Setxattr/Lsetxattr leads
to an index out of range panic. Fix this by passing an nil
unsafe.Pointer to the underlying syscall in this case.

Change-Id: I5ef3983c6304c5317ed5b49afc4ed19791864dbb
Reviewed-on: https://go-review.googlesource.com/c/146198
Run-TryBot: Tobias Klauser <tobias.klauser@gmail.com>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Ian Lance Taylor <iant@golang.org>
diff --git a/unix/xattr_bsd.go b/unix/xattr_bsd.go
index 9304993..30c1d71 100644
--- a/unix/xattr_bsd.go
+++ b/unix/xattr_bsd.go
@@ -81,7 +81,10 @@
 // flags are unused on FreeBSD
 
 func Fsetxattr(fd int, attr string, data []byte, flags int) (err error) {
-	d := unsafe.Pointer(&data[0])
+	var d unsafe.Pointer
+	if len(data) > 0 {
+		d = unsafe.Pointer(&data[0])
+	}
 	datasiz := len(data)
 
 	nsid, a, err := xattrnamespace(attr)
@@ -94,7 +97,10 @@
 }
 
 func Setxattr(file string, attr string, data []byte, flags int) (err error) {
-	d := unsafe.Pointer(&data[0])
+	var d unsafe.Pointer
+	if len(data) > 0 {
+		d = unsafe.Pointer(&data[0])
+	}
 	datasiz := len(data)
 
 	nsid, a, err := xattrnamespace(attr)
@@ -107,7 +113,10 @@
 }
 
 func Lsetxattr(link string, attr string, data []byte, flags int) (err error) {
-	d := unsafe.Pointer(&data[0])
+	var d unsafe.Pointer
+	if len(data) > 0 {
+		d = unsafe.Pointer(&data[0])
+	}
 	datasiz := len(data)
 
 	nsid, a, err := xattrnamespace(attr)
diff --git a/unix/xattr_test.go b/unix/xattr_test.go
index 11a76ce..57fc84f 100644
--- a/unix/xattr_test.go
+++ b/unix/xattr_test.go
@@ -24,13 +24,19 @@
 
 	xattrName := "user.test"
 	xattrDataSet := "gopher"
-	err := unix.Setxattr(f, xattrName, []byte(xattrDataSet), 0)
+
+	err := unix.Setxattr(f, xattrName, []byte{}, 0)
 	if err == unix.ENOTSUP || err == unix.EOPNOTSUPP {
 		t.Skip("filesystem does not support extended attributes, skipping test")
 	} else if err != nil {
 		t.Fatalf("Setxattr: %v", err)
 	}
 
+	err = unix.Setxattr(f, xattrName, []byte(xattrDataSet), 0)
+	if err != nil {
+		t.Fatalf("Setxattr: %v", err)
+	}
+
 	// find size
 	size, err := unix.Listxattr(f, nil)
 	if err != nil {