@@ -431,56 +431,36 @@ mod test {
431
431
TupleStruct :: arbitrary ( & mut unstructured) . unwrap ( )
432
432
}
433
433
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
+ ) {
457
443
// No-messed works
458
444
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) ;
462
446
let no_messed_nd = NonDeterminism :: default ( ) . with_ram ( no_messed_memory. clone ( ) ) ;
463
447
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 ( ) ) ;
465
449
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) ;
476
456
477
457
// Messed-up encoding fails: Too big but still u32
478
458
const POINTER_TO_MESSED_UP_SI : BFieldElement = BFieldElement :: new ( 5 ) ;
479
459
let mut messed_up_memory = no_messed_memory. clone ( ) ;
480
460
messed_up_memory. insert ( POINTER_TO_MESSED_UP_SI , bfe ! ( TupleStruct :: MAX_OFFSET + 1 ) ) ;
481
461
let messed_up_nd_0 = NonDeterminism :: default ( ) . with_ram ( messed_up_memory. clone ( ) ) ;
482
462
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 ( ) ) ;
484
464
let instruction_error = vm_state_fail0. run ( ) . unwrap_err ( ) ;
485
465
assert_eq ! ( InstructionError :: AssertionFailed , instruction_error, ) ;
486
466
@@ -490,14 +470,107 @@ mod test {
490
470
messed_up_memory. insert ( POINTER_TO_MESSED_UP_SI , negative_number) ;
491
471
let messed_up_nd_1 = NonDeterminism :: default ( ) . with_ram ( messed_up_memory. clone ( ) ) ;
492
472
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 ( ) ) ;
494
474
let instruction_error = vm_state_fail1. run ( ) . unwrap_err ( ) ;
495
475
assert_eq ! (
496
476
InstructionError :: FailedU32Conversion ( negative_number) ,
497
477
instruction_error,
498
478
) ;
499
479
}
500
480
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
+
501
574
#[ test]
502
575
fn load_and_decode_tuple_struct_containing_enums_from_memory ( ) {
503
576
let random_object = prepare_random_object ( random ( ) ) ;
0 commit comments