diff options
author | Roland Shoemaker <roland@golang.org> | 2022-03-28 18:41:26 -0700 |
---|---|---|
committer | Michael Knyszek <mknyszek@google.com> | 2022-07-12 15:20:21 +0000 |
commit | 58facfbe7db2fbb9afed794b281a70bdb12a60ae (patch) | |
tree | f2ef77981d1ddf6a7a1c085f01b59656231d0901 /src/encoding | |
parent | ed2f33e1a7e0d18f61bd56f7ee067331d612c27e (diff) | |
download | go-58facfbe7db2fbb9afed794b281a70bdb12a60ae.tar.gz go-58facfbe7db2fbb9afed794b281a70bdb12a60ae.zip |
[release-branch.go1.17] encoding/xml: use iterative Skip, rather than recursive
Prevents exhausting the stack limit in _incredibly_ deeply nested
structures.
Fixes #53711
Updates #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 <julieqiu@google.com>
Reviewed-by: Damien Neil <dneil@google.com>
(cherry picked from commit 9278cb78443d2b4deb24cbb5b61c9ba5ac688d49)
Reviewed-on: https://go-review.googlesource.com/c/go/+/417068
TryBot-Result: Gopher Robot <gobot@golang.org>
Reviewed-by: Heschi Kreinick <heschi@google.com>
Run-TryBot: Michael Knyszek <mknyszek@google.com>
Diffstat (limited to 'src/encoding')
-rw-r--r-- | src/encoding/xml/read.go | 15 | ||||
-rw-r--r-- | src/encoding/xml/read_test.go | 18 |
2 files changed, 26 insertions, 7 deletions
diff --git a/src/encoding/xml/read.go b/src/encoding/xml/read.go index ef5df3f7f6..e9f9d2efa9 100644 --- a/src/encoding/xml/read.go +++ b/src/encoding/xml/read.go @@ -732,12 +732,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 { @@ -745,11 +745,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 8c2e70fa22..4ccab3d010 100644 --- a/src/encoding/xml/read_test.go +++ b/src/encoding/xml/read_test.go @@ -5,8 +5,10 @@ package xml import ( + "bytes" "io" "reflect" + "runtime" "strings" "testing" "time" @@ -1079,3 +1081,19 @@ func TestUnmarshalWhitespaceAttrs(t *testing.T) { t.Fatalf("whitespace attrs: Unmarshal:\nhave: %#+v\nwant: %#+v", v, want) } } + +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("<a>"), 17_000_000), &example) +} |