Skip to content

Commit

Permalink
Handle undefined from JSON.stringify (#321)
Browse files Browse the repository at this point in the history
mini_racer uses V8's JSON.stringify to serialize results but it
returns undefined instead of a string for certain inputs, like WASM
string refs.

When that undefined value is then passed to Ruby's JSON parser, it
raises an exception (using rb_raise) that longjmps out of a lexical
scope where we hold the v8::Locker, without properly unlocking it
again.

Fixes: #320
  • Loading branch information
bnoordhuis authored Sep 21, 2024
1 parent 8c13559 commit e713b65
Show file tree
Hide file tree
Showing 2 changed files with 19 additions and 4 deletions.
11 changes: 7 additions & 4 deletions ext/mini_racer_extension/mini_racer_extension.cc
Original file line number Diff line number Diff line change
Expand Up @@ -429,14 +429,17 @@ static void prepare_result(MaybeLocal<Value> v8res,
Local<Object> object = local_value->ToObject(context).ToLocalChecked();
const unsigned argc = 1;
Local<Value> argv[argc] = { object };
MaybeLocal<Value> json = stringify->Call(context, JSON, argc, argv);
MaybeLocal<Value> maybe_json = stringify->Call(context, JSON, argc, argv);
Local<Value> json;

if (json.IsEmpty()) {
if (!maybe_json.ToLocal(&json)) {
evalRes.executed = false;
} else {
evalRes.json = true;
// JSON.stringify() returns undefined for inputs that
// are exotic objects, like WASM function or string refs
evalRes.json = !json->IsUndefined();
Persistent<Value>* persistent = new Persistent<Value>();
persistent->Reset(isolate, json.ToLocalChecked());
persistent->Reset(isolate, json);
evalRes.value = persistent;
}
}
Expand Down
12 changes: 12 additions & 0 deletions test/mini_racer_test.rb
Original file line number Diff line number Diff line change
Expand Up @@ -1050,6 +1050,18 @@ def test_deep_object_js
end
end

def test_wasm_ref
if RUBY_ENGINE == "truffleruby"
skip "TruffleRuby does not support WebAssembly"
end
context = MiniRacer::Context.new
assert_nil context.eval("
var b = [0,97,115,109,1,0,0,0,1,26,5,80,0,95,0,80,0,95,1,127,0,96,0,1,110,96,1,100,2,1,111,96,0,1,100,3,3,4,3,3,2,4,7,26,2,12,99,114,101,97,116,101,83,116,114,117,99,116,0,1,7,114,101,102,70,117,110,99,0,2,9,5,1,3,0,1,0,10,23,3,8,0,32,0,20,2,251,27,11,7,0,65,12,251,0,1,11,4,0,210,0,11,0,44,4,110,97,109,101,1,37,3,0,11,101,120,112,111,114,116,101,100,65,110,121,1,12,99,114,101,97,116,101,83,116,114,117,99,116,2,7,114,101,102,70,117,110,99]
var o = new WebAssembly.Instance(new WebAssembly.Module(new Uint8Array(b))).exports
o.refFunc()(o.createStruct) // exotic object
")
end

def test_stackdepth_bounds
assert_raises(ArgumentError) do
MiniRacer::Context.new(marshal_stack_depth: -2)
Expand Down

0 comments on commit e713b65

Please sign in to comment.