1
0
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:
Roland Shoemaker 2022-03-28 18:41:26 -07:00 committed by Michael Knyszek
parent ed2f33e1a7
commit 58facfbe7d
2 changed files with 26 additions and 7 deletions

View File

@ -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--
} }
} }
} }

View File

@ -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)
}