]> Cypherpunks repositories - gostls13.git/commitdiff
encoding/xml: embedded reference to substruct causes XML marshaller to panic on encoding
authorhopehook <hopehook.com@gmail.com>
Sun, 13 Feb 2022 14:03:56 +0000 (22:03 +0800)
committerIan Lance Taylor <iant@golang.org>
Sun, 20 Feb 2022 20:58:11 +0000 (20:58 +0000)
When encoding a xml attribute is zero value (IsValid == false), we need
a `continue` to jump over the attribute. If not, followed marshalAttr
function will panic.

Fixes: #50164
Change-Id: I42e064558e7becfbf47728b14cbf5c7afa1e8798
Reviewed-on: https://go-review.googlesource.com/c/go/+/385514
Reviewed-by: Daniel Martí <mvdan@mvdan.cc>
Trust: Daniel Martí <mvdan@mvdan.cc>
Run-TryBot: Daniel Martí <mvdan@mvdan.cc>
TryBot-Result: Gopher Robot <gobot@golang.org>
Reviewed-by: Ian Lance Taylor <iant@golang.org>
src/encoding/xml/marshal.go
src/encoding/xml/marshal_test.go

index 6859be04a221ec4ba22a8c6bd6cdf4e2c99ee994..7792ac77f8a814da31bd820a108d7daca5a7ad85 100644 (file)
@@ -512,7 +512,7 @@ func (p *printer) marshalValue(val reflect.Value, finfo *fieldInfo, startTemplat
                }
                fv := finfo.value(val, dontInitNilPointers)
 
-               if finfo.flags&fOmitEmpty != 0 && isEmptyValue(fv) {
+               if finfo.flags&fOmitEmpty != 0 && (!fv.IsValid() || isEmptyValue(fv)) {
                        continue
                }
 
index 5fdbae7ef0a8bd2cd2e30c8d5b9923863da2041f..3fe7e2dc001c4ddb3fda2fb6ef1913d42d72b701 100644 (file)
@@ -2495,3 +2495,39 @@ func TestInvalidXMLName(t *testing.T) {
                t.Errorf("error %q does not contain %q", err, want)
        }
 }
+
+// Issue 50164. Crash on zero value XML attribute.
+type LayerOne struct {
+       XMLName Name `xml:"l1"`
+
+       Value     *float64 `xml:"value,omitempty"`
+       *LayerTwo `xml:",omitempty"`
+}
+
+type LayerTwo struct {
+       ValueTwo *int `xml:"value_two,attr,omitempty"`
+}
+
+func TestMarshalZeroValue(t *testing.T) {
+       proofXml := `<l1><value>1.2345</value></l1>`
+       var l1 LayerOne
+       err := Unmarshal([]byte(proofXml), &l1)
+       if err != nil {
+               t.Fatalf("unmarshal XML error: %v", err)
+       }
+       want := float64(1.2345)
+       got := *l1.Value
+       if got != want {
+               t.Fatalf("unexpected unmarshal result, want %f but got %f", want, got)
+       }
+
+       // Marshal again (or Encode again)
+       // In issue 50164, here `Marshal(l1)` will panic because of the zero value of xml attribute ValueTwo `value_two`.
+       anotherXML, err := Marshal(l1)
+       if err != nil {
+               t.Fatalf("marshal XML error: %v", err)
+       }
+       if string(anotherXML) != proofXml {
+               t.Fatalf("unexpected unmarshal result, want %q but got %q", proofXml, anotherXML)
+       }
+}