nebius/SWE-rebench-V2-PRs huggingface dataset:
Repository: mitchellh/mapstructure
Pull request #155 (2019-02-03 08:50:13)

Fix empty slice not allocated
Add a testcase, which will fail without patch.

Closes: #146


Patch:
diff --git a/mapstructure.go b/mapstructure.go
index 256ee63..0640ce1 100644
--- a/mapstructure.go
+++ b/mapstructure.go
@@ -840,8 +840,8 @@ func (d *Decoder) decodeSlice(name string, data interface{}, val reflect.Value)
 
 		}
 
-		// If the input value is empty, then don't allocate since non-nil != nil
-		if dataVal.Len() == 0 {
+		// If the input value is nil, then don't allocate since empty != nil
+		if dataVal.IsNil() {
 			return nil
 		}
 


Test patch:
diff --git a/mapstructure_test.go b/mapstructure_test.go
index 27ac10e..6a733ff 100644
--- a/mapstructure_test.go
+++ b/mapstructure_test.go
@@ -1545,6 +1545,17 @@ func TestDecodeTable(t *testing.T) {
 			},
 			false,
 		},
+		{
+			"struct with empty slice",
+			&map[string]interface{}{
+				"Vbar": []string{},
+			},
+			&Slice{},
+			&Slice{
+				Vbar: []string{},
+			},
+			false,
+		},
 		{
 			"struct with slice of struct property",
 			&SliceOfStruct{
Repository: mitchellh/mapstructure
Pull request #222 (2020-12-07 14:46:37)

Ability to use encoding.TextUnmarshaler
Fixes  #204


Patch:
diff --git a/decode_hooks.go b/decode_hooks.go
index 77578d0..92e6f76 100644
--- a/decode_hooks.go
+++ b/decode_hooks.go
@@ -1,6 +1,7 @@
 package mapstructure
 
 import (
+	"encoding"
 	"errors"
 	"fmt"
 	"net"
@@ -230,3 +231,26 @@ func RecursiveStructToMapHookFunc() DecodeHookFunc {
 		return f.Interface(), nil
 	}
 }
+
+// TextUnmarshallerHookFunc returns a DecodeHookFunc that applies
+// strings to the UnmarshalText function, when the target type
+// implements the encoding.TextUnmarshaler interface
+func TextUnmarshallerHookFunc() DecodeHookFuncType {
+	return func(
+		f reflect.Type,
+		t reflect.Type,
+		data interface{}) (interface{}, error) {
+		if f.Kind() != reflect.String {
+			return data, nil
+		}
+		result := reflect.New(t).Interface()
+		unmarshaller, ok := result.(encoding.TextUnmarshaler)
+		if !ok {
+			return data, nil
+		}
+		if err := unmarshaller.UnmarshalText([]byte(data.(string))); err != nil {
+			return nil, err
+		}
+		return result, nil
+	}
+}


Test patch:
diff --git a/decode_hooks_test.go b/decode_hooks_test.go
index d690253..b3165bc 100644
--- a/decode_hooks_test.go
+++ b/decode_hooks_test.go
@@ -2,6 +2,7 @@ package mapstructure
 
 import (
 	"errors"
+	"math/big"
 	"net"
 	"reflect"
 	"testing"
@@ -419,3 +420,28 @@ func TestStructToMapHookFuncTabled(t *testing.T) {
 
 	}
 }
+
+func TestTextUnmarshallerHookFunc(t *testing.T) {
+	cases := []struct {
+		f, t   reflect.Value
+		result interface{}
+		err    bool
+	}{
+		{reflect.ValueOf("42"), reflect.ValueOf(big.Int{}), big.NewInt(42), false},
+		{reflect.ValueOf("invalid"), reflect.ValueOf(big.Int{}), nil, true},
+		{reflect.ValueOf("5"), reflect.ValueOf("5"), "5", false},
+	}
+
+	for i, tc := range cases {
+		f := TextUnmarshallerHookFunc()
+		actual, err := DecodeHookExec(f, tc.f, tc.t)
+		if tc.err != (err != nil) {
+			t.Fatalf("case %d: expected err %#v", i, tc.err)
+		}
+		if !reflect.DeepEqual(actual, tc.result) {
+			t.Fatalf(
+				"case %d: expected %#v, got %#v",
+				i, tc.result, actual)
+		}
+	}
+}
Repository: mitchellh/mapstructure
Pull request #251 (2021-07-09 14:16:05)

Fix possible panic when using ComposeDecodeHookFunc() with no funcs
On < v1.3.3, `ComposeDecodeHookFunc()` was safe to use with no args, but since decea915226622f93c74393f562948d16af8a118 (v1.4.1) it can cause a panic due to it accidentally replacing the `input` with an untyped `nil` after the `nil` check on L405 https://github.com/mitchellh/mapstructure/blob/4664f9ee512b4dfa71b501c4960d469c205b2cf1/mapstructure.go#L405

This PR restores the previous behaviour with minimal impact to allow easier upgrades


Patch:
diff --git a/decode_hooks.go b/decode_hooks.go
index 92e6f76..5d871df 100644
--- a/decode_hooks.go
+++ b/decode_hooks.go
@@ -63,6 +63,11 @@ func ComposeDecodeHookFunc(fs ...DecodeHookFunc) DecodeHookFunc {
 	return func(f reflect.Value, t reflect.Value) (interface{}, error) {
 		var err error
 		var data interface{}
+
+		if len(fs) == 0 {
+			data = f.Interface()
+		}
+
 		newFrom := f
 		for _, f1 := range fs {
 			data, err = DecodeHookExec(f1, newFrom, t)


Test patch:
diff --git a/decode_hooks_test.go b/decode_hooks_test.go
index b3165bc..cfa3c18 100644
--- a/decode_hooks_test.go
+++ b/decode_hooks_test.go
@@ -84,6 +84,38 @@ func TestComposeDecodeHookFunc_kinds(t *testing.T) {
 	}
 }
 
+func TestComposeDecodeHookFunc_safe_nofuncs(t *testing.T) {
+	f := ComposeDecodeHookFunc()
+	type myStruct2 struct {
+		MyInt int
+	}
+
+	type myStruct1 struct {
+		Blah map[string]myStruct2
+	}
+
+	src := &myStruct1{Blah: map[string]myStruct2{
+		"test": {
+			MyInt: 1,
+		},
+	}}
+
+	dst := &myStruct1{}
+	dConf := &DecoderConfig{
+		Result:      dst,
+		ErrorUnused: true,
+		DecodeHook:  f,
+	}
+	d, err := NewDecoder(dConf)
+	if err != nil {
+		t.Fatal(err)
+	}
+	err = d.Decode(src)
+	if err != nil {
+		t.Fatal(err)
+	}
+}
+
 func TestStringToSliceHookFunc(t *testing.T) {
 	f := StringToSliceHookFunc(",")
Repository: mitchellh/mapstructure
Pull request #261 (2021-11-30 07:50:57)

Add support for parsing json.Number to uint64
`json.Number` can represent a number in range [2^63 + 1, 2^64), which is suitable for an uint64 value but overflow for an int64 value. When parsing `json.Number` to uint64, current implementation can't handle number in this range.

Since `json.Number` is basically string, we can parse string to uint64 directly. I've also add some unit tests.


Patch:
diff --git a/mapstructure.go b/mapstructure.go
index dcee0f2..6b81b00 100644
--- a/mapstructure.go
+++ b/mapstructure.go
@@ -684,16 +684,12 @@ func (d *Decoder) decodeUint(name string, data interface{}, val reflect.Value) e
 		}
 	case dataType.PkgPath() == "encoding/json" && dataType.Name() == "Number":
 		jn := data.(json.Number)
-		i, err := jn.Int64()
+		i, err := strconv.ParseUint(string(jn), 0, 64)
 		if err != nil {
 			return fmt.Errorf(
 				"error decoding json.Number into %s: %s", name, err)
 		}
-		if i < 0 && !d.config.WeaklyTypedInput {
-			return fmt.Errorf("cannot parse '%s', %d overflows uint",
-				name, i)
-		}
-		val.SetUint(uint64(i))
+		val.SetUint(i)
 	default:
 		return fmt.Errorf(
 			"'%s' expected type '%s', got unconvertible type '%s', value: '%v'",


Test patch:
diff --git a/mapstructure_test.go b/mapstructure_test.go
index 04549b4..a78e77a 100644
--- a/mapstructure_test.go
+++ b/mapstructure_test.go
@@ -24,6 +24,7 @@ type Basic struct {
 	Vdata       interface{}
 	VjsonInt    int
 	VjsonUint   uint
+	VjsonUint64 uint64
 	VjsonFloat  float64
 	VjsonNumber json.Number
 }
@@ -224,6 +225,7 @@ func TestBasicTypes(t *testing.T) {
 		"vdata":       42,
 		"vjsonInt":    json.Number("1234"),
 		"vjsonUint":   json.Number("1234"),
+		"vjsonUint64": json.Number("9223372036854775809"), // 2^63 + 1
 		"vjsonFloat":  json.Number("1234.5"),
 		"vjsonNumber": json.Number("1234.5"),
 	}
@@ -287,6 +289,10 @@ func TestBasicTypes(t *testing.T) {
 		t.Errorf("vjsonuint value should be 1234: %#v", result.VjsonUint)
 	}
 
+	if result.VjsonUint64 != 9223372036854775809 {
+		t.Errorf("vjsonuint64 value should be 9223372036854775809: %#v", result.VjsonUint64)
+	}
+
 	if result.VjsonFloat != 1234.5 {
 		t.Errorf("vjsonfloat value should be 1234.5: %#v", result.VjsonFloat)
 	}
@@ -1721,6 +1727,7 @@ func TestDecodeTable(t *testing.T) {
 				"Vdata":       []byte("data"),
 				"VjsonInt":    0,
 				"VjsonUint":   uint(0),
+				"VjsonUint64": uint64(0),
 				"VjsonFloat":  0.0,
 				"VjsonNumber": json.Number(""),
 			},
@@ -1762,6 +1769,7 @@ func TestDecodeTable(t *testing.T) {
 					"Vdata":       []byte("data"),
 					"VjsonInt":    0,
 					"VjsonUint":   uint(0),
+					"VjsonUint64": uint64(0),
 					"VjsonFloat":  0.0,
 					"VjsonNumber": json.Number(""),
 				},
Repository: mitchellh/mapstructure
Pull request #266 (2021-12-30 01:39:03)

slice mapping bug fix
```go
type Test struct {
	Attributes []byte `json:"attributes"`
}

type TestReq struct {
	Attributes []byte `json:"attributes"`
}

func TestMapping(t *testing.T) {
	req := TestReq{Attributes: []byte(`[{"data": "some data"}]`)}

	var test Test
	test.Attributes = []byte(`[{"a" : "1"}]`)

	err := mapstructure.Decode(req, &test)
	if err != nil {
		panic(err)
	}

	fmt.Println(string(test.Attributes))
	// result will be [{"data": "some data"}]
}

func TestMappingFail(t *testing.T) {
	req := TestReq{Attributes: []byte(`[{"data":"some data"}]`)}

	var test Test
	test.Attributes = []byte(`[{"a":"1111111111111111111111111111111111111111111111"}]`)

	err := mapstructure.Decode(req, &test)
	if err != nil {
		panic(err)
	}

	fmt.Println(string(test.Attributes))
	// result will be [{"data": "some data"}]11111111111111111111111111111111"}]
}

```


Patch:
diff --git a/mapstructure.go b/mapstructure.go
index 9ff5741..7581806 100644
--- a/mapstructure.go
+++ b/mapstructure.go
@@ -1123,6 +1123,8 @@ func (d *Decoder) decodeSlice(name string, data interface{}, val reflect.Value)
 	if valSlice.IsNil() || d.config.ZeroFields {
 		// Make a new slice to hold our result, same size as the original data.
 		valSlice = reflect.MakeSlice(sliceType, dataVal.Len(), dataVal.Len())
+	} else if valSlice.Len() > dataVal.Len() {
+		valSlice = valSlice.Slice(0, dataVal.Len())
 	}
 
 	// Accumulate any errors


Test patch:
diff --git a/mapstructure_test.go b/mapstructure_test.go
index bef5f85..d31129d 100644
--- a/mapstructure_test.go
+++ b/mapstructure_test.go
@@ -138,6 +138,11 @@ type Slice struct {
 	Vbar []string
 }
 
+type SliceOfByte struct {
+	Vfoo string
+	Vbar []byte
+}
+
 type SliceOfAlias struct {
 	Vfoo string
 	Vbar SliceAlias
@@ -1654,6 +1659,34 @@ func TestSlice(t *testing.T) {
 	testSliceInput(t, inputStringSlicePointer, outputStringSlice)
 }
 
+func TestNotEmptyByteSlice(t *testing.T) {
+	t.Parallel()
+
+	inputByteSlice := map[string]interface{}{
+		"vfoo": "foo",
+		"vbar": []byte(`{"bar": "bar"}`),
+	}
+
+	result := SliceOfByte{
+		Vfoo: "another foo",
+		Vbar: []byte(`{"bar": "bar bar bar bar bar bar bar bar"}`),
+	}
+
+	err := Decode(inputByteSlice, &result)
+	if err != nil {
+		t.Fatalf("got unexpected error: %s", err)
+	}
+
+	expected := SliceOfByte{
+		Vfoo: "foo",
+		Vbar: []byte(`{"bar": "bar"}`),
+	}
+
+	if !reflect.DeepEqual(result, expected) {
+		t.Errorf("bad: %#v", result)
+	}
+}
+
 func TestInvalidSlice(t *testing.T) {
 	t.Parallel()
Repository: mitchellh/mapstructure
Pull request #277 (2022-03-25 17:30:56)

DecoderConfig: Introduce `IgnoreUntaggedFields`
This is to enable us to more easily (safely & predictably) serialize various structs representing [indexes in go-memdb](https://pkg.go.dev/github.com/hashicorp/go-memdb#Indexer), so that these can be displayed in a useful format in a (memdb) UI.

There are of course builtin indexes which wouldn't necessarily need such special decoding mode, but that assumes we gate the UI on a particular version of go-memdb which has these tags added. More importantly there are custom indexes downstream which may not have any tags and this makes decoded map unpredictable and hard to work with.



Patch:
diff --git a/mapstructure.go b/mapstructure.go
index 6b81b00..581d80f 100644
--- a/mapstructure.go
+++ b/mapstructure.go
@@ -259,6 +259,10 @@ type DecoderConfig struct {
 	// defaults to "mapstructure"
 	TagName string
 
+	// IgnoreUntaggedFields ignores all struct fields without explicit
+	// TagName, comparable to `mapstructure:"-"` as default behaviour.
+	IgnoreUntaggedFields bool
+
 	// MatchName is the function used to match the map key to the struct
 	// field name or tag. Defaults to `strings.EqualFold`. This can be used
 	// to implement case-sensitive tag values, support snake casing, etc.
@@ -906,6 +910,10 @@ func (d *Decoder) decodeMapFromStruct(name string, dataVal reflect.Value, val re
 		tagValue := f.Tag.Get(d.config.TagName)
 		keyName := f.Name
 
+		if tagValue == "" && d.config.IgnoreUntaggedFields {
+			continue
+		}
+
 		// If Squash is set in the config, we squash the field down.
 		squash := d.config.Squash && v.Kind() == reflect.Struct && f.Anonymous
 


Test patch:
diff --git a/mapstructure_test.go b/mapstructure_test.go
index a78e77a..ec3bccd 100644
--- a/mapstructure_test.go
+++ b/mapstructure_test.go
@@ -2482,6 +2482,46 @@ func TestDecoder_MatchName(t *testing.T) {
 	}
 }
 
+func TestDecoder_IgnoreUntaggedFields(t *testing.T) {
+	type Input struct {
+		UntaggedNumber int
+		TaggedNumber   int `mapstructure:"tagged_number"`
+		UntaggedString string
+		TaggedString   string `mapstructure:"tagged_string"`
+	}
+	input := &Input{
+		UntaggedNumber: 31,
+		TaggedNumber:   42,
+		UntaggedString: "hidden",
+		TaggedString:   "visible",
+	}
+
+	actual := make(map[string]interface{})
+	config := &DecoderConfig{
+		Result:               &actual,
+		IgnoreUntaggedFields: true,
+	}
+
+	decoder, err := NewDecoder(config)
+	if err != nil {
+		t.Fatalf("err: %s", err)
+	}
+
+	err = decoder.Decode(input)
+	if err != nil {
+		t.Fatalf("err: %s", err)
+	}
+
+	expected := map[string]interface{}{
+		"tagged_number": 42,
+		"tagged_string": "visible",
+	}
+
+	if !reflect.DeepEqual(expected, actual) {
+		t.Fatalf("Decode() expected: %#v\ngot: %#v", expected, actual)
+	}
+}
+
 func testSliceInput(t *testing.T, input map[string]interface{}, expected *Slice) {
 	var result Slice
 	err := Decode(input, &result)
Repository: mitchellh/mapstructure
Pull request #280 (2022-04-20 17:22:16)

Fix squash not working when decoder config option is set and squash struct tags are present
This fixes an issue where squash would be disabled for struct fields that have the `",squash"` tag if the decoder also has `Squash: true` set in its config.


Patch:
diff --git a/mapstructure.go b/mapstructure.go
index 6b81b00..f941dd5 100644
--- a/mapstructure.go
+++ b/mapstructure.go
@@ -920,7 +920,7 @@ func (d *Decoder) decodeMapFromStruct(name string, dataVal reflect.Value, val re
 			}
 
 			// If "squash" is specified in the tag, we squash the field down.
-			squash = !squash && strings.Index(tagValue[index+1:], "squash") != -1
+			squash = squash || strings.Index(tagValue[index+1:], "squash") != -1
 			if squash {
 				// When squashing, the embedded type can be a pointer to a struct.
 				if v.Kind() == reflect.Ptr && v.Elem().Kind() == reflect.Struct {


Test patch:
diff --git a/mapstructure_test.go b/mapstructure_test.go
index a78e77a..1ec32e5 100644
--- a/mapstructure_test.go
+++ b/mapstructure_test.go
@@ -812,6 +812,53 @@ func TestDecodeFrom_EmbeddedSquashConfig(t *testing.T) {
 	}
 }
 
+func TestDecodeFrom_EmbeddedSquashConfig_WithTags(t *testing.T) {
+	t.Parallel()
+
+	var v interface{}
+	var ok bool
+
+	input := EmbeddedSquash{
+		Basic: Basic{
+			Vstring: "foo",
+		},
+		Vunique: "bar",
+	}
+
+	result := map[string]interface{}{}
+	config := &DecoderConfig{
+		Squash: true,
+		Result: &result,
+	}
+	decoder, err := NewDecoder(config)
+	if err != nil {
+		t.Fatalf("got an err: %s", err.Error())
+	}
+
+	err = decoder.Decode(input)
+	if err != nil {
+		t.Fatalf("got an err: %s", err.Error())
+	}
+
+	if _, ok = result["Basic"]; ok {
+		t.Error("basic should not be present in map")
+	}
+
+	v, ok = result["Vstring"]
+	if !ok {
+		t.Error("vstring should be present in map")
+	} else if !reflect.DeepEqual(v, "foo") {
+		t.Errorf("vstring value should be 'foo': %#v", v)
+	}
+
+	v, ok = result["Vunique"]
+	if !ok {
+		t.Error("vunique should be present in map")
+	} else if !reflect.DeepEqual(v, "bar") {
+		t.Errorf("vunique value should be 'bar': %#v", v)
+	}
+}
+
 func TestDecode_SquashOnNonStructType(t *testing.T) {
 	t.Parallel()
Repository: mitchellh/mapstructure
Pull request #328 (2023-04-18 17:25:42)

prevent panic in TextUnmarshallerHookFunc
if reflect.Kind is reflect.String, it doesn't necessary means it's `string` type. It can be string-based type


Patch:
diff --git a/decode_hooks.go b/decode_hooks.go
index 3a754ca..c1f99da 100644
--- a/decode_hooks.go
+++ b/decode_hooks.go
@@ -271,7 +271,11 @@ func TextUnmarshallerHookFunc() DecodeHookFuncType {
 		if !ok {
 			return data, nil
 		}
-		if err := unmarshaller.UnmarshalText([]byte(data.(string))); err != nil {
+		str, ok := data.(string)
+		if !ok {
+			str = reflect.Indirect(reflect.ValueOf(&data)).Elem().String()
+		}
+		if err := unmarshaller.UnmarshalText([]byte(str)); err != nil {
 			return nil, err
 		}
 		return result, nil


Test patch:
diff --git a/decode_hooks_test.go b/decode_hooks_test.go
index bf02952..b773960 100644
--- a/decode_hooks_test.go
+++ b/decode_hooks_test.go
@@ -1,6 +1,7 @@
 package mapstructure
 
 import (
+	"encoding/json"
 	"errors"
 	"math/big"
 	"net"
@@ -542,6 +543,8 @@ func TestStructToMapHookFuncTabled(t *testing.T) {
 }
 
 func TestTextUnmarshallerHookFunc(t *testing.T) {
+	type MyString string
+
 	cases := []struct {
 		f, t   reflect.Value
 		result interface{}
@@ -550,8 +553,9 @@ func TestTextUnmarshallerHookFunc(t *testing.T) {
 		{reflect.ValueOf("42"), reflect.ValueOf(big.Int{}), big.NewInt(42), false},
 		{reflect.ValueOf("invalid"), reflect.ValueOf(big.Int{}), nil, true},
 		{reflect.ValueOf("5"), reflect.ValueOf("5"), "5", false},
+		{reflect.ValueOf(json.Number("42")), reflect.ValueOf(big.Int{}), big.NewInt(42), false},
+		{reflect.ValueOf(MyString("42")), reflect.ValueOf(big.Int{}), big.NewInt(42), false},
 	}
-
 	for i, tc := range cases {
 		f := TextUnmarshallerHookFunc()
 		actual, err := DecodeHookExec(f, tc.f, tc.t)