diff options
author | Kenneth Pouncey <kjpou@pt.lu> | 2019-11-25 17:24:33 +0300 |
---|---|---|
committer | Larry Ewing <lewing@microsoft.com> | 2019-11-25 17:24:33 +0300 |
commit | 5d981c267981505f425826ae0a3cc79dd08ecde4 (patch) | |
tree | 68ee07a47f6bc0dcd018e5355c703cd6fd27f1a7 /sdks | |
parent | e8d70c333fdff44a41c755f3c9d4a2ab74c7ffd5 (diff) |
[wasm] [bindings] Method invoke signature argument validation. (#17853)
* Implement validation for signature and argument count consistency.
- throw error `Parameter count mismatch.` when arguments and signature counts are not consistent.
* Fix tests that have Parameter count mismatch.
* Add browser binding tests for `Parameter count mismatch
Diffstat (limited to 'sdks')
4 files changed, 126 insertions, 52 deletions
diff --git a/sdks/wasm/src/binding_support.js b/sdks/wasm/src/binding_support.js index bb5fda95e95..bc6b9386e20 100644 --- a/sdks/wasm/src/binding_support.js +++ b/sdks/wasm/src/binding_support.js @@ -604,70 +604,83 @@ var BindingSupportLib = { call_method: function (method, this_arg, args_marshal, args) { this.bindings_lazy_init (); - var extra_args_mem = 0; - for (var i = 0; i < args.length; ++i) { - //long/double memory must be 8 bytes aligned and I'm being lazy here - if (args_marshal[i] == 'i' || args_marshal[i] == 'f' || args_marshal[i] == 'l' || args_marshal[i] == 'd' || args_marshal[i] == 'j' || args_marshal[i] == 'k') - extra_args_mem += 8; - } + // Allocate memory for error + var is_error = Module._malloc (4); + // Set arguement memory to null; + var args_mem = null; + var has_args = args !== null && typeof args !== "undefined" && args.length > 0; + var has_args_marshal = args_marshal !== null && typeof args_marshal !== "undefined" && args_marshal.length > 0; + + if (has_args_marshal && (!has_args || args.length < args_marshal.leghth)) + throw Error("Parameter count mismatch."); + + // check if the method signature needs argument mashalling + if (has_args_marshal && has_args) { + var extra_args_mem = 0; + for (var i = 0; i < args.length; ++i) { + //long/double memory must be 8 bytes aligned and I'm being lazy here + if (args_marshal[i] == 'i' || args_marshal[i] == 'f' || args_marshal[i] == 'l' || args_marshal[i] == 'd' || args_marshal[i] == 'j' || args_marshal[i] == 'k') + extra_args_mem += 8; + } - var extra_args_mem = extra_args_mem ? Module._malloc (extra_args_mem) : 0; - var extra_arg_idx = 0; - var args_mem = Module._malloc (args.length * 4); - var eh_throw = Module._malloc (4); - for (var i = 0; i < args.length; ++i) { - if (args_marshal[i] == 's') { - Module.setValue (args_mem + i * 4, this.js_string_to_mono_string (args [i]), "i32"); - } else if (args_marshal[i] == 'm') { - Module.setValue (args_mem + i * 4, args [i], "i32"); - } else if (args_marshal[i] == 'o') { - Module.setValue (args_mem + i * 4, this.js_to_mono_obj (args [i]), "i32"); - } else if (args_marshal[i] == 'j' || args_marshal[i] == 'k') { - var enumVal = this.js_to_mono_enum(method, i, args[i]); - - var extra_cell = extra_args_mem + extra_arg_idx; - extra_arg_idx += 8; - - if (args_marshal[i] == 'j') - Module.setValue (extra_cell, enumVal, "i32"); - else if (args_marshal[i] == 'k') - Module.setValue (extra_cell, enumVal, "i64"); - - Module.setValue (args_mem + i * 4, extra_cell, "i32"); - } else if (args_marshal[i] == 'i' || args_marshal[i] == 'f' || args_marshal[i] == 'l' || args_marshal[i] == 'd') { - var extra_cell = extra_args_mem + extra_arg_idx; - extra_arg_idx += 8; - - if (args_marshal[i] == 'i') - Module.setValue (extra_cell, args [i], "i32"); - else if (args_marshal[i] == 'l') - Module.setValue (extra_cell, args [i], "i64"); - else if (args_marshal[i] == 'f') - Module.setValue (extra_cell, args [i], "float"); - else - Module.setValue (extra_cell, args [i], "double"); - - Module.setValue (args_mem + i * 4, extra_cell, "i32"); + var extra_args_mem = extra_args_mem ? Module._malloc (extra_args_mem) : 0; + var extra_arg_idx = 0; + args_mem = Module._malloc (args.length * 4); + + for (var i = 0; i < args.length; ++i) { + if (args_marshal[i] == 's') { + Module.setValue (args_mem + i * 4, this.js_string_to_mono_string (args [i]), "i32"); + } else if (args_marshal[i] == 'm') { + Module.setValue (args_mem + i * 4, args [i], "i32"); + } else if (args_marshal[i] == 'o') { + Module.setValue (args_mem + i * 4, this.js_to_mono_obj (args [i]), "i32"); + } else if (args_marshal[i] == 'j' || args_marshal[i] == 'k') { + var enumVal = this.js_to_mono_enum(method, i, args[i]); + + var extra_cell = extra_args_mem + extra_arg_idx; + extra_arg_idx += 8; + + if (args_marshal[i] == 'j') + Module.setValue (extra_cell, enumVal, "i32"); + else if (args_marshal[i] == 'k') + Module.setValue (extra_cell, enumVal, "i64"); + + Module.setValue (args_mem + i * 4, extra_cell, "i32"); + } else if (args_marshal[i] == 'i' || args_marshal[i] == 'f' || args_marshal[i] == 'l' || args_marshal[i] == 'd') { + var extra_cell = extra_args_mem + extra_arg_idx; + extra_arg_idx += 8; + + if (args_marshal[i] == 'i') + Module.setValue (extra_cell, args [i], "i32"); + else if (args_marshal[i] == 'l') + Module.setValue (extra_cell, args [i], "i64"); + else if (args_marshal[i] == 'f') + Module.setValue (extra_cell, args [i], "float"); + else + Module.setValue (extra_cell, args [i], "double"); + + Module.setValue (args_mem + i * 4, extra_cell, "i32"); + } } } - Module.setValue (eh_throw, 0, "i32"); + Module.setValue (is_error, 0, "i32"); - var res = this.invoke_method (method, this_arg, args_mem, eh_throw); + var res = this.invoke_method (method, this_arg, args_mem, is_error); - var eh_res = Module.getValue (eh_throw, "i32"); + var eh_res = Module.getValue (is_error, "i32"); if (extra_args_mem) Module._free (extra_args_mem); - Module._free (args_mem); - Module._free (eh_throw); + if (args_mem) + Module._free (args_mem); + Module._free (is_error); if (eh_res != 0) { var msg = this.conv_string (res); throw new Error (msg); //the convention is that invoke_method ToString () any outgoing exception } - if (args_marshal !== null && typeof args_marshal !== "undefined") - { + if (has_args_marshal && has_args) { if (args_marshal.length >= args.length && args_marshal [args.length] === "m") return res; } diff --git a/sdks/wasm/tests/browser/src/BindingsTestSuite/BindingsTestSuite.cs b/sdks/wasm/tests/browser/src/BindingsTestSuite/BindingsTestSuite.cs index 5a15eb6523f..3c0e95ecc89 100644 --- a/sdks/wasm/tests/browser/src/BindingsTestSuite/BindingsTestSuite.cs +++ b/sdks/wasm/tests/browser/src/BindingsTestSuite/BindingsTestSuite.cs @@ -258,5 +258,16 @@ namespace BindingsTestSuite var arr = new WebAssembly.Core.Array(); return arr.Pop(); } + + public static int ParameterTest () + { + return -1; + } + + public static int ParameterTest2 (string param1) + { + return -1; + } + } } diff --git a/sdks/wasm/tests/browser/src/BrowserTestSuite/core-bindings-spec.js b/sdks/wasm/tests/browser/src/BrowserTestSuite/core-bindings-spec.js index f8b5fbb35ae..cf75040f01b 100644 --- a/sdks/wasm/tests/browser/src/BrowserTestSuite/core-bindings-spec.js +++ b/sdks/wasm/tests/browser/src/BrowserTestSuite/core-bindings-spec.js @@ -627,6 +627,56 @@ describe("The WebAssembly Core Bindings Test Suite",function(){ var pop = _document.Module.BINDING.call_static_method("[BindingsTestSuite]BindingsTestSuite.Program:ArrayPop", []); assert.equal(pop, undefined, "result does not match expected value unidentified."); assert.equal(pop, null, "result does not match expected value null."); - }, DEFAULT_TIMEOUT); + }, DEFAULT_TIMEOUT); + + it('BindingTestSuite: Should error with Parameter count mismatch #1.', () => { + //karmaHTML.corebindingsspec.document gives the access to the Document object of 'http-spec.html' file + var _document = karmaHTML.corebindingsspec.document; + try { + var result = _document.Module.BINDING.call_static_method("[BindingsTestSuite]BindingsTestSuite.Program:ParameterTest", ["hello"]); + assert.equal(result, 0, "result should have been Parameter count mismatch."); + } catch (e) { + } + }, DEFAULT_TIMEOUT); + + it('BindingTestSuite: Should error with Parameter count mismatch #2.', () => { + //karmaHTML.corebindingsspec.document gives the access to the Document object of 'http-spec.html' file + var _document = karmaHTML.corebindingsspec.document; + try { + var result = _document.Module.BINDING.call_static_method("[BindingsTestSuite]BindingsTestSuite.Program:ParameterTest2", []); + assert.equal(result, 0, "result should have been Parameter count mismatch."); + } catch (e) { + } + }, DEFAULT_TIMEOUT); + + it('BindingTestSuite: Should error with Parameter count mismatch #3.', () => { + //karmaHTML.corebindingsspec.document gives the access to the Document object of 'http-spec.html' file + var _document = karmaHTML.corebindingsspec.document; + try { + var result = _document.Module.BINDING.call_static_method("[BindingsTestSuite]BindingsTestSuite.Program:ParameterTest2"); + assert.equal(result, 0, "result should have been Parameter count mismatch."); + } catch (e) { + } + }, DEFAULT_TIMEOUT); + it('BindingTestSuite: Should NOT error with Parameter count mismatch #1.', () => { + //karmaHTML.corebindingsspec.document gives the access to the Document object of 'http-spec.html' file + var _document = karmaHTML.corebindingsspec.document; + var result = _document.Module.BINDING.call_static_method("[BindingsTestSuite]BindingsTestSuite.Program:ParameterTest", []); + assert.equal(result, -1, "result does not match expected result."); + }, DEFAULT_TIMEOUT); + + it('BindingTestSuite: Should NOT error with Parameter count mismatch #2.', () => { + //karmaHTML.corebindingsspec.document gives the access to the Document object of 'http-spec.html' file + var _document = karmaHTML.corebindingsspec.document; + var result = _document.Module.BINDING.call_static_method("[BindingsTestSuite]BindingsTestSuite.Program:ParameterTest"); + assert.equal(result, -1, "result does not match expected result."); + }, DEFAULT_TIMEOUT); + + it('BindingTestSuite: Should NOT error with Parameter count mismatch #3.', () => { + //karmaHTML.corebindingsspec.document gives the access to the Document object of 'http-spec.html' file + var _document = karmaHTML.corebindingsspec.document; + var result = _document.Module.BINDING.call_static_method("[BindingsTestSuite]BindingsTestSuite.Program:ParameterTest2", [null]); + assert.equal(result, -1, "result does not match expected result."); + }, DEFAULT_TIMEOUT); }); diff --git a/sdks/wasm/tests/browser/src/BrowserTestSuite/issues-spec.js b/sdks/wasm/tests/browser/src/BrowserTestSuite/issues-spec.js index 00671a43332..2c04c961785 100644 --- a/sdks/wasm/tests/browser/src/BrowserTestSuite/issues-spec.js +++ b/sdks/wasm/tests/browser/src/BrowserTestSuite/issues-spec.js @@ -33,7 +33,7 @@ describe("The WebAssembly Issues Test Suite",function(){ var _document = karmaHTML.issuesspec.document; - _document.Module.BINDING.call_static_method("[IssuesTestSuite]TestSuite.Program:BugInterpRecursion", []); + _document.Module.BINDING.call_static_method("[IssuesTestSuite]TestSuite.Program:BugInterpRecursion", [null]); expect(_document.constructor.name).toEqual('HTMLDocument'); // really nothing to assert here except if a recursion occurs. }, DEFAULT_TIMEOUT); |