diff options
-rw-r--r-- | cli/js/dispatch_json_test.ts | 20 | ||||
-rw-r--r-- | cli/js/dispatch_minimal_test.ts | 42 | ||||
-rw-r--r-- | cli/ops/dispatch_json.rs | 8 | ||||
-rw-r--r-- | cli/ops/dispatch_minimal.rs | 17 |
4 files changed, 84 insertions, 3 deletions
diff --git a/cli/js/dispatch_json_test.ts b/cli/js/dispatch_json_test.ts index 11dadc620..07549d295 100644 --- a/cli/js/dispatch_json_test.ts +++ b/cli/js/dispatch_json_test.ts @@ -1,4 +1,11 @@ -import { testPerm, assertMatch, unreachable } from "./test_util.ts"; +import { + test, + testPerm, + assert, + assertEquals, + assertMatch, + unreachable +} from "./test_util.ts"; const openErrorStackPattern = new RegExp( `^.* @@ -17,3 +24,14 @@ testPerm({ read: true }, async function sendAsyncStackTrace(): Promise<void> { } ); }); + +test(async function malformedJsonControlBuffer(): Promise<void> { + // @ts-ignore + const res = Deno.core.send(10, new Uint8Array([1, 2, 3, 4, 5])); + const resText = new TextDecoder().decode(res); + // eslint-disable-next-line @typescript-eslint/no-explicit-any + const resJson = JSON.parse(resText) as any; + assert(!resJson.ok); + assert(resJson.err); + assertEquals(resJson.err!.kind, Deno.ErrorKind.InvalidInput); +}); diff --git a/cli/js/dispatch_minimal_test.ts b/cli/js/dispatch_minimal_test.ts new file mode 100644 index 000000000..a08252171 --- /dev/null +++ b/cli/js/dispatch_minimal_test.ts @@ -0,0 +1,42 @@ +import { + test, + assert, + assertEquals, + assertMatch, + unreachable +} from "./test_util.ts"; + +const readErrorStackPattern = new RegExp( + `^.* + at unwrapResponse \\(.*dispatch_minimal\\.ts:.*\\) + at Object.sendAsync \\(.*dispatch_minimal\\.ts:.*\\) + at async Object\\.open \\(.*files\\.ts:.*\\).*$`, + "ms" +); + +test(async function sendAsyncStackTrace(): Promise<void> { + const buf = new Uint8Array(10); + await Deno.read(10, "nonexistent.txt", buf) + .then(unreachable) + .catch( + (error): void => { + assertMatch(error.stack, readErrorStackPattern); + } + ); +}); +test(async function malformedMinimalControlBuffer(): Promise<void> { + // @ts-ignore + const res = Deno.core.send(1, new Uint8Array([1, 2, 3, 4, 5])); + const header = res.slice(0, 12); + const buf32 = new Int32Array( + header.buffer, + header.byteOffset, + header.byteLength / 4 + ); + const arg = buf32[1]; + const result = buf32[2]; + const message = new TextDecoder().decode(res.slice(12)); + assert(arg < 0); + assertEquals(result, Deno.ErrorKind.InvalidInput); + assertEquals(message, "Unparsable control buffer"); +}); diff --git a/cli/ops/dispatch_json.rs b/cli/ops/dispatch_json.rs index 3a8faf2a8..5f1caac6f 100644 --- a/cli/ops/dispatch_json.rs +++ b/cli/ops/dispatch_json.rs @@ -48,7 +48,13 @@ where D: Fn(Value, Option<PinnedBuf>) -> Result<JsonOp, ErrBox>, { move |control: &[u8], zero_copy: Option<PinnedBuf>| { - let async_args: AsyncArgs = serde_json::from_slice(control).unwrap(); + let async_args: AsyncArgs = match serde_json::from_slice(control) { + Ok(args) => args, + Err(e) => { + let buf = serialize_result(None, Err(ErrBox::from(e))); + return CoreOp::Sync(buf); + } + }; let promise_id = async_args.promise_id; let is_sync = promise_id.is_none(); diff --git a/cli/ops/dispatch_minimal.rs b/cli/ops/dispatch_minimal.rs index 6170890a3..c19521bf1 100644 --- a/cli/ops/dispatch_minimal.rs +++ b/cli/ops/dispatch_minimal.rs @@ -5,6 +5,7 @@ //! messages. The first i32 is used to determine if a message a flatbuffer //! message or a "minimal" message. use crate::deno_error::GetErrorKind; +use crate::msg::ErrorKind; use byteorder::{LittleEndian, WriteBytesExt}; use deno::Buf; use deno::CoreOp; @@ -115,7 +116,21 @@ pub fn minimal_op( d: Dispatcher, ) -> impl Fn(&[u8], Option<PinnedBuf>) -> CoreOp { move |control: &[u8], zero_copy: Option<PinnedBuf>| { - let mut record = parse_min_record(control).unwrap(); + let mut record = match parse_min_record(control) { + Some(r) => r, + None => { + let error_record = ErrorRecord { + promise_id: 0, + arg: -1, + error_code: ErrorKind::InvalidInput as i32, + error_message: "Unparsable control buffer" + .to_string() + .as_bytes() + .to_owned(), + }; + return Op::Sync(error_record.into()); + } + }; let is_sync = record.promise_id == 0; let rid = record.arg; let min_op = d(rid, zero_copy); |