mirror of
https://github.com/golang/go
synced 2024-11-11 18:31:38 -07:00
[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>
This commit is contained in:
parent
ed2f33e1a7
commit
58facfbe7d
@ -732,12 +732,12 @@ Loop:
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Skip reads tokens until it has consumed the end element
|
// Skip reads tokens until it has consumed the end element
|
||||||
// matching the most recent start element already consumed.
|
// matching the most recent start element already consumed,
|
||||||
// It recurs if it encounters a start element, so it can be used to
|
// skipping nested structures.
|
||||||
// skip nested structures.
|
|
||||||
// It returns nil if it finds an end element matching the start
|
// It returns nil if it finds an end element matching the start
|
||||||
// element; otherwise it returns an error describing the problem.
|
// element; otherwise it returns an error describing the problem.
|
||||||
func (d *Decoder) Skip() error {
|
func (d *Decoder) Skip() error {
|
||||||
|
var depth int64
|
||||||
for {
|
for {
|
||||||
tok, err := d.Token()
|
tok, err := d.Token()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -745,11 +745,12 @@ func (d *Decoder) Skip() error {
|
|||||||
}
|
}
|
||||||
switch tok.(type) {
|
switch tok.(type) {
|
||||||
case StartElement:
|
case StartElement:
|
||||||
if err := d.Skip(); err != nil {
|
depth++
|
||||||
return err
|
|
||||||
}
|
|
||||||
case EndElement:
|
case EndElement:
|
||||||
return nil
|
if depth == 0 {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
depth--
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -5,8 +5,10 @@
|
|||||||
package xml
|
package xml
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"bytes"
|
||||||
"io"
|
"io"
|
||||||
"reflect"
|
"reflect"
|
||||||
|
"runtime"
|
||||||
"strings"
|
"strings"
|
||||||
"testing"
|
"testing"
|
||||||
"time"
|
"time"
|
||||||
@ -1079,3 +1081,19 @@ func TestUnmarshalWhitespaceAttrs(t *testing.T) {
|
|||||||
t.Fatalf("whitespace attrs: Unmarshal:\nhave: %#+v\nwant: %#+v", v, want)
|
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)
|
||||||
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user