Skip to content

Crash via abi.JSON #24930

Closed
Closed
@holiman

Description

reported by @samczsun

There's a crasher in abi:

diff --git a/accounts/abi/bind/base_test.go b/accounts/abi/bind/base_test.go
index f59459a0ab..daf2444340 100644
--- a/accounts/abi/bind/base_test.go
+++ b/accounts/abi/bind/base_test.go
@@ -488,3 +488,7 @@ func TestCall(t *testing.T) {
 		}
 	}
 }
+
+func TestCrasher(t *testing.T) {
+	abi.JSON(strings.NewReader(`[{"inputs":[{"type":"tuple[]","components":[{"type":"bool","name":"_1"}]}]}]`))
+}

Results in

=== RUN   TestCrasher
--- FAIL: TestCrasher (0.00s)
panic: reflect.StructOf: field 0 has invalid name [recovered]
	panic: reflect.StructOf: field 0 has invalid name

goroutine 28 [running]:
testing.tRunner.func1.2({0x9e15a0, 0xc0001d7100})
	/usr/local/go/src/testing/testing.go:1389 +0x24e
testing.tRunner.func1()
	/usr/local/go/src/testing/testing.go:1392 +0x39f
panic({0x9e15a0, 0xc0001d7100})
	/usr/local/go/src/runtime/panic.go:838 +0x207
reflect.StructOf({0xc0001d1ea0, 0x1, 0x2?})
	/usr/local/go/src/reflect/type.go:2454 +0x28e5
github.com/ethereum/go-ethereum/accounts/abi.NewType({0xc0001ffd40, 0x5}, {0x0, 0x0}, {0xc00014da40?, 0x1, 0x4})
	/home/user/go/src/github.com/ethereum/go-ethereum/accounts/abi/type.go:191 +0xbe8
github.com/ethereum/go-ethereum/accounts/abi.NewType({0xc0001ffd40, 0x7}, {0x0, 0x0}, {0xc00014da40?, 0x1, 0x4})
	/home/user/go/src/github.com/ethereum/go-ethereum/accounts/abi/type.go:85 +0x22b
github.com/ethereum/go-ethereum/accounts/abi.(*Argument).UnmarshalJSON(0xc0002546c0, {0xc00025200c, 0x3d, 0x1f4})
	/home/user/go/src/github.com/ethereum/go-ethereum/accounts/abi/argument.go:52 +0x13c
encoding/json.(*decodeState).object(0xc0001765a0, {0xa41680?, 0xc0002546c0?, 0xb?})
	/usr/local/go/src/encoding/json/decode.go:612 +0x68a
encoding/json.(*decodeState).value(0xc0001765a0, {0xa41680?, 0xc0002546c0?, 0x1?})
	/usr/local/go/src/encoding/json/decode.go:373 +0x45
encoding/json.(*decodeState).array(0xc0001765a0, {0x9d6aa0?, 0xc00024e840?, 0xf9b601?})
	/usr/local/go/src/encoding/json/decode.go:561 +0x626
encoding/json.(*decodeState).value(0xc0001765a0, {0x9d6aa0?, 0xc00024e840?, 0xc000252003?})
	/usr/local/go/src/encoding/json/decode.go:363 +0x7e
encoding/json.(*decodeState).object(0xc0001765a0, {0xa74260?, 0xc00024e820?, 0x199?})
	/usr/local/go/src/encoding/json/decode.go:774 +0xca5
encoding/json.(*decodeState).value(0xc0001765a0, {0xa74260?, 0xc00024e820?, 0x1?})
	/usr/local/go/src/encoding/json/decode.go:373 +0x45
encoding/json.(*decodeState).array(0xc0001765a0, {0x9c8200?, 0xc00011e7e0?, 0x0?})
	/usr/local/go/src/encoding/json/decode.go:561 +0x626
encoding/json.(*decodeState).value(0xc0001765a0, {0x9c8200?, 0xc00011e7e0?, 0x90?})
	/usr/local/go/src/encoding/json/decode.go:363 +0x7e
encoding/json.(*decodeState).unmarshal(0xc0001765a0, {0x9c8200?, 0xc00011e7e0?})
	/usr/local/go/src/encoding/json/decode.go:180 +0x1de
encoding/json.Unmarshal({0xc000252000, 0x4c, 0x200}, {0x9c8200, 0xc00011e7e0})
	/usr/local/go/src/encoding/json/decode.go:107 +0x125
github.com/ethereum/go-ethereum/accounts/abi.(*ABI).UnmarshalJSON(0xc000113d40, {0xc000252000, 0x4c, 0x200})
	/home/user/go/src/github.com/ethereum/go-ethereum/accounts/abi/abi.go:156 +0x8b
encoding/json.(*decodeState).array(0xc00014d928, {0xa6a160?, 0xc000113d40?, 0xc00005ec70?})
	/usr/local/go/src/encoding/json/decode.go:506 +0x3f6
encoding/json.(*decodeState).value(0xc00014d928, {0xa6a160?, 0xc000113d40?, 0xc00005ecc0?})
	/usr/local/go/src/encoding/json/decode.go:363 +0x7e
encoding/json.(*decodeState).unmarshal(0xc00014d928, {0xa6a160?, 0xc000113d40?})
	/usr/local/go/src/encoding/json/decode.go:180 +0x1de
encoding/json.(*Decoder).Decode(0xc00014d900, {0xa6a160, 0xc000113d40})
	/usr/local/go/src/encoding/json/stream.go:73 +0x177
github.com/ethereum/go-ethereum/accounts/abi.JSON({_, _})
	/home/user/go/src/github.com/ethereum/go-ethereum/accounts/abi/abi.go:51 +0xbf
github.com/ethereum/go-ethereum/accounts/abi/bind_test.TestCrasher(0x0?)
	/home/user/go/src/github.com/ethereum/go-ethereum/accounts/abi/bind/base_test.go:493 +0x65
testing.tRunner(0xc00024e4e0, 0xb5fda0)
	/usr/local/go/src/testing/testing.go:1439 +0x102
created by testing.(*T).Run
	/usr/local/go/src/testing/testing.go:1486 +0x35f

The method we're using, reflect.StructOf has the following doc:

StructOf currently does not generate wrapper methods for embedded
fields and panics if passed unexported StructFields.

So there appears to be no publically available version of StructOf which returns an error rather than panicing. Also, the check that fails is isValidFieldName(field.Name), which is also an unexported method from package reflect, so we can't just check it in advance before calling StructOf.

Reflect seems to have a thing for panic which is not very nice to have to work around.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions