compiler: Check owned decoder byte filling
9c0b254685e0c7f6ad37c3a8617a28f36a98860dc529bfa98aa62871786dbc1b
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 { |