Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
G
Geth-Modification
Project
Project
Details
Activity
Releases
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
张蕾
Geth-Modification
Commits
25931f12
Commit
25931f12
authored
May 12, 2016
by
Péter Szilágyi
Browse files
Options
Browse Files
Download
Plain Diff
Merge pull request #2551 from obscuren/abi-interface-slice-fix
accounts/abi: fixed unpacking in to already sliced interfaces
parents
d89e57ea
91a7a4a7
Changes
3
Hide whitespace changes
Inline
Side-by-side
Showing
3 changed files
with
94 additions
and
31 deletions
+94
-31
abi.go
accounts/abi/abi.go
+29
-30
abi_test.go
accounts/abi/abi_test.go
+31
-0
reflect.go
accounts/abi/reflect.go
+34
-1
No files found.
accounts/abi/abi.go
View file @
25931f12
...
@@ -238,8 +238,16 @@ func (abi ABI) Unpack(v interface{}, name string, output []byte) error {
...
@@ -238,8 +238,16 @@ func (abi ABI) Unpack(v interface{}, name string, output []byte) error {
return
fmt
.
Errorf
(
"abi: unmarshalling empty output"
)
return
fmt
.
Errorf
(
"abi: unmarshalling empty output"
)
}
}
value
:=
reflect
.
ValueOf
(
v
)
.
Elem
()
// make sure the passed value is a pointer
typ
:=
value
.
Type
()
valueOf
:=
reflect
.
ValueOf
(
v
)
if
reflect
.
Ptr
!=
valueOf
.
Kind
()
{
return
fmt
.
Errorf
(
"abi: Unpack(non-pointer %T)"
,
v
)
}
var
(
value
=
valueOf
.
Elem
()
typ
=
value
.
Type
()
)
if
len
(
method
.
Outputs
)
>
1
{
if
len
(
method
.
Outputs
)
>
1
{
switch
value
.
Kind
()
{
switch
value
.
Kind
()
{
...
@@ -268,6 +276,25 @@ func (abi ABI) Unpack(v interface{}, name string, output []byte) error {
...
@@ -268,6 +276,25 @@ func (abi ABI) Unpack(v interface{}, name string, output []byte) error {
return
fmt
.
Errorf
(
"abi: cannot marshal tuple in to slice %T (only []interface{} is supported)"
,
v
)
return
fmt
.
Errorf
(
"abi: cannot marshal tuple in to slice %T (only []interface{} is supported)"
,
v
)
}
}
// if the slice already contains values, set those instead of the interface slice itself.
if
value
.
Len
()
>
0
{
if
len
(
method
.
Outputs
)
>
value
.
Len
()
{
return
fmt
.
Errorf
(
"abi: cannot marshal in to slices of unequal size (require: %v, got: %v)"
,
len
(
method
.
Outputs
),
value
.
Len
())
}
for
i
:=
0
;
i
<
len
(
method
.
Outputs
);
i
++
{
marshalledValue
,
err
:=
toGoType
(
i
,
method
.
Outputs
[
i
],
output
)
if
err
!=
nil
{
return
err
}
reflectValue
:=
reflect
.
ValueOf
(
marshalledValue
)
if
err
:=
set
(
value
.
Index
(
i
)
.
Elem
(),
reflectValue
,
method
.
Outputs
[
i
]);
err
!=
nil
{
return
err
}
}
return
nil
}
// create a new slice and start appending the unmarshalled
// create a new slice and start appending the unmarshalled
// values to the new interface slice.
// values to the new interface slice.
z
:=
reflect
.
MakeSlice
(
typ
,
0
,
len
(
method
.
Outputs
))
z
:=
reflect
.
MakeSlice
(
typ
,
0
,
len
(
method
.
Outputs
))
...
@@ -296,34 +323,6 @@ func (abi ABI) Unpack(v interface{}, name string, output []byte) error {
...
@@ -296,34 +323,6 @@ func (abi ABI) Unpack(v interface{}, name string, output []byte) error {
return
nil
return
nil
}
}
// set attempts to assign src to dst by either setting, copying or otherwise.
//
// set is a bit more lenient when it comes to assignment and doesn't force an as
// strict ruleset as bare `reflect` does.
func
set
(
dst
,
src
reflect
.
Value
,
output
Argument
)
error
{
dstType
:=
dst
.
Type
()
srcType
:=
src
.
Type
()
switch
{
case
dstType
.
AssignableTo
(
src
.
Type
())
:
dst
.
Set
(
src
)
case
dstType
.
Kind
()
==
reflect
.
Array
&&
srcType
.
Kind
()
==
reflect
.
Slice
:
if
!
dstType
.
Elem
()
.
AssignableTo
(
r_byte
)
{
return
fmt
.
Errorf
(
"abi: cannot unmarshal %v in to array of elem %v"
,
src
.
Type
(),
dstType
.
Elem
())
}
if
dst
.
Len
()
<
output
.
Type
.
SliceSize
{
return
fmt
.
Errorf
(
"abi: cannot unmarshal src (len=%d) in to dst (len=%d)"
,
output
.
Type
.
SliceSize
,
dst
.
Len
())
}
reflect
.
Copy
(
dst
,
src
)
case
dstType
.
Kind
()
==
reflect
.
Interface
:
dst
.
Set
(
src
)
default
:
return
fmt
.
Errorf
(
"abi: cannot unmarshal %v in to %v"
,
src
.
Type
(),
dst
.
Type
())
}
return
nil
}
func
(
abi
*
ABI
)
UnmarshalJSON
(
data
[]
byte
)
error
{
func
(
abi
*
ABI
)
UnmarshalJSON
(
data
[]
byte
)
error
{
var
fields
[]
struct
{
var
fields
[]
struct
{
Type
string
Type
string
...
...
accounts/abi/abi_test.go
View file @
25931f12
...
@@ -289,6 +289,37 @@ func TestSimpleMethodUnpack(t *testing.T) {
...
@@ -289,6 +289,37 @@ func TestSimpleMethodUnpack(t *testing.T) {
}
}
}
}
func
TestUnpackSetInterfaceSlice
(
t
*
testing
.
T
)
{
var
(
var1
=
new
(
uint8
)
var2
=
new
(
uint8
)
)
out
:=
[]
interface
{}{
var1
,
var2
}
abi
,
err
:=
JSON
(
strings
.
NewReader
(
`[{"type":"function", "name":"ints", "outputs":[{"type":"uint8"}, {"type":"uint8"}]}]`
))
if
err
!=
nil
{
t
.
Fatal
(
err
)
}
marshalledReturn
:=
append
(
pad
([]
byte
{
1
},
32
,
true
),
pad
([]
byte
{
2
},
32
,
true
)
...
)
err
=
abi
.
Unpack
(
&
out
,
"ints"
,
marshalledReturn
)
if
err
!=
nil
{
t
.
Fatal
(
err
)
}
if
*
var1
!=
1
{
t
.
Errorf
(
"expected var1 to be 1, got"
,
*
var1
)
}
if
*
var2
!=
2
{
t
.
Errorf
(
"expected var2 to be 2, got"
,
*
var2
)
}
out
=
[]
interface
{}{
var1
}
err
=
abi
.
Unpack
(
&
out
,
"ints"
,
marshalledReturn
)
expErr
:=
"abi: cannot marshal in to slices of unequal size (require: 2, got: 1)"
if
err
==
nil
||
err
.
Error
()
!=
expErr
{
t
.
Error
(
"expected err:"
,
expErr
,
"Got:"
,
err
)
}
}
func
TestPack
(
t
*
testing
.
T
)
{
func
TestPack
(
t
*
testing
.
T
)
{
for
i
,
test
:=
range
[]
struct
{
for
i
,
test
:=
range
[]
struct
{
typ
string
typ
string
...
...
accounts/abi/reflect.go
View file @
25931f12
...
@@ -16,7 +16,10 @@
...
@@ -16,7 +16,10 @@
package
abi
package
abi
import
"reflect"
import
(
"fmt"
"reflect"
)
// indirect recursively dereferences the value until it either gets the value
// indirect recursively dereferences the value until it either gets the value
// or finds a big.Int
// or finds a big.Int
...
@@ -62,3 +65,33 @@ func mustArrayToByteSlice(value reflect.Value) reflect.Value {
...
@@ -62,3 +65,33 @@ func mustArrayToByteSlice(value reflect.Value) reflect.Value {
reflect
.
Copy
(
slice
,
value
)
reflect
.
Copy
(
slice
,
value
)
return
slice
return
slice
}
}
// set attempts to assign src to dst by either setting, copying or otherwise.
//
// set is a bit more lenient when it comes to assignment and doesn't force an as
// strict ruleset as bare `reflect` does.
func
set
(
dst
,
src
reflect
.
Value
,
output
Argument
)
error
{
dstType
:=
dst
.
Type
()
srcType
:=
src
.
Type
()
switch
{
case
dstType
.
AssignableTo
(
src
.
Type
())
:
dst
.
Set
(
src
)
case
dstType
.
Kind
()
==
reflect
.
Array
&&
srcType
.
Kind
()
==
reflect
.
Slice
:
if
!
dstType
.
Elem
()
.
AssignableTo
(
r_byte
)
{
return
fmt
.
Errorf
(
"abi: cannot unmarshal %v in to array of elem %v"
,
src
.
Type
(),
dstType
.
Elem
())
}
if
dst
.
Len
()
<
output
.
Type
.
SliceSize
{
return
fmt
.
Errorf
(
"abi: cannot unmarshal src (len=%d) in to dst (len=%d)"
,
output
.
Type
.
SliceSize
,
dst
.
Len
())
}
reflect
.
Copy
(
dst
,
src
)
case
dstType
.
Kind
()
==
reflect
.
Interface
:
dst
.
Set
(
src
)
case
dstType
.
Kind
()
==
reflect
.
Ptr
:
return
set
(
dst
.
Elem
(),
src
,
output
)
default
:
return
fmt
.
Errorf
(
"abi: cannot unmarshal %v in to %v"
,
src
.
Type
(),
dst
.
Type
())
}
return
nil
}
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment