diff options
author | Robert Zaremba <robert.zaremba@scale-it.pl> | 2017-11-10 09:30:26 +0800 |
---|---|---|
committer | Martin Holst Swende <martin@swende.se> | 2017-12-21 22:14:50 +0800 |
commit | 0ed8b838a991f81f79cc6ed4fa961c563203a7a2 (patch) | |
tree | 1b6c813a7271b73b4bc0f57ad8bf2ce49325285e /accounts | |
parent | 9becba5540540bc37d4ad5eaaf7e4c1937a6542f (diff) | |
download | dexon-0ed8b838a991f81f79cc6ed4fa961c563203a7a2.tar.gz dexon-0ed8b838a991f81f79cc6ed4fa961c563203a7a2.tar.zst dexon-0ed8b838a991f81f79cc6ed4fa961c563203a7a2.zip |
accounts/abi: fix event unpack into slice
+ The event slice unpacker doesn't correctly extract element from the
slice. The indexed arguments are not ignored as they should be
(the data offset should not include the indexed arguments).
+ The `Elem()` call in the slice unpack doesn't work.
The Slice related tests fails because of that.
+ the check in the loop are suboptimal and have been extracted
out of the loop.
+ extracted common code from event and method tupleUnpack
Diffstat (limited to 'accounts')
-rw-r--r-- | accounts/abi/argument.go | 10 | ||||
-rw-r--r-- | accounts/abi/event.go | 23 | ||||
-rw-r--r-- | accounts/abi/method.go | 16 | ||||
-rw-r--r-- | accounts/abi/reflect.go | 8 | ||||
-rw-r--r-- | accounts/abi/unpack.go | 2 |
5 files changed, 36 insertions, 23 deletions
diff --git a/accounts/abi/argument.go b/accounts/abi/argument.go index 4691318ce..cd856061e 100644 --- a/accounts/abi/argument.go +++ b/accounts/abi/argument.go @@ -49,3 +49,13 @@ func (a *Argument) UnmarshalJSON(data []byte) error { return nil } + +func countNonIndexedArguments(args []Argument) int { + out := 0 + for i := range args { + if !args[i].Indexed { + out++ + } + } + return out +} diff --git a/accounts/abi/event.go b/accounts/abi/event.go index 0d3c3c4fa..b67bc96a8 100644 --- a/accounts/abi/event.go +++ b/accounts/abi/event.go @@ -59,16 +59,19 @@ func (e Event) tupleUnpack(v interface{}, output []byte) error { var ( value = valueOf.Elem() typ = value.Type() + kind = value.Kind() ) - - if value.Kind() != reflect.Struct { - return fmt.Errorf("abi: cannot unmarshal tuple in to %v", typ) + if err := requireUnpackKind(value, typ, kind, e.Inputs, true); err != nil { + return err } + // `i` counts the nonindexed arguments. + // `j` counts the number of complex types. + // both `i` and `j` are used to to correctly compute `data` offset. i, j := -1, 0 for _, input := range e.Inputs { if input.Indexed { - // can't read, continue + // Indexed arguments are not packed into data continue } i++ @@ -83,7 +86,7 @@ func (e Event) tupleUnpack(v interface{}, output []byte) error { } reflectValue := reflect.ValueOf(marshalledValue) - switch value.Kind() { + switch kind { case reflect.Struct: for j := 0; j < typ.NumField(); j++ { field := typ.Field(j) @@ -95,19 +98,13 @@ func (e Event) tupleUnpack(v interface{}, output []byte) error { } } case reflect.Slice, reflect.Array: - if value.Len() < i { - return fmt.Errorf("abi: insufficient number of arguments for unpack, want %d, got %d", i, value.Len()) - } v := value.Index(i) - if v.Kind() != reflect.Ptr && v.Kind() != reflect.Interface { - return fmt.Errorf("abi: cannot unmarshal %v in to %v", v.Type(), reflectValue.Type()) + if err := requireAssignable(v, reflectValue); err != nil { + return err } - reflectValue := reflect.ValueOf(marshalledValue) if err := set(v.Elem(), reflectValue, input); err != nil { return err } - default: - return fmt.Errorf("abi: cannot unmarshal tuple in to %v", typ) } } return nil diff --git a/accounts/abi/method.go b/accounts/abi/method.go index 66e8751f3..ee79b51cb 100644 --- a/accounts/abi/method.go +++ b/accounts/abi/method.go @@ -101,7 +101,11 @@ func (method Method) tupleUnpack(v interface{}, output []byte) error { var ( value = valueOf.Elem() typ = value.Type() + kind = value.Kind() ) + if err := requireUnpackKind(value, typ, kind, method.Outputs, false); err != nil { + return err + } j := 0 for i := 0; i < len(method.Outputs); i++ { @@ -117,7 +121,7 @@ func (method Method) tupleUnpack(v interface{}, output []byte) error { } reflectValue := reflect.ValueOf(marshalledValue) - switch value.Kind() { + switch kind { case reflect.Struct: for j := 0; j < typ.NumField(); j++ { field := typ.Field(j) @@ -129,19 +133,13 @@ func (method Method) tupleUnpack(v interface{}, output []byte) error { } } case reflect.Slice, reflect.Array: - if value.Len() < i { - return fmt.Errorf("abi: insufficient number of arguments for unpack, want %d, got %d", len(method.Outputs), value.Len()) - } v := value.Index(i) - if v.Kind() != reflect.Ptr && v.Kind() != reflect.Interface { - return fmt.Errorf("abi: cannot unmarshal %v in to %v", v.Type(), reflectValue.Type()) + if err := requireAssignable(v, reflectValue); err != nil { + return err } - reflectValue := reflect.ValueOf(marshalledValue) if err := set(v.Elem(), reflectValue, method.Outputs[i]); err != nil { return err } - default: - return fmt.Errorf("abi: cannot unmarshal tuple in to %v", typ) } } return nil diff --git a/accounts/abi/reflect.go b/accounts/abi/reflect.go index e953b77c1..fbcd576e5 100644 --- a/accounts/abi/reflect.go +++ b/accounts/abi/reflect.go @@ -85,3 +85,11 @@ func set(dst, src reflect.Value, output Argument) error { } return nil } + +// requireAssignable assures that `dest` is a pointer and it's not an interface. +func requireAssignable(dst, src reflect.Value) error { + if dst.Kind() != reflect.Ptr && dst.Kind() != reflect.Interface { + return fmt.Errorf("abi: cannot unmarshal %v into %v", src.Type(), dst.Type()) + } + return nil +} diff --git a/accounts/abi/unpack.go b/accounts/abi/unpack.go index 051fc1916..5adb91ff7 100644 --- a/accounts/abi/unpack.go +++ b/accounts/abi/unpack.go @@ -202,4 +202,4 @@ func lengthPrefixPointsTo(index int, output []byte) (start int, length int, err //fmt.Printf("LENGTH PREFIX INFO: \nsize: %v\noffset: %v\nstart: %v\n", length, offset, start) return -} +}
\ No newline at end of file |