1
0
Fork 0
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:
Bartek Iwańczuk 2019-10-25 19:23:16 +02:00 committed by Ry Dahl
parent 2270abbc44
commit dfcdc03152
4 changed files with 84 additions and 3 deletions

View file

@ -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);
});

View 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");
});

View file

@ -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();

View file

@ -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);