Skip to content
This repository was archived by the owner on Aug 2, 2021. It is now read-only.

Commit 299d65f

Browse files
committed
Merge branch 'master' into swarm-network-rewrite
2 parents 3aa08b9 + 1e457b6 commit 299d65f

31 files changed

+303
-2972
lines changed

README.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ Official golang implementation of the Ethereum protocol.
55
[![API Reference](
66
https://assets-git-camo.f3mw1.com/915b7be44ada53c290eb157634330494ebe3e30a/68747470733a2f2f676f646f632e6f72672f6769746875622e636f6d2f676f6c616e672f6764646f3f7374617475732e737667
77
)](https://godoc.org/github.com/ethereum/go-ethereum)
8+
[![Go Report Card](https://goreportcard.com/badge/github.com/ethereum/go-ethereum)](https://goreportcard.com/report/github.com/ethereum/go-ethereum)
89
[![Gitter](https://badges.gitter.im/Join%20Chat.svg)](https://gitter.im/ethereum/go-ethereum?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge)
910

1011
Automated builds are available for stable releases and the unstable master branch.

accounts/abi/abi.go

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -136,11 +136,11 @@ func (abi *ABI) UnmarshalJSON(data []byte) error {
136136

137137
// MethodById looks up a method by the 4-byte id
138138
// returns nil if none found
139-
func (abi *ABI) MethodById(sigdata []byte) *Method {
139+
func (abi *ABI) MethodById(sigdata []byte) (*Method, error) {
140140
for _, method := range abi.Methods {
141141
if bytes.Equal(method.Id(), sigdata[:4]) {
142-
return &method
142+
return &method, nil
143143
}
144144
}
145-
return nil
145+
return nil, fmt.Errorf("no method with id: %#x", sigdata[:4])
146146
}

accounts/abi/abi_test.go

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -689,7 +689,11 @@ func TestABI_MethodById(t *testing.T) {
689689
}
690690
for name, m := range abi.Methods {
691691
a := fmt.Sprintf("%v", m)
692-
b := fmt.Sprintf("%v", abi.MethodById(m.Id()))
692+
m2, err := abi.MethodById(m.Id())
693+
if err != nil {
694+
t.Fatalf("Failed to look up ABI method: %v", err)
695+
}
696+
b := fmt.Sprintf("%v", m2)
693697
if a != b {
694698
t.Errorf("Method %v (id %v) not 'findable' by id in ABI", name, common.ToHex(m.Id()))
695699
}

accounts/abi/argument.go

Lines changed: 60 additions & 50 deletions
Original file line numberDiff line numberDiff line change
@@ -67,28 +67,43 @@ func (arguments Arguments) LengthNonIndexed() int {
6767
return out
6868
}
6969

70+
// NonIndexed returns the arguments with indexed arguments filtered out
71+
func (arguments Arguments) NonIndexed() Arguments {
72+
var ret []Argument
73+
for _, arg := range arguments {
74+
if !arg.Indexed {
75+
ret = append(ret, arg)
76+
}
77+
}
78+
return ret
79+
}
80+
7081
// isTuple returns true for non-atomic constructs, like (uint,uint) or uint[]
7182
func (arguments Arguments) isTuple() bool {
7283
return len(arguments) > 1
7384
}
7485

7586
// Unpack performs the operation hexdata -> Go format
7687
func (arguments Arguments) Unpack(v interface{}, data []byte) error {
77-
if arguments.isTuple() {
78-
return arguments.unpackTuple(v, data)
79-
}
80-
return arguments.unpackAtomic(v, data)
81-
}
8288

83-
func (arguments Arguments) unpackTuple(v interface{}, output []byte) error {
8489
// make sure the passed value is arguments pointer
85-
valueOf := reflect.ValueOf(v)
86-
if reflect.Ptr != valueOf.Kind() {
90+
if reflect.Ptr != reflect.ValueOf(v).Kind() {
8791
return fmt.Errorf("abi: Unpack(non-pointer %T)", v)
8892
}
93+
marshalledValues, err := arguments.UnpackValues(data)
94+
if err != nil {
95+
return err
96+
}
97+
if arguments.isTuple() {
98+
return arguments.unpackTuple(v, marshalledValues)
99+
}
100+
return arguments.unpackAtomic(v, marshalledValues)
101+
}
102+
103+
func (arguments Arguments) unpackTuple(v interface{}, marshalledValues []interface{}) error {
89104

90105
var (
91-
value = valueOf.Elem()
106+
value = reflect.ValueOf(v).Elem()
92107
typ = value.Type()
93108
kind = value.Kind()
94109
)
@@ -110,30 +125,9 @@ func (arguments Arguments) unpackTuple(v interface{}, output []byte) error {
110125
exists[field] = true
111126
}
112127
}
113-
// `i` counts the nonindexed arguments.
114-
// `j` counts the number of complex types.
115-
// both `i` and `j` are used to to correctly compute `data` offset.
128+
for i, arg := range arguments.NonIndexed() {
116129

117-
i, j := -1, 0
118-
for _, arg := range arguments {
119-
120-
if arg.Indexed {
121-
// can't read, continue
122-
continue
123-
}
124-
i++
125-
marshalledValue, err := toGoType((i+j)*32, arg.Type, output)
126-
if err != nil {
127-
return err
128-
}
129-
130-
if arg.Type.T == ArrayTy {
131-
// combined index ('i' + 'j') need to be adjusted only by size of array, thus
132-
// we need to decrement 'j' because 'i' was incremented
133-
j += arg.Type.Size - 1
134-
}
135-
136-
reflectValue := reflect.ValueOf(marshalledValue)
130+
reflectValue := reflect.ValueOf(marshalledValues[i])
137131

138132
switch kind {
139133
case reflect.Struct:
@@ -166,34 +160,52 @@ func (arguments Arguments) unpackTuple(v interface{}, output []byte) error {
166160
}
167161

168162
// unpackAtomic unpacks ( hexdata -> go ) a single value
169-
func (arguments Arguments) unpackAtomic(v interface{}, output []byte) error {
170-
// make sure the passed value is arguments pointer
171-
valueOf := reflect.ValueOf(v)
172-
if reflect.Ptr != valueOf.Kind() {
173-
return fmt.Errorf("abi: Unpack(non-pointer %T)", v)
174-
}
175-
arg := arguments[0]
176-
if arg.Indexed {
177-
return fmt.Errorf("abi: attempting to unpack indexed variable into element.")
163+
func (arguments Arguments) unpackAtomic(v interface{}, marshalledValues []interface{}) error {
164+
if len(marshalledValues) != 1 {
165+
return fmt.Errorf("abi: wrong length, expected single value, got %d", len(marshalledValues))
178166
}
167+
elem := reflect.ValueOf(v).Elem()
168+
reflectValue := reflect.ValueOf(marshalledValues[0])
169+
return set(elem, reflectValue, arguments.NonIndexed()[0])
170+
}
179171

180-
value := valueOf.Elem()
172+
// UnpackValues can be used to unpack ABI-encoded hexdata according to the ABI-specification,
173+
// without supplying a struct to unpack into. Instead, this method returns a list containing the
174+
// values. An atomic argument will be a list with one element.
175+
func (arguments Arguments) UnpackValues(data []byte) ([]interface{}, error) {
176+
retval := make([]interface{}, 0, arguments.LengthNonIndexed())
177+
virtualArgs := 0
178+
for index, arg := range arguments.NonIndexed() {
179+
marshalledValue, err := toGoType((index+virtualArgs)*32, arg.Type, data)
180+
if arg.Type.T == ArrayTy {
181+
// If we have a static array, like [3]uint256, these are coded as
182+
// just like uint256,uint256,uint256.
183+
// This means that we need to add two 'virtual' arguments when
184+
// we count the index from now on
181185

182-
marshalledValue, err := toGoType(0, arg.Type, output)
183-
if err != nil {
184-
return err
186+
virtualArgs += arg.Type.Size - 1
187+
}
188+
if err != nil {
189+
return nil, err
190+
}
191+
retval = append(retval, marshalledValue)
185192
}
186-
return set(value, reflect.ValueOf(marshalledValue), arg)
193+
return retval, nil
187194
}
188195

189-
// Unpack performs the operation Go format -> Hexdata
196+
// PackValues performs the operation Go format -> Hexdata
197+
// It is the semantic opposite of UnpackValues
198+
func (arguments Arguments) PackValues(args []interface{}) ([]byte, error) {
199+
return arguments.Pack(args...)
200+
}
201+
202+
// Pack performs the operation Go format -> Hexdata
190203
func (arguments Arguments) Pack(args ...interface{}) ([]byte, error) {
191204
// Make sure arguments match up and pack them
192205
abiArgs := arguments
193206
if len(args) != len(abiArgs) {
194207
return nil, fmt.Errorf("argument count mismatch: %d for %d", len(args), len(abiArgs))
195208
}
196-
197209
// variable input is the output appended at the end of packed
198210
// output. This is used for strings and bytes types input.
199211
var variableInput []byte
@@ -207,7 +219,6 @@ func (arguments Arguments) Pack(args ...interface{}) ([]byte, error) {
207219
inputOffset += 32
208220
}
209221
}
210-
211222
var ret []byte
212223
for i, a := range args {
213224
input := abiArgs[i]
@@ -216,7 +227,6 @@ func (arguments Arguments) Pack(args ...interface{}) ([]byte, error) {
216227
if err != nil {
217228
return nil, err
218229
}
219-
220230
// check for a slice type (string, bytes, slice)
221231
if input.Type.requiresLengthPrefix() {
222232
// calculate the offset

accounts/abi/unpack.go

Lines changed: 27 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -95,6 +95,9 @@ func readFixedBytes(t Type, word []byte) (interface{}, error) {
9595

9696
// iteratively unpack elements
9797
func forEachUnpack(t Type, output []byte, start, size int) (interface{}, error) {
98+
if size < 0 {
99+
return nil, fmt.Errorf("cannot marshal input to array, size is negative (%d)", size)
100+
}
98101
if start+32*size > len(output) {
99102
return nil, fmt.Errorf("abi: cannot marshal in to go array: offset %d would go over slice boundary (len=%d)", len(output), start+32*size)
100103
}
@@ -181,16 +184,32 @@ func toGoType(index int, t Type, output []byte) (interface{}, error) {
181184

182185
// interprets a 32 byte slice as an offset and then determines which indice to look to decode the type.
183186
func lengthPrefixPointsTo(index int, output []byte) (start int, length int, err error) {
184-
offset := int(binary.BigEndian.Uint64(output[index+24 : index+32]))
185-
if offset+32 > len(output) {
186-
return 0, 0, fmt.Errorf("abi: cannot marshal in to go slice: offset %d would go over slice boundary (len=%d)", len(output), offset+32)
187+
bigOffsetEnd := big.NewInt(0).SetBytes(output[index : index+32])
188+
bigOffsetEnd.Add(bigOffsetEnd, common.Big32)
189+
outputLength := big.NewInt(int64(len(output)))
190+
191+
if bigOffsetEnd.Cmp(outputLength) > 0 {
192+
return 0, 0, fmt.Errorf("abi: cannot marshal in to go slice: offset %v would go over slice boundary (len=%v)", bigOffsetEnd, outputLength)
187193
}
188-
length = int(binary.BigEndian.Uint64(output[offset+24 : offset+32]))
189-
if offset+32+length > len(output) {
190-
return 0, 0, fmt.Errorf("abi: cannot marshal in to go type: length insufficient %d require %d", len(output), offset+32+length)
194+
195+
if bigOffsetEnd.BitLen() > 63 {
196+
return 0, 0, fmt.Errorf("abi offset larger than int64: %v", bigOffsetEnd)
191197
}
192-
start = offset + 32
193198

194-
//fmt.Printf("LENGTH PREFIX INFO: \nsize: %v\noffset: %v\nstart: %v\n", length, offset, start)
199+
offsetEnd := int(bigOffsetEnd.Uint64())
200+
lengthBig := big.NewInt(0).SetBytes(output[offsetEnd-32 : offsetEnd])
201+
202+
totalSize := big.NewInt(0)
203+
totalSize.Add(totalSize, bigOffsetEnd)
204+
totalSize.Add(totalSize, lengthBig)
205+
if totalSize.BitLen() > 63 {
206+
return 0, 0, fmt.Errorf("abi length larger than int64: %v", totalSize)
207+
}
208+
209+
if totalSize.Cmp(outputLength) > 0 {
210+
return 0, 0, fmt.Errorf("abi: cannot marshal in to go type: length insufficient %v require %v", outputLength, totalSize)
211+
}
212+
start = int(bigOffsetEnd.Uint64())
213+
length = int(lengthBig.Uint64())
195214
return
196215
}

accounts/abi/unpack_test.go

Lines changed: 71 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -130,7 +130,7 @@ var unpackTests = []unpackTest{
130130
{
131131
def: `[{"type": "bytes32"}]`,
132132
enc: "0100000000000000000000000000000000000000000000000000000000000000",
133-
want: common.HexToHash("0100000000000000000000000000000000000000000000000000000000000000"),
133+
want: [32]byte{1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
134134
},
135135
{
136136
def: `[{"type": "function"}]`,
@@ -683,3 +683,73 @@ func TestUnmarshal(t *testing.T) {
683683
t.Fatal("expected error:", err)
684684
}
685685
}
686+
687+
func TestOOMMaliciousInput(t *testing.T) {
688+
oomTests := []unpackTest{
689+
{
690+
def: `[{"type": "uint8[]"}]`,
691+
enc: "0000000000000000000000000000000000000000000000000000000000000020" + // offset
692+
"0000000000000000000000000000000000000000000000000000000000000003" + // num elems
693+
"0000000000000000000000000000000000000000000000000000000000000001" + // elem 1
694+
"0000000000000000000000000000000000000000000000000000000000000002", // elem 2
695+
},
696+
{ // Length larger than 64 bits
697+
def: `[{"type": "uint8[]"}]`,
698+
enc: "0000000000000000000000000000000000000000000000000000000000000020" + // offset
699+
"00ffffffffffffffffffffffffffffffffffffffffffffff0000000000000002" + // num elems
700+
"0000000000000000000000000000000000000000000000000000000000000001" + // elem 1
701+
"0000000000000000000000000000000000000000000000000000000000000002", // elem 2
702+
},
703+
{ // Offset very large (over 64 bits)
704+
def: `[{"type": "uint8[]"}]`,
705+
enc: "00ffffffffffffffffffffffffffffffffffffffffffffff0000000000000020" + // offset
706+
"0000000000000000000000000000000000000000000000000000000000000002" + // num elems
707+
"0000000000000000000000000000000000000000000000000000000000000001" + // elem 1
708+
"0000000000000000000000000000000000000000000000000000000000000002", // elem 2
709+
},
710+
{ // Offset very large (below 64 bits)
711+
def: `[{"type": "uint8[]"}]`,
712+
enc: "0000000000000000000000000000000000000000000000007ffffffffff00020" + // offset
713+
"0000000000000000000000000000000000000000000000000000000000000002" + // num elems
714+
"0000000000000000000000000000000000000000000000000000000000000001" + // elem 1
715+
"0000000000000000000000000000000000000000000000000000000000000002", // elem 2
716+
},
717+
{ // Offset negative (as 64 bit)
718+
def: `[{"type": "uint8[]"}]`,
719+
enc: "000000000000000000000000000000000000000000000000f000000000000020" + // offset
720+
"0000000000000000000000000000000000000000000000000000000000000002" + // num elems
721+
"0000000000000000000000000000000000000000000000000000000000000001" + // elem 1
722+
"0000000000000000000000000000000000000000000000000000000000000002", // elem 2
723+
},
724+
725+
{ // Negative length
726+
def: `[{"type": "uint8[]"}]`,
727+
enc: "0000000000000000000000000000000000000000000000000000000000000020" + // offset
728+
"000000000000000000000000000000000000000000000000f000000000000002" + // num elems
729+
"0000000000000000000000000000000000000000000000000000000000000001" + // elem 1
730+
"0000000000000000000000000000000000000000000000000000000000000002", // elem 2
731+
},
732+
{ // Very large length
733+
def: `[{"type": "uint8[]"}]`,
734+
enc: "0000000000000000000000000000000000000000000000000000000000000020" + // offset
735+
"0000000000000000000000000000000000000000000000007fffffffff000002" + // num elems
736+
"0000000000000000000000000000000000000000000000000000000000000001" + // elem 1
737+
"0000000000000000000000000000000000000000000000000000000000000002", // elem 2
738+
},
739+
}
740+
for i, test := range oomTests {
741+
def := fmt.Sprintf(`[{ "name" : "method", "outputs": %s}]`, test.def)
742+
abi, err := JSON(strings.NewReader(def))
743+
if err != nil {
744+
t.Fatalf("invalid ABI definition %s: %v", def, err)
745+
}
746+
encb, err := hex.DecodeString(test.enc)
747+
if err != nil {
748+
t.Fatalf("invalid hex: %s" + test.enc)
749+
}
750+
_, err = abi.Methods["method"].Outputs.UnpackValues(encb)
751+
if err == nil {
752+
t.Fatalf("Expected error on malicious input, test %d", i)
753+
}
754+
}
755+
}

cmd/geth/consolecmd.go

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ import (
2222
"os/signal"
2323
"path/filepath"
2424
"strings"
25+
"syscall"
2526

2627
"github.com/ethereum/go-ethereum/cmd/utils"
2728
"github.com/ethereum/go-ethereum/console"
@@ -207,7 +208,7 @@ func ephemeralConsole(ctx *cli.Context) error {
207208
}
208209
// Wait for pending callbacks, but stop for Ctrl-C.
209210
abort := make(chan os.Signal, 1)
210-
signal.Notify(abort, os.Interrupt)
211+
signal.Notify(abort, syscall.SIGINT, syscall.SIGTERM)
211212

212213
go func() {
213214
<-abort

cmd/puppeth/wizard_intro.go

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -59,15 +59,16 @@ func (w *wizard) run() {
5959
fmt.Println()
6060

6161
// Make sure we have a good network name to work with fmt.Println()
62+
// Docker accepts hyphens in image names, but doesn't like it for container names
6263
if w.network == "" {
63-
fmt.Println("Please specify a network name to administer (no spaces, please)")
64+
fmt.Println("Please specify a network name to administer (no spaces or hyphens, please)")
6465
for {
6566
w.network = w.readString()
66-
if !strings.Contains(w.network, " ") {
67+
if !strings.Contains(w.network, " ") && !strings.Contains(w.network, "-") {
6768
fmt.Printf("\nSweet, you can set this via --network=%s next time!\n\n", w.network)
6869
break
6970
}
70-
log.Error("I also like to live dangerously, still no spaces")
71+
log.Error("I also like to live dangerously, still no spaces or hyphens")
7172
}
7273
}
7374
log.Info("Administering Ethereum network", "name", w.network)

0 commit comments

Comments
 (0)