compiler: Check owned decoder operand construction

a3152d79fce8af3347d8267883261284107008e30f694772cc86eadd60352fe4
Alexis Sellier committed ago 1 parent d96dc590
lib/std/lang/il/binary/reader.rad +8 -2
144 144
145 145
/// Read a counted sequence of values.
146 146
export unsafe fn values 'input (input: &mut Reader 'input) -> *unsafe mut [il::Val] throws (binary::Error) {
147 147
    let n = try count(input, 1);
148 148
    let result = try storage(input, @sizeOf(il::Val), @alignOf(il::Val), n) as *mut [il::Val];
149 -
    for i in 0..n {
149 +
    let initialized = try fillValues(input, result);
150 +
    return (&mut initialized[..]) as *unsafe mut [il::Val];
151 +
}
152 +
153 +
/// Fill an owned operand table with checked tagged values in input order.
154 +
fn fillValues 'input (input: &mut Reader 'input, result: *mut [il::Val]) -> *mut [il::Val] throws (binary::Error) {
155 +
    for i in 0..result.len {
150 156
        set result[i] = try val(input);
151 157
    }
152 -
    return (&mut result[..]) as *unsafe mut [il::Val];
158 +
    return result;
153 159
}
154 160
155 161
/// Read a checked bin operation tag.
156 162
fn binOp 'input (input: &mut Reader 'input) -> il::BinOp throws (binary::Error) {
157 163
    let tag = try integer(input, 1) as u8;
lib/std/lang/il/binary/tests.rad +27 -0
375 375
        }
376 376
        assert arena.offset == (3 if capacity == 3 else 0);
377 377
    }
378 378
}
379 379
380 +
/// Invalid values stop counted decoding at the failing tag or register index.
381 +
@test unsafe fn invalidValueSequences() throws (testing::TestError) {
382 +
    let namesTable: [*[u8]; 0] = [];
383 +
    for position in 0..2 {
384 +
        for invalidTag in [false, true] {
385 +
            let mut encoded: [u8; 14] = [2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0];
386 +
            if invalidTag {
387 +
                set encoded[4 + position * 5] = 255;
388 +
            } else {
389 +
                set encoded[5 + position * 5] = 1;
390 +
            }
391 +
            let mut arena = alloc::new(&mut MEMORY[..128]);
392 +
            let source: 'input = &encoded[..], names = &namesTable[..] in {
393 +
                let mut input = reader::new(source, &mut arena, names);
394 +
                set input.registers = 1;
395 +
                let mut failed = false;
396 +
                try reader::values(&mut input) catch err {
397 +
                    assert err == binary::Error::Invalid;
398 +
                    set failed = true;
399 +
                };
400 +
                assert failed;
401 +
                assert input.offset == position * 5 + (5 if invalidTag else 9);
402 +
            }
403 +
        }
404 +
    }
405 +
}
406 +
380 407
/// Check every value tag and empty and nonempty sequences.
381 408
@test unsafe fn values() throws (testing::TestError) {
382 409
    let mut buffer: [u8; 64] = [0; 64];
383 410
    let namesTable: [*[u8]; 2] = ["data", "fn"];
384 411
    let storage: 'buffer = &mut buffer[..], names = &namesTable[..] in {