Skip to content

Commit

Permalink
fix: stack panic truncation (#465)
Browse files Browse the repository at this point in the history
Fix stack being truncated due to double conversion to _error.

Fixes #329
  • Loading branch information
stevenh authored Nov 28, 2022
1 parent aeda017 commit 3697ad1
Show file tree
Hide file tree
Showing 4 changed files with 59 additions and 3 deletions.
3 changes: 1 addition & 2 deletions global.go
Original file line number Diff line number Diff line change
Expand Up @@ -165,7 +165,6 @@ func (runtime *_runtime) newDate(epoch float64) *_object {
}

func (runtime *_runtime) newError(name string, message Value, stackFramesToPop int) *_object {
var self *_object
switch name {
case "EvalError":
return runtime.newEvalError(message)
Expand All @@ -181,7 +180,7 @@ func (runtime *_runtime) newError(name string, message Value, stackFramesToPop i
return runtime.newURIError(message)
}

self = runtime.newErrorObject(name, message, stackFramesToPop)
self := runtime.newErrorObject(name, message, stackFramesToPop)
self.prototype = runtime.global.ErrorPrototype
if name != "" {
self.defineProperty("name", toValue_string(name), 0111, false)
Expand Down
23 changes: 23 additions & 0 deletions issue_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -994,3 +994,26 @@ func Test_issue302(t *testing.T) {
})
}
}

func Test_issue329(t *testing.T) {
vm := New()
val, err := vm.Run(`
run(c);
var stackLen;
function run(fn) {
try {
fn();
} catch (err) {
stackLen = err.stack.split(/\n/).length;
}
};
function c() { d() }
function d() { return 'x'.join(',') }
stackLen;
`)
require.NoError(t, err)
length, err := val.Export()
require.NoError(t, err)
require.Equal(t, uint32(6), length)
}
2 changes: 1 addition & 1 deletion runtime.go
Original file line number Diff line number Diff line change
Expand Up @@ -130,7 +130,7 @@ func (self *_runtime) tryCatchEvaluate(inner func() Value) (tryValue Value, exce
switch caught := caught.(type) {
case _error:
exception = true
tryValue = toValue_object(self.newError(caught.name, caught.messageValue(), 0))
tryValue = toValue_object(self.newErrorObjectError(caught))
case Value:
exception = true
tryValue = caught
Expand Down
34 changes: 34 additions & 0 deletions type_error.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,3 +22,37 @@ func (rt *_runtime) newErrorObject(name string, message Value, stackFramesToPop

return self
}

func (rt *_runtime) newErrorObjectError(err _error) *_object {
self := rt.newClassObject(classError)
self.defineProperty("message", err.messageValue(), 0111, false)
self.value = err
switch err.name {
case "EvalError":
self.prototype = rt.global.EvalErrorPrototype
case "TypeError":
self.prototype = rt.global.TypeErrorPrototype
case "RangeError":
self.prototype = rt.global.RangeErrorPrototype
case "ReferenceError":
self.prototype = rt.global.ReferenceErrorPrototype
case "SyntaxError":
self.prototype = rt.global.SyntaxErrorPrototype
case "URIError":
self.prototype = rt.global.URIErrorPrototype
default:
self.prototype = rt.global.ErrorPrototype
}

self.defineOwnProperty("stack", _property{
value: _propertyGetSet{
rt.newNativeFunction("get", "internal", 0, func(FunctionCall) Value {
return toValue_string(self.value.(_error).formatWithStack())
}),
&_nilGetSetObject,
},
mode: modeConfigureMask & modeOnMask,
}, false)

return self
}

0 comments on commit 3697ad1

Please sign in to comment.