mirror of
https://github.com/golang/go.git
synced 2025-12-08 06:10:04 +00:00
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 <julieqiu@google.com> Reviewed-by: Damien Neil <dneil@google.com> Reviewed-on: https://go-review.googlesource.com/c/go/+/417062 Run-TryBot: Michael Knyszek <mknyszek@google.com> Reviewed-by: Heschi Kreinick <heschi@google.com> TryBot-Result: Gopher Robot <gobot@golang.org>
This commit is contained in:
parent
c4c1993fd2
commit
08c46ed43d
2 changed files with 25 additions and 7 deletions
|
|
@ -747,12 +747,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 {
|
||||||
|
|
@ -760,11 +760,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--
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -9,6 +9,7 @@ import (
|
||||||
"errors"
|
"errors"
|
||||||
"io"
|
"io"
|
||||||
"reflect"
|
"reflect"
|
||||||
|
"runtime"
|
||||||
"strings"
|
"strings"
|
||||||
"testing"
|
"testing"
|
||||||
"time"
|
"time"
|
||||||
|
|
@ -1109,3 +1110,19 @@ func TestCVE202228131(t *testing.T) {
|
||||||
t.Fatalf("Unmarshal unexpected error: got %q, want %q", err, errExeceededMaxUnmarshalDepth)
|
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("<a>"), 17_000_000), &example)
|
||||||
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue