compiler: Check owned decoder operand construction
a3152d79fce8af3347d8267883261284107008e30f694772cc86eadd60352fe4
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 { |