compiler: Check owned decoder byte filling

9c0b254685e0c7f6ad37c3a8617a28f36a98860dc529bfa98aa62871786dbc1b
Alexis Sellier committed ago 1 parent 9b1ca970
lib/std/lang/il/binary/reader.rad +6 -0
75 75
76 76
/// Read a length-prefixed byte string and copy it into the arena.
77 77
export unsafe fn bytes 'input (input: &mut Reader 'input) -> *[u8] throws (binary::Error) {
78 78
    let n = try count(input, 1);
79 79
    let result = try storage(input, @sizeOf(u8), @alignOf(u8), n) as *mut [u8];
80 +
    return fillBytes(input, result);
81 +
}
82 +
83 +
/// Fill an owned byte buffer from input and advance past the copied bytes.
84 +
fn fillBytes 'input (input: &mut Reader 'input, result: *mut [u8]) -> *[u8] {
85 +
    let n = result.len;
80 86
    for i in 0..n {
81 87
        set result[i] = input.bytes[input.offset + i];
82 88
    }
83 89
    set input.offset += n;
84 90
    return result;
lib/std/lang/il/binary/tests.rad +25 -0
350 350
            typ, handle: il::Val::Undef, offset: il::Val::Undef, value: il::Val::Undef,
351 351
        }, &write[..]);
352 352
    }
353 353
}
354 354
355 +
/// Byte decoding retains exact allocation and cursor state on storage failure.
356 +
@test unsafe fn byteStorage() throws (testing::TestError) {
357 +
    let encoded: [u8; 11] = [0, 0, 0, 0, 3, 0, 0, 0, 65, 0, 255];
358 +
    let namesTable: [*[u8]; 0] = [];
359 +
    for capacity in 0..4 {
360 +
        let mut arena = alloc::new(&mut MEMORY[..capacity]);
361 +
        let source: 'input = &encoded[..], names = &namesTable[..] in {
362 +
            let mut input = reader::new(source, &mut arena, names);
363 +
            let empty = try! reader::bytes(&mut input);
364 +
            assert empty.len == 0;
365 +
            assert input.offset == 4;
366 +
            let mut failed = false;
367 +
            let result = try reader::bytes(&mut input) catch err {
368 +
                assert err == binary::Error::Storage;
369 +
                set failed = true;
370 +
                &[] as *[u8]
371 +
            };
372 +
            assert failed == (capacity < 3);
373 +
            assert input.offset == (8 if failed else 11);
374 +
            if not failed { try testing::expectBytesEq(result, &[65, 0, 255]); }
375 +
        }
376 +
        assert arena.offset == (3 if capacity == 3 else 0);
377 +
    }
378 +
}
379 +
355 380
/// Check every value tag and empty and nonempty sequences.
356 381
@test unsafe fn values() throws (testing::TestError) {
357 382
    let mut buffer: [u8; 64] = [0; 64];
358 383
    let namesTable: [*[u8]; 2] = ["data", "fn"];
359 384
    let storage: 'buffer = &mut buffer[..], names = &namesTable[..] in {