Skip to main content

bind/interpreter/
instruction_decoder.rs

1// Copyright 2022 The Fuchsia Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5use crate::bytecode_constants::*;
6use crate::compiler::Symbol;
7use crate::interpreter::common::*;
8use crate::parser::bind_library;
9use num_traits::FromPrimitive;
10use serde::{Deserialize, Serialize};
11use std::collections::HashMap;
12
13#[derive(Debug, PartialEq, Clone, Serialize, Deserialize)]
14pub struct DecodedCondition {
15    pub is_equal: bool,
16    pub lhs: Symbol,
17    pub rhs: Symbol,
18}
19
20// Verifies and converts instruction bytecode into a set of DecodedInstructions.
21// TODO(https://fxbug.dev/42175142): Add IDs to the Label and Jump statements.
22#[derive(Debug, PartialEq, Clone, Serialize, Deserialize)]
23pub enum DecodedInstruction {
24    UnconditionalAbort,
25    Condition(DecodedCondition),
26    Jump(Option<DecodedCondition>),
27    Label,
28}
29
30#[derive(Debug, Clone)]
31pub struct InstructionDecoder<'a> {
32    symbol_table: &'a HashMap<u32, String>,
33    inst_iter: BytecodeIter<'a>,
34}
35
36impl<'a> InstructionDecoder<'a> {
37    pub fn new(
38        symbol_table: &'a HashMap<u32, String>,
39        instructions: &'a Vec<u8>,
40    ) -> InstructionDecoder<'a> {
41        InstructionDecoder { symbol_table: symbol_table, inst_iter: instructions.iter() }
42    }
43
44    pub fn decode(&mut self) -> Result<Vec<DecodedInstruction>, BytecodeError> {
45        let mut decoded_instructions: Vec<DecodedInstruction> = vec![];
46        while let Some(byte) = self.inst_iter.next() {
47            let op_byte = FromPrimitive::from_u8(*byte).ok_or(BytecodeError::InvalidOp(*byte))?;
48            let instruction = match op_byte {
49                RawOp::UnconditionalJump | RawOp::JumpIfEqual | RawOp::JumpIfNotEqual => {
50                    self.decode_control_flow_statement(op_byte)?
51                }
52                RawOp::EqualCondition | RawOp::InequalCondition => DecodedInstruction::Condition(
53                    self.decode_conditional_statement(op_byte == RawOp::EqualCondition)?,
54                ),
55                RawOp::Abort => DecodedInstruction::UnconditionalAbort,
56                RawOp::JumpLandPad => DecodedInstruction::Label,
57            };
58            decoded_instructions.push(instruction);
59        }
60
61        Ok(decoded_instructions)
62    }
63
64    fn decode_control_flow_statement(
65        &mut self,
66        op_byte: RawOp,
67    ) -> Result<DecodedInstruction, BytecodeError> {
68        // TODO(https://fxbug.dev/42175045): verify offset amount takes you to a jump landing pad.
69        let offset_amount = next_u32(&mut self.inst_iter)?;
70
71        let condition = match op_byte {
72            RawOp::JumpIfEqual => Some(self.decode_conditional_statement(true)?),
73            RawOp::JumpIfNotEqual => Some(self.decode_conditional_statement(false)?),
74            RawOp::UnconditionalJump => None,
75            _ => {
76                return Err(BytecodeError::InvalidOp(op_byte as u8));
77            }
78        };
79
80        if self.inst_iter.len() as u32 <= offset_amount {
81            return Err(BytecodeError::InvalidJumpLocation);
82        }
83
84        Ok(DecodedInstruction::Jump(condition))
85    }
86
87    fn decode_conditional_statement(
88        &mut self,
89        is_equal: bool,
90    ) -> Result<DecodedCondition, BytecodeError> {
91        // Read in the LHS value first, followed by the RHS value.
92        let lhs = self.decode_value()?;
93        let rhs = self.decode_value()?;
94        Ok(DecodedCondition { is_equal: is_equal, lhs: lhs, rhs: rhs })
95    }
96
97    fn decode_value(&mut self) -> Result<Symbol, BytecodeError> {
98        let val_primitive = *next_u8(&mut self.inst_iter)?;
99        let val_type = FromPrimitive::from_u8(val_primitive)
100            .ok_or(BytecodeError::InvalidValueType(val_primitive))?;
101        let val = next_u32(&mut self.inst_iter)?;
102
103        match val_type {
104            RawValueType::NumberValue => Ok(Symbol::NumberValue(val as u64)),
105            RawValueType::BoolValue => match val {
106                FALSE_VAL => Ok(Symbol::BoolValue(false)),
107                TRUE_VAL => Ok(Symbol::BoolValue(true)),
108                _ => Err(BytecodeError::InvalidBoolValue(val)),
109            },
110            RawValueType::Key => {
111                Ok(Symbol::Key(self.lookup_symbol_table(val)?, bind_library::ValueType::Str))
112            }
113            RawValueType::StringValue => Ok(Symbol::StringValue(self.lookup_symbol_table(val)?)),
114            RawValueType::EnumValue => Ok(Symbol::EnumValue(self.lookup_symbol_table(val)?)),
115        }
116    }
117
118    fn lookup_symbol_table(&self, key: u32) -> Result<String, BytecodeError> {
119        self.symbol_table
120            .get(&key)
121            .ok_or(BytecodeError::MissingEntryInSymbolTable(key))
122            .map(|val| val.to_string())
123    }
124}
125
126#[cfg(test)]
127mod test {
128    use super::*;
129    use crate::interpreter::decode_bind_rules::{DecodedRules, NODE_TYPE_HEADER_SZ};
130    use crate::interpreter::test_common::*;
131
132    fn append_section_header(bytecode: &mut Vec<u8>, magic_num: u32, sz: u32) {
133        bytecode.extend_from_slice(&magic_num.to_be_bytes());
134        bytecode.extend_from_slice(&sz.to_le_bytes());
135    }
136
137    fn append_node_header(bytecode: &mut Vec<u8>, node_type: RawParentType, node_id: u32, sz: u32) {
138        bytecode.push(node_type as u8);
139        bytecode.extend_from_slice(&node_id.to_le_bytes());
140        bytecode.extend_from_slice(&sz.to_le_bytes());
141    }
142
143    #[test]
144    fn test_invalid_value_type() {
145        let mut bytecode: Vec<u8> = BIND_HEADER.to_vec();
146        bytecode.push(BYTECODE_DISABLE_DEBUG);
147        append_section_header(&mut bytecode, SYMB_MAGIC_NUM, 0);
148
149        let instructions = [0x01, 0x01, 0, 0, 0, 0x05, 0x10, 0, 0, 0, 0];
150        append_section_header(&mut bytecode, INSTRUCTION_MAGIC_NUM, instructions.len() as u32);
151        bytecode.extend_from_slice(&instructions);
152
153        assert_eq!(Err(BytecodeError::InvalidValueType(0x10)), DecodedRules::new(bytecode));
154    }
155
156    #[test]
157    fn test_value_string_missing_in_symbols() {
158        let mut bytecode: Vec<u8> = BIND_HEADER.to_vec();
159        bytecode.push(BYTECODE_DISABLE_DEBUG);
160        append_section_header(&mut bytecode, SYMB_MAGIC_NUM, 0);
161
162        let instructions = [0x01, 0x02, 0, 0, 0, 0x05, 0x10, 0, 0, 0, 0];
163        append_section_header(&mut bytecode, INSTRUCTION_MAGIC_NUM, instructions.len() as u32);
164        bytecode.extend_from_slice(&instructions);
165
166        assert_eq!(
167            Err(BytecodeError::MissingEntryInSymbolTable(0x05000000)),
168            DecodedRules::new(bytecode)
169        );
170    }
171
172    #[test]
173    fn test_value_enum_missing_in_symbols() {
174        let mut bytecode: Vec<u8> = BIND_HEADER.to_vec();
175        bytecode.push(BYTECODE_DISABLE_DEBUG);
176        append_section_header(&mut bytecode, SYMB_MAGIC_NUM, 0);
177
178        let instructions = [0x01, 0x04, 0, 0, 0, 0x05, 0x10, 0, 0, 0, 0];
179        append_section_header(&mut bytecode, INSTRUCTION_MAGIC_NUM, instructions.len() as u32);
180        bytecode.extend_from_slice(&instructions);
181
182        assert_eq!(
183            Err(BytecodeError::MissingEntryInSymbolTable(0x05000000)),
184            DecodedRules::new(bytecode)
185        );
186    }
187
188    #[test]
189    fn test_value_invalid_bool() {
190        let mut bytecode: Vec<u8> = BIND_HEADER.to_vec();
191        bytecode.push(BYTECODE_DISABLE_DEBUG);
192        append_section_header(&mut bytecode, SYMB_MAGIC_NUM, 0);
193
194        let instructions = [0x01, 0x01, 0, 0, 0, 0x05, 0x03, 0, 0, 0, 0x01];
195        append_section_header(&mut bytecode, INSTRUCTION_MAGIC_NUM, instructions.len() as u32);
196        bytecode.extend_from_slice(&instructions);
197
198        assert_eq!(Err(BytecodeError::InvalidBoolValue(0x01000000)), DecodedRules::new(bytecode));
199    }
200
201    #[test]
202    fn test_invalid_outofbounds_jump_offset() {
203        let mut bytecode: Vec<u8> = BIND_HEADER.to_vec();
204        bytecode.push(BYTECODE_DISABLE_DEBUG);
205        append_section_header(&mut bytecode, SYMB_MAGIC_NUM, 0);
206
207        let instructions = [
208            0x11, 0x01, 0, 0, 0, 0x01, 0, 0, 0, 0x05, 0x01, 0x10, 0, 0,
209            0, // jump 1 if 0x05000000 == 0x10
210            0x30, 0x20, // abort, jump pad
211            0x10, 0x02, 0, 0,
212            0, // jump 2 (this is the invalid jump as there is only 2 bytes left)
213            0x30, 0x20, // abort, jump pad
214        ];
215        append_section_header(&mut bytecode, INSTRUCTION_MAGIC_NUM, instructions.len() as u32);
216        bytecode.extend_from_slice(&instructions);
217
218        // The last jump would put your instruction pointer past the last element.
219        assert_eq!(Err(BytecodeError::InvalidJumpLocation), DecodedRules::new(bytecode));
220    }
221
222    #[test]
223    fn test_invalid_outofbounds_jump_offset_composite_primary() {
224        let mut bytecode: Vec<u8> = BIND_HEADER.to_vec();
225        bytecode.push(BYTECODE_DISABLE_DEBUG);
226        append_section_header(&mut bytecode, SYMB_MAGIC_NUM, 27);
227
228        let device_name: [u8; 5] = [0x49, 0x42, 0x49, 0x53, 0]; // "IBIS"
229        bytecode.extend_from_slice(&[1, 0, 0, 0]);
230        bytecode.extend_from_slice(&device_name);
231
232        let primary_node_name: [u8; 5] = [0x52, 0x41, 0x49, 0x4C, 0]; // "RAIL"
233        bytecode.extend_from_slice(&[2, 0, 0, 0]);
234        bytecode.extend_from_slice(&primary_node_name);
235
236        let node_name_1: [u8; 5] = [0x43, 0x4F, 0x4F, 0x54, 0]; // "COOT"
237        bytecode.extend_from_slice(&[3, 0, 0, 0]);
238        bytecode.extend_from_slice(&node_name_1);
239
240        // There is a jump 4 that would go out of bounds for the primary node instructions.
241        let primary_node_inst =
242            [0x01, 0x01, 0, 0, 0, 0x05, 0x01, 0x10, 0, 0x20, 0, 0x10, 0x04, 0, 0, 0];
243
244        let additional_node_inst = [0x02, 0x01, 0, 0, 0, 0x02, 0x02, 0, 0, 0x10];
245
246        let composite_insts_sz = COMPOSITE_NAME_ID_BYTES
247            + ((NODE_TYPE_HEADER_SZ * 2) + primary_node_inst.len() + additional_node_inst.len())
248                as u32;
249        append_section_header(&mut bytecode, COMPOSITE_MAGIC_NUM, composite_insts_sz);
250
251        // Add device name ID.
252        bytecode.extend_from_slice(&[1, 0, 0, 0]);
253
254        append_node_header(
255            &mut bytecode,
256            RawParentType::Primary,
257            2,
258            primary_node_inst.len() as u32,
259        );
260        bytecode.extend_from_slice(&primary_node_inst);
261
262        // Add the additional node.
263        append_node_header(
264            &mut bytecode,
265            RawParentType::Additional,
266            3,
267            additional_node_inst.len() as u32,
268        );
269        bytecode.extend_from_slice(&additional_node_inst);
270
271        assert_eq!(Err(BytecodeError::InvalidJumpLocation), DecodedRules::new(bytecode));
272    }
273
274    #[test]
275    fn test_invalid_outofbounds_jump_offset_composite_additional() {
276        let mut bytecode: Vec<u8> = BIND_HEADER.to_vec();
277        bytecode.push(BYTECODE_DISABLE_DEBUG);
278        append_section_header(&mut bytecode, SYMB_MAGIC_NUM, 27);
279
280        let device_name: [u8; 5] = [0x49, 0x42, 0x49, 0x53, 0]; // "IBIS"
281        bytecode.extend_from_slice(&[1, 0, 0, 0]);
282        bytecode.extend_from_slice(&device_name);
283
284        let primary_node_name: [u8; 5] = [0x52, 0x41, 0x49, 0x4C, 0]; // "RAIL"
285        bytecode.extend_from_slice(&[2, 0, 0, 0]);
286        bytecode.extend_from_slice(&primary_node_name);
287
288        let node_name_1: [u8; 5] = [0x43, 0x4F, 0x4F, 0x54, 0]; // "COOT"
289        bytecode.extend_from_slice(&[3, 0, 0, 0]);
290        bytecode.extend_from_slice(&node_name_1);
291
292        let primary_node_inst = [0x02, 0x01, 0, 0, 0, 0x02, 0x01, 0, 0, 0, 0x10];
293
294        // There is a jump 4 that would go out of bounds for the additional node instructions.
295        let additional_node_inst =
296            [0x01, 0x01, 0, 0, 0, 0x05, 0x01, 0x10, 0, 0x20, 0, 0x10, 0x04, 0, 0, 0];
297
298        let composite_insts_sz = COMPOSITE_NAME_ID_BYTES
299            + ((NODE_TYPE_HEADER_SZ * 2) + primary_node_inst.len() + additional_node_inst.len())
300                as u32;
301        append_section_header(&mut bytecode, COMPOSITE_MAGIC_NUM, composite_insts_sz);
302
303        // Add device name ID.
304        bytecode.extend_from_slice(&[1, 0, 0, 0]);
305
306        append_node_header(
307            &mut bytecode,
308            RawParentType::Primary,
309            2,
310            primary_node_inst.len() as u32,
311        );
312        bytecode.extend_from_slice(&primary_node_inst);
313
314        // Add the additional node.
315        append_node_header(
316            &mut bytecode,
317            RawParentType::Additional,
318            3,
319            additional_node_inst.len() as u32,
320        );
321        bytecode.extend_from_slice(&additional_node_inst);
322
323        assert_eq!(Err(BytecodeError::InvalidJumpLocation), DecodedRules::new(bytecode));
324    }
325
326    #[test]
327    fn test_invalid_value_type_composite_primary() {
328        let mut bytecode: Vec<u8> = BIND_HEADER.to_vec();
329        bytecode.push(BYTECODE_DISABLE_DEBUG);
330        append_section_header(&mut bytecode, SYMB_MAGIC_NUM, 27);
331
332        let device_name: [u8; 5] = [0x49, 0x42, 0x49, 0x53, 0]; // "IBIS"
333        bytecode.extend_from_slice(&[1, 0, 0, 0]);
334        bytecode.extend_from_slice(&device_name);
335
336        let primary_node_name: [u8; 5] = [0x52, 0x41, 0x49, 0x4C, 0]; // "RAIL"
337        bytecode.extend_from_slice(&[2, 0, 0, 0]);
338        bytecode.extend_from_slice(&primary_node_name);
339
340        let node_name_1: [u8; 5] = [0x43, 0x4F, 0x4F, 0x54, 0]; // "COOT"
341        bytecode.extend_from_slice(&[3, 0, 0, 0]);
342        bytecode.extend_from_slice(&node_name_1);
343
344        // There is no value type enum for 0x05.
345        let primary_node_inst = [0x02, 0x01, 0, 0, 0, 0x02, 0x05, 0, 0, 0, 0x10];
346
347        let additional_node_inst = [0x01, 0x01, 0, 0, 0, 0x05, 0x01, 0x10, 0, 0x20, 0];
348
349        let composite_insts_sz = COMPOSITE_NAME_ID_BYTES
350            + ((NODE_TYPE_HEADER_SZ * 2) + primary_node_inst.len() + additional_node_inst.len())
351                as u32;
352        append_section_header(&mut bytecode, COMPOSITE_MAGIC_NUM, composite_insts_sz);
353
354        // Add device name ID.
355        bytecode.extend_from_slice(&[1, 0, 0, 0]);
356
357        append_node_header(
358            &mut bytecode,
359            RawParentType::Primary,
360            2,
361            primary_node_inst.len() as u32,
362        );
363        bytecode.extend_from_slice(&primary_node_inst);
364
365        // Add the additional node.
366        append_node_header(
367            &mut bytecode,
368            RawParentType::Additional,
369            3,
370            additional_node_inst.len() as u32,
371        );
372        bytecode.extend_from_slice(&additional_node_inst);
373
374        assert_eq!(Err(BytecodeError::InvalidValueType(0x05)), DecodedRules::new(bytecode));
375    }
376
377    #[test]
378    fn test_invalid_value_type_composite_additional() {
379        let mut bytecode: Vec<u8> = BIND_HEADER.to_vec();
380        bytecode.push(BYTECODE_DISABLE_DEBUG);
381        append_section_header(&mut bytecode, SYMB_MAGIC_NUM, 27);
382
383        let device_name: [u8; 5] = [0x49, 0x42, 0x49, 0x53, 0]; // "IBIS"
384        bytecode.extend_from_slice(&[1, 0, 0, 0]);
385        bytecode.extend_from_slice(&device_name);
386
387        let primary_node_name: [u8; 5] = [0x52, 0x41, 0x49, 0x4C, 0]; // "RAIL"
388        bytecode.extend_from_slice(&[2, 0, 0, 0]);
389        bytecode.extend_from_slice(&primary_node_name);
390
391        let node_name_1: [u8; 5] = [0x43, 0x4F, 0x4F, 0x54, 0]; // "COOT"
392        bytecode.extend_from_slice(&[3, 0, 0, 0]);
393        bytecode.extend_from_slice(&node_name_1);
394
395        let primary_node_inst = [0x01, 0x01, 0, 0, 0, 0x05, 0x01, 0x10, 0, 0x20, 0];
396
397        // There is no value type enum for 0x05.
398        let additional_node_inst = [0x02, 0x01, 0, 0, 0, 0x02, 0x05, 0, 0, 0, 0x10];
399
400        let composite_insts_sz = COMPOSITE_NAME_ID_BYTES
401            + ((NODE_TYPE_HEADER_SZ * 2) + primary_node_inst.len() + additional_node_inst.len())
402                as u32;
403        append_section_header(&mut bytecode, COMPOSITE_MAGIC_NUM, composite_insts_sz);
404
405        // Add device name ID.
406        bytecode.extend_from_slice(&[1, 0, 0, 0]);
407
408        append_node_header(
409            &mut bytecode,
410            RawParentType::Primary,
411            2,
412            primary_node_inst.len() as u32,
413        );
414        bytecode.extend_from_slice(&primary_node_inst);
415
416        // Add the additional node.
417        append_node_header(
418            &mut bytecode,
419            RawParentType::Additional,
420            3,
421            additional_node_inst.len() as u32,
422        );
423        bytecode.extend_from_slice(&additional_node_inst);
424
425        assert_eq!(Err(BytecodeError::InvalidValueType(0x05)), DecodedRules::new(bytecode));
426    }
427
428    #[test]
429    fn test_value_key_missing_in_symbols_composite_primary() {
430        let mut bytecode: Vec<u8> = BIND_HEADER.to_vec();
431        bytecode.push(BYTECODE_DISABLE_DEBUG);
432        append_section_header(&mut bytecode, SYMB_MAGIC_NUM, 27);
433
434        let device_name: [u8; 5] = [0x49, 0x42, 0x49, 0x53, 0]; // "IBIS"
435        bytecode.extend_from_slice(&[1, 0, 0, 0]);
436        bytecode.extend_from_slice(&device_name);
437
438        let primary_node_name: [u8; 5] = [0x52, 0x41, 0x49, 0x4C, 0]; // "RAIL"
439        bytecode.extend_from_slice(&[2, 0, 0, 0]);
440        bytecode.extend_from_slice(&primary_node_name);
441
442        let node_name_1: [u8; 5] = [0x43, 0x4F, 0x4F, 0x54, 0]; // "COOT"
443        bytecode.extend_from_slice(&[3, 0, 0, 0]);
444        bytecode.extend_from_slice(&node_name_1);
445
446        // There is no key type (type 0x00) with key 0x10000000.
447        let primary_node_inst = [0x02, 0x01, 0, 0, 0, 0x02, 0x00, 0, 0, 0, 0x10];
448
449        let additional_node_inst = [0x01, 0x01, 0, 0, 0, 0x05, 0x01, 0x10, 0, 0x20, 0];
450
451        let composite_insts_sz = COMPOSITE_NAME_ID_BYTES
452            + ((NODE_TYPE_HEADER_SZ * 2) + primary_node_inst.len() + additional_node_inst.len())
453                as u32;
454        append_section_header(&mut bytecode, COMPOSITE_MAGIC_NUM, composite_insts_sz);
455
456        // Add device name ID.
457        bytecode.extend_from_slice(&[1, 0, 0, 0]);
458
459        append_node_header(
460            &mut bytecode,
461            RawParentType::Primary,
462            2,
463            primary_node_inst.len() as u32,
464        );
465        bytecode.extend_from_slice(&primary_node_inst);
466
467        // Add the additional node.
468        append_node_header(
469            &mut bytecode,
470            RawParentType::Additional,
471            3,
472            additional_node_inst.len() as u32,
473        );
474        bytecode.extend_from_slice(&additional_node_inst);
475
476        assert_eq!(
477            Err(BytecodeError::MissingEntryInSymbolTable(0x10000000)),
478            DecodedRules::new(bytecode)
479        );
480    }
481
482    #[test]
483    fn test_value_key_missing_in_symbols_composite_additional() {
484        let mut bytecode: Vec<u8> = BIND_HEADER.to_vec();
485        bytecode.push(BYTECODE_DISABLE_DEBUG);
486        append_section_header(&mut bytecode, SYMB_MAGIC_NUM, 27);
487
488        let device_name: [u8; 5] = [0x49, 0x42, 0x49, 0x53, 0]; // "IBIS"
489        bytecode.extend_from_slice(&[1, 0, 0, 0]);
490        bytecode.extend_from_slice(&device_name);
491
492        let primary_node_name: [u8; 5] = [0x52, 0x41, 0x49, 0x4C, 0]; // "RAIL"
493        bytecode.extend_from_slice(&[2, 0, 0, 0]);
494        bytecode.extend_from_slice(&primary_node_name);
495
496        let node_name_1: [u8; 5] = [0x43, 0x4F, 0x4F, 0x54, 0]; // "COOT"
497        bytecode.extend_from_slice(&[3, 0, 0, 0]);
498        bytecode.extend_from_slice(&node_name_1);
499
500        let primary_node_inst = [0x01, 0x01, 0, 0, 0, 0x05, 0x01, 0x10, 0, 0x20, 0];
501
502        // There is no key type (type 0x00) with key 0x10000000.
503        let additional_node_inst = [0x02, 0x01, 0, 0, 0, 0x02, 0x00, 0, 0, 0, 0x10];
504
505        let composite_insts_sz = COMPOSITE_NAME_ID_BYTES
506            + ((NODE_TYPE_HEADER_SZ * 2) + primary_node_inst.len() + additional_node_inst.len())
507                as u32;
508        append_section_header(&mut bytecode, COMPOSITE_MAGIC_NUM, composite_insts_sz);
509
510        // Add device name ID.
511        bytecode.extend_from_slice(&[1, 0, 0, 0]);
512
513        append_node_header(
514            &mut bytecode,
515            RawParentType::Primary,
516            2,
517            primary_node_inst.len() as u32,
518        );
519        bytecode.extend_from_slice(&primary_node_inst);
520
521        // Add the additional node.
522        append_node_header(
523            &mut bytecode,
524            RawParentType::Additional,
525            3,
526            additional_node_inst.len() as u32,
527        );
528        bytecode.extend_from_slice(&additional_node_inst);
529
530        assert_eq!(
531            Err(BytecodeError::MissingEntryInSymbolTable(0x10000000)),
532            DecodedRules::new(bytecode)
533        );
534    }
535
536    #[test]
537    fn test_value_string_missing_in_symbols_composite_primary() {
538        let mut bytecode: Vec<u8> = BIND_HEADER.to_vec();
539        bytecode.push(BYTECODE_DISABLE_DEBUG);
540        append_section_header(&mut bytecode, SYMB_MAGIC_NUM, 27);
541
542        let device_name: [u8; 5] = [0x49, 0x42, 0x49, 0x53, 0]; // "IBIS"
543        bytecode.extend_from_slice(&[1, 0, 0, 0]);
544        bytecode.extend_from_slice(&device_name);
545
546        let primary_node_name: [u8; 5] = [0x52, 0x41, 0x49, 0x4C, 0]; // "RAIL"
547        bytecode.extend_from_slice(&[2, 0, 0, 0]);
548        bytecode.extend_from_slice(&primary_node_name);
549
550        let node_name_1: [u8; 5] = [0x43, 0x4F, 0x4F, 0x54, 0]; // "COOT"
551        bytecode.extend_from_slice(&[3, 0, 0, 0]);
552        bytecode.extend_from_slice(&node_name_1);
553
554        // There is no string literal (type 0x02) with key 0x10000000.
555        let primary_node_inst = [0x02, 0x01, 0, 0, 0, 0x02, 0x02, 0, 0, 0, 0x10];
556
557        let additional_node_inst = [0x01, 0x01, 0, 0, 0, 0x05, 0x01, 0x10, 0, 0x20, 0];
558
559        let composite_insts_sz = COMPOSITE_NAME_ID_BYTES
560            + ((NODE_TYPE_HEADER_SZ * 2) + primary_node_inst.len() + additional_node_inst.len())
561                as u32;
562        append_section_header(&mut bytecode, COMPOSITE_MAGIC_NUM, composite_insts_sz);
563
564        // Add device name ID.
565        bytecode.extend_from_slice(&[1, 0, 0, 0]);
566
567        append_node_header(
568            &mut bytecode,
569            RawParentType::Primary,
570            2,
571            primary_node_inst.len() as u32,
572        );
573        bytecode.extend_from_slice(&primary_node_inst);
574
575        // Add the additional node.
576        append_node_header(
577            &mut bytecode,
578            RawParentType::Additional,
579            3,
580            additional_node_inst.len() as u32,
581        );
582        bytecode.extend_from_slice(&additional_node_inst);
583
584        assert_eq!(
585            Err(BytecodeError::MissingEntryInSymbolTable(0x10000000)),
586            DecodedRules::new(bytecode)
587        );
588    }
589
590    #[test]
591    fn test_value_string_missing_in_symbols_composite_additional() {
592        let mut bytecode: Vec<u8> = BIND_HEADER.to_vec();
593        bytecode.push(BYTECODE_DISABLE_DEBUG);
594        append_section_header(&mut bytecode, SYMB_MAGIC_NUM, 27);
595
596        let device_name: [u8; 5] = [0x49, 0x42, 0x49, 0x53, 0]; // "IBIS"
597        bytecode.extend_from_slice(&[1, 0, 0, 0]);
598        bytecode.extend_from_slice(&device_name);
599
600        let primary_node_name: [u8; 5] = [0x52, 0x41, 0x49, 0x4C, 0]; // "RAIL"
601        bytecode.extend_from_slice(&[2, 0, 0, 0]);
602        bytecode.extend_from_slice(&primary_node_name);
603
604        let node_name_1: [u8; 5] = [0x43, 0x4F, 0x4F, 0x54, 0]; // "COOT"
605        bytecode.extend_from_slice(&[3, 0, 0, 0]);
606        bytecode.extend_from_slice(&node_name_1);
607
608        let primary_node_inst = [0x01, 0x01, 0, 0, 0, 0x05, 0x01, 0x10, 0, 0x20, 0];
609
610        // There is no string literal (type 0x02) with key 0x10000000.
611        let additional_node_inst = [0x02, 0x01, 0, 0, 0, 0x02, 0x02, 0, 0, 0, 0x10];
612
613        let composite_insts_sz = COMPOSITE_NAME_ID_BYTES
614            + ((NODE_TYPE_HEADER_SZ * 2) + primary_node_inst.len() + additional_node_inst.len())
615                as u32;
616        append_section_header(&mut bytecode, COMPOSITE_MAGIC_NUM, composite_insts_sz);
617
618        // Add device name ID.
619        bytecode.extend_from_slice(&[1, 0, 0, 0]);
620
621        append_node_header(
622            &mut bytecode,
623            RawParentType::Primary,
624            2,
625            primary_node_inst.len() as u32,
626        );
627        bytecode.extend_from_slice(&primary_node_inst);
628
629        // Add the additional node.
630        append_node_header(
631            &mut bytecode,
632            RawParentType::Additional,
633            3,
634            additional_node_inst.len() as u32,
635        );
636        bytecode.extend_from_slice(&additional_node_inst);
637
638        assert_eq!(
639            Err(BytecodeError::MissingEntryInSymbolTable(0x10000000)),
640            DecodedRules::new(bytecode)
641        );
642    }
643
644    #[test]
645    fn test_value_enum_missing_in_symbols_composite_primary() {
646        let mut bytecode: Vec<u8> = BIND_HEADER.to_vec();
647        bytecode.push(BYTECODE_DISABLE_DEBUG);
648        append_section_header(&mut bytecode, SYMB_MAGIC_NUM, 27);
649
650        let device_name: [u8; 5] = [0x49, 0x42, 0x49, 0x53, 0]; // "IBIS"
651        bytecode.extend_from_slice(&[1, 0, 0, 0]);
652        bytecode.extend_from_slice(&device_name);
653
654        let primary_node_name: [u8; 5] = [0x52, 0x41, 0x49, 0x4C, 0]; // "RAIL"
655        bytecode.extend_from_slice(&[2, 0, 0, 0]);
656        bytecode.extend_from_slice(&primary_node_name);
657
658        let node_name_1: [u8; 5] = [0x43, 0x4F, 0x4F, 0x54, 0]; // "COOT"
659        bytecode.extend_from_slice(&[3, 0, 0, 0]);
660        bytecode.extend_from_slice(&node_name_1);
661
662        // There is no enum value (type 0x04) with key 0x10000000.
663        let primary_node_inst = [0x02, 0x01, 0, 0, 0, 0x02, 0x04, 0, 0, 0, 0x10];
664
665        let additional_node_inst = [0x01, 0x01, 0, 0, 0, 0x05, 0x01, 0x10, 0, 0x20, 0];
666
667        let composite_insts_sz = COMPOSITE_NAME_ID_BYTES
668            + ((NODE_TYPE_HEADER_SZ * 2) + primary_node_inst.len() + additional_node_inst.len())
669                as u32;
670        append_section_header(&mut bytecode, COMPOSITE_MAGIC_NUM, composite_insts_sz);
671
672        // Add device name ID.
673        bytecode.extend_from_slice(&[1, 0, 0, 0]);
674
675        append_node_header(
676            &mut bytecode,
677            RawParentType::Primary,
678            2,
679            primary_node_inst.len() as u32,
680        );
681        bytecode.extend_from_slice(&primary_node_inst);
682
683        // Add the additional node.
684        append_node_header(
685            &mut bytecode,
686            RawParentType::Additional,
687            3,
688            additional_node_inst.len() as u32,
689        );
690        bytecode.extend_from_slice(&additional_node_inst);
691
692        assert_eq!(
693            Err(BytecodeError::MissingEntryInSymbolTable(0x10000000)),
694            DecodedRules::new(bytecode)
695        );
696    }
697
698    #[test]
699    fn test_value_enum_missing_in_symbols_composite_additional() {
700        let mut bytecode: Vec<u8> = BIND_HEADER.to_vec();
701        bytecode.push(BYTECODE_DISABLE_DEBUG);
702        append_section_header(&mut bytecode, SYMB_MAGIC_NUM, 27);
703
704        let device_name: [u8; 5] = [0x49, 0x42, 0x49, 0x53, 0]; // "IBIS"
705        bytecode.extend_from_slice(&[1, 0, 0, 0]);
706        bytecode.extend_from_slice(&device_name);
707
708        let primary_node_name: [u8; 5] = [0x52, 0x41, 0x49, 0x4C, 0]; // "RAIL"
709        bytecode.extend_from_slice(&[2, 0, 0, 0]);
710        bytecode.extend_from_slice(&primary_node_name);
711
712        let node_name_1: [u8; 5] = [0x43, 0x4F, 0x4F, 0x54, 0]; // "COOT"
713        bytecode.extend_from_slice(&[3, 0, 0, 0]);
714        bytecode.extend_from_slice(&node_name_1);
715
716        let primary_node_inst = [0x01, 0x01, 0, 0, 0, 0x05, 0x01, 0x10, 0, 0x20, 0];
717
718        // There is no enum value (type 0x04) with key 0x10000000.
719        let additional_node_inst = [0x02, 0x01, 0, 0, 0, 0x02, 0x04, 0, 0, 0, 0x10];
720
721        let composite_insts_sz = COMPOSITE_NAME_ID_BYTES
722            + ((NODE_TYPE_HEADER_SZ * 2) + primary_node_inst.len() + additional_node_inst.len())
723                as u32;
724        append_section_header(&mut bytecode, COMPOSITE_MAGIC_NUM, composite_insts_sz);
725
726        // Add device name ID.
727        bytecode.extend_from_slice(&[1, 0, 0, 0]);
728
729        append_node_header(
730            &mut bytecode,
731            RawParentType::Primary,
732            2,
733            primary_node_inst.len() as u32,
734        );
735        bytecode.extend_from_slice(&primary_node_inst);
736
737        // Add the additional node.
738        append_node_header(
739            &mut bytecode,
740            RawParentType::Additional,
741            3,
742            additional_node_inst.len() as u32,
743        );
744        bytecode.extend_from_slice(&additional_node_inst);
745
746        assert_eq!(
747            Err(BytecodeError::MissingEntryInSymbolTable(0x10000000)),
748            DecodedRules::new(bytecode)
749        );
750    }
751
752    #[test]
753    fn test_value_invalid_bool_composite_primary() {
754        let mut bytecode: Vec<u8> = BIND_HEADER.to_vec();
755        bytecode.push(BYTECODE_DISABLE_DEBUG);
756        append_section_header(&mut bytecode, SYMB_MAGIC_NUM, 27);
757
758        let device_name: [u8; 5] = [0x49, 0x42, 0x49, 0x53, 0]; // "IBIS"
759        bytecode.extend_from_slice(&[1, 0, 0, 0]);
760        bytecode.extend_from_slice(&device_name);
761
762        let primary_node_name: [u8; 5] = [0x52, 0x41, 0x49, 0x4C, 0]; // "RAIL"
763        bytecode.extend_from_slice(&[2, 0, 0, 0]);
764        bytecode.extend_from_slice(&primary_node_name);
765
766        let node_name_1: [u8; 5] = [0x43, 0x4F, 0x4F, 0x54, 0]; // "COOT"
767        bytecode.extend_from_slice(&[3, 0, 0, 0]);
768        bytecode.extend_from_slice(&node_name_1);
769
770        // 0x10000000 is not a valid bool value.
771        let primary_node_inst = [0x02, 0x01, 0, 0, 0, 0x02, 0x03, 0, 0, 0, 0x10];
772
773        let additional_node_inst = [0x01, 0x01, 0, 0, 0, 0x05, 0x01, 0x10, 0, 0x20, 0];
774
775        let composite_insts_sz = COMPOSITE_NAME_ID_BYTES
776            + ((NODE_TYPE_HEADER_SZ * 2) + primary_node_inst.len() + additional_node_inst.len())
777                as u32;
778        append_section_header(&mut bytecode, COMPOSITE_MAGIC_NUM, composite_insts_sz);
779
780        // Add device name ID.
781        bytecode.extend_from_slice(&[1, 0, 0, 0]);
782
783        append_node_header(
784            &mut bytecode,
785            RawParentType::Primary,
786            2,
787            primary_node_inst.len() as u32,
788        );
789        bytecode.extend_from_slice(&primary_node_inst);
790
791        // Add the additional node.
792        append_node_header(
793            &mut bytecode,
794            RawParentType::Additional,
795            3,
796            additional_node_inst.len() as u32,
797        );
798        bytecode.extend_from_slice(&additional_node_inst);
799
800        assert_eq!(Err(BytecodeError::InvalidBoolValue(0x10000000)), DecodedRules::new(bytecode));
801    }
802
803    #[test]
804    fn test_value_invalid_bool_composite_additional() {
805        let mut bytecode: Vec<u8> = BIND_HEADER.to_vec();
806        bytecode.push(BYTECODE_DISABLE_DEBUG);
807        append_section_header(&mut bytecode, SYMB_MAGIC_NUM, 27);
808
809        let device_name: [u8; 5] = [0x49, 0x42, 0x49, 0x53, 0]; // "IBIS"
810        bytecode.extend_from_slice(&[1, 0, 0, 0]);
811        bytecode.extend_from_slice(&device_name);
812
813        let primary_node_name: [u8; 5] = [0x52, 0x41, 0x49, 0x4C, 0]; // "RAIL"
814        bytecode.extend_from_slice(&[2, 0, 0, 0]);
815        bytecode.extend_from_slice(&primary_node_name);
816
817        let node_name_1: [u8; 5] = [0x43, 0x4F, 0x4F, 0x54, 0]; // "COOT"
818        bytecode.extend_from_slice(&[3, 0, 0, 0]);
819        bytecode.extend_from_slice(&node_name_1);
820
821        let primary_node_inst = [0x01, 0x01, 0, 0, 0, 0x05, 0x01, 0x10, 0, 0x20, 0];
822
823        // 0x10000000 is not a valid bool value.
824        let additional_node_inst = [0x02, 0x01, 0, 0, 0, 0x02, 0x03, 0, 0, 0, 0x10];
825
826        let composite_insts_sz = COMPOSITE_NAME_ID_BYTES
827            + ((NODE_TYPE_HEADER_SZ * 2) + primary_node_inst.len() + additional_node_inst.len())
828                as u32;
829        append_section_header(&mut bytecode, COMPOSITE_MAGIC_NUM, composite_insts_sz);
830
831        // Add device name ID.
832        bytecode.extend_from_slice(&[1, 0, 0, 0]);
833
834        append_node_header(
835            &mut bytecode,
836            RawParentType::Primary,
837            2,
838            primary_node_inst.len() as u32,
839        );
840        bytecode.extend_from_slice(&primary_node_inst);
841
842        // Add the additional node.
843        append_node_header(
844            &mut bytecode,
845            RawParentType::Additional,
846            3,
847            additional_node_inst.len() as u32,
848        );
849        bytecode.extend_from_slice(&additional_node_inst);
850
851        assert_eq!(Err(BytecodeError::InvalidBoolValue(0x10000000)), DecodedRules::new(bytecode));
852    }
853}