Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix: invoke user recover with implicit panics #3067

Merged
merged 15 commits into from
Nov 22, 2024
7 changes: 7 additions & 0 deletions gnovm/pkg/gnolang/alloc.go
Original file line number Diff line number Diff line change
Expand Up @@ -194,13 +194,20 @@
}

func (alloc *Allocator) NewListArray(n int) *ArrayValue {
if n < 0 {
panic(&Exception{Value: typedString("len out of range")})
}
alloc.AllocateListArray(int64(n))
return &ArrayValue{
List: make([]TypedValue, n),
}
}

func (alloc *Allocator) NewDataArray(n int) *ArrayValue {
if n < 0 {
panic(&Exception{Value: typedString("len out of range")})

Check warning on line 208 in gnovm/pkg/gnolang/alloc.go

View check run for this annotation

Codecov / codecov/patch

gnovm/pkg/gnolang/alloc.go#L208

Added line #L208 was not covered by tests
}

alloc.AllocateDataArray(int64(n))
return &ArrayValue{
Data: make([]byte, n),
Expand Down
2 changes: 1 addition & 1 deletion gnovm/pkg/gnolang/debugger_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -158,7 +158,7 @@ func TestDebug(t *testing.T) {
{in: "up xxx", out: `"xxx": invalid syntax`},
{in: "b 37\nc\np b\n", out: "(3 int)"},
{in: "b 27\nc\np b\n", out: `("!zero" string)`},
{in: "b 22\nc\np t.A[3]\n", out: "Command failed: slice index out of bounds: 3 (len=3)"},
{in: "b 22\nc\np t.A[3]\n", out: "Command failed: &{(\"slice index out of bounds: 3 (len=3)\" string) <nil> }"},
{in: "b 43\nc\nc\nc\np i\ndetach\n", out: "(1 int)"},
})

Expand Down
18 changes: 17 additions & 1 deletion gnovm/pkg/gnolang/machine.go
Original file line number Diff line number Diff line change
Expand Up @@ -829,7 +829,9 @@ func (m *Machine) RunFunc(fn Name) {

func (m *Machine) RunMain() {
defer func() {
if r := recover(); r != nil {
r := recover()

if r != nil {
switch r := r.(type) {
case UnhandledPanicError:
fmt.Printf("Machine.RunMain() panic: %s\nStacktrace: %s\n",
Expand Down Expand Up @@ -1280,6 +1282,20 @@ const (
// main run loop.

func (m *Machine) Run() {
defer func() {
r := recover()

if r != nil {
switch r := r.(type) {
case *Exception:
m.Panic(r.Value)
m.Run()
default:
panic(r)
}
}
}()

for {
if m.Debugger.enabled {
m.Debug()
Expand Down
12 changes: 10 additions & 2 deletions gnovm/pkg/gnolang/op_assign.go
Original file line number Diff line number Diff line change
Expand Up @@ -131,7 +131,11 @@
}
}
// lv /= rv
quoAssign(lv.TV, rv)
err := quoAssign(lv.TV, rv)
petar-dambovaliev marked this conversation as resolved.
Show resolved Hide resolved
if err != nil {
panic(err)

Check warning on line 136 in gnovm/pkg/gnolang/op_assign.go

View check run for this annotation

Codecov / codecov/patch

gnovm/pkg/gnolang/op_assign.go#L136

Added line #L136 was not covered by tests
}

if lv.Base != nil {
m.Realm.DidUpdate(lv.Base.(Object), nil, nil)
}
Expand All @@ -154,7 +158,11 @@
}
}
// lv %= rv
remAssign(lv.TV, rv)
err := remAssign(lv.TV, rv)
if err != nil {
panic(err)

Check warning on line 163 in gnovm/pkg/gnolang/op_assign.go

View check run for this annotation

Codecov / codecov/patch

gnovm/pkg/gnolang/op_assign.go#L163

Added line #L163 was not covered by tests
}

if lv.Base != nil {
m.Realm.DidUpdate(lv.Base.(Object), nil, nil)
}
Expand Down
108 changes: 104 additions & 4 deletions gnovm/pkg/gnolang/op_binary.go
Original file line number Diff line number Diff line change
Expand Up @@ -252,7 +252,10 @@
}

// lv / rv
quoAssign(lv, rv)
err := quoAssign(lv, rv)
if err != nil {
panic(err)
}
}

func (m *Machine) doOpRem() {
Expand All @@ -266,7 +269,10 @@
}

// lv % rv
remAssign(lv, rv)
err := remAssign(lv, rv)
if err != nil {
panic(err)

Check warning on line 274 in gnovm/pkg/gnolang/op_binary.go

View check run for this annotation

Codecov / codecov/patch

gnovm/pkg/gnolang/op_binary.go#L274

Added line #L274 was not covered by tests
}
}

func (m *Machine) doOpShl() {
Expand Down Expand Up @@ -845,45 +851,94 @@
}

// for doOpQuo and doOpQuoAssign.
func quoAssign(lv, rv *TypedValue) {
func quoAssign(lv, rv *TypedValue) *Exception {
expt := &Exception{
Value: typedString("division by zero"),
}

// set the result in lv.
// NOTE this block is replicated in op_assign.go
switch baseOf(lv.T) {
case IntType:
if rv.GetInt() == 0 {
return expt
}
lv.SetInt(lv.GetInt() / rv.GetInt())
case Int8Type:
if rv.GetInt8() == 0 {
return expt
}

Check warning on line 870 in gnovm/pkg/gnolang/op_binary.go

View check run for this annotation

Codecov / codecov/patch

gnovm/pkg/gnolang/op_binary.go#L869-L870

Added lines #L869 - L870 were not covered by tests
lv.SetInt8(lv.GetInt8() / rv.GetInt8())
case Int16Type:
if rv.GetInt16() == 0 {
return expt
}

Check warning on line 875 in gnovm/pkg/gnolang/op_binary.go

View check run for this annotation

Codecov / codecov/patch

gnovm/pkg/gnolang/op_binary.go#L874-L875

Added lines #L874 - L875 were not covered by tests
lv.SetInt16(lv.GetInt16() / rv.GetInt16())
case Int32Type, UntypedRuneType:
if rv.GetInt32() == 0 {
return expt
}

Check warning on line 880 in gnovm/pkg/gnolang/op_binary.go

View check run for this annotation

Codecov / codecov/patch

gnovm/pkg/gnolang/op_binary.go#L879-L880

Added lines #L879 - L880 were not covered by tests
lv.SetInt32(lv.GetInt32() / rv.GetInt32())
case Int64Type:
if rv.GetInt64() == 0 {
return expt
}

Check warning on line 885 in gnovm/pkg/gnolang/op_binary.go

View check run for this annotation

Codecov / codecov/patch

gnovm/pkg/gnolang/op_binary.go#L884-L885

Added lines #L884 - L885 were not covered by tests
lv.SetInt64(lv.GetInt64() / rv.GetInt64())
case UintType:
if rv.GetUint() == 0 {
return expt
}

Check warning on line 890 in gnovm/pkg/gnolang/op_binary.go

View check run for this annotation

Codecov / codecov/patch

gnovm/pkg/gnolang/op_binary.go#L889-L890

Added lines #L889 - L890 were not covered by tests
lv.SetUint(lv.GetUint() / rv.GetUint())
case Uint8Type:
if rv.GetUint8() == 0 {
return expt
}

Check warning on line 895 in gnovm/pkg/gnolang/op_binary.go

View check run for this annotation

Codecov / codecov/patch

gnovm/pkg/gnolang/op_binary.go#L894-L895

Added lines #L894 - L895 were not covered by tests
lv.SetUint8(lv.GetUint8() / rv.GetUint8())
case DataByteType:
if rv.GetUint8() == 0 {
return expt
}

Check warning on line 900 in gnovm/pkg/gnolang/op_binary.go

View check run for this annotation

Codecov / codecov/patch

gnovm/pkg/gnolang/op_binary.go#L899-L900

Added lines #L899 - L900 were not covered by tests
lv.SetDataByte(lv.GetDataByte() / rv.GetUint8())
case Uint16Type:
if rv.GetUint16() == 0 {
return expt
}

Check warning on line 905 in gnovm/pkg/gnolang/op_binary.go

View check run for this annotation

Codecov / codecov/patch

gnovm/pkg/gnolang/op_binary.go#L904-L905

Added lines #L904 - L905 were not covered by tests
lv.SetUint16(lv.GetUint16() / rv.GetUint16())
case Uint32Type:
if rv.GetUint32() == 0 {
return expt
}

Check warning on line 910 in gnovm/pkg/gnolang/op_binary.go

View check run for this annotation

Codecov / codecov/patch

gnovm/pkg/gnolang/op_binary.go#L909-L910

Added lines #L909 - L910 were not covered by tests
lv.SetUint32(lv.GetUint32() / rv.GetUint32())
case Uint64Type:
if rv.GetUint64() == 0 {
return expt
}

Check warning on line 915 in gnovm/pkg/gnolang/op_binary.go

View check run for this annotation

Codecov / codecov/patch

gnovm/pkg/gnolang/op_binary.go#L914-L915

Added lines #L914 - L915 were not covered by tests
lv.SetUint64(lv.GetUint64() / rv.GetUint64())
case Float32Type:
// NOTE: gno doesn't fuse *+.
if rv.GetFloat32() == 0 {
return expt
}

Check warning on line 921 in gnovm/pkg/gnolang/op_binary.go

View check run for this annotation

Codecov / codecov/patch

gnovm/pkg/gnolang/op_binary.go#L919-L921

Added lines #L919 - L921 were not covered by tests
lv.SetFloat32(lv.GetFloat32() / rv.GetFloat32())
// XXX FOR DETERMINISM, PANIC IF NAN.
case Float64Type:
// NOTE: gno doesn't fuse *+.
if rv.GetFloat64() == 0 {
return expt
}

Check warning on line 928 in gnovm/pkg/gnolang/op_binary.go

View check run for this annotation

Codecov / codecov/patch

gnovm/pkg/gnolang/op_binary.go#L927-L928

Added lines #L927 - L928 were not covered by tests
lv.SetFloat64(lv.GetFloat64() / rv.GetFloat64())
// XXX FOR DETERMINISM, PANIC IF NAN.
case BigintType, UntypedBigintType:
if rv.GetBigInt().Sign() == 0 {
return expt
}

Check warning on line 934 in gnovm/pkg/gnolang/op_binary.go

View check run for this annotation

Codecov / codecov/patch

gnovm/pkg/gnolang/op_binary.go#L933-L934

Added lines #L933 - L934 were not covered by tests
lb := lv.GetBigInt()
lb = big.NewInt(0).Quo(lb, rv.GetBigInt())
lv.V = BigintValue{V: lb}
case BigdecType, UntypedBigdecType:
if rv.GetBigDec().Cmp(apd.New(0, 0)) == 0 {
return expt
}

Check warning on line 941 in gnovm/pkg/gnolang/op_binary.go

View check run for this annotation

Codecov / codecov/patch

gnovm/pkg/gnolang/op_binary.go#L940-L941

Added lines #L940 - L941 were not covered by tests
lb := lv.GetBigDec()
rb := rv.GetBigDec()
quo := apd.New(0, 0)
Expand All @@ -898,36 +953,79 @@
lv.T,
))
}

return nil
}

// for doOpRem and doOpRemAssign.
func remAssign(lv, rv *TypedValue) {
func remAssign(lv, rv *TypedValue) *Exception {
expt := &Exception{
Value: typedString("division by zero"),
}

// set the result in lv.
// NOTE this block is replicated in op_assign.go
switch baseOf(lv.T) {
case IntType:
if rv.GetInt() == 0 {
return expt
}

Check warning on line 972 in gnovm/pkg/gnolang/op_binary.go

View check run for this annotation

Codecov / codecov/patch

gnovm/pkg/gnolang/op_binary.go#L971-L972

Added lines #L971 - L972 were not covered by tests
lv.SetInt(lv.GetInt() % rv.GetInt())
case Int8Type:
if rv.GetInt8() == 0 {
return expt
}

Check warning on line 977 in gnovm/pkg/gnolang/op_binary.go

View check run for this annotation

Codecov / codecov/patch

gnovm/pkg/gnolang/op_binary.go#L976-L977

Added lines #L976 - L977 were not covered by tests
lv.SetInt8(lv.GetInt8() % rv.GetInt8())
case Int16Type:
if rv.GetInt16() == 0 {
return expt
}

Check warning on line 982 in gnovm/pkg/gnolang/op_binary.go

View check run for this annotation

Codecov / codecov/patch

gnovm/pkg/gnolang/op_binary.go#L981-L982

Added lines #L981 - L982 were not covered by tests
lv.SetInt16(lv.GetInt16() % rv.GetInt16())
case Int32Type, UntypedRuneType:
if rv.GetInt32() == 0 {
return expt
}

Check warning on line 987 in gnovm/pkg/gnolang/op_binary.go

View check run for this annotation

Codecov / codecov/patch

gnovm/pkg/gnolang/op_binary.go#L986-L987

Added lines #L986 - L987 were not covered by tests
lv.SetInt32(lv.GetInt32() % rv.GetInt32())
case Int64Type:
if rv.GetInt64() == 0 {
return expt
}

Check warning on line 992 in gnovm/pkg/gnolang/op_binary.go

View check run for this annotation

Codecov / codecov/patch

gnovm/pkg/gnolang/op_binary.go#L991-L992

Added lines #L991 - L992 were not covered by tests
lv.SetInt64(lv.GetInt64() % rv.GetInt64())
case UintType:
if rv.GetUint() == 0 {
return expt
}

Check warning on line 997 in gnovm/pkg/gnolang/op_binary.go

View check run for this annotation

Codecov / codecov/patch

gnovm/pkg/gnolang/op_binary.go#L996-L997

Added lines #L996 - L997 were not covered by tests
lv.SetUint(lv.GetUint() % rv.GetUint())
case Uint8Type:
if rv.GetUint8() == 0 {
return expt
}

Check warning on line 1002 in gnovm/pkg/gnolang/op_binary.go

View check run for this annotation

Codecov / codecov/patch

gnovm/pkg/gnolang/op_binary.go#L1001-L1002

Added lines #L1001 - L1002 were not covered by tests
lv.SetUint8(lv.GetUint8() % rv.GetUint8())
case DataByteType:
if rv.GetUint8() == 0 {
return expt
}

Check warning on line 1007 in gnovm/pkg/gnolang/op_binary.go

View check run for this annotation

Codecov / codecov/patch

gnovm/pkg/gnolang/op_binary.go#L1006-L1007

Added lines #L1006 - L1007 were not covered by tests
lv.SetDataByte(lv.GetDataByte() % rv.GetUint8())
case Uint16Type:
if rv.GetUint16() == 0 {
return expt
}

Check warning on line 1012 in gnovm/pkg/gnolang/op_binary.go

View check run for this annotation

Codecov / codecov/patch

gnovm/pkg/gnolang/op_binary.go#L1011-L1012

Added lines #L1011 - L1012 were not covered by tests
lv.SetUint16(lv.GetUint16() % rv.GetUint16())
case Uint32Type:
if rv.GetUint32() == 0 {
return expt
}

Check warning on line 1017 in gnovm/pkg/gnolang/op_binary.go

View check run for this annotation

Codecov / codecov/patch

gnovm/pkg/gnolang/op_binary.go#L1016-L1017

Added lines #L1016 - L1017 were not covered by tests
lv.SetUint32(lv.GetUint32() % rv.GetUint32())
case Uint64Type:
if rv.GetUint64() == 0 {
return expt
}

Check warning on line 1022 in gnovm/pkg/gnolang/op_binary.go

View check run for this annotation

Codecov / codecov/patch

gnovm/pkg/gnolang/op_binary.go#L1021-L1022

Added lines #L1021 - L1022 were not covered by tests
lv.SetUint64(lv.GetUint64() % rv.GetUint64())
case BigintType, UntypedBigintType:
if rv.GetBigInt().Sign() == 0 {
return expt
}

Check warning on line 1027 in gnovm/pkg/gnolang/op_binary.go

View check run for this annotation

Codecov / codecov/patch

gnovm/pkg/gnolang/op_binary.go#L1025-L1027

Added lines #L1025 - L1027 were not covered by tests

lb := lv.GetBigInt()
lb = big.NewInt(0).Rem(lb, rv.GetBigInt())
lv.V = BigintValue{V: lb}
Expand All @@ -937,6 +1035,8 @@
lv.T,
))
}

return nil
}

// for doOpBand and doOpBandAssign.
Expand Down
4 changes: 4 additions & 0 deletions gnovm/pkg/gnolang/op_expressions.go
Original file line number Diff line number Diff line change
Expand Up @@ -145,6 +145,10 @@ func (m *Machine) doOpStar() {
xv := m.PopValue()
switch bt := baseOf(xv.T).(type) {
case *PointerType:
if xv.V == nil {
panic(&Exception{Value: typedString("nil pointer dereference")})
petar-dambovaliev marked this conversation as resolved.
Show resolved Hide resolved
}

pv := xv.V.(PointerValue)
if pv.TV.T == DataByteType {
tv := TypedValue{T: bt.Elt}
Expand Down
5 changes: 5 additions & 0 deletions gnovm/pkg/gnolang/uverse.go
Original file line number Diff line number Diff line change
Expand Up @@ -838,6 +838,11 @@
li := lv.ConvertGetInt()
cv := vargs.TV.GetPointerAtIndexInt(m.Store, 1).Deref()
ci := cv.ConvertGetInt()

if ci < li {
panic(&Exception{Value: typedString(`makeslice: cap out of range`)})

Check warning on line 843 in gnovm/pkg/gnolang/uverse.go

View check run for this annotation

Codecov / codecov/patch

gnovm/pkg/gnolang/uverse.go#L843

Added line #L843 was not covered by tests
}

if et.Kind() == Uint8Kind {
arrayValue := m.Alloc.NewDataArray(ci)
m.PushValue(TypedValue{
Expand Down
Loading
Loading