From: Roland Shoemaker Date: Tue, 29 Mar 2022 01:41:26 +0000 (-0700) Subject: encoding/xml: use iterative Skip, rather than recursive X-Git-Tag: go1.19rc2~1^2~5 X-Git-Url: http://www.git.cypherpunks.su/?a=commitdiff_plain;h=08c46ed43d80bbb67cb904944ea3417989be4af3;p=gostls13.git encoding/xml: use iterative Skip, rather than recursive Prevents exhausting the stack limit in _incredibly_ deeply nested structures. Fixes #53614 Fixes CVE-2022-28131 Change-Id: I47db4595ce10cecc29fbd06afce7b299868599e6 Reviewed-on: https://team-review.git.corp.google.com/c/golang/go-private/+/1419912 Reviewed-by: Julie Qiu Reviewed-by: Damien Neil Reviewed-on: https://go-review.googlesource.com/c/go/+/417062 Run-TryBot: Michael Knyszek Reviewed-by: Heschi Kreinick TryBot-Result: Gopher Robot --- diff --git a/src/encoding/xml/read.go b/src/encoding/xml/read.go index 01613065e3..a6fb665458 100644 --- a/src/encoding/xml/read.go +++ b/src/encoding/xml/read.go @@ -747,12 +747,12 @@ Loop: } // Skip reads tokens until it has consumed the end element -// matching the most recent start element already consumed. -// It recurs if it encounters a start element, so it can be used to -// skip nested structures. +// matching the most recent start element already consumed, +// skipping nested structures. // It returns nil if it finds an end element matching the start // element; otherwise it returns an error describing the problem. func (d *Decoder) Skip() error { + var depth int64 for { tok, err := d.Token() if err != nil { @@ -760,11 +760,12 @@ func (d *Decoder) Skip() error { } switch tok.(type) { case StartElement: - if err := d.Skip(); err != nil { - return err - } + depth++ case EndElement: - return nil + if depth == 0 { + return nil + } + depth-- } } } diff --git a/src/encoding/xml/read_test.go b/src/encoding/xml/read_test.go index 42059db3ae..58d1eddb61 100644 --- a/src/encoding/xml/read_test.go +++ b/src/encoding/xml/read_test.go @@ -9,6 +9,7 @@ import ( "errors" "io" "reflect" + "runtime" "strings" "testing" "time" @@ -1109,3 +1110,19 @@ func TestCVE202228131(t *testing.T) { t.Fatalf("Unmarshal unexpected error: got %q, want %q", err, errExeceededMaxUnmarshalDepth) } } + +func TestCVE202230633(t *testing.T) { + if runtime.GOARCH == "wasm" { + t.Skip("causes memory exhaustion on js/wasm") + } + defer func() { + p := recover() + if p != nil { + t.Fatal("Unmarshal panicked") + } + }() + var example struct { + Things []string + } + Unmarshal(bytes.Repeat([]byte(""), 17_000_000), &example) +}