lib/std/lang/il/binary/tests.rad 2.8 KiB raw
1
//! Binary RIL input-boundary regression tests.
2
3
use std::lang::alloc;
4
use std::lang::il;
5
use std::lang::strings;
6
use std::testing;
7
8
/// Scratch space reused after each failed decode.
9
static ARENA: [u8; 65536] = undefined;
10
/// Stable interned names refer to the same binary buffer throughout each test.
11
static POOL: strings::Pool = strings::Pool { table: undefined, count: 0 };
12
13
/// Return whether structural decoding rejects the supplied bytes.
14
fn rejected(bytes: *[u8], arena: *mut alloc::Arena) -> bool {
15
    alloc::reset(arena);
16
    try super::decode(bytes, arena, &mut POOL) catch { return true; };
17
    return false;
18
}
19
20
/// Every incomplete prefix fails, including cuts inside strings, literals and references.
21
@test fn truncatedImage() throws (testing::TestError) {
22
    for i in 0..POOL.table.len { set POOL.table[i] = &[]; }
23
    set POOL.count = 0;
24
    let bytes: [u8; 6] = [0, 255, 128, 34, 92, 10];
25
    let values = &[
26
        il::DataValue { item: il::DataItem::Fn("callee"), count: 1 },
27
        il::DataValue { item: il::DataItem::Sym("data"), count: 1 },
28
        il::DataValue { item: il::DataItem::Str(&bytes[..]), count: 1 },
29
        il::DataValue { item: il::DataItem::Val { typ: il::Type::W64, val: -1 }, count: 1 },
30
    ];
31
    let data = &[il::Data { name: "data", size: 30, alignment: 8, readOnly: true, isZeroInit: false, values }];
32
    let mut body = [
33
        il::Instr::Copy { dst: il::Reg { n: 0 }, val: il::Val::DataSym("data") },
34
        il::Instr::Load { typ: il::Type::W64, dst: il::Reg { n: 1 }, src: il::Reg { n: 0 }, offset: 0 },
35
        il::Instr::Call { retTy: il::Type::W64, dst: il::Reg { n: 2 }, func: il::Val::FnAddr("callee"), args: &[il::Val::Reg(il::Reg { n: 1 })] },
36
        il::Instr::MemoryFence,
37
        il::Instr::Ret { val: il::Val::Reg(il::Reg { n: 2 }) },
38
    ];
39
    let mut calleeBody = [il::Instr::Ret { val: il::Val::Reg(il::Reg { n: 0 }) }];
40
    let main = il::Fn {
41
        name: "main", params: &[], returnType: il::Type::W64, isExtern: false, isLeaf: false,
42
        blocks: &[il::Block { label: "entry", params: &[], instrs: &mut body[..], locs: &[], preds: &[], loopDepth: 0 }],
43
    };
44
    let callee = il::Fn {
45
        name: "callee", params: &[il::Param { value: il::Reg { n: 0 }, type: il::Type::W64 }],
46
        returnType: il::Type::W64, isExtern: false, isLeaf: true,
47
        blocks: &[il::Block { label: "entry", params: &[], instrs: &mut calleeBody[..], locs: &[], preds: &[], loopDepth: 0 }],
48
    };
49
    let image = super::Image { program: il::Program { data, fns: &[&main, &callee] }, entry: "main" };
50
    let mut arena = alloc::new(&mut ARENA[..]);
51
    let mut output: [u8; 1024] = undefined;
52
    let size = try! super::encode(&image, &mut arena, &mut output[..]);
53
    for i in 0..size { try testing::expect(rejected(&output[..i], &mut arena)); }
54
    try testing::expectNot(rejected(&output[..size], &mut arena));
55
}