From 5f6f5e345ea3fd19d031cb2ae3c8d2894e51639e Mon Sep 17 00:00:00 2001 From: Guillaume Ballet Date: Tue, 2 Jun 2020 18:06:22 +0200 Subject: [PATCH] console: handle undefined + null in console funcs (#21160) --- console/bridge.go | 18 +++++++++------- console/bridge_test.go | 48 ++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 58 insertions(+), 8 deletions(-) create mode 100644 console/bridge_test.go diff --git a/console/bridge.go b/console/bridge.go index b35f56f3b2..ace8aeeba0 100644 --- a/console/bridge.go +++ b/console/bridge.go @@ -233,11 +233,12 @@ func (b *bridge) UnlockAccount(call jsre.Call) (goja.Value, error) { if len(call.Arguments) < 1 { return nil, fmt.Errorf("usage: unlockAccount(account, [ password, duration ])") } + + account := call.Argument(0) // Make sure we have an account specified to unlock. - if call.Argument(0).ExportType().Kind() != reflect.String { + if goja.IsUndefined(account) || goja.IsNull(account) || account.ExportType().Kind() != reflect.String { return nil, fmt.Errorf("first argument must be the account to unlock") } - account := call.Argument(0) // If password is not given or is the null value, prompt the user for it. var passwd goja.Value @@ -285,10 +286,10 @@ func (b *bridge) Sign(call jsre.Call) (goja.Value, error) { passwd = call.Argument(2) ) - if message.ExportType().Kind() != reflect.String { + if goja.IsUndefined(message) || message.ExportType().Kind() != reflect.String { return nil, fmt.Errorf("first argument must be the message to sign") } - if account.ExportType().Kind() != reflect.String { + if goja.IsUndefined(account) || account.ExportType().Kind() != reflect.String { return nil, fmt.Errorf("second argument must be the account to sign with") } @@ -317,10 +318,11 @@ func (b *bridge) Sleep(call jsre.Call) (goja.Value, error) { if nArgs := len(call.Arguments); nArgs < 1 { return nil, fmt.Errorf("usage: sleep()") } - if !isNumber(call.Argument(0)) { + sleepObj := call.Argument(0) + if goja.IsUndefined(sleepObj) || goja.IsNull(sleepObj) || !isNumber(sleepObj) { return nil, fmt.Errorf("usage: sleep()") } - sleep := call.Argument(0).ToFloat() + sleep := sleepObj.ToFloat() time.Sleep(time.Duration(sleep * float64(time.Second))) return call.VM.ToValue(true), nil } @@ -338,13 +340,13 @@ func (b *bridge) SleepBlocks(call jsre.Call) (goja.Value, error) { return nil, fmt.Errorf("usage: sleepBlocks([, max sleep in seconds])") } if nArgs >= 1 { - if !isNumber(call.Argument(0)) { + if goja.IsNull(call.Argument(0)) || goja.IsUndefined(call.Argument(0)) || !isNumber(call.Argument(0)) { return nil, fmt.Errorf("expected number as first argument") } blocks = call.Argument(0).ToInteger() } if nArgs >= 2 { - if !isNumber(call.Argument(1)) { + if goja.IsNull(call.Argument(1)) || goja.IsUndefined(call.Argument(1)) || !isNumber(call.Argument(1)) { return nil, fmt.Errorf("expected number as second argument") } sleep = call.Argument(1).ToInteger() diff --git a/console/bridge_test.go b/console/bridge_test.go new file mode 100644 index 0000000000..e57e294fc5 --- /dev/null +++ b/console/bridge_test.go @@ -0,0 +1,48 @@ +// Copyright 2020 The go-ethereum Authors +// This file is part of the go-ethereum library. +// +// The go-ethereum library is free software: you can redistribute it and/or modify +// it under the terms of the GNU Lesser General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// The go-ethereum library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public License +// along with the go-ethereum library. If not, see . + +package console + +import ( + "testing" + + "github.com/dop251/goja" + "github.com/ethereum/go-ethereum/internal/jsre" +) + +// TestUndefinedAsParam ensures that personal functions can receive +// `undefined` as a parameter. +func TestUndefinedAsParam(t *testing.T) { + b := bridge{} + call := jsre.Call{} + call.Arguments = []goja.Value{goja.Undefined()} + + b.UnlockAccount(call) + b.Sign(call) + b.Sleep(call) +} + +// TestNullAsParam ensures that personal functions can receive +// `null` as a parameter. +func TestNullAsParam(t *testing.T) { + b := bridge{} + call := jsre.Call{} + call.Arguments = []goja.Value{goja.Null()} + + b.UnlockAccount(call) + b.Sign(call) + b.Sleep(call) +}