Merge pull request #337 from libgit2/cmn/go16-blob-pointer

Work around the finnicky 1.6 CGo pointer checks
diff --git a/.travis.yml b/.travis.yml
index f796389..79ad168 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -10,6 +10,8 @@
   - 1.3
   - 1.4
   - 1.5
+  - 1.6
+  - 1.7
   - tip
 
 matrix:
diff --git a/blob.go b/blob.go
index 1a86e60..8b3e94f 100644
--- a/blob.go
+++ b/blob.go
@@ -37,15 +37,24 @@
 	defer runtime.UnlockOSThread()
 
 	var id C.git_oid
-	var ptr unsafe.Pointer
+	var size C.size_t
 
+	// Go 1.6 added some increased checking of passing pointer to
+	// C, but its check depends on its expectations of waht we
+	// pass to the C function, so unless we take the address of
+	// its contents at the call site itself, it can fail when
+	// 'data' is a slice of a slice.
+	//
+	// When we're given an empty slice, create a dummy one where 0
+	// isn't out of bounds.
 	if len(data) > 0 {
-		ptr = unsafe.Pointer(&data[0])
+		size = C.size_t(len(data))
 	} else {
-		ptr = unsafe.Pointer(nil)
+		data = []byte{0}
+		size = C.size_t(0)
 	}
 
-	ecode := C.git_blob_create_frombuffer(&id, repo.ptr, ptr, C.size_t(len(data)))
+	ecode := C.git_blob_create_frombuffer(&id, repo.ptr, unsafe.Pointer(&data[0]), size)
 	if ecode < 0 {
 		return nil, MakeGitError(ecode)
 	}
diff --git a/blob_test.go b/blob_test.go
index 2b5ec4f..6b7cd49 100644
--- a/blob_test.go
+++ b/blob_test.go
@@ -1,9 +1,21 @@
 package git
 
 import (
+	"bytes"
 	"testing"
 )
 
+type bufWrapper struct {
+	buf     [64]byte
+	pointer []byte
+}
+
+func doublePointerBytes() []byte {
+	o := &bufWrapper{}
+	o.pointer = o.buf[0:10]
+	return o.pointer[0:1]
+}
+
 func TestCreateBlobFromBuffer(t *testing.T) {
 	repo := createTestRepo(t)
 	defer cleanupTestRepo(t, repo)
@@ -14,4 +26,16 @@
 	if id.String() != "e69de29bb2d1d6434b8b29ae775ad8c2e48c5391" {
 		t.Fatal("Empty buffer did not deliver empty blob id")
 	}
+
+	for _, data := range []([]byte){[]byte("hello there"), doublePointerBytes()} {
+		id, err = repo.CreateBlobFromBuffer(data)
+		checkFatal(t, err)
+
+		blob, err := repo.LookupBlob(id)
+		checkFatal(t, err)
+		if !bytes.Equal(blob.Contents(), data) {
+			t.Fatal("Loaded bytes don't match original bytes:",
+				blob.Contents(), "!=", data)
+		}
+	}
 }