mirror of
https://github.com/denoland/deno.git
synced 2024-12-24 16:19:12 -05:00
fix: handle malformed control buffers (#3202)
This commit is contained in:
parent
2270abbc44
commit
dfcdc03152
4 changed files with 84 additions and 3 deletions
|
@ -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);
|
||||
});
|
||||
|
|
42
cli/js/dispatch_minimal_test.ts
Normal file
42
cli/js/dispatch_minimal_test.ts
Normal file
|
@ -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");
|
||||
});
|
|
@ -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();
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
|
Loading…
Reference in a new issue