Repository: fxamacker/cbor (go)

Issue:
bug: encoding uninitialized cbor.(Raw)Tag returns malformed CBOR data 
### What version of fxamacker/cbor are you using?

v2.2.0

### Does this issue reproduce with the latest release?

Yes

### What OS and CPU architecture are you using (`go env`)?

<details><summary><code>go env</code> Output</summary><br><pre>
$ go env
GOARCH="amd64"
GOBIN=""
GOCACHE="/home/user/.cache/go-build"
GOEXE=""
GOFLAGS=""
GOHOSTARCH="amd64"
GOHOSTOS="linux"
GOOS="linux"
GOPATH="/home/user/go"
GOPROXY=""
GORACE=""
GOROOT="/usr/local/go"
GOTMPDIR=""
GOTOOLDIR="/usr/local/go/pkg/tool/linux_amd64"
GCCGO="gccgo"
CC="gcc"
CXX="g++"
CGO_ENABLED="1"
GOMOD=""
CGO_CFLAGS="-g -O2"
CGO_CPPFLAGS=""
CGO_CXXFLAGS="-g -O2"
CGO_FFLAGS="-g -O2"
CGO_LDFLAGS="-g -O2"
PKG_CONFIG="pkg-config"
GOGCCFLAGS="-fPIC -m64 -pthread -fmessage-length=0 -fdebug-prefix-map=/tmp/go-build778508732=/tmp/go-build -gno-record-gcc-switches"
</pre></details>

### What did you do?

Encode uninitialized cbor.(Raw)Tag.

```
var tag cbor.Tag
b, err := cbor.Marshal(tag)
fmt.Printf("Marshal(%+v) returns 0x%x, error %v\n", tag, b, err)
// Marshal({Number:0 Content:<nil>}) returns 0xc0f6, error <nil>

var rtag cbor.RawTag
b, err = cbor.Marshal(rtag)
fmt.Printf("Marshal(%+v) returns 0x%x, error %v\n", rtag, b, err)
// Marshal({Number:0 Content:[]}) returns 0xc0, error <nil>
```

### What did you expect to see?

Encoding uninitialized cbor.(Raw)Tag should return either valid CBOR data or error.  

### What did you see instead?

See comments in code snippet in previous section.


Pull request:
Encode uninitialized cbor.(Raw)Tag to CBOR null
Closes #256



Patch:
diff --git a/encode.go b/encode.go
index 0f4a9d5..95d2c23 100644
--- a/encode.go
+++ b/encode.go
@@ -1233,6 +1233,12 @@ func encodeTag(e *encoderBuffer, em *encMode, v reflect.Value) error {
 
 	t := v.Interface().(Tag)
 
+	if t.Number == 0 && t.Content == nil {
+		// Marshal uninitialized cbor.Tag
+		e.Write(cborNil)
+		return nil
+	}
+
 	// Marshal tag number
 	encodeHead(e, byte(cborTypeTag), t.Number)
 
diff --git a/tag.go b/tag.go
index 847a0ee..924f74d 100644
--- a/tag.go
+++ b/tag.go
@@ -49,7 +49,15 @@ func (t *RawTag) UnmarshalCBOR(data []byte) error {
 
 // MarshalCBOR returns CBOR encoding of t.
 func (t RawTag) MarshalCBOR() ([]byte, error) {
+	if t.Number == 0 && len(t.Content) == 0 {
+		// Marshal uninitialized cbor.RawTag
+		b := make([]byte, len(cborNil))
+		copy(b, cborNil)
+		return b, nil
+	}
+
 	e := getEncoderBuffer()
+
 	encodeHead(e, byte(cborTypeTag), t.Number)
 
 	buf := make([]byte, len(e.Bytes())+len(t.Content))


Test patch:
diff --git a/tag_test.go b/tag_test.go
index 5117f54..f8322b8 100644
--- a/tag_test.go
+++ b/tag_test.go
@@ -1193,6 +1193,28 @@ func TestTagMarshalError(t *testing.T) {
 	}
 }
 
+func TestMarshalUninitializedTag(t *testing.T) {
+	var v Tag
+	b, err := Marshal(v)
+	if err != nil {
+		t.Errorf("Marshal(%v) returned error %v", v, err)
+	}
+	if !bytes.Equal(b, cborNil) {
+		t.Errorf("Marshal(%v) = 0x%x, want 0x%x", v, b, cborNil)
+	}
+}
+
+func TestMarshalUninitializedRawTag(t *testing.T) {
+	var v RawTag
+	b, err := Marshal(v)
+	if err != nil {
+		t.Errorf("Marshal(%v) returned error %v", v, err)
+	}
+	if !bytes.Equal(b, cborNil) {
+		t.Errorf("Marshal(%v) = 0x%x, want 0x%x", v, b, cborNil)
+	}
+}
+
 func TestEncodeTag(t *testing.T) {
 	m := make(map[interface{}]bool)
 	m[10] = true