@@ -364,6 +364,24 @@ static int iter_string_set_next(YR_ITERATOR* self, YR_VALUE_STACK* stack)
364
364
return ERROR_SUCCESS ;
365
365
}
366
366
367
+ // Global table that contains the "next" function for different types of
368
+ // iterators. The reason for using this table is to avoid storing pointers
369
+ // in the YARA's VM stack. Instead of the pointers we store an index within
370
+ // this table.
371
+ static YR_ITERATOR_NEXT_FUNC iter_next_func_table [] = {
372
+ iter_array_next ,
373
+ iter_dict_next ,
374
+ iter_int_range_next ,
375
+ iter_int_enum_next ,
376
+ iter_string_set_next ,
377
+ };
378
+
379
+ #define ITER_NEXT_ARRAY 0
380
+ #define ITER_NEXT_DICT 1
381
+ #define ITER_NEXT_INT_RANGE 2
382
+ #define ITER_NEXT_INT_ENUM 3
383
+ #define ITER_NEXT_STRING_SET 4
384
+
367
385
int yr_execute_code (YR_SCAN_CONTEXT * context )
368
386
{
369
387
YR_DEBUG_FPRINTF (2 , stderr , "+ %s() {\n" , __FUNCTION__ );
@@ -466,7 +484,7 @@ int yr_execute_code(YR_SCAN_CONTEXT* context)
466
484
pop (r1 );
467
485
r2 .it -> array_it .array = r1 .o ;
468
486
r2 .it -> array_it .index = 0 ;
469
- r2 .it -> next = iter_array_next ;
487
+ r2 .it -> next_func_idx = ITER_NEXT_ARRAY ;
470
488
push (r2 );
471
489
}
472
490
@@ -487,7 +505,7 @@ int yr_execute_code(YR_SCAN_CONTEXT* context)
487
505
pop (r1 );
488
506
r2 .it -> dict_it .dict = r1 .o ;
489
507
r2 .it -> dict_it .index = 0 ;
490
- r2 .it -> next = iter_dict_next ;
508
+ r2 .it -> next_func_idx = ITER_NEXT_DICT ;
491
509
push (r2 );
492
510
}
493
511
@@ -511,7 +529,7 @@ int yr_execute_code(YR_SCAN_CONTEXT* context)
511
529
pop (r1 );
512
530
r3 .it -> int_range_it .next = r1 .i ;
513
531
r3 .it -> int_range_it .last = r2 .i ;
514
- r3 .it -> next = iter_int_range_next ;
532
+ r3 .it -> next_func_idx = ITER_NEXT_INT_RANGE ;
515
533
push (r3 );
516
534
}
517
535
@@ -537,7 +555,7 @@ int yr_execute_code(YR_SCAN_CONTEXT* context)
537
555
{
538
556
r3 .it -> int_enum_it .count = r1 .i ;
539
557
r3 .it -> int_enum_it .next = 0 ;
540
- r3 .it -> next = iter_int_enum_next ;
558
+ r3 .it -> next_func_idx = ITER_NEXT_INT_ENUM ;
541
559
542
560
for (int64_t i = r1 .i ; i > 0 ; i -- )
543
561
{
@@ -572,7 +590,7 @@ int yr_execute_code(YR_SCAN_CONTEXT* context)
572
590
{
573
591
r3 .it -> string_set_it .count = r1 .i ;
574
592
r3 .it -> string_set_it .index = 0 ;
575
- r3 .it -> next = iter_string_set_next ;
593
+ r3 .it -> next_func_idx = ITER_NEXT_STRING_SET ;
576
594
577
595
for (int64_t i = r1 .i ; i > 0 ; i -- )
578
596
{
@@ -594,11 +612,22 @@ int yr_execute_code(YR_SCAN_CONTEXT* context)
594
612
// Loads the iterator in r1, but leaves the iterator in the stack.
595
613
pop (r1 );
596
614
push (r1 );
597
- // The iterator's next function is responsible for pushing the next
598
- // item in the stack, and a boolean indicating if there are more items
599
- // to retrieve. The boolean will be at the top of the stack after
600
- // calling "next".
601
- result = r1 .it -> next (r1 .it , & stack );
615
+
616
+ if (r1 .it -> next_func_idx <
617
+ sizeof (iter_next_func_table ) / sizeof (YR_ITERATOR_NEXT_FUNC ))
618
+ {
619
+ // The iterator's next function is responsible for pushing the next
620
+ // item in the stack, and a boolean indicating if there are more items
621
+ // to retrieve. The boolean will be at the top of the stack after
622
+ // calling "next".
623
+ result = iter_next_func_table [r1 .it -> next_func_idx ](r1 .it , & stack );
624
+ }
625
+ else
626
+ {
627
+ // next_func_idx is outside the valid range, this should not happend.
628
+ result = ERROR_INTERNAL_FATAL_ERROR ;
629
+ }
630
+
602
631
stop = (result != ERROR_SUCCESS );
603
632
break ;
604
633
0 commit comments