Skip to content

Commit 68a4a13

Browse files
committed
test(tasm_object): verify that all macros crash VM on bad lengths
Add negative tests for the `get_encoding_length` and `field_with_size` macros in addition to the test of the `field` macro that was already there.
1 parent f5af542 commit 68a4a13

File tree

1 file changed

+112
-39
lines changed

1 file changed

+112
-39
lines changed

tasm-lib/src/structure/tasm_object.rs

Lines changed: 112 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -431,56 +431,36 @@ mod test {
431431
TupleStruct::arbitrary(&mut unstructured).unwrap()
432432
}
433433

434-
#[test]
435-
fn mess_with_size_indicators_negative_test() {
436-
let random_object = prepare_random_object(random());
437-
438-
const START_OF_OBJ: BFieldElement = BFieldElement::ZERO;
439-
let third_to_last_field = field!(TupleStruct::field_4);
440-
let code = triton_asm!(
441-
// _
442-
443-
push {START_OF_OBJ}
444-
// _ *tuple_struct
445-
446-
{&third_to_last_field}
447-
// _ *digest
448-
449-
addi {Digest::LEN - 1}
450-
read_mem {Digest::LEN}
451-
pop 1
452-
// _ [digest]
453-
454-
halt
455-
);
456-
434+
/// Verify correct field-getter behavior when the dynamically-sized
435+
/// field of the `Vec<BFieldElement>`, 2nd to last field in
436+
/// `[TupleStruct]` gets a malicious size-indicator.
437+
fn prop_negative_test_messed_up_size_indicators(
438+
program: &Program,
439+
tuple_struct: &TupleStruct,
440+
obj_pointer: BFieldElement,
441+
expected_stack: &[BFieldElement],
442+
) {
457443
// No-messed works
458444
let mut no_messed_memory = HashMap::new();
459-
encode_to_memory(&mut no_messed_memory, START_OF_OBJ, &random_object);
460-
461-
let program = Program::new(&code);
445+
encode_to_memory(&mut no_messed_memory, obj_pointer, tuple_struct);
462446
let no_messed_nd = NonDeterminism::default().with_ram(no_messed_memory.clone());
463447
let mut vm_state_pass =
464-
VMState::new(&program, PublicInput::default(), no_messed_nd.clone());
448+
VMState::new(program, PublicInput::default(), no_messed_nd.clone());
465449
vm_state_pass.run().unwrap();
466-
assert_eq!(
467-
random_object.4.values(),
468-
[
469-
vm_state_pass.op_stack[0],
470-
vm_state_pass.op_stack[1],
471-
vm_state_pass.op_stack[2],
472-
vm_state_pass.op_stack[3],
473-
vm_state_pass.op_stack[4]
474-
]
475-
);
450+
451+
let expected_output_len = expected_stack.len();
452+
let actual_stack = (0..expected_output_len)
453+
.map(|i| vm_state_pass.op_stack[i])
454+
.collect_vec();
455+
assert_eq!(expected_stack, actual_stack);
476456

477457
// Messed-up encoding fails: Too big but still u32
478458
const POINTER_TO_MESSED_UP_SI: BFieldElement = BFieldElement::new(5);
479459
let mut messed_up_memory = no_messed_memory.clone();
480460
messed_up_memory.insert(POINTER_TO_MESSED_UP_SI, bfe!(TupleStruct::MAX_OFFSET + 1));
481461
let messed_up_nd_0 = NonDeterminism::default().with_ram(messed_up_memory.clone());
482462
let mut vm_state_fail0 =
483-
VMState::new(&program, PublicInput::default(), messed_up_nd_0.clone());
463+
VMState::new(program, PublicInput::default(), messed_up_nd_0.clone());
484464
let instruction_error = vm_state_fail0.run().unwrap_err();
485465
assert_eq!(InstructionError::AssertionFailed, instruction_error,);
486466

@@ -490,14 +470,107 @@ mod test {
490470
messed_up_memory.insert(POINTER_TO_MESSED_UP_SI, negative_number);
491471
let messed_up_nd_1 = NonDeterminism::default().with_ram(messed_up_memory.clone());
492472
let mut vm_state_fail1 =
493-
VMState::new(&program, PublicInput::default(), messed_up_nd_1.clone());
473+
VMState::new(program, PublicInput::default(), messed_up_nd_1.clone());
494474
let instruction_error = vm_state_fail1.run().unwrap_err();
495475
assert_eq!(
496476
InstructionError::FailedU32Conversion(negative_number),
497477
instruction_error,
498478
);
499479
}
500480

481+
#[test]
482+
fn mess_with_size_indicators_total_size_negative_test() {
483+
const START_OF_OBJ: BFieldElement = BFieldElement::ZERO;
484+
let random_object = prepare_random_object(random());
485+
let get_encoding_length = TupleStruct::get_encoding_length();
486+
let code_using_total_length_getter = triton_asm!(
487+
// _
488+
push { START_OF_OBJ }
489+
// _ *tuple_struct
490+
491+
{&get_encoding_length}
492+
// _ total_len
493+
494+
halt
495+
);
496+
497+
let program = Program::new(&code_using_total_length_getter);
498+
let expected_stack_benign_nd = [bfe!(random_object.encode().len() as u64)];
499+
prop_negative_test_messed_up_size_indicators(
500+
&program,
501+
&random_object,
502+
START_OF_OBJ,
503+
&expected_stack_benign_nd,
504+
);
505+
}
506+
507+
#[test]
508+
fn mess_with_size_indicators_field_and_size_getter_negative_test() {
509+
const START_OF_OBJ: BFieldElement = BFieldElement::ZERO;
510+
let random_object = prepare_random_object(random());
511+
let fourth_to_last_field = field_with_size!(TupleStruct::field_3);
512+
let code_using_field_and_size_getter = triton_asm!(
513+
// _
514+
push { START_OF_OBJ }
515+
// _ *tuple_struct
516+
517+
{&fourth_to_last_field}
518+
// _ *digests digests_size
519+
520+
swap 1
521+
// _ digests_size *digests
522+
523+
read_mem 1
524+
pop 1
525+
// _ digests_size digests_len
526+
527+
halt
528+
);
529+
530+
let program = Program::new(&code_using_field_and_size_getter);
531+
let expected_field_size = bfe!(random_object.3.len() as u64 * Digest::LEN as u64 + 1);
532+
let expected_list_len = bfe!(random_object.3.len() as u64);
533+
let expected_stack_benign_nd = [expected_list_len, expected_field_size];
534+
prop_negative_test_messed_up_size_indicators(
535+
&program,
536+
&random_object,
537+
START_OF_OBJ,
538+
&expected_stack_benign_nd,
539+
);
540+
}
541+
542+
#[test]
543+
fn mess_with_size_indicators_field_getter_negative_test() {
544+
const START_OF_OBJ: BFieldElement = BFieldElement::ZERO;
545+
let random_object = prepare_random_object(random());
546+
let third_to_last_field = field!(TupleStruct::field_4);
547+
let code_using_field_getter = triton_asm!(
548+
// _
549+
550+
push {START_OF_OBJ}
551+
// _ *tuple_struct
552+
553+
{&third_to_last_field}
554+
// _ *digest
555+
556+
addi {Digest::LEN - 1}
557+
read_mem {Digest::LEN}
558+
pop 1
559+
// _ [digest]
560+
561+
halt
562+
);
563+
564+
let program = Program::new(&code_using_field_getter);
565+
let expected_output_benign_nd = random_object.4.values();
566+
prop_negative_test_messed_up_size_indicators(
567+
&program,
568+
&random_object,
569+
START_OF_OBJ,
570+
&expected_output_benign_nd,
571+
);
572+
}
573+
501574
#[test]
502575
fn load_and_decode_tuple_struct_containing_enums_from_memory() {
503576
let random_object = prepare_random_object(random());

0 commit comments

Comments
 (0)