Coverage Report

Created: 2025-07-23 06:46

/src/yara/libyara/exec.c
Line
Count
Source (jump to first uncovered line)
1
/*
2
Copyright (c) 2013-2014. The YARA Authors. All Rights Reserved.
3
4
Redistribution and use in source and binary forms, with or without modification,
5
are permitted provided that the following conditions are met:
6
7
1. Redistributions of source code must retain the above copyright notice, this
8
list of conditions and the following disclaimer.
9
10
2. Redistributions in binary form must reproduce the above copyright notice,
11
this list of conditions and the following disclaimer in the documentation and/or
12
other materials provided with the distribution.
13
14
3. Neither the name of the copyright holder nor the names of its contributors
15
may be used to endorse or promote products derived from this software without
16
specific prior written permission.
17
18
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
19
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
20
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
21
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
22
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
23
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
24
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
25
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
26
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
27
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28
*/
29
30
#include <assert.h>
31
#include <float.h>
32
#include <math.h>
33
#include <string.h>
34
#include <yara.h>
35
#include <yara/arena.h>
36
#include <yara/endian.h>
37
#include <yara/error.h>
38
#include <yara/exec.h>
39
#include <yara/globals.h>
40
#include <yara/limits.h>
41
#include <yara/mem.h>
42
#include <yara/modules.h>
43
#include <yara/object.h>
44
#include <yara/re.h>
45
#include <yara/sizedstr.h>
46
#include <yara/stopwatch.h>
47
#include <yara/strutils.h>
48
#include <yara/unaligned.h>
49
#include <yara/utils.h>
50
51
25.7k
#define MEM_SIZE YR_MAX_LOOP_NESTING*(YR_MAX_LOOP_VARS + YR_INTERNAL_LOOP_VARS)
52
53
#define push(x)                         \
54
208k
  if (stack.sp < stack.capacity)        \
55
208k
  {                                     \
56
208k
    stack.items[stack.sp++] = (x);      \
57
208k
  }                                     \
58
208k
  else                                  \
59
208k
  {                                     \
60
0
    result = ERROR_EXEC_STACK_OVERFLOW; \
61
0
    stop = true;                        \
62
0
    break;                              \
63
0
  }
64
65
#define pop(x)                   \
66
208k
  {                              \
67
208k
    assert(stack.sp > 0);        \
68
208k
    x = stack.items[--stack.sp]; \
69
208k
  }
70
71
203k
#define is_undef(x) IS_UNDEFINED((x).i)
72
73
#define ensure_defined(x) \
74
177k
  if (is_undef(x))        \
75
177k
  {                       \
76
56.0k
    r1.i = YR_UNDEFINED;  \
77
56.0k
    push(r1);             \
78
56.0k
    break;                \
79
56.0k
  }
80
81
#define ensure_within_mem(x)             \
82
0
  if (x < 0 || x >= MEM_SIZE)            \
83
0
  {                                      \
84
0
    stop = true;                         \
85
0
    result = ERROR_INTERNAL_FATAL_ERROR; \
86
0
    break;                               \
87
0
  }
88
89
// Make sure that the string pointer is within the rules arena.
90
#define ensure_within_rules_arena(x)                              \
91
135k
  {                                                               \
92
135k
    YR_ARENA_REF ref;                                             \
93
135k
    if (yr_arena_ptr_to_ref(context->rules->arena, x, &ref) == 0) \
94
135k
    {                                                             \
95
0
      stop = true;                                                \
96
0
      result = ERROR_INTERNAL_FATAL_ERROR;                        \
97
0
      break;                                                      \
98
0
    }                                                             \
99
135k
  }
100
101
#define check_object_canary(o)           \
102
42.2k
  if (o->canary != context->canary)      \
103
42.2k
  {                                      \
104
0
    stop = true;                         \
105
0
    result = ERROR_INTERNAL_FATAL_ERROR; \
106
0
    break;                               \
107
0
  }
108
109
0
#define little_endian_uint8_t(x)  (x)
110
0
#define little_endian_int8_t(x)   (x)
111
0
#define little_endian_uint16_t(x) yr_le16toh(x)
112
0
#define little_endian_int16_t(x)  yr_le16toh(x)
113
0
#define little_endian_uint32_t(x) yr_le32toh(x)
114
0
#define little_endian_int32_t(x)  yr_le32toh(x)
115
116
0
#define big_endian_uint8_t(x)  (x)
117
0
#define big_endian_int8_t(x)   (x)
118
0
#define big_endian_uint16_t(x) yr_be16toh(x)
119
0
#define big_endian_int16_t(x)  yr_be16toh(x)
120
0
#define big_endian_uint32_t(x) yr_be32toh(x)
121
0
#define big_endian_int32_t(x)  yr_be32toh(x)
122
123
#define function_read(type, endianess)                            \
124
  int64_t read_##type##_##endianess(                              \
125
      YR_MEMORY_BLOCK_ITERATOR* iterator, size_t offset)          \
126
0
  {                                                               \
127
0
    YR_MEMORY_BLOCK* block = iterator->first(iterator);           \
128
0
    while (block != NULL)                                         \
129
0
    {                                                             \
130
0
      if (offset >= block->base && block->size >= sizeof(type) && \
131
0
          offset <= block->base + block->size - sizeof(type))     \
132
0
      {                                                           \
133
0
        type result;                                              \
134
0
        const uint8_t* data = yr_fetch_block_data(block);         \
135
0
        if (data == NULL)                                         \
136
0
          return YR_UNDEFINED;                                    \
137
0
        result = *(type*) (data + offset - block->base);          \
138
0
        result = endianess##_##type(result);                      \
139
0
        return result;                                            \
140
0
      }                                                           \
141
0
      block = iterator->next(iterator);                           \
142
0
    }                                                             \
143
0
    return YR_UNDEFINED;                                          \
144
0
  };
Unexecuted instantiation: read_uint8_t_little_endian
Unexecuted instantiation: read_uint16_t_little_endian
Unexecuted instantiation: read_uint32_t_little_endian
Unexecuted instantiation: read_int8_t_little_endian
Unexecuted instantiation: read_int16_t_little_endian
Unexecuted instantiation: read_int32_t_little_endian
Unexecuted instantiation: read_uint8_t_big_endian
Unexecuted instantiation: read_uint16_t_big_endian
Unexecuted instantiation: read_uint32_t_big_endian
Unexecuted instantiation: read_int8_t_big_endian
Unexecuted instantiation: read_int16_t_big_endian
Unexecuted instantiation: read_int32_t_big_endian
145
146
function_read(uint8_t, little_endian);
147
function_read(uint16_t, little_endian);
148
function_read(uint32_t, little_endian);
149
function_read(int8_t, little_endian);
150
function_read(int16_t, little_endian);
151
function_read(int32_t, little_endian);
152
function_read(uint8_t, big_endian);
153
function_read(uint16_t, big_endian);
154
function_read(uint32_t, big_endian);
155
function_read(int8_t, big_endian);
156
function_read(int16_t, big_endian);
157
function_read(int32_t, big_endian);
158
159
static const uint8_t* jmp_if(int condition, const uint8_t* ip)
160
18.4k
{
161
18.4k
  int32_t off = 0;
162
163
18.4k
  if (condition)
164
0
  {
165
    // The condition is true, the instruction pointer (ip) is incremented in
166
    // the amount specified by the jump's offset, which is a int32_t following
167
    // the jump opcode. The ip is currently past the opcode and pointing to
168
    // the offset.
169
170
    // Copy the offset from the instruction stream to a local variable.
171
0
    off = yr_unaligned_u32(ip);
172
173
    // The offset is relative to the jump opcode, but now the ip is one byte
174
    // past the opcode, so we need to decrement it by one.
175
0
    off -= 1;
176
0
  }
177
18.4k
  else
178
18.4k
  {
179
    // The condition is false, the execution flow proceeds with the instruction
180
    // right after the jump.
181
18.4k
    off = sizeof(int32_t);
182
18.4k
  }
183
184
18.4k
  return ip + off;
185
18.4k
}
186
187
static int iter_array_next(YR_ITERATOR* self, YR_VALUE_STACK* stack)
188
0
{
189
  // Check that there's two available slots in the stack, one for the next
190
  // item returned by the iterator and another one for the boolean that
191
  // indicates if there are more items.
192
0
  if (stack->sp + 1 >= stack->capacity)
193
0
    return ERROR_EXEC_STACK_OVERFLOW;
194
195
  // If the array that must be iterated is undefined stop the iteration right
196
  // aways, as if the array would be empty.
197
0
  if (IS_UNDEFINED(self->array_it.array))
198
0
    goto _stop_iter;
199
200
  // If the current index is equal or larger than array's length the iterator
201
  // has reached the end of the array.
202
0
  if (self->array_it.index >= yr_object_array_length(self->array_it.array))
203
0
    goto _stop_iter;
204
205
  // Push the false value that indicates that the iterator is not exhausted.
206
0
  stack->items[stack->sp++].i = 0;
207
208
0
  YR_OBJECT* obj = yr_object_array_get_item(
209
0
      self->array_it.array, 0, self->array_it.index);
210
211
0
  if (obj != NULL)
212
0
    stack->items[stack->sp++].o = obj;
213
0
  else
214
0
    stack->items[stack->sp++].i = YR_UNDEFINED;
215
216
0
  self->array_it.index++;
217
218
0
  return ERROR_SUCCESS;
219
220
0
_stop_iter:
221
222
  // Push true for indicating the iterator has been exhausted.
223
0
  stack->items[stack->sp++].i = 1;
224
  // Push YR_UNDEFINED as a placeholder for the next item.
225
0
  stack->items[stack->sp++].i = YR_UNDEFINED;
226
227
0
  return ERROR_SUCCESS;
228
0
}
229
230
static int iter_dict_next(YR_ITERATOR* self, YR_VALUE_STACK* stack)
231
0
{
232
  // Check that there's three available slots in the stack, two for the next
233
  // item returned by the iterator and its key, and another one for the boolean
234
  // that indicates if there are more items.
235
0
  if (stack->sp + 2 >= stack->capacity)
236
0
    return ERROR_EXEC_STACK_OVERFLOW;
237
238
  // If the dictionary that must be iterated is undefined, stop the iteration
239
  // right away, as if the dictionary would be empty.
240
0
  if (IS_UNDEFINED(self->dict_it.dict))
241
0
    goto _stop_iter;
242
243
0
  YR_DICTIONARY_ITEMS* items = object_as_dictionary(self->dict_it.dict)->items;
244
245
  // If the dictionary has no items or the iterator reached the last item, abort
246
  // the iteration, if not push the next key and value.
247
0
  if (items == NULL || self->dict_it.index == items->used)
248
0
    goto _stop_iter;
249
250
  // Push the false value that indicates that the iterator is not exhausted.
251
0
  stack->items[stack->sp++].i = 0;
252
253
0
  if (items->objects[self->dict_it.index].obj != NULL)
254
0
  {
255
0
    stack->items[stack->sp++].o = items->objects[self->dict_it.index].obj;
256
0
    stack->items[stack->sp++].p = items->objects[self->dict_it.index].key;
257
0
  }
258
0
  else
259
0
  {
260
0
    stack->items[stack->sp++].i = YR_UNDEFINED;
261
0
    stack->items[stack->sp++].i = YR_UNDEFINED;
262
0
  }
263
264
0
  self->dict_it.index++;
265
266
0
  return ERROR_SUCCESS;
267
268
0
_stop_iter:
269
270
  // Push true for indicating the iterator has been exhausted.
271
0
  stack->items[stack->sp++].i = 1;
272
  // Push YR_UNDEFINED as a placeholder for the next key and value.
273
0
  stack->items[stack->sp++].i = YR_UNDEFINED;
274
0
  stack->items[stack->sp++].i = YR_UNDEFINED;
275
276
0
  return ERROR_SUCCESS;
277
0
}
278
279
static int iter_int_range_next(YR_ITERATOR* self, YR_VALUE_STACK* stack)
280
0
{
281
  // Check that there's two available slots in the stack, one for the next
282
  // item returned by the iterator and another one for the boolean that
283
  // indicates if there are more items.
284
0
  if (stack->sp + 1 >= stack->capacity)
285
0
    return ERROR_EXEC_STACK_OVERFLOW;
286
287
0
  if (!IS_UNDEFINED(self->int_range_it.next) &&
288
0
      !IS_UNDEFINED(self->int_range_it.last) &&
289
0
      self->int_range_it.next <= self->int_range_it.last)
290
0
  {
291
    // Push the false value that indicates that the iterator is not exhausted.
292
0
    stack->items[stack->sp++].i = 0;
293
0
    stack->items[stack->sp++].i = self->int_range_it.next;
294
0
    self->int_range_it.next++;
295
0
  }
296
0
  else
297
0
  {
298
    // Push true for indicating the iterator has been exhausted.
299
0
    stack->items[stack->sp++].i = 1;
300
    // Push YR_UNDEFINED as a placeholder for the next item.
301
0
    stack->items[stack->sp++].i = YR_UNDEFINED;
302
0
  }
303
304
0
  return ERROR_SUCCESS;
305
0
}
306
307
static int iter_int_enum_next(YR_ITERATOR* self, YR_VALUE_STACK* stack)
308
0
{
309
  // Check that there's two available slots in the stack, one for the next
310
  // item returned by the iterator and another one for the boolean that
311
  // indicates if there are more items.
312
0
  if (stack->sp + 1 >= stack->capacity)
313
0
    return ERROR_EXEC_STACK_OVERFLOW;
314
315
0
  if (!IS_UNDEFINED(self->int_enum_it.next) &&
316
0
      !IS_UNDEFINED(self->int_enum_it.count) &&
317
0
      self->int_enum_it.next < self->int_enum_it.count)
318
0
  {
319
    // Push the false value that indicates that the iterator is not exhausted.
320
0
    stack->items[stack->sp++].i = 0;
321
0
    stack->items[stack->sp++].i =
322
0
        self->int_enum_it.items[self->int_enum_it.next];
323
0
    self->int_enum_it.next++;
324
0
  }
325
0
  else
326
0
  {
327
    // Push true for indicating the iterator has been exhausted.
328
0
    stack->items[stack->sp++].i = 1;
329
    // Push YR_UNDEFINED as a placeholder for the next item.
330
0
    stack->items[stack->sp++].i = YR_UNDEFINED;
331
0
  }
332
333
0
  return ERROR_SUCCESS;
334
0
}
335
336
static int iter_string_set_next(YR_ITERATOR* self, YR_VALUE_STACK* stack)
337
0
{
338
  // Check that there's two available slots in the stack, one for the next
339
  // item returned by the iterator and another one for the boolean that
340
  // indicates if there are more items.
341
0
  if (stack->sp + 1 >= stack->capacity)
342
0
    return ERROR_EXEC_STACK_OVERFLOW;
343
344
  // If the current index is equal or larger than array's length the iterator
345
  // has reached the end of the array.
346
0
  if (self->string_set_it.index >= self->string_set_it.count)
347
0
    goto _stop_iter;
348
349
  // Push the false value that indicates that the iterator is not exhausted.
350
0
  stack->items[stack->sp++].i = 0;
351
0
  stack->items[stack->sp++].s =
352
0
      self->string_set_it.strings[self->string_set_it.index];
353
0
  self->string_set_it.index++;
354
355
0
  return ERROR_SUCCESS;
356
357
0
_stop_iter:
358
359
  // Push true for indicating the iterator has been exhausted.
360
0
  stack->items[stack->sp++].i = 1;
361
  // Push YR_UNDEFINED as a placeholder for the next item.
362
0
  stack->items[stack->sp++].i = YR_UNDEFINED;
363
364
0
  return ERROR_SUCCESS;
365
0
}
366
367
static int iter_text_string_set_next(YR_ITERATOR* self, YR_VALUE_STACK* stack)
368
0
{
369
  // Check that there's two available slots in the stack, one for the next
370
  // item returned by the iterator and another one for the boolean that
371
  // indicates if there are more items.
372
0
  if (stack->sp + 1 >= stack->capacity)
373
0
    return ERROR_EXEC_STACK_OVERFLOW;
374
375
  // If the current index is equal or larger than array's length the iterator
376
  // has reached the end of the array.
377
0
  if (self->text_string_set_it.index >= self->text_string_set_it.count)
378
0
    goto _stop_iter;
379
380
  // Push the false value that indicates that the iterator is not exhausted.
381
0
  stack->items[stack->sp++].i = 0;
382
0
  stack->items[stack->sp++].ss =
383
0
      self->text_string_set_it.strings[self->text_string_set_it.index];
384
0
  self->text_string_set_it.index++;
385
386
0
  return ERROR_SUCCESS;
387
388
0
_stop_iter:
389
390
  // Push true for indicating the iterator has been exhausted.
391
0
  stack->items[stack->sp++].i = 1;
392
  // Push YR_UNDEFINED as a placeholder for the next item.
393
0
  stack->items[stack->sp++].i = YR_UNDEFINED;
394
395
0
  return ERROR_SUCCESS;
396
0
}
397
398
// Global table that contains the "next" function for different types of
399
// iterators. The reason for using this table is to avoid storing pointers
400
// in the YARA's VM stack. Instead of the pointers we store an index within
401
// this table.
402
static YR_ITERATOR_NEXT_FUNC iter_next_func_table[] = {
403
    iter_array_next,
404
    iter_dict_next,
405
    iter_int_range_next,
406
    iter_int_enum_next,
407
    iter_string_set_next,
408
    iter_text_string_set_next,
409
};
410
411
0
#define ITER_NEXT_ARRAY           0
412
0
#define ITER_NEXT_DICT            1
413
0
#define ITER_NEXT_INT_RANGE       2
414
0
#define ITER_NEXT_INT_ENUM        3
415
0
#define ITER_NEXT_STRING_SET      4
416
0
#define ITER_NEXT_TEXT_STRING_SET 5
417
418
int yr_execute_code(YR_SCAN_CONTEXT* context)
419
25.7k
{
420
25.7k
  YR_DEBUG_FPRINTF(2, stderr, "+ %s() {\n", __FUNCTION__);
421
422
25.7k
  const uint8_t* ip = context->rules->code_start;
423
424
25.7k
  YR_VALUE mem[MEM_SIZE];
425
25.7k
  YR_VALUE args[YR_MAX_FUNCTION_ARGS];
426
25.7k
  YR_VALUE r1;
427
25.7k
  YR_VALUE r2;
428
25.7k
  YR_VALUE r3;
429
25.7k
  YR_VALUE r4;
430
431
25.7k
  YR_VALUE_STACK stack;
432
433
25.7k
  uint64_t elapsed_time;
434
435
#ifdef YR_PROFILING_ENABLED
436
  uint64_t start_time;
437
#endif
438
439
25.7k
  uint32_t current_rule_idx = 0;
440
25.7k
  YR_RULE* current_rule = NULL;
441
25.7k
  YR_RULE* rule;
442
25.7k
  YR_MATCH* match;
443
25.7k
  YR_OBJECT_FUNCTION* function;
444
25.7k
  YR_OBJECT** obj_ptr;
445
25.7k
  YR_ARENA* obj_arena;
446
25.7k
  YR_NOTEBOOK* it_notebook;
447
448
25.7k
  char* identifier;
449
25.7k
  char* args_fmt;
450
451
25.7k
  int found;
452
25.7k
  int count;
453
25.7k
  int result = ERROR_SUCCESS;
454
25.7k
  int cycle = 0;
455
25.7k
  int obj_count = 0;
456
457
25.7k
  bool stop = false;
458
459
25.7k
  uint8_t opcode;
460
461
25.7k
  yr_get_configuration_uint32(YR_CONFIG_STACK_SIZE, &stack.capacity);
462
463
25.7k
  stack.sp = 0;
464
25.7k
  stack.items = (YR_VALUE*) yr_malloc(stack.capacity * sizeof(YR_VALUE));
465
466
25.7k
  if (stack.items == NULL)
467
0
    return ERROR_INSUFFICIENT_MEMORY;
468
469
25.7k
  FAIL_ON_ERROR_WITH_CLEANUP(
470
25.7k
      yr_arena_create(1, 512 * sizeof(YR_OBJECT*), &obj_arena),
471
25.7k
      yr_free(stack.items));
472
473
25.7k
  FAIL_ON_ERROR_WITH_CLEANUP(
474
25.7k
      yr_notebook_create(512 * sizeof(YR_ITERATOR), &it_notebook),
475
25.7k
      yr_arena_release(obj_arena);
476
25.7k
      yr_free(stack.items));
477
478
#ifdef YR_PROFILING_ENABLED
479
  start_time = yr_stopwatch_elapsed_ns(&context->stopwatch);
480
#endif
481
482
25.7k
#if YR_PARANOID_EXEC
483
25.7k
  memset(mem, 0, MEM_SIZE * sizeof(mem[0]));
484
25.7k
#endif
485
486
322k
  while (!stop)
487
296k
  {
488
    // Read the opcode from the address indicated by the instruction pointer.
489
296k
    opcode = *ip;
490
491
    // Advance the instruction pointer, which now points past the opcode.
492
296k
    ip++;
493
494
296k
    switch (opcode)
495
296k
    {
496
0
    case OP_NOP:
497
0
      YR_DEBUG_FPRINTF(2, stderr, "- case OP_NOP: // %s()\n", __FUNCTION__);
498
0
      break;
499
500
25.7k
    case OP_HALT:
501
25.7k
      YR_DEBUG_FPRINTF(2, stderr, "- case OP_HALT: // %s()\n", __FUNCTION__);
502
25.7k
      assert(stack.sp == 0);  // When HALT is reached the stack should be empty.
503
25.7k
      stop = true;
504
25.7k
      break;
505
506
0
    case OP_ITER_START_ARRAY:
507
0
      YR_DEBUG_FPRINTF(
508
0
          2, stderr, "- case OP_ITER_START_ARRAY: // %s()\n", __FUNCTION__);
509
0
      r2.p = yr_notebook_alloc(it_notebook, sizeof(YR_ITERATOR));
510
511
0
      if (r2.p == NULL)
512
0
      {
513
0
        result = ERROR_INSUFFICIENT_MEMORY;
514
0
      }
515
0
      else
516
0
      {
517
0
        pop(r1);
518
0
        r2.it->array_it.array = r1.o;
519
0
        r2.it->array_it.index = 0;
520
0
        r2.it->next_func_idx = ITER_NEXT_ARRAY;
521
0
        push(r2);
522
0
      }
523
524
0
      stop = (result != ERROR_SUCCESS);
525
0
      break;
526
527
0
    case OP_ITER_START_DICT:
528
0
      YR_DEBUG_FPRINTF(
529
0
          2, stderr, "- case OP_ITER_START_DICT: // %s()\n", __FUNCTION__);
530
0
      r2.p = yr_notebook_alloc(it_notebook, sizeof(YR_ITERATOR));
531
532
0
      if (r2.p == NULL)
533
0
      {
534
0
        result = ERROR_INSUFFICIENT_MEMORY;
535
0
      }
536
0
      else
537
0
      {
538
0
        pop(r1);
539
0
        r2.it->dict_it.dict = r1.o;
540
0
        r2.it->dict_it.index = 0;
541
0
        r2.it->next_func_idx = ITER_NEXT_DICT;
542
0
        push(r2);
543
0
      }
544
545
0
      stop = (result != ERROR_SUCCESS);
546
0
      break;
547
548
0
    case OP_ITER_START_INT_RANGE:
549
0
      YR_DEBUG_FPRINTF(
550
0
          2, stderr, "- case OP_ITER_START_INT_RANGE: // %s()\n", __FUNCTION__);
551
      // Creates an iterator for an integer range. The higher bound of the
552
      // range is at the top of the stack followed by the lower bound.
553
0
      r3.p = yr_notebook_alloc(it_notebook, sizeof(YR_ITERATOR));
554
555
0
      if (r3.p == NULL)
556
0
      {
557
0
        result = ERROR_INSUFFICIENT_MEMORY;
558
0
      }
559
0
      else
560
0
      {
561
0
        pop(r2);
562
0
        pop(r1);
563
0
        r3.it->int_range_it.next = r1.i;
564
0
        r3.it->int_range_it.last = r2.i;
565
0
        r3.it->next_func_idx = ITER_NEXT_INT_RANGE;
566
0
        push(r3);
567
0
      }
568
569
0
      stop = (result != ERROR_SUCCESS);
570
0
      break;
571
572
0
    case OP_ITER_START_INT_ENUM:
573
0
      YR_DEBUG_FPRINTF(
574
0
          2, stderr, "- case OP_ITER_START_INT_ENUM: // %s()\n", __FUNCTION__);
575
      // Creates an iterator for an integer enumeration. The number of items
576
      // in the enumeration is at the top of the stack, followed by the
577
      // items in reverse order.
578
0
      pop(r1);
579
580
0
      r3.p = yr_notebook_alloc(
581
0
          it_notebook, sizeof(YR_ITERATOR) + sizeof(uint64_t) * (size_t) r1.i);
582
583
0
      if (r3.p == NULL)
584
0
      {
585
0
        result = ERROR_INSUFFICIENT_MEMORY;
586
0
      }
587
0
      else
588
0
      {
589
0
        r3.it->int_enum_it.count = r1.i;
590
0
        r3.it->int_enum_it.next = 0;
591
0
        r3.it->next_func_idx = ITER_NEXT_INT_ENUM;
592
593
0
        for (int64_t i = r1.i; i > 0; i--)
594
0
        {
595
0
          pop(r2);
596
0
          r3.it->int_enum_it.items[i - 1] = r2.i;
597
0
        }
598
599
0
        push(r3);
600
0
      }
601
602
0
      stop = (result != ERROR_SUCCESS);
603
0
      break;
604
605
0
    case OP_ITER_START_STRING_SET:
606
0
      YR_DEBUG_FPRINTF(
607
0
          2,
608
0
          stderr,
609
0
          "- case OP_ITER_START_STRING_SET: // %s()\n",
610
0
          __FUNCTION__);
611
612
0
      pop(r1);
613
614
0
      r3.p = yr_notebook_alloc(
615
0
          it_notebook,
616
0
          sizeof(YR_ITERATOR) + sizeof(YR_STRING*) * (size_t) r1.i);
617
618
0
      if (r3.p == NULL)
619
0
      {
620
0
        result = ERROR_INSUFFICIENT_MEMORY;
621
0
      }
622
0
      else
623
0
      {
624
0
        r3.it->string_set_it.count = r1.i;
625
0
        r3.it->string_set_it.index = 0;
626
0
        r3.it->next_func_idx = ITER_NEXT_STRING_SET;
627
628
0
        for (int64_t i = r1.i; i > 0; i--)
629
0
        {
630
0
          pop(r2);
631
0
          r3.it->string_set_it.strings[i - 1] = r2.s;
632
0
        }
633
634
        // One last pop of the UNDEFINED string
635
0
        pop(r2);
636
0
        push(r3);
637
0
      }
638
639
0
      stop = (result != ERROR_SUCCESS);
640
0
      break;
641
642
0
    case OP_ITER_START_TEXT_STRING_SET:
643
0
      YR_DEBUG_FPRINTF(
644
0
          2,
645
0
          stderr,
646
0
          "- case OP_ITER_START_TEXT_STRING_SET: // %s()\n",
647
0
          __FUNCTION__);
648
649
0
      pop(r1);
650
651
0
      r3.p = yr_notebook_alloc(
652
0
          it_notebook,
653
0
          sizeof(YR_ITERATOR) + sizeof(SIZED_STRING*) * (size_t) r1.i);
654
655
0
      if (r3.p == NULL)
656
0
      {
657
0
        result = ERROR_INSUFFICIENT_MEMORY;
658
0
      }
659
0
      else
660
0
      {
661
0
        r3.it->text_string_set_it.count = r1.i;
662
0
        r3.it->text_string_set_it.index = 0;
663
0
        r3.it->next_func_idx = ITER_NEXT_TEXT_STRING_SET;
664
665
0
        for (int64_t i = r1.i; i > 0; i--)
666
0
        {
667
0
          pop(r2);
668
0
          r3.it->text_string_set_it.strings[i - 1] = r2.ss;
669
0
        }
670
671
0
        push(r3);
672
0
      }
673
674
0
      stop = (result != ERROR_SUCCESS);
675
0
      break;
676
677
0
    case OP_ITER_NEXT:
678
0
      YR_DEBUG_FPRINTF(
679
0
          2, stderr, "- case OP_ITER_NEXT: // %s()\n", __FUNCTION__);
680
      // Loads the iterator in r1, but leaves the iterator in the stack.
681
0
      pop(r1);
682
0
      push(r1);
683
684
0
      if (r1.it->next_func_idx <
685
0
          sizeof(iter_next_func_table) / sizeof(YR_ITERATOR_NEXT_FUNC))
686
0
      {
687
        // The iterator's next function is responsible for pushing the next
688
        // item in the stack, and a boolean indicating if there are more items
689
        // to retrieve. The boolean will be at the top of the stack after
690
        // calling "next".
691
0
        result = iter_next_func_table[r1.it->next_func_idx](r1.it, &stack);
692
0
      }
693
0
      else
694
0
      {
695
        // next_func_idx is outside the valid range, this should not happend.
696
0
        result = ERROR_INTERNAL_FATAL_ERROR;
697
0
      }
698
699
0
      stop = (result != ERROR_SUCCESS);
700
0
      break;
701
702
0
    case OP_ITER_CONDITION:
703
0
      YR_DEBUG_FPRINTF(
704
0
          2, stderr, "- case OP_ITER_CONDITION: // %s()\n", __FUNCTION__);
705
706
      // Evaluate the iteration condition of the loop. This instruction
707
      // evaluates to 1 if the loop should continue and 0 if it shouldn't
708
      // (due to short-circuit evaluation).
709
710
0
      pop(r2);  // min. expression - all, any, none, integer
711
0
      pop(r3);  // number of true expressions
712
0
      pop(r4);  // last expression result
713
714
      // In case of 'all' loop, end once we the body failed
715
0
      if (is_undef(r2))
716
0
      {
717
0
        r1.i = r4.i != 0 ? 1 : 0;
718
0
      }
719
      // In case of 'none' loop, end once the body succeed
720
0
      else if (r2.i == 0)
721
0
      {
722
0
        r1.i = r4.i != 1 ? 1 : 0;
723
0
      }
724
      // In case of other loops, end once we satified min. expr.
725
0
      else
726
0
      {
727
0
        r1.i = r3.i + r4.i < r2.i ? 1 : 0;
728
0
      }
729
730
      // Push whether loop should continue and repush
731
      // the last expression result
732
0
      push(r1);
733
0
      push(r4);
734
0
      break;
735
736
0
    case OP_ITER_END:
737
0
      YR_DEBUG_FPRINTF(
738
0
          2, stderr, "- case OP_ITER_END: // %s()\n", __FUNCTION__);
739
740
      // Evaluate the whole loop. Whether it was successful or not
741
      // and whether it satisfied it's quantifier.
742
743
0
      pop(r2);  // min. expression - all, any, none, integer
744
0
      pop(r3);  // number of true expressions
745
0
      pop(r4);  // number of total iterations
746
747
      // If there was 0 iterations in total, it doesn't
748
      // matter what other numbers show. We can't evaluate
749
      // the loop as true.
750
0
      if (r4.i == 0)
751
0
      {
752
0
        r1.i = 0;
753
0
      }
754
0
      else if (is_undef(r2))
755
0
      {
756
0
        r1.i = r3.i == r4.i ? 1 : 0;
757
0
      }
758
0
      else if (r2.i == 0)
759
0
      {
760
0
        r1.i = r3.i == 0 ? 1 : 0;
761
0
      }
762
0
      else
763
0
      {
764
0
        r1.i = r3.i >= r2.i ? 1 : 0;
765
0
      }
766
767
0
      push(r1);
768
0
      break;
769
770
10.8k
    case OP_PUSH:
771
10.8k
      YR_DEBUG_FPRINTF(2, stderr, "- case OP_PUSH: // %s()\n", __FUNCTION__);
772
10.8k
      r1.i = yr_unaligned_u64(ip);
773
10.8k
      ip += sizeof(uint64_t);
774
10.8k
      push(r1);
775
10.8k
      break;
776
777
23.4k
    case OP_PUSH_8:
778
23.4k
      r1.i = *ip;
779
23.4k
      YR_DEBUG_FPRINTF(
780
23.4k
          2,
781
23.4k
          stderr,
782
23.4k
          "- case OP_PUSH_8: r1.i=%" PRId64 " // %s()\n",
783
23.4k
          r1.i,
784
23.4k
          __FUNCTION__);
785
23.4k
      ip += sizeof(uint8_t);
786
23.4k
      push(r1);
787
23.4k
      break;
788
789
0
    case OP_PUSH_16:
790
0
      r1.i = yr_unaligned_u16(ip);
791
0
      YR_DEBUG_FPRINTF(
792
0
          2,
793
0
          stderr,
794
0
          "- case OP_PUSH_16: r1.i=%" PRId64 " // %s()\n",
795
0
          r1.i,
796
0
          __FUNCTION__);
797
0
      ip += sizeof(uint16_t);
798
0
      push(r1);
799
0
      break;
800
801
0
    case OP_PUSH_32:
802
0
      r1.i = yr_unaligned_u32(ip);
803
0
      YR_DEBUG_FPRINTF(
804
0
          2,
805
0
          stderr,
806
0
          "- case OP_PUSH_32: r1.i=%" PRId64 " // %s()\n",
807
0
          r1.i,
808
0
          __FUNCTION__);
809
0
      ip += sizeof(uint32_t);
810
0
      push(r1);
811
0
      break;
812
813
0
    case OP_PUSH_U:
814
0
      YR_DEBUG_FPRINTF(2, stderr, "- case OP_PUSH_U: // %s()\n", __FUNCTION__);
815
0
      r1.i = YR_UNDEFINED;
816
0
      push(r1);
817
0
      break;
818
819
0
    case OP_POP:
820
0
      YR_DEBUG_FPRINTF(2, stderr, "- case OP_POP: // %s()\n", __FUNCTION__);
821
0
      pop(r1);
822
0
      break;
823
824
0
    case OP_CLEAR_M:
825
0
      YR_DEBUG_FPRINTF(2, stderr, "- case OP_CLEAR_M: // %s()\n", __FUNCTION__);
826
0
      r1.i = yr_unaligned_u64(ip);
827
0
      ip += sizeof(uint64_t);
828
0
#if YR_PARANOID_EXEC
829
0
      ensure_within_mem(r1.i);
830
0
#endif
831
0
      mem[r1.i].i = 0;
832
0
      break;
833
834
0
    case OP_ADD_M:
835
0
      YR_DEBUG_FPRINTF(2, stderr, "- case OP_ADD_M: // %s()\n", __FUNCTION__);
836
0
      r1.i = yr_unaligned_u64(ip);
837
0
      ip += sizeof(uint64_t);
838
0
#if YR_PARANOID_EXEC
839
0
      ensure_within_mem(r1.i);
840
0
#endif
841
0
      pop(r2);
842
0
      if (!is_undef(r2))
843
0
        mem[r1.i].i += r2.i;
844
0
      break;
845
846
0
    case OP_INCR_M:
847
0
      YR_DEBUG_FPRINTF(2, stderr, "- case OP_INCR_M: // %s()\n", __FUNCTION__);
848
0
      r1.i = yr_unaligned_u64(ip);
849
0
      ip += sizeof(uint64_t);
850
0
#if YR_PARANOID_EXEC
851
0
      ensure_within_mem(r1.i);
852
0
#endif
853
0
      mem[r1.i].i++;
854
0
      break;
855
856
0
    case OP_PUSH_M:
857
0
      YR_DEBUG_FPRINTF(2, stderr, "- case OP_PUSH_M: // %s()\n", __FUNCTION__);
858
0
      r1.i = yr_unaligned_u64(ip);
859
0
      ip += sizeof(uint64_t);
860
0
#if YR_PARANOID_EXEC
861
0
      ensure_within_mem(r1.i);
862
0
#endif
863
0
      r1 = mem[r1.i];
864
0
      push(r1);
865
0
      break;
866
867
0
    case OP_POP_M:
868
0
      YR_DEBUG_FPRINTF(2, stderr, "- case OP_POP_M: // %s()\n", __FUNCTION__);
869
0
      r1.i = yr_unaligned_u64(ip);
870
0
      ip += sizeof(uint64_t);
871
0
#if YR_PARANOID_EXEC
872
0
      ensure_within_mem(r1.i);
873
0
#endif
874
0
      pop(r2);
875
0
      mem[r1.i] = r2;
876
0
      break;
877
878
0
    case OP_SET_M:
879
0
      YR_DEBUG_FPRINTF(2, stderr, "- case OP_SET_M: // %s()\n", __FUNCTION__);
880
0
      r1.i = yr_unaligned_u64(ip);
881
0
      ip += sizeof(uint64_t);
882
0
#if YR_PARANOID_EXEC
883
0
      ensure_within_mem(r1.i);
884
0
#endif
885
0
      pop(r2);
886
0
      push(r2);
887
0
      if (!is_undef(r2))
888
0
        mem[r1.i] = r2;
889
0
      break;
890
891
0
    case OP_SWAPUNDEF:
892
0
      YR_DEBUG_FPRINTF(
893
0
          2, stderr, "- case OP_SWAPUNDEF: // %s()\n", __FUNCTION__);
894
0
      r1.i = yr_unaligned_u64(ip);
895
0
      ip += sizeof(uint64_t);
896
0
#if YR_PARANOID_EXEC
897
0
      ensure_within_mem(r1.i);
898
0
#endif
899
0
      pop(r2);
900
901
0
      if (is_undef(r2))
902
0
      {
903
0
        r1 = mem[r1.i];
904
0
        push(r1);
905
0
      }
906
0
      else
907
0
      {
908
0
        push(r2);
909
0
      }
910
0
      break;
911
912
0
    case OP_JNUNDEF:
913
      // Jump if the top the stack is not undefined without modifying the stack.
914
0
      YR_DEBUG_FPRINTF(2, stderr, "- case OP_JNUNDEF: // %s()\n", __FUNCTION__);
915
0
      pop(r1);
916
0
      push(r1);
917
0
      ip = jmp_if(!is_undef(r1), ip);
918
0
      break;
919
920
0
    case OP_JUNDEF_P:
921
      // Removes a value from the top of the stack and jump if the value is not
922
      // undefined.
923
0
      YR_DEBUG_FPRINTF(
924
0
          2, stderr, "- case OP_JUNDEF_P: // %s()\n", __FUNCTION__);
925
0
      pop(r1);
926
0
      ip = jmp_if(is_undef(r1), ip);
927
0
      break;
928
929
0
    case OP_JL_P:
930
      // Pops two values A and B from the stack and jump if A < B. B is popped
931
      // first, and then A.
932
0
      YR_DEBUG_FPRINTF(2, stderr, "- case OP_JL_P: // %s()\n", __FUNCTION__);
933
0
      pop(r2);
934
0
      pop(r1);
935
0
      ip = jmp_if(r1.i < r2.i, ip);
936
0
      break;
937
938
0
    case OP_JLE_P:
939
      // Pops two values A and B from the stack and jump if A <= B. B is popped
940
      // first, and then A.
941
0
      YR_DEBUG_FPRINTF(2, stderr, "- case OP_JLE_P: // %s()\n", __FUNCTION__);
942
0
      pop(r2);
943
0
      pop(r1);
944
0
      ip = jmp_if(r1.i <= r2.i, ip);
945
0
      break;
946
947
0
    case OP_JTRUE:
948
      // Jump if the top of the stack is true without modifying the stack. If
949
      // the top of the stack is undefined the jump is not taken.
950
0
      YR_DEBUG_FPRINTF(2, stderr, "- case OP_JTRUE: // %s()\n", __FUNCTION__);
951
0
      pop(r1);
952
0
      push(r1);
953
0
      ip = jmp_if(!is_undef(r1) && r1.i, ip);
954
0
      break;
955
956
0
    case OP_JTRUE_P:
957
      // Removes a value from the stack and jump if it is true. If the value
958
      // is undefined the jump is not taken.
959
0
      YR_DEBUG_FPRINTF(2, stderr, "- case OP_JTRUE_P: // %s()\n", __FUNCTION__);
960
0
      pop(r1);
961
0
      ip = jmp_if(!is_undef(r1) && r1.i, ip);
962
0
      break;
963
964
0
    case OP_JFALSE:
965
      // Jump if the top of the stack is false without modifying the stack. If
966
      // the top of the stack is undefined the jump is not taken.
967
0
      YR_DEBUG_FPRINTF(2, stderr, "- case OP_JFALSE: // %s()\n", __FUNCTION__);
968
0
      pop(r1);
969
0
      push(r1);
970
0
      ip = jmp_if(!is_undef(r1) && !r1.i, ip);
971
0
      break;
972
973
0
    case OP_JFALSE_P:
974
      // Removes a value from the stack and jump if it is false. If the value
975
      // is undefined the jump is not taken.
976
0
      YR_DEBUG_FPRINTF(
977
0
          2, stderr, "- case OP_JFALSE_P: // %s()\n", __FUNCTION__);
978
0
      pop(r1);
979
0
      ip = jmp_if(!is_undef(r1) && !r1.i, ip);
980
0
      break;
981
982
0
    case OP_JZ:
983
      // Jump if the value at the top of the stack is 0 without modifying the
984
      // stack.
985
0
      YR_DEBUG_FPRINTF(2, stderr, "- case OP_JZ: // %s()\n", __FUNCTION__);
986
0
      pop(r1);
987
0
      push(r1);
988
0
      ip = jmp_if(r1.i == 0, ip);
989
0
      break;
990
991
0
    case OP_JZ_P:
992
      // Removes a value from the stack and jump if the value is 0.
993
0
      YR_DEBUG_FPRINTF(2, stderr, "- case OP_JZ_P: // %s()\n", __FUNCTION__);
994
0
      pop(r1);
995
0
      ip = jmp_if(r1.i == 0, ip);
996
0
      break;
997
998
0
    case OP_AND:
999
0
      YR_DEBUG_FPRINTF(2, stderr, "- case OP_AND: // %s()\n", __FUNCTION__);
1000
0
      pop(r2);
1001
0
      pop(r1);
1002
1003
0
      if (is_undef(r1))
1004
0
        r1.i = 0;
1005
1006
0
      if (is_undef(r2))
1007
0
        r2.i = 0;
1008
1009
0
      r1.i = r1.i && r2.i;
1010
0
      push(r1);
1011
0
      break;
1012
1013
0
    case OP_OR:
1014
0
      YR_DEBUG_FPRINTF(2, stderr, "- case OP_OR: // %s()\n", __FUNCTION__);
1015
0
      pop(r2);
1016
0
      pop(r1);
1017
1018
0
      if (is_undef(r1))
1019
0
        r1.i = 0;
1020
1021
0
      if (is_undef(r2))
1022
0
        r2.i = 0;
1023
1024
0
      r1.i = r1.i || r2.i;
1025
0
      push(r1);
1026
0
      break;
1027
1028
0
    case OP_NOT:
1029
0
      YR_DEBUG_FPRINTF(2, stderr, "- case OP_NOT: // %s()\n", __FUNCTION__);
1030
0
      pop(r1);
1031
1032
0
      if (is_undef(r1))
1033
0
        r1.i = YR_UNDEFINED;
1034
0
      else
1035
0
        r1.i = !r1.i;
1036
1037
0
      push(r1);
1038
0
      break;
1039
1040
0
    case OP_DEFINED:
1041
0
      pop(r1);
1042
0
      r1.i = !is_undef(r1);
1043
0
      push(r1);
1044
0
      break;
1045
1046
0
    case OP_MOD:
1047
0
      YR_DEBUG_FPRINTF(2, stderr, "- case OP_MOD: // %s()\n", __FUNCTION__);
1048
0
      pop(r2);
1049
0
      pop(r1);
1050
0
      ensure_defined(r2);
1051
0
      ensure_defined(r1);
1052
      // If divisor is zero the result is undefined. It's also undefined
1053
      // when dividing INT64_MIN by -1.
1054
0
      if (r2.i == 0 || (r1.i == INT64_MIN && r2.i == -1))
1055
0
        r1.i = YR_UNDEFINED;
1056
0
      else
1057
0
        r1.i = r1.i % r2.i;
1058
0
      push(r1);
1059
0
      break;
1060
1061
0
    case OP_SHR:
1062
0
      YR_DEBUG_FPRINTF(2, stderr, "- case OP_SHR: // %s()\n", __FUNCTION__);
1063
0
      pop(r2);
1064
0
      pop(r1);
1065
0
      ensure_defined(r2);
1066
0
      ensure_defined(r1);
1067
0
      if (r2.i < 0)
1068
0
        r1.i = YR_UNDEFINED;
1069
0
      else if (r2.i < 64)
1070
0
        r1.i = r1.i >> r2.i;
1071
0
      else
1072
0
        r1.i = 0;
1073
0
      push(r1);
1074
0
      break;
1075
1076
0
    case OP_SHL:
1077
0
      YR_DEBUG_FPRINTF(2, stderr, "- case OP_SHL: // %s()\n", __FUNCTION__);
1078
0
      pop(r2);
1079
0
      pop(r1);
1080
0
      ensure_defined(r2);
1081
0
      ensure_defined(r1);
1082
0
      if (r2.i < 0)
1083
0
        r1.i = YR_UNDEFINED;
1084
0
      else if (r2.i < 64)
1085
0
        r1.i = r1.i << r2.i;
1086
0
      else
1087
0
        r1.i = 0;
1088
0
      push(r1);
1089
0
      break;
1090
1091
0
    case OP_BITWISE_NOT:
1092
0
      YR_DEBUG_FPRINTF(
1093
0
          2, stderr, "- case OP_BITWISE_NOT: // %s()\n", __FUNCTION__);
1094
0
      pop(r1);
1095
0
      ensure_defined(r1);
1096
0
      r1.i = ~r1.i;
1097
0
      push(r1);
1098
0
      break;
1099
1100
0
    case OP_BITWISE_AND:
1101
0
      YR_DEBUG_FPRINTF(
1102
0
          2, stderr, "- case OP_BITWISE_AND: // %s()\n", __FUNCTION__);
1103
0
      pop(r2);
1104
0
      pop(r1);
1105
0
      ensure_defined(r2);
1106
0
      ensure_defined(r1);
1107
0
      r1.i = r1.i & r2.i;
1108
0
      push(r1);
1109
0
      break;
1110
1111
0
    case OP_BITWISE_OR:
1112
0
      YR_DEBUG_FPRINTF(
1113
0
          2, stderr, "- case OP_BITWISE_OR: // %s()\n", __FUNCTION__);
1114
0
      pop(r2);
1115
0
      pop(r1);
1116
0
      ensure_defined(r2);
1117
0
      ensure_defined(r1);
1118
0
      r1.i = r1.i | r2.i;
1119
0
      push(r1);
1120
0
      break;
1121
1122
0
    case OP_BITWISE_XOR:
1123
0
      YR_DEBUG_FPRINTF(
1124
0
          2, stderr, "- case OP_BITWISE_XOR: // %s()\n", __FUNCTION__);
1125
0
      pop(r2);
1126
0
      pop(r1);
1127
0
      ensure_defined(r2);
1128
0
      ensure_defined(r1);
1129
0
      r1.i = r1.i ^ r2.i;
1130
0
      push(r1);
1131
0
      break;
1132
1133
0
    case OP_PUSH_RULE:
1134
0
      YR_DEBUG_FPRINTF(
1135
0
          2, stderr, "- case OP_PUSH_RULE: // %s()\n", __FUNCTION__);
1136
0
      r1.i = yr_unaligned_u64(ip);
1137
0
      ip += sizeof(uint64_t);
1138
1139
0
      rule = &context->rules->rules_table[r1.i];
1140
1141
0
      if (RULE_IS_DISABLED(rule))
1142
0
      {
1143
0
        r2.i = YR_UNDEFINED;
1144
0
      }
1145
0
      else
1146
0
      {
1147
0
        if (yr_bitmask_is_set(context->rule_matches_flags, r1.i))
1148
0
          r2.i = 1;
1149
0
        else
1150
0
          r2.i = 0;
1151
0
      }
1152
1153
0
      push(r2);
1154
0
      break;
1155
1156
18.4k
    case OP_INIT_RULE:
1157
18.4k
      YR_DEBUG_FPRINTF(
1158
18.4k
          2, stderr, "- case OP_INIT_RULE: // %s()\n", __FUNCTION__);
1159
1160
      // After the opcode there's an int32_t corresponding to the jump's
1161
      // offset and an uint32_t corresponding to the rule's index.
1162
18.4k
      current_rule_idx = yr_unaligned_u32(ip + sizeof(int32_t));
1163
1164
      // The curent rule index can't be larger than the number of rules.
1165
18.4k
      assert(current_rule_idx < context->rules->num_rules);
1166
1167
18.4k
      current_rule = &context->rules->rules_table[current_rule_idx];
1168
1169
      // If the rule is disabled, let's skip its code.
1170
18.4k
      bool skip_rule = RULE_IS_DISABLED(current_rule);
1171
1172
      // The rule is also skipped if it is not required to be evaluated.
1173
18.4k
      skip_rule |= yr_bitmask_is_not_set(
1174
18.4k
          context->required_eval, current_rule_idx);
1175
1176
18.4k
      ip = jmp_if(skip_rule, ip);
1177
1178
18.4k
      if (skip_rule)
1179
0
      {
1180
        // If the rule is skipped it is false, and if a global rule is false
1181
        // we must mark its namespace as unsatisfied.
1182
0
        if (RULE_IS_GLOBAL(current_rule))
1183
0
          yr_bitmask_set(context->ns_unsatisfied_flags, current_rule->ns->idx);
1184
0
      }
1185
18.4k
      else
1186
18.4k
      {
1187
        // If not taking the jump, skip the bytes corresponding to the
1188
        // rule's index.
1189
18.4k
        ip += sizeof(uint32_t);
1190
18.4k
      }
1191
1192
18.4k
      break;
1193
1194
18.4k
    case OP_MATCH_RULE:
1195
18.4k
      YR_DEBUG_FPRINTF(
1196
18.4k
          2, stderr, "- case OP_MATCH_RULE: // %s()\n", __FUNCTION__);
1197
18.4k
      pop(r1);
1198
1199
18.4k
      r2.i = yr_unaligned_u64(ip);
1200
18.4k
      ip += sizeof(uint64_t);
1201
1202
18.4k
      rule = &context->rules->rules_table[r2.i];
1203
1204
18.4k
#if YR_PARANOID_EXEC
1205
18.4k
      ensure_within_rules_arena(rule);
1206
18.4k
#endif
1207
1208
18.4k
      if (!is_undef(r1) && r1.i)
1209
1.21k
        yr_bitmask_set(context->rule_matches_flags, r2.i);
1210
17.2k
      else if (RULE_IS_GLOBAL(rule))
1211
0
        yr_bitmask_set(context->ns_unsatisfied_flags, rule->ns->idx);
1212
1213
#ifdef YR_PROFILING_ENABLED
1214
      elapsed_time = yr_stopwatch_elapsed_ns(&context->stopwatch);
1215
      context->profiling_info[r2.i].exec_time += (elapsed_time - start_time);
1216
      start_time = elapsed_time;
1217
#endif
1218
1219
18.4k
      assert(stack.sp == 0);  // at this point the stack should be empty.
1220
18.4k
      break;
1221
1222
33.7k
    case OP_OBJ_LOAD:
1223
33.7k
      YR_DEBUG_FPRINTF(
1224
33.7k
          2, stderr, "- case OP_OBJ_LOAD: // %s()\n", __FUNCTION__);
1225
1226
33.7k
      identifier = yr_unaligned_char_ptr(ip);
1227
33.7k
      ip += sizeof(uint64_t);
1228
1229
33.7k
#if YR_PARANOID_EXEC
1230
33.7k
      ensure_within_rules_arena(identifier);
1231
33.7k
#endif
1232
1233
33.7k
      r1.o = (YR_OBJECT*) yr_hash_table_lookup(
1234
33.7k
          context->objects_table, identifier, NULL);
1235
1236
33.7k
      assert(r1.o != NULL);
1237
33.7k
      push(r1);
1238
33.7k
      break;
1239
1240
57.1k
    case OP_OBJ_FIELD:
1241
57.1k
      YR_DEBUG_FPRINTF(
1242
57.1k
          2, stderr, "- case OP_OBJ_FIELD: // %s()\n", __FUNCTION__);
1243
1244
57.1k
      identifier = yr_unaligned_char_ptr(ip);
1245
57.1k
      ip += sizeof(uint64_t);
1246
1247
57.1k
#if YR_PARANOID_EXEC
1248
57.1k
      ensure_within_rules_arena(identifier);
1249
57.1k
#endif
1250
1251
57.1k
      pop(r1);
1252
57.1k
      ensure_defined(r1);
1253
1254
39.5k
      r1.o = yr_object_lookup_field(r1.o, identifier);
1255
1256
39.5k
      if (r1.o == NULL)
1257
0
      {
1258
0
        result = ERROR_INVALID_FIELD_NAME;
1259
0
        stop = true;
1260
0
        break;
1261
0
      }
1262
1263
39.5k
      push(r1);
1264
39.5k
      break;
1265
1266
33.7k
    case OP_OBJ_VALUE:
1267
33.7k
      YR_DEBUG_FPRINTF(
1268
33.7k
          2, stderr, "- case OP_OBJ_VALUE: // %s()\n", __FUNCTION__);
1269
33.7k
      pop(r1);
1270
33.7k
      ensure_defined(r1);
1271
1272
15.0k
#if YR_PARANOID_EXEC
1273
15.0k
      check_object_canary(r1.o);
1274
15.0k
#endif
1275
1276
15.0k
      switch (r1.o->type)
1277
15.0k
      {
1278
8.17k
      case OBJECT_TYPE_INTEGER:
1279
8.17k
        r1.i = r1.o->value.i;
1280
8.17k
        break;
1281
1282
0
      case OBJECT_TYPE_FLOAT:
1283
0
        if (yr_isnan(r1.o->value.d))
1284
0
          r1.i = YR_UNDEFINED;
1285
0
        else
1286
0
          r1.d = r1.o->value.d;
1287
0
        break;
1288
1289
6.85k
      case OBJECT_TYPE_STRING:
1290
6.85k
        if (r1.o->value.ss == NULL)
1291
6.42k
          r1.i = YR_UNDEFINED;
1292
424
        else
1293
424
          r1.ss = r1.o->value.ss;
1294
6.85k
        break;
1295
1296
0
      default:
1297
0
        assert(false);
1298
15.0k
      }
1299
1300
15.0k
      push(r1);
1301
15.0k
      break;
1302
1303
23.4k
    case OP_INDEX_ARRAY:
1304
23.4k
      YR_DEBUG_FPRINTF(
1305
23.4k
          2, stderr, "- case OP_INDEX_ARRAY: // %s()\n", __FUNCTION__);
1306
23.4k
      pop(r1);  // index
1307
23.4k
      pop(r2);  // array
1308
1309
23.4k
      ensure_defined(r1);
1310
23.4k
      ensure_defined(r2);
1311
1312
19.5k
      assert(r2.o->type == OBJECT_TYPE_ARRAY);
1313
1314
19.5k
#if YR_PARANOID_EXEC
1315
19.5k
      check_object_canary(r2.o);
1316
19.5k
#endif
1317
1318
19.5k
      r1.o = yr_object_array_get_item(r2.o, 0, (int) r1.i);
1319
1320
19.5k
      if (r1.o == NULL)
1321
13.8k
        r1.i = YR_UNDEFINED;
1322
1323
19.5k
      push(r1);
1324
19.5k
      break;
1325
1326
0
    case OP_LOOKUP_DICT:
1327
0
      YR_DEBUG_FPRINTF(
1328
0
          2, stderr, "- case OP_LOOKUP_DICT: // %s()\n", __FUNCTION__);
1329
0
      pop(r1);  // key
1330
0
      pop(r2);  // dictionary
1331
1332
0
      ensure_defined(r1);
1333
0
      ensure_defined(r2);
1334
1335
0
      assert(r2.o->type == OBJECT_TYPE_DICTIONARY);
1336
1337
0
#if YR_PARANOID_EXEC
1338
0
      check_object_canary(r2.o);
1339
0
#endif
1340
1341
0
      r1.o = yr_object_dict_get_item(r2.o, 0, r1.ss->c_string);
1342
1343
0
      if (r1.o == NULL)
1344
0
        r1.i = YR_UNDEFINED;
1345
1346
0
      push(r1);
1347
0
      break;
1348
1349
7.62k
    case OP_CALL:
1350
7.62k
      YR_DEBUG_FPRINTF(2, stderr, "- case OP_CALL: // %s()\n", __FUNCTION__);
1351
1352
7.62k
      args_fmt = yr_unaligned_char_ptr(ip);
1353
7.62k
      ip += sizeof(uint64_t);
1354
1355
7.62k
      int i = (int) strlen(args_fmt);
1356
7.62k
      count = 0;
1357
1358
7.62k
#if YR_PARANOID_EXEC
1359
7.62k
      if (i > YR_MAX_FUNCTION_ARGS)
1360
0
      {
1361
0
        stop = true;
1362
0
        result = ERROR_INTERNAL_FATAL_ERROR;
1363
0
        break;
1364
0
      }
1365
7.62k
#endif
1366
1367
      // pop arguments from stack and copy them to args array
1368
1369
15.2k
      while (i > 0)
1370
7.62k
      {
1371
7.62k
        pop(r1);
1372
1373
7.62k
        if (is_undef(r1))  // count the number of undefined args
1374
4.89k
          count++;
1375
1376
7.62k
        args[i - 1] = r1;
1377
7.62k
        i--;
1378
7.62k
      }
1379
1380
15.2k
      pop(r2);
1381
15.2k
      ensure_defined(r2);
1382
1383
7.62k
#if YR_PARANOID_EXEC
1384
7.62k
      check_object_canary(r2.o);
1385
7.62k
#endif
1386
1387
7.62k
      if (count > 0)
1388
4.89k
      {
1389
        // If there are undefined args, result for function call
1390
        // is undefined as well.
1391
1392
4.89k
        r1.i = YR_UNDEFINED;
1393
4.89k
        push(r1);
1394
4.89k
        break;
1395
4.89k
      }
1396
1397
2.72k
      function = object_as_function(r2.o);
1398
2.72k
      result = ERROR_INTERNAL_FATAL_ERROR;
1399
1400
2.72k
      for (i = 0; i < YR_MAX_OVERLOADED_FUNCTIONS; i++)
1401
2.72k
      {
1402
2.72k
        if (function->prototypes[i].arguments_fmt == NULL)
1403
0
          break;
1404
1405
2.72k
        if (strcmp(function->prototypes[i].arguments_fmt, args_fmt) == 0)
1406
2.72k
        {
1407
2.72k
          result = function->prototypes[i].code(args, context, function);
1408
2.72k
          break;
1409
2.72k
        }
1410
2.72k
      }
1411
1412
      // If i == YR_MAX_OVERLOADED_FUNCTIONS at this point no matching
1413
      // prototype was found, but this shouldn't happen.
1414
2.72k
      assert(i < YR_MAX_OVERLOADED_FUNCTIONS);
1415
1416
      // Make a copy of the returned object and push the copy into the stack,
1417
      // function->return_obj can't be pushed because it can change in
1418
      // subsequent calls to the same function.
1419
2.72k
      if (result == ERROR_SUCCESS)
1420
2.72k
        result = yr_object_copy(function->return_obj, &r1.o);
1421
1422
      // A pointer to the copied object is stored in a arena in order to
1423
      // free the object before exiting yr_execute_code, obj_count tracks
1424
      // the number of objects written.
1425
2.72k
      if (result == ERROR_SUCCESS)
1426
2.72k
      {
1427
2.72k
        result = yr_arena_write_data(obj_arena, 0, &r1.o, sizeof(r1.o), NULL);
1428
2.72k
        obj_count++;
1429
2.72k
      }
1430
0
      else
1431
0
      {
1432
0
        r1.i = YR_UNDEFINED;
1433
0
      }
1434
1435
2.72k
      stop = (result != ERROR_SUCCESS);
1436
2.72k
      push(r1);
1437
2.72k
      break;
1438
1439
0
    case OP_FOUND:
1440
0
      pop(r1);
1441
0
      r2.i = context->matches[r1.s->idx].tail != NULL ? 1 : 0;
1442
0
      YR_DEBUG_FPRINTF(
1443
0
          2,
1444
0
          stderr,
1445
0
          "- case OP_FOUND: r2.i=%" PRId64 " // %s()\n",
1446
0
          r2.i,
1447
0
          __FUNCTION__);
1448
0
      push(r2);
1449
0
      break;
1450
1451
0
    case OP_FOUND_AT:
1452
0
      YR_DEBUG_FPRINTF(
1453
0
          2, stderr, "- case OP_FOUND_AT: // %s()\n", __FUNCTION__);
1454
0
      pop(r2);
1455
0
      pop(r1);
1456
1457
0
      ensure_defined(r1);
1458
1459
0
#if YR_PARANOID_EXEC
1460
0
      ensure_within_rules_arena(r2.p);
1461
0
#endif
1462
1463
0
      match = context->matches[r2.s->idx].head;
1464
0
      r3.i = false;
1465
1466
0
      while (match != NULL)
1467
0
      {
1468
0
        if (r1.i == match->base + match->offset)
1469
0
        {
1470
0
          r3.i = true;
1471
0
          break;
1472
0
        }
1473
1474
0
        if (r1.i < match->base + match->offset)
1475
0
          break;
1476
1477
0
        match = match->next;
1478
0
      }
1479
1480
0
      push(r3);
1481
0
      break;
1482
1483
0
    case OP_FOUND_IN:
1484
0
      YR_DEBUG_FPRINTF(
1485
0
          2, stderr, "- case OP_FOUND_IN: // %s()\n", __FUNCTION__);
1486
0
      pop(r3);
1487
0
      pop(r2);
1488
0
      pop(r1);
1489
1490
0
      ensure_defined(r1);
1491
0
      ensure_defined(r2);
1492
1493
0
#if YR_PARANOID_EXEC
1494
0
      ensure_within_rules_arena(r3.p);
1495
0
#endif
1496
1497
0
      match = context->matches[r3.s->idx].head;
1498
0
      r4.i = false;
1499
1500
0
      while (match != NULL && !r4.i)
1501
0
      {
1502
0
        if (match->base + match->offset >= r1.i &&
1503
0
            match->base + match->offset <= r2.i)
1504
0
        {
1505
0
          r4.i = true;
1506
0
        }
1507
1508
0
        if (match->base + match->offset > r2.i)
1509
0
          break;
1510
1511
0
        match = match->next;
1512
0
      }
1513
1514
0
      push(r4);
1515
0
      break;
1516
1517
0
    case OP_COUNT:
1518
0
      YR_DEBUG_FPRINTF(2, stderr, "- case OP_COUNT: // %s()\n", __FUNCTION__);
1519
0
      pop(r1);
1520
1521
0
#if YR_PARANOID_EXEC
1522
0
      ensure_within_rules_arena(r1.p);
1523
0
#endif
1524
1525
0
      r2.i = context->matches[r1.s->idx].count;
1526
0
      push(r2);
1527
0
      break;
1528
1529
0
    case OP_COUNT_IN:
1530
0
      YR_DEBUG_FPRINTF(
1531
0
          2, stderr, "- case OP_COUNT_IN: // %s()\n", __FUNCTION__);
1532
0
      pop(r3);
1533
0
      pop(r2);
1534
0
      pop(r1);
1535
1536
0
      ensure_defined(r1);
1537
0
      ensure_defined(r2);
1538
1539
0
#if YR_PARANOID_EXEC
1540
0
      ensure_within_rules_arena(r3.p);
1541
0
#endif
1542
1543
0
      match = context->matches[r3.s->idx].head;
1544
0
      r4.i = 0;
1545
1546
0
      while (match != NULL)
1547
0
      {
1548
0
        if (match->base + match->offset >= r1.i &&
1549
0
            match->base + match->offset <= r2.i)
1550
0
        {
1551
0
          r4.i++;
1552
0
        }
1553
1554
0
        if (match->base + match->offset > r2.i)
1555
0
          break;
1556
1557
0
        match = match->next;
1558
0
      }
1559
1560
0
      push(r4);
1561
0
      break;
1562
1563
0
    case OP_OFFSET:
1564
0
      YR_DEBUG_FPRINTF(2, stderr, "- case OP_OFFSET: // %s()\n", __FUNCTION__);
1565
0
      pop(r2);
1566
0
      pop(r1);
1567
1568
0
      ensure_defined(r1);
1569
1570
0
#if YR_PARANOID_EXEC
1571
0
      ensure_within_rules_arena(r2.p);
1572
0
#endif
1573
1574
0
      match = context->matches[r2.s->idx].head;
1575
1576
0
      i = 1;
1577
0
      r3.i = YR_UNDEFINED;
1578
1579
0
      while (match != NULL && r3.i == YR_UNDEFINED)
1580
0
      {
1581
0
        if (r1.i == i)
1582
0
          r3.i = match->base + match->offset;
1583
1584
0
        i++;
1585
0
        match = match->next;
1586
0
      }
1587
1588
0
      push(r3);
1589
0
      break;
1590
1591
0
    case OP_LENGTH:
1592
0
      YR_DEBUG_FPRINTF(2, stderr, "- case OP_LENGTH: // %s()\n", __FUNCTION__);
1593
0
      pop(r2);
1594
0
      pop(r1);
1595
1596
0
      ensure_defined(r1);
1597
1598
0
#if YR_PARANOID_EXEC
1599
0
      ensure_within_rules_arena(r2.p);
1600
0
#endif
1601
1602
0
      match = context->matches[r2.s->idx].head;
1603
1604
0
      i = 1;
1605
0
      r3.i = YR_UNDEFINED;
1606
1607
0
      while (match != NULL && r3.i == YR_UNDEFINED)
1608
0
      {
1609
0
        if (r1.i == i)
1610
0
          r3.i = match->match_length;
1611
1612
0
        i++;
1613
0
        match = match->next;
1614
0
      }
1615
1616
0
      push(r3);
1617
0
      break;
1618
1619
0
    case OP_OF:
1620
0
    case OP_OF_PERCENT:
1621
0
      r2.i = yr_unaligned_u64(ip);
1622
0
      ip += sizeof(uint64_t);
1623
0
      assert(r2.i == OF_STRING_SET || r2.i == OF_RULE_SET);
1624
0
      found = 0;
1625
0
      count = 0;
1626
0
      pop(r1);
1627
1628
0
      while (!is_undef(r1))
1629
0
      {
1630
0
        if (r2.i == OF_STRING_SET)
1631
0
        {
1632
0
          if (context->matches[r1.s->idx].tail != NULL)
1633
0
          {
1634
0
            found++;
1635
0
          }
1636
0
        }
1637
0
        else
1638
0
        {
1639
          // r1.i is 1 if the rule has already matched and zero otherwise.
1640
0
          found += r1.i;
1641
0
        }
1642
0
        count++;
1643
0
        pop(r1);
1644
0
      }
1645
1646
0
      pop(r2);
1647
1648
0
      if (opcode == OP_OF)
1649
0
      {
1650
0
        YR_DEBUG_FPRINTF(2, stderr, "- case OP_OF: // %s()\n", __FUNCTION__);
1651
1652
        // Quantifier is "all"
1653
0
        if (is_undef(r2))
1654
0
        {
1655
0
          r1.i = found >= count ? 1 : 0;
1656
0
        }
1657
        // Quantifier is 0 or none. This is a special case in which we want
1658
        // exactly 0 strings matching. More information at:
1659
        // https://github.com/VirusTotal/yara/issues/1695
1660
0
        else if (r2.i == 0)
1661
0
        {
1662
0
          r1.i = found == 0 ? 1 : 0;
1663
0
        }
1664
        // In all other cases the number of strings matching should be at
1665
        // least the amount specified by the quantifier.
1666
0
        else
1667
0
        {
1668
0
          r1.i = found >= r2.i ? 1 : 0;
1669
0
        }
1670
0
      }
1671
0
      else  // OP_OF_PERCENT
1672
0
      {
1673
0
        YR_DEBUG_FPRINTF(
1674
0
            2, stderr, "- case OP_OF_PERCENT: // %s()\n", __FUNCTION__);
1675
1676
        // If, by some weird reason, we manage to get an undefined string
1677
        // reference as the first thing on the stack then count would be zero.
1678
        // I don't know how this could ever happen but better to check for it.
1679
0
        if (is_undef(r2) || count == 0)
1680
0
          r1.i = YR_UNDEFINED;
1681
0
        else
1682
0
          r1.i = (((double) found / count) * 100) >= r2.i ? 1 : 0;
1683
0
      }
1684
1685
0
      push(r1);
1686
0
      break;
1687
1688
0
    case OP_OF_FOUND_IN:
1689
0
      YR_DEBUG_FPRINTF(
1690
0
          2, stderr, "- case OP_OF_FOUND_IN: // %s()\n", __FUNCTION__);
1691
1692
0
      found = 0;
1693
0
      count = 0;
1694
1695
0
      pop(r2);  // Offset range end
1696
0
      pop(r1);  // Offset range start
1697
0
      pop(r3);  // First string
1698
1699
      // If any of the range boundaries are undefined the result is also
1700
      // undefined, be we need to unwind the stack first.
1701
0
      if (is_undef(r1) || is_undef(r2))
1702
0
      {
1703
        // Remove all the strings.
1704
0
        while (!is_undef(r3)) pop(r3);
1705
        // Remove the quantifier at the bottom of the stack.
1706
0
        pop(r3);
1707
0
        r1.i = YR_UNDEFINED;
1708
0
        push(r1);
1709
0
        break;
1710
0
      }
1711
1712
0
      while (!is_undef(r3))
1713
0
      {
1714
0
#if YR_PARANOID_EXEC
1715
0
        ensure_within_rules_arena(r3.p);
1716
0
#endif
1717
0
        match = context->matches[r3.s->idx].head;
1718
1719
0
        while (match != NULL)
1720
0
        {
1721
          // String match within range start and range end?
1722
0
          if (match->base + match->offset >= r1.i &&
1723
0
              match->base + match->offset <= r2.i)
1724
0
          {
1725
0
            found++;
1726
0
            break;
1727
0
          }
1728
1729
          // If current match is past range end, we can stop as matches
1730
          // are sorted by offset in increasing order, so all remaining
1731
          // matches are part the range end too.
1732
0
          if (match->base + match->offset > r1.i)
1733
0
            break;
1734
1735
0
          match = match->next;
1736
0
        }
1737
1738
0
        count++;
1739
0
        pop(r3);
1740
0
      }
1741
1742
0
      pop(r2);  // Quantifier X in expressions like "X of string_set in range"
1743
1744
      // Quantifier is "all".
1745
0
      if (is_undef(r2))
1746
0
      {
1747
0
        r1.i = found >= count ? 1 : 0;
1748
0
      }
1749
      // Quantifier is 0 or none. This is a special case in which we want
1750
      // exactly 0 strings matching. More information at:
1751
      // https://github.com/VirusTotal/yara/issues/1695
1752
0
      else if (r2.i == 0)
1753
0
      {
1754
0
        r1.i = found == 0 ? 1 : 0;
1755
0
      }
1756
      // In all other cases the number of strings matching should be at least
1757
      // the amount specified by the quantifier.
1758
0
      else
1759
0
      {
1760
0
        r1.i = found >= r2.i ? 1 : 0;
1761
0
      }
1762
1763
0
      push(r1);
1764
0
      break;
1765
1766
0
    case OP_OF_FOUND_AT:
1767
0
      YR_DEBUG_FPRINTF(
1768
0
          2, stderr, "- case OP_OF_FOUND_AT: // %s()\n", __FUNCTION__);
1769
1770
0
      found = 0;
1771
0
      count = 0;
1772
1773
0
      pop(r2);  // Match location
1774
0
      pop(r1);  // First string
1775
1776
      // Match location must be defined.
1777
0
      if (is_undef(r2))
1778
0
      {
1779
        // Remove all the strings.
1780
0
        while (!is_undef(r1)) pop(r1);
1781
        // Remove the quantifier at the bottom of the stack.
1782
0
        pop(r1);
1783
0
        r1.i = YR_UNDEFINED;
1784
0
        push(r1);
1785
0
        break;
1786
0
      }
1787
1788
0
      while (!is_undef(r1))
1789
0
      {
1790
0
#if YR_PARANOID_EXEC
1791
0
        ensure_within_rules_arena(r1.p);
1792
0
#endif
1793
0
        match = context->matches[r1.s->idx].head;
1794
1795
0
        while (match != NULL)
1796
0
        {
1797
          // String match at the desired location?
1798
0
          if (match->base + match->offset == r2.i)
1799
0
          {
1800
0
            found++;
1801
0
            break;
1802
0
          }
1803
1804
          // If current match is past desired location, we can stop as matches
1805
          // are sorted by offset in increasing order, so all remaining
1806
          // matches are past it.
1807
0
          if (match->base + match->offset > r2.i)
1808
0
            break;
1809
1810
0
          match = match->next;
1811
0
        }
1812
1813
0
        count++;
1814
0
        pop(r1);
1815
0
      }
1816
1817
0
      pop(r2);  // Quantifier X in expressions like "X of string_set in range"
1818
1819
      // Quantifier is "all".
1820
0
      if (is_undef(r2))
1821
0
      {
1822
0
        r1.i = found >= count ? 1 : 0;
1823
0
      }
1824
      // Quantifier is 0 or none. This is a special case in which we want
1825
      // exactly 0 strings matching. More information at:
1826
      // https://github.com/VirusTotal/yara/issues/1695
1827
0
      else if (r2.i == 0)
1828
0
      {
1829
0
        r1.i = found == 0 ? 1 : 0;
1830
0
      }
1831
      // In all other cases the number of strings matching should be at least
1832
      // the amount specified by the quantifier.
1833
0
      else
1834
0
      {
1835
0
        r1.i = found >= r2.i ? 1 : 0;
1836
0
      }
1837
1838
0
      push(r1);
1839
0
      break;
1840
1841
0
    case OP_FILESIZE:
1842
0
      r1.i = context->file_size;
1843
0
      YR_DEBUG_FPRINTF(
1844
0
          2,
1845
0
          stderr,
1846
0
          "- case OP_FILESIZE: r1.i=%" PRId64 "%s // %s()\n",
1847
0
          r1.i,
1848
0
          r1.i == YR_UNDEFINED ? " AKA YR_UNDEFINED" : "",
1849
0
          __FUNCTION__);
1850
0
      push(r1);
1851
0
      break;
1852
1853
0
    case OP_ENTRYPOINT:
1854
0
      YR_DEBUG_FPRINTF(
1855
0
          2, stderr, "- case OP_ENTRYPOINT: // %s()\n", __FUNCTION__);
1856
0
      r1.i = context->entry_point;
1857
0
      push(r1);
1858
0
      break;
1859
1860
0
    case OP_INT8:
1861
0
      YR_DEBUG_FPRINTF(2, stderr, "- case OP_INT8: // %s()\n", __FUNCTION__);
1862
0
      pop(r1);
1863
0
      r1.i = read_int8_t_little_endian(context->iterator, (size_t) r1.i);
1864
0
      push(r1);
1865
0
      break;
1866
1867
0
    case OP_INT16:
1868
0
      YR_DEBUG_FPRINTF(2, stderr, "- case OP_INT16: // %s()\n", __FUNCTION__);
1869
0
      pop(r1);
1870
0
      r1.i = read_int16_t_little_endian(context->iterator, (size_t) r1.i);
1871
0
      push(r1);
1872
0
      break;
1873
1874
0
    case OP_INT32:
1875
0
      YR_DEBUG_FPRINTF(2, stderr, "- case OP_INT32: // %s()\n", __FUNCTION__);
1876
0
      pop(r1);
1877
0
      r1.i = read_int32_t_little_endian(context->iterator, (size_t) r1.i);
1878
0
      push(r1);
1879
0
      break;
1880
1881
0
    case OP_UINT8:
1882
0
      YR_DEBUG_FPRINTF(2, stderr, "- case OP_UINT8: // %s()\n", __FUNCTION__);
1883
0
      pop(r1);
1884
0
      r1.i = read_uint8_t_little_endian(context->iterator, (size_t) r1.i);
1885
0
      push(r1);
1886
0
      break;
1887
1888
0
    case OP_UINT16:
1889
0
      YR_DEBUG_FPRINTF(2, stderr, "- case OP_UINT16: // %s()\n", __FUNCTION__);
1890
0
      pop(r1);
1891
0
      r1.i = read_uint16_t_little_endian(context->iterator, (size_t) r1.i);
1892
0
      push(r1);
1893
0
      break;
1894
1895
0
    case OP_UINT32:
1896
0
      YR_DEBUG_FPRINTF(2, stderr, "- case OP_UINT32: // %s()\n", __FUNCTION__);
1897
0
      pop(r1);
1898
0
      r1.i = read_uint32_t_little_endian(context->iterator, (size_t) r1.i);
1899
0
      push(r1);
1900
0
      break;
1901
1902
0
    case OP_INT8BE:
1903
0
      YR_DEBUG_FPRINTF(2, stderr, "- case OP_INT8BE: // %s()\n", __FUNCTION__);
1904
0
      pop(r1);
1905
0
      r1.i = read_int8_t_big_endian(context->iterator, (size_t) r1.i);
1906
0
      push(r1);
1907
0
      break;
1908
1909
0
    case OP_INT16BE:
1910
0
      YR_DEBUG_FPRINTF(2, stderr, "- case OP_INT16BE: // %s()\n", __FUNCTION__);
1911
0
      pop(r1);
1912
0
      r1.i = read_int16_t_big_endian(context->iterator, (size_t) r1.i);
1913
0
      push(r1);
1914
0
      break;
1915
1916
0
    case OP_INT32BE:
1917
0
      YR_DEBUG_FPRINTF(2, stderr, "- case OP_INT32BE: // %s()\n", __FUNCTION__);
1918
0
      pop(r1);
1919
0
      r1.i = read_int32_t_big_endian(context->iterator, (size_t) r1.i);
1920
0
      push(r1);
1921
0
      break;
1922
1923
0
    case OP_UINT8BE:
1924
0
      YR_DEBUG_FPRINTF(2, stderr, "- case OP_UINT8BE: // %s()\n", __FUNCTION__);
1925
0
      pop(r1);
1926
0
      r1.i = read_uint8_t_big_endian(context->iterator, (size_t) r1.i);
1927
0
      push(r1);
1928
0
      break;
1929
1930
0
    case OP_UINT16BE:
1931
0
      YR_DEBUG_FPRINTF(
1932
0
          2, stderr, "- case OP_UINT16BE: // %s()\n", __FUNCTION__);
1933
0
      pop(r1);
1934
0
      r1.i = read_uint16_t_big_endian(context->iterator, (size_t) r1.i);
1935
0
      push(r1);
1936
0
      break;
1937
1938
0
    case OP_UINT32BE:
1939
0
      YR_DEBUG_FPRINTF(
1940
0
          2, stderr, "- case OP_UINT32BE: // %s()\n", __FUNCTION__);
1941
0
      pop(r1);
1942
0
      r1.i = read_uint32_t_big_endian(context->iterator, (size_t) r1.i);
1943
0
      push(r1);
1944
0
      break;
1945
1946
25.7k
    case OP_IMPORT:
1947
25.7k
      YR_DEBUG_FPRINTF(2, stderr, "- case OP_IMPORT: // %s()\n", __FUNCTION__);
1948
25.7k
      r1.i = yr_unaligned_u64(ip);
1949
25.7k
      ip += sizeof(uint64_t);
1950
1951
25.7k
#if YR_PARANOID_EXEC
1952
25.7k
      ensure_within_rules_arena(r1.p);
1953
25.7k
#endif
1954
1955
25.7k
      result = yr_modules_load((char*) r1.p, context);
1956
1957
25.7k
      if (result != ERROR_SUCCESS)
1958
0
        stop = true;
1959
1960
25.7k
      break;
1961
1962
0
    case OP_MATCHES:
1963
0
      YR_DEBUG_FPRINTF(2, stderr, "- case OP_MATCHES: // %s()\n", __FUNCTION__);
1964
0
      pop(r2);
1965
0
      pop(r1);
1966
1967
0
      ensure_defined(r2);
1968
0
      ensure_defined(r1);
1969
1970
0
      result = yr_re_exec(
1971
0
          context,
1972
0
          (uint8_t*) r2.re->code,
1973
0
          (uint8_t*) r1.ss->c_string,
1974
0
          r1.ss->length,
1975
0
          0,
1976
0
          r2.re->flags | RE_FLAGS_SCAN,
1977
0
          NULL,
1978
0
          NULL,
1979
0
          &found);
1980
1981
0
      if (result != ERROR_SUCCESS)
1982
0
        stop = true;
1983
1984
0
      r1.i = found >= 0;
1985
0
      push(r1);
1986
0
      break;
1987
1988
0
    case OP_INT_TO_DBL:
1989
0
      YR_DEBUG_FPRINTF(
1990
0
          2, stderr, "- case OP_INT_TO_DBL: // %s()\n", __FUNCTION__);
1991
0
      r1.i = yr_unaligned_u64(ip);
1992
0
      ip += sizeof(uint64_t);
1993
1994
0
#if YR_PARANOID_EXEC
1995
0
      if (r1.i > stack.sp || stack.sp - r1.i >= stack.capacity)
1996
0
      {
1997
0
        stop = true;
1998
0
        result = ERROR_INTERNAL_FATAL_ERROR;
1999
0
        break;
2000
0
      }
2001
0
#endif
2002
2003
0
      r2 = stack.items[stack.sp - r1.i];
2004
2005
0
      if (is_undef(r2))
2006
0
        stack.items[stack.sp - r1.i].i = YR_UNDEFINED;
2007
0
      else
2008
0
        stack.items[stack.sp - r1.i].d = (double) r2.i;
2009
0
      break;
2010
2011
0
    case OP_STR_TO_BOOL:
2012
0
      YR_DEBUG_FPRINTF(
2013
0
          2, stderr, "- case OP_STR_TO_BOOL: // %s()\n", __FUNCTION__);
2014
0
      pop(r1);
2015
0
      ensure_defined(r1);
2016
0
      r1.i = r1.ss->length > 0;
2017
0
      push(r1);
2018
0
      break;
2019
2020
7.62k
    case OP_INT_EQ:
2021
7.62k
      YR_DEBUG_FPRINTF(2, stderr, "- case OP_INT_EQ: // %s()\n", __FUNCTION__);
2022
7.62k
      pop(r2);
2023
7.62k
      pop(r1);
2024
7.62k
      ensure_defined(r2);
2025
2.72k
      ensure_defined(r1);
2026
2.16k
      r1.i = r1.i == r2.i;
2027
2.16k
      push(r1);
2028
2.16k
      break;
2029
2030
0
    case OP_INT_NEQ:
2031
0
      YR_DEBUG_FPRINTF(2, stderr, "- case OP_INT_NEQ: // %s()\n", __FUNCTION__);
2032
0
      pop(r2);
2033
0
      pop(r1);
2034
0
      ensure_defined(r2);
2035
0
      ensure_defined(r1);
2036
0
      r1.i = r1.i != r2.i;
2037
0
      push(r1);
2038
0
      break;
2039
2040
0
    case OP_INT_LT:
2041
0
      YR_DEBUG_FPRINTF(2, stderr, "- case OP_INT_LT: // %s()\n", __FUNCTION__);
2042
0
      pop(r2);
2043
0
      pop(r1);
2044
0
      ensure_defined(r2);
2045
0
      ensure_defined(r1);
2046
0
      r1.i = r1.i < r2.i;
2047
0
      push(r1);
2048
0
      break;
2049
2050
0
    case OP_INT_GT:
2051
0
      YR_DEBUG_FPRINTF(2, stderr, "- case OP_INT_GT: // %s()\n", __FUNCTION__);
2052
0
      pop(r2);
2053
0
      pop(r1);
2054
0
      ensure_defined(r2);
2055
0
      ensure_defined(r1);
2056
0
      r1.i = r1.i > r2.i;
2057
0
      push(r1);
2058
0
      break;
2059
2060
0
    case OP_INT_LE:
2061
0
      YR_DEBUG_FPRINTF(2, stderr, "- case OP_INT_LE: // %s()\n", __FUNCTION__);
2062
0
      pop(r2);
2063
0
      pop(r1);
2064
0
      ensure_defined(r2);
2065
0
      ensure_defined(r1);
2066
0
      r1.i = r1.i <= r2.i;
2067
0
      push(r1);
2068
0
      break;
2069
2070
0
    case OP_INT_GE:
2071
0
      YR_DEBUG_FPRINTF(2, stderr, "- case OP_INT_GE: // %s()\n", __FUNCTION__);
2072
0
      pop(r2);
2073
0
      pop(r1);
2074
0
      ensure_defined(r2);
2075
0
      ensure_defined(r1);
2076
0
      r1.i = r1.i >= r2.i;
2077
0
      push(r1);
2078
0
      break;
2079
2080
0
    case OP_INT_ADD:
2081
0
      YR_DEBUG_FPRINTF(2, stderr, "- case OP_INT_ADD: // %s()\n", __FUNCTION__);
2082
0
      pop(r2);
2083
0
      pop(r1);
2084
0
      ensure_defined(r2);
2085
0
      ensure_defined(r1);
2086
0
      r1.i = r1.i + r2.i;
2087
0
      push(r1);
2088
0
      break;
2089
2090
0
    case OP_INT_SUB:
2091
0
      YR_DEBUG_FPRINTF(2, stderr, "- case OP_INT_SUB: // %s()\n", __FUNCTION__);
2092
0
      pop(r2);
2093
0
      pop(r1);
2094
0
      ensure_defined(r2);
2095
0
      ensure_defined(r1);
2096
0
      r1.i = r1.i - r2.i;
2097
0
      push(r1);
2098
0
      break;
2099
2100
0
    case OP_INT_MUL:
2101
0
      YR_DEBUG_FPRINTF(2, stderr, "- case OP_INT_MUL: // %s()\n", __FUNCTION__);
2102
0
      pop(r2);
2103
0
      pop(r1);
2104
0
      ensure_defined(r2);
2105
0
      ensure_defined(r1);
2106
0
      r1.i = r1.i * r2.i;
2107
0
      push(r1);
2108
0
      break;
2109
2110
0
    case OP_INT_DIV:
2111
0
      YR_DEBUG_FPRINTF(2, stderr, "- case OP_INT_DIV: // %s()\n", __FUNCTION__);
2112
0
      pop(r2);
2113
0
      pop(r1);
2114
0
      ensure_defined(r2);
2115
0
      ensure_defined(r1);
2116
      // If divisor is zero the result is undefined. It's also undefined
2117
      // when dividing INT64_MIN by -1.
2118
0
      if (r2.i == 0 || (r1.i == INT64_MIN && r2.i == -1))
2119
0
        r1.i = YR_UNDEFINED;
2120
0
      else
2121
0
        r1.i = r1.i / r2.i;
2122
0
      push(r1);
2123
0
      break;
2124
2125
0
    case OP_INT_MINUS:
2126
0
      YR_DEBUG_FPRINTF(
2127
0
          2, stderr, "- case OP_INT_MINUS: // %s()\n", __FUNCTION__);
2128
0
      pop(r1);
2129
0
      ensure_defined(r1);
2130
0
      r1.i = -r1.i;
2131
0
      push(r1);
2132
0
      break;
2133
2134
0
    case OP_DBL_LT:
2135
0
      YR_DEBUG_FPRINTF(2, stderr, "- case OP_DBL_LT: // %s()\n", __FUNCTION__);
2136
0
      pop(r2);
2137
0
      pop(r1);
2138
0
      if (is_undef(r1) || is_undef(r2))
2139
0
        r1.i = false;
2140
0
      else
2141
0
        r1.i = r1.d < r2.d;
2142
0
      push(r1);
2143
0
      break;
2144
2145
0
    case OP_DBL_GT:
2146
0
      YR_DEBUG_FPRINTF(2, stderr, "- case OP_DBL_GT: // %s()\n", __FUNCTION__);
2147
0
      pop(r2);
2148
0
      pop(r1);
2149
0
      ensure_defined(r2);
2150
0
      ensure_defined(r1);
2151
0
      r1.i = r1.d > r2.d;
2152
0
      push(r1);
2153
0
      break;
2154
2155
0
    case OP_DBL_LE:
2156
0
      YR_DEBUG_FPRINTF(2, stderr, "- case OP_DBL_LE: // %s()\n", __FUNCTION__);
2157
0
      pop(r2);
2158
0
      pop(r1);
2159
0
      ensure_defined(r2);
2160
0
      ensure_defined(r1);
2161
0
      r1.i = r1.d <= r2.d;
2162
0
      push(r1);
2163
0
      break;
2164
2165
0
    case OP_DBL_GE:
2166
0
      YR_DEBUG_FPRINTF(2, stderr, "- case OP_DBL_GE: // %s()\n", __FUNCTION__);
2167
0
      pop(r2);
2168
0
      pop(r1);
2169
0
      ensure_defined(r2);
2170
0
      ensure_defined(r1);
2171
0
      r1.i = r1.d >= r2.d;
2172
0
      push(r1);
2173
0
      break;
2174
2175
0
    case OP_DBL_EQ:
2176
0
      YR_DEBUG_FPRINTF(2, stderr, "- case OP_DBL_EQ: // %s()\n", __FUNCTION__);
2177
0
      pop(r2);
2178
0
      pop(r1);
2179
0
      ensure_defined(r2);
2180
0
      ensure_defined(r1);
2181
0
      r1.i = fabs(r1.d - r2.d) < DBL_EPSILON;
2182
0
      push(r1);
2183
0
      break;
2184
2185
0
    case OP_DBL_NEQ:
2186
0
      YR_DEBUG_FPRINTF(2, stderr, "- case OP_DBL_NEQ: // %s()\n", __FUNCTION__);
2187
0
      pop(r2);
2188
0
      pop(r1);
2189
0
      ensure_defined(r2);
2190
0
      ensure_defined(r1);
2191
0
      r1.i = fabs(r1.d - r2.d) >= DBL_EPSILON;
2192
0
      push(r1);
2193
0
      break;
2194
2195
0
    case OP_DBL_ADD:
2196
0
      YR_DEBUG_FPRINTF(2, stderr, "- case OP_DBL_ADD: // %s()\n", __FUNCTION__);
2197
0
      pop(r2);
2198
0
      pop(r1);
2199
0
      ensure_defined(r2);
2200
0
      ensure_defined(r1);
2201
0
      r1.d = r1.d + r2.d;
2202
0
      push(r1);
2203
0
      break;
2204
2205
0
    case OP_DBL_SUB:
2206
0
      YR_DEBUG_FPRINTF(2, stderr, "- case OP_DBL_SUB: // %s()\n", __FUNCTION__);
2207
0
      pop(r2);
2208
0
      pop(r1);
2209
0
      ensure_defined(r2);
2210
0
      ensure_defined(r1);
2211
0
      r1.d = r1.d - r2.d;
2212
0
      push(r1);
2213
0
      break;
2214
2215
0
    case OP_DBL_MUL:
2216
0
      YR_DEBUG_FPRINTF(2, stderr, "- case OP_DBL_MUL: // %s()\n", __FUNCTION__);
2217
0
      pop(r2);
2218
0
      pop(r1);
2219
0
      ensure_defined(r2);
2220
0
      ensure_defined(r1);
2221
0
      r1.d = r1.d * r2.d;
2222
0
      push(r1);
2223
0
      break;
2224
2225
0
    case OP_DBL_DIV:
2226
0
      YR_DEBUG_FPRINTF(2, stderr, "- case OP_DBL_DIV: // %s()\n", __FUNCTION__);
2227
0
      pop(r2);
2228
0
      pop(r1);
2229
0
      ensure_defined(r2);
2230
0
      ensure_defined(r1);
2231
0
      r1.d = r1.d / r2.d;
2232
0
      push(r1);
2233
0
      break;
2234
2235
0
    case OP_DBL_MINUS:
2236
0
      YR_DEBUG_FPRINTF(
2237
0
          2, stderr, "- case OP_DBL_MINUS: // %s()\n", __FUNCTION__);
2238
0
      pop(r1);
2239
0
      ensure_defined(r1);
2240
0
      r1.d = -r1.d;
2241
0
      push(r1);
2242
0
      break;
2243
2244
10.8k
    case OP_STR_EQ:
2245
10.8k
    case OP_STR_NEQ:
2246
10.8k
    case OP_STR_LT:
2247
10.8k
    case OP_STR_LE:
2248
10.8k
    case OP_STR_GT:
2249
10.8k
    case OP_STR_GE:
2250
10.8k
      pop(r2);
2251
10.8k
      pop(r1);
2252
2253
10.8k
      ensure_defined(r2);
2254
10.8k
      ensure_defined(r1);
2255
2256
424
      switch (opcode)
2257
424
      {
2258
424
      case OP_STR_EQ:
2259
424
        YR_DEBUG_FPRINTF(
2260
424
            2, stderr, "- case OP_STR_EQ: // %s()\n", __FUNCTION__);
2261
424
        r1.i = (ss_compare(r1.ss, r2.ss) == 0);
2262
424
        break;
2263
0
      case OP_STR_NEQ:
2264
0
        YR_DEBUG_FPRINTF(
2265
0
            2, stderr, "- case OP_STR_NEQ: // %s()\n", __FUNCTION__);
2266
0
        r1.i = (ss_compare(r1.ss, r2.ss) != 0);
2267
0
        break;
2268
0
      case OP_STR_LT:
2269
0
        YR_DEBUG_FPRINTF(
2270
0
            2, stderr, "- case OP_STR_LT: // %s()\n", __FUNCTION__);
2271
0
        r1.i = (ss_compare(r1.ss, r2.ss) < 0);
2272
0
        break;
2273
0
      case OP_STR_LE:
2274
0
        YR_DEBUG_FPRINTF(
2275
0
            2, stderr, "- case OP_STR_LE: // %s()\n", __FUNCTION__);
2276
0
        r1.i = (ss_compare(r1.ss, r2.ss) <= 0);
2277
0
        break;
2278
0
      case OP_STR_GT:
2279
0
        YR_DEBUG_FPRINTF(
2280
0
            2, stderr, "- case OP_STR_GT: // %s()\n", __FUNCTION__);
2281
0
        r1.i = (ss_compare(r1.ss, r2.ss) > 0);
2282
0
        break;
2283
0
      case OP_STR_GE:
2284
0
        YR_DEBUG_FPRINTF(
2285
0
            2, stderr, "- case OP_STR_GE: // %s()\n", __FUNCTION__);
2286
0
        r1.i = (ss_compare(r1.ss, r2.ss) >= 0);
2287
0
        break;
2288
424
      }
2289
2290
424
      push(r1);
2291
424
      break;
2292
2293
0
    case OP_CONTAINS:
2294
0
    case OP_ICONTAINS:
2295
0
    case OP_STARTSWITH:
2296
0
    case OP_ISTARTSWITH:
2297
0
    case OP_ENDSWITH:
2298
0
    case OP_IENDSWITH:
2299
0
    case OP_IEQUALS:
2300
0
      pop(r2);
2301
0
      pop(r1);
2302
2303
0
      ensure_defined(r1);
2304
0
      ensure_defined(r2);
2305
2306
0
      switch (opcode)
2307
0
      {
2308
0
      case OP_CONTAINS:
2309
0
        YR_DEBUG_FPRINTF(
2310
0
            2, stderr, "- case OP_CONTAINS: // %s()\n", __FUNCTION__);
2311
0
        r1.i = ss_contains(r1.ss, r2.ss);
2312
0
        break;
2313
0
      case OP_ICONTAINS:
2314
0
        YR_DEBUG_FPRINTF(
2315
0
            2, stderr, "- case OP_ICONTAINS: // %s()\n", __FUNCTION__);
2316
0
        r1.i = ss_icontains(r1.ss, r2.ss);
2317
0
        break;
2318
0
      case OP_STARTSWITH:
2319
0
        YR_DEBUG_FPRINTF(
2320
0
            2, stderr, "- case OP_STARTSWITH: // %s()\n", __FUNCTION__);
2321
0
        r1.i = ss_startswith(r1.ss, r2.ss);
2322
0
        break;
2323
0
      case OP_ISTARTSWITH:
2324
0
        YR_DEBUG_FPRINTF(
2325
0
            2, stderr, "- case OP_ISTARTSWITH: // %s()\n", __FUNCTION__);
2326
0
        r1.i = ss_istartswith(r1.ss, r2.ss);
2327
0
        break;
2328
0
      case OP_ENDSWITH:
2329
0
        YR_DEBUG_FPRINTF(
2330
0
            2, stderr, "- case OP_ENDSWITH: // %s()\n", __FUNCTION__);
2331
0
        r1.i = ss_endswith(r1.ss, r2.ss);
2332
0
        break;
2333
0
      case OP_IENDSWITH:
2334
0
        YR_DEBUG_FPRINTF(
2335
0
            2, stderr, "- case OP_IENDSWITH: // %s()\n", __FUNCTION__);
2336
0
        r1.i = ss_iendswith(r1.ss, r2.ss);
2337
0
        break;
2338
0
      case OP_IEQUALS:
2339
0
        YR_DEBUG_FPRINTF(
2340
0
            2, stderr, "- case OP_IEQUALS: // %s()\n", __FUNCTION__);
2341
0
        r1.i = ss_icompare(r1.ss, r2.ss) == 0;
2342
0
        break;
2343
0
      }
2344
2345
0
      push(r1);
2346
0
      break;
2347
2348
0
    default:
2349
0
      YR_DEBUG_FPRINTF(
2350
0
          2, stderr, "- case <unknown instruction>: // %s()\n", __FUNCTION__);
2351
      // Unknown instruction, this shouldn't happen.
2352
0
      assert(false);
2353
296k
    }
2354
2355
    // Check for timeout every 100 instruction cycles. If timeout == 0 it means
2356
    // no timeout at all.
2357
2358
296k
    if (context->timeout > 0ULL && ++cycle == 100)
2359
0
    {
2360
0
      elapsed_time = yr_stopwatch_elapsed_ns(&context->stopwatch);
2361
2362
0
      if (elapsed_time > context->timeout)
2363
0
      {
2364
#ifdef YR_PROFILING_ENABLED
2365
        context->profiling_info[current_rule_idx].exec_time +=
2366
            (elapsed_time - start_time);
2367
#endif
2368
0
        result = ERROR_SCAN_TIMEOUT;
2369
0
        stop = true;
2370
0
      }
2371
2372
0
      cycle = 0;
2373
0
    }
2374
296k
  }
2375
2376
25.7k
  obj_ptr = yr_arena_get_ptr(obj_arena, 0, 0);
2377
2378
28.5k
  for (int i = 0; i < obj_count; i++) yr_object_destroy(obj_ptr[i]);
2379
2380
25.7k
  yr_arena_release(obj_arena);
2381
25.7k
  yr_notebook_destroy(it_notebook);
2382
25.7k
  yr_modules_unload_all(context);
2383
25.7k
  yr_free(stack.items);
2384
2385
25.7k
  YR_DEBUG_FPRINTF(
2386
25.7k
      2,
2387
25.7k
      stderr,
2388
25.7k
      "} = %d AKA %s // %s()\n",
2389
25.7k
      result,
2390
25.7k
      yr_debug_error_as_string(result),
2391
25.7k
      __FUNCTION__);
2392
2393
25.7k
  return result;
2394
25.7k
}