mirror of
git://git.yoctoproject.org/poky
synced 2026-10-01 08:26:24 +00:00
Source: https://github.com/golang/go MR: 120622, 120625 Type: Security Fix Disposition: Backport from76f8b7304d&&2678d0c957ChangeID: aabb29a6dd6a89842f451c95af228aaf66e58bb5 Description: Fixed CVE: 1. CVE-2022-30632 2. CVE-2022-30633 (From OE-Core rev: 9ffaae887743d77839fb758657b1dec71a9b8880) Signed-off-by: Hitendra Prajapati <hprajapati@mvista.com> Signed-off-by: Steve Sakoman <steve@sakoman.com> Signed-off-by: Richard Purdie <richard.purdie@linuxfoundation.org>
132 lines
4.8 KiB
Diff
132 lines
4.8 KiB
Diff
From ab6e2ffdcab0501bcc2de4b196c1c18ae2301d4b Mon Sep 17 00:00:00 2001
|
|
From: Hitendra Prajapati <hprajapati@mvista.com>
|
|
Date: Thu, 25 Aug 2022 13:29:55 +0530
|
|
Subject: [PATCH] CVE-2022-30633
|
|
|
|
Upstream-Status: Backport [https://github.com/golang/go/commit/2678d0c957193dceef336c969a9da74dd716a827]
|
|
CVE: CVE-2022-30633
|
|
Signed-off-by: Hitendra Prajapati <hprajapati@mvista.com>
|
|
---
|
|
src/encoding/xml/read.go | 27 +++++++++++++++++++--------
|
|
src/encoding/xml/read_test.go | 14 ++++++++++++++
|
|
2 files changed, 33 insertions(+), 8 deletions(-)
|
|
|
|
diff --git a/src/encoding/xml/read.go b/src/encoding/xml/read.go
|
|
index 10a60ee..4ffed80 100644
|
|
--- a/src/encoding/xml/read.go
|
|
+++ b/src/encoding/xml/read.go
|
|
@@ -148,7 +148,7 @@ func (d *Decoder) DecodeElement(v interface{}, start *StartElement) error {
|
|
if val.Kind() != reflect.Ptr {
|
|
return errors.New("non-pointer passed to Unmarshal")
|
|
}
|
|
- return d.unmarshal(val.Elem(), start)
|
|
+ return d.unmarshal(val.Elem(), start, 0)
|
|
}
|
|
|
|
// An UnmarshalError represents an error in the unmarshaling process.
|
|
@@ -304,8 +304,15 @@ var (
|
|
textUnmarshalerType = reflect.TypeOf((*encoding.TextUnmarshaler)(nil)).Elem()
|
|
)
|
|
|
|
+const maxUnmarshalDepth = 10000
|
|
+
|
|
+var errExeceededMaxUnmarshalDepth = errors.New("exceeded max depth")
|
|
+
|
|
// Unmarshal a single XML element into val.
|
|
-func (d *Decoder) unmarshal(val reflect.Value, start *StartElement) error {
|
|
+func (d *Decoder) unmarshal(val reflect.Value, start *StartElement, depth int) error {
|
|
+ if depth >= maxUnmarshalDepth {
|
|
+ return errExeceededMaxUnmarshalDepth
|
|
+ }
|
|
// Find start element if we need it.
|
|
if start == nil {
|
|
for {
|
|
@@ -398,7 +405,7 @@ func (d *Decoder) unmarshal(val reflect.Value, start *StartElement) error {
|
|
v.Set(reflect.Append(val, reflect.Zero(v.Type().Elem())))
|
|
|
|
// Recur to read element into slice.
|
|
- if err := d.unmarshal(v.Index(n), start); err != nil {
|
|
+ if err := d.unmarshal(v.Index(n), start, depth+1); err != nil {
|
|
v.SetLen(n)
|
|
return err
|
|
}
|
|
@@ -521,13 +528,15 @@ Loop:
|
|
case StartElement:
|
|
consumed := false
|
|
if sv.IsValid() {
|
|
- consumed, err = d.unmarshalPath(tinfo, sv, nil, &t)
|
|
+ // unmarshalPath can call unmarshal, so we need to pass the depth through so that
|
|
+ // we can continue to enforce the maximum recusion limit.
|
|
+ consumed, err = d.unmarshalPath(tinfo, sv, nil, &t, depth)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
if !consumed && saveAny.IsValid() {
|
|
consumed = true
|
|
- if err := d.unmarshal(saveAny, &t); err != nil {
|
|
+ if err := d.unmarshal(saveAny, &t, depth+1); err != nil {
|
|
return err
|
|
}
|
|
}
|
|
@@ -672,7 +681,7 @@ func copyValue(dst reflect.Value, src []byte) (err error) {
|
|
// The consumed result tells whether XML elements have been consumed
|
|
// from the Decoder until start's matching end element, or if it's
|
|
// still untouched because start is uninteresting for sv's fields.
|
|
-func (d *Decoder) unmarshalPath(tinfo *typeInfo, sv reflect.Value, parents []string, start *StartElement) (consumed bool, err error) {
|
|
+func (d *Decoder) unmarshalPath(tinfo *typeInfo, sv reflect.Value, parents []string, start *StartElement, depth int) (consumed bool, err error) {
|
|
recurse := false
|
|
Loop:
|
|
for i := range tinfo.fields {
|
|
@@ -687,7 +696,7 @@ Loop:
|
|
}
|
|
if len(finfo.parents) == len(parents) && finfo.name == start.Name.Local {
|
|
// It's a perfect match, unmarshal the field.
|
|
- return true, d.unmarshal(finfo.value(sv), start)
|
|
+ return true, d.unmarshal(finfo.value(sv), start, depth+1)
|
|
}
|
|
if len(finfo.parents) > len(parents) && finfo.parents[len(parents)] == start.Name.Local {
|
|
// It's a prefix for the field. Break and recurse
|
|
@@ -716,7 +725,9 @@ Loop:
|
|
}
|
|
switch t := tok.(type) {
|
|
case StartElement:
|
|
- consumed2, err := d.unmarshalPath(tinfo, sv, parents, &t)
|
|
+ // the recursion depth of unmarshalPath is limited to the path length specified
|
|
+ // by the struct field tag, so we don't increment the depth here.
|
|
+ consumed2, err := d.unmarshalPath(tinfo, sv, parents, &t, depth)
|
|
if err != nil {
|
|
return true, err
|
|
}
|
|
diff --git a/src/encoding/xml/read_test.go b/src/encoding/xml/read_test.go
|
|
index 8c2e70f..6a20b1a 100644
|
|
--- a/src/encoding/xml/read_test.go
|
|
+++ b/src/encoding/xml/read_test.go
|
|
@@ -5,6 +5,7 @@
|
|
package xml
|
|
|
|
import (
|
|
+ "errors"
|
|
"io"
|
|
"reflect"
|
|
"strings"
|
|
@@ -1079,3 +1080,16 @@ func TestUnmarshalWhitespaceAttrs(t *testing.T) {
|
|
t.Fatalf("whitespace attrs: Unmarshal:\nhave: %#+v\nwant: %#+v", v, want)
|
|
}
|
|
}
|
|
+
|
|
+func TestCVE202228131(t *testing.T) {
|
|
+ type nested struct {
|
|
+ Parent *nested `xml:",any"`
|
|
+ }
|
|
+ var n nested
|
|
+ err := Unmarshal(bytes.Repeat([]byte("<a>"), maxUnmarshalDepth+1), &n)
|
|
+ if err == nil {
|
|
+ t.Fatal("Unmarshal did not fail")
|
|
+ } else if !errors.Is(err, errExeceededMaxUnmarshalDepth) {
|
|
+ t.Fatalf("Unmarshal unexpected error: got %q, want %q", err, errExeceededMaxUnmarshalDepth)
|
|
+ }
|
|
+}
|
|
--
|
|
2.25.1
|
|
|