Coverage Report

Created: 2026-08-13 06:11

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/yara/libyara/exec.c
Line
Count
Source
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
7.62k
#define MEM_SIZE YR_MAX_LOOP_NESTING*(YR_MAX_LOOP_VARS + YR_INTERNAL_LOOP_VARS)
52
53
#define push(x)                         \
54
0
  if (stack.sp < stack.capacity)        \
55
0
  {                                     \
56
0
    stack.items[stack.sp++] = (x);      \
57
0
  }                                     \
58
0
  else                                  \
59
0
  {                                     \
60
0
    result = ERROR_EXEC_STACK_OVERFLOW; \
61
0
    stop = true;                        \
62
0
    break;                              \
63
0
  }
64
65
#define pop(x)                   \
66
0
  {                              \
67
0
    assert(stack.sp > 0);        \
68
0
    x = stack.items[--stack.sp]; \
69
0
  }
70
71
0
#define is_undef(x) IS_UNDEFINED((x).i)
72
73
#define ensure_defined(x) \
74
0
  if (is_undef(x))        \
75
0
  {                       \
76
0
    r1.i = YR_UNDEFINED;  \
77
0
    push(r1);             \
78
0
    break;                \
79
0
  }
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
7.62k
  {                                                               \
92
7.62k
    YR_ARENA_REF ref;                                             \
93
7.62k
    if (yr_arena_ptr_to_ref(context->rules->arena, x, &ref) == 0) \
94
7.62k
    {                                                             \
95
0
      stop = true;                                                \
96
0
      result = ERROR_INTERNAL_FATAL_ERROR;                        \
97
0
      break;                                                      \
98
0
    }                                                             \
99
7.62k
  }
100
101
#define check_object_canary(o)           \
102
0
  if (o->canary != context->canary)      \
103
0
  {                                      \
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
  };
145
146
0
function_read(uint8_t, little_endian);
147
0
function_read(uint16_t, little_endian);
148
0
function_read(uint32_t, little_endian);
149
0
function_read(int8_t, little_endian);
150
0
function_read(int16_t, little_endian);
151
0
function_read(int32_t, little_endian);
152
0
function_read(uint8_t, big_endian);
153
0
function_read(uint16_t, big_endian);
154
0
function_read(uint32_t, big_endian);
155
0
function_read(int8_t, big_endian);
156
0
function_read(int16_t, big_endian);
157
0
function_read(int32_t, big_endian);
158
159
static const uint8_t* jmp_if(int condition, const uint8_t* ip)
160
0
{
161
0
  int32_t off = 0;
162
163
0
  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
0
  else
178
0
  {
179
    // The condition is false, the execution flow proceeds with the instruction
180
    // right after the jump.
181
0
    off = sizeof(int32_t);
182
0
  }
183
184
0
  return ip + off;
185
0
}
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
7.62k
{
420
7.62k
  YR_DEBUG_FPRINTF(2, stderr, "+ %s() {\n", __FUNCTION__);
421
422
7.62k
  const uint8_t* ip = context->rules->code_start;
423
424
7.62k
  YR_VALUE mem[MEM_SIZE];
425
7.62k
  YR_VALUE args[YR_MAX_FUNCTION_ARGS];
426
7.62k
  YR_VALUE r1;
427
7.62k
  YR_VALUE r2;
428
7.62k
  YR_VALUE r3;
429
7.62k
  YR_VALUE r4;
430
431
7.62k
  YR_VALUE_STACK stack;
432
433
7.62k
  uint64_t elapsed_time;
434
435
#ifdef YR_PROFILING_ENABLED
436
  uint64_t start_time;
437
#endif
438
439
7.62k
  uint32_t current_rule_idx = 0;
440
7.62k
  YR_RULE* current_rule = NULL;
441
7.62k
  YR_RULE* rule;
442
7.62k
  YR_MATCH* match;
443
7.62k
  YR_OBJECT_FUNCTION* function;
444
7.62k
  YR_OBJECT** obj_ptr;
445
7.62k
  YR_ARENA* obj_arena;
446
7.62k
  YR_NOTEBOOK* it_notebook;
447
448
7.62k
  char* identifier;
449
7.62k
  char* args_fmt;
450
451
7.62k
  int found;
452
7.62k
  int count;
453
7.62k
  int result = ERROR_SUCCESS;
454
7.62k
  int cycle = 0;
455
7.62k
  int obj_count = 0;
456
457
7.62k
  bool stop = false;
458
459
7.62k
  uint8_t opcode;
460
461
7.62k
  yr_get_configuration_uint32(YR_CONFIG_STACK_SIZE, &stack.capacity);
462
463
7.62k
  stack.sp = 0;
464
7.62k
  stack.items = (YR_VALUE*) yr_malloc(stack.capacity * sizeof(YR_VALUE));
465
466
7.62k
  if (stack.items == NULL)
467
0
    return ERROR_INSUFFICIENT_MEMORY;
468
469
7.62k
  FAIL_ON_ERROR_WITH_CLEANUP(
470
7.62k
      yr_arena_create(1, 512 * sizeof(YR_OBJECT*), &obj_arena),
471
7.62k
      yr_free(stack.items));
472
473
7.62k
  FAIL_ON_ERROR_WITH_CLEANUP(
474
7.62k
      yr_notebook_create(512 * sizeof(YR_ITERATOR), &it_notebook),
475
7.62k
      yr_arena_release(obj_arena);
476
7.62k
      yr_free(stack.items));
477
478
#ifdef YR_PROFILING_ENABLED
479
  start_time = yr_stopwatch_elapsed_ns(&context->stopwatch);
480
#endif
481
482
7.62k
#if YR_PARANOID_EXEC
483
7.62k
  memset(mem, 0, MEM_SIZE * sizeof(mem[0]));
484
7.62k
#endif
485
486
22.8k
  while (!stop)
487
15.2k
  {
488
    // Read the opcode from the address indicated by the instruction pointer.
489
15.2k
    opcode = *ip;
490
491
    // Advance the instruction pointer, which now points past the opcode.
492
15.2k
    ip++;
493
494
15.2k
    switch (opcode)
495
15.2k
    {
496
0
    case OP_NOP:
497
0
      YR_DEBUG_FPRINTF(2, stderr, "- case OP_NOP: // %s()\n", __FUNCTION__);
498
0
      break;
499
500
7.62k
    case OP_HALT:
501
7.62k
      YR_DEBUG_FPRINTF(2, stderr, "- case OP_HALT: // %s()\n", __FUNCTION__);
502
7.62k
      assert(stack.sp == 0);  // When HALT is reached the stack should be empty.
503
7.62k
      stop = true;
504
7.62k
      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
      // The count comes from the compiled rules and a hand-crafted file can
581
      // set it to a value that overflows the allocation size below or makes
582
      // the loop pop past the stack. It can't be larger than the number of
583
      // items currently on the stack.
584
0
      if (r1.i < 0 || (uint64_t) r1.i > stack.sp)
585
0
      {
586
0
        result = ERROR_INTERNAL_FATAL_ERROR;
587
0
        stop = true;
588
0
        break;
589
0
      }
590
591
0
      r3.p = yr_notebook_alloc(
592
0
          it_notebook, sizeof(YR_ITERATOR) + sizeof(uint64_t) * (size_t) r1.i);
593
594
0
      if (r3.p == NULL)
595
0
      {
596
0
        result = ERROR_INSUFFICIENT_MEMORY;
597
0
      }
598
0
      else
599
0
      {
600
0
        r3.it->int_enum_it.count = r1.i;
601
0
        r3.it->int_enum_it.next = 0;
602
0
        r3.it->next_func_idx = ITER_NEXT_INT_ENUM;
603
604
0
        for (int64_t i = r1.i; i > 0; i--)
605
0
        {
606
0
          pop(r2);
607
0
          r3.it->int_enum_it.items[i - 1] = r2.i;
608
0
        }
609
610
0
        push(r3);
611
0
      }
612
613
0
      stop = (result != ERROR_SUCCESS);
614
0
      break;
615
616
0
    case OP_ITER_START_STRING_SET:
617
0
      YR_DEBUG_FPRINTF(
618
0
          2,
619
0
          stderr,
620
0
          "- case OP_ITER_START_STRING_SET: // %s()\n",
621
0
          __FUNCTION__);
622
623
0
      pop(r1);
624
625
      // One extra value (the undefined string) is popped below, so the count
626
      // must be strictly smaller than the number of items on the stack. A
627
      // hand-crafted count would otherwise overflow the allocation or pop past
628
      // the stack.
629
0
      if (r1.i < 0 || (uint64_t) r1.i >= stack.sp)
630
0
      {
631
0
        result = ERROR_INTERNAL_FATAL_ERROR;
632
0
        stop = true;
633
0
        break;
634
0
      }
635
636
0
      r3.p = yr_notebook_alloc(
637
0
          it_notebook,
638
0
          sizeof(YR_ITERATOR) + sizeof(YR_STRING*) * (size_t) r1.i);
639
640
0
      if (r3.p == NULL)
641
0
      {
642
0
        result = ERROR_INSUFFICIENT_MEMORY;
643
0
      }
644
0
      else
645
0
      {
646
0
        r3.it->string_set_it.count = r1.i;
647
0
        r3.it->string_set_it.index = 0;
648
0
        r3.it->next_func_idx = ITER_NEXT_STRING_SET;
649
650
0
        for (int64_t i = r1.i; i > 0; i--)
651
0
        {
652
0
          pop(r2);
653
0
          r3.it->string_set_it.strings[i - 1] = r2.s;
654
0
        }
655
656
        // One last pop of the UNDEFINED string
657
0
        pop(r2);
658
0
        push(r3);
659
0
      }
660
661
0
      stop = (result != ERROR_SUCCESS);
662
0
      break;
663
664
0
    case OP_ITER_START_TEXT_STRING_SET:
665
0
      YR_DEBUG_FPRINTF(
666
0
          2,
667
0
          stderr,
668
0
          "- case OP_ITER_START_TEXT_STRING_SET: // %s()\n",
669
0
          __FUNCTION__);
670
671
0
      pop(r1);
672
673
      // The count comes from the compiled rules and can't be larger than the
674
      // number of items on the stack, otherwise the allocation below overflows
675
      // or the loop pops past the stack.
676
0
      if (r1.i < 0 || (uint64_t) r1.i > stack.sp)
677
0
      {
678
0
        result = ERROR_INTERNAL_FATAL_ERROR;
679
0
        stop = true;
680
0
        break;
681
0
      }
682
683
0
      r3.p = yr_notebook_alloc(
684
0
          it_notebook,
685
0
          sizeof(YR_ITERATOR) + sizeof(SIZED_STRING*) * (size_t) r1.i);
686
687
0
      if (r3.p == NULL)
688
0
      {
689
0
        result = ERROR_INSUFFICIENT_MEMORY;
690
0
      }
691
0
      else
692
0
      {
693
0
        r3.it->text_string_set_it.count = r1.i;
694
0
        r3.it->text_string_set_it.index = 0;
695
0
        r3.it->next_func_idx = ITER_NEXT_TEXT_STRING_SET;
696
697
0
        for (int64_t i = r1.i; i > 0; i--)
698
0
        {
699
0
          pop(r2);
700
0
          r3.it->text_string_set_it.strings[i - 1] = r2.ss;
701
0
        }
702
703
0
        push(r3);
704
0
      }
705
706
0
      stop = (result != ERROR_SUCCESS);
707
0
      break;
708
709
0
    case OP_ITER_NEXT:
710
0
      YR_DEBUG_FPRINTF(
711
0
          2, stderr, "- case OP_ITER_NEXT: // %s()\n", __FUNCTION__);
712
      // Loads the iterator in r1, but leaves the iterator in the stack.
713
0
      pop(r1);
714
0
      push(r1);
715
716
0
      if (r1.it->next_func_idx <
717
0
          sizeof(iter_next_func_table) / sizeof(YR_ITERATOR_NEXT_FUNC))
718
0
      {
719
        // The iterator's next function is responsible for pushing the next
720
        // item in the stack, and a boolean indicating if there are more items
721
        // to retrieve. The boolean will be at the top of the stack after
722
        // calling "next".
723
0
        result = iter_next_func_table[r1.it->next_func_idx](r1.it, &stack);
724
0
      }
725
0
      else
726
0
      {
727
        // next_func_idx is outside the valid range, this should not happend.
728
0
        result = ERROR_INTERNAL_FATAL_ERROR;
729
0
      }
730
731
0
      stop = (result != ERROR_SUCCESS);
732
0
      break;
733
734
0
    case OP_ITER_CONDITION:
735
0
      YR_DEBUG_FPRINTF(
736
0
          2, stderr, "- case OP_ITER_CONDITION: // %s()\n", __FUNCTION__);
737
738
      // Evaluate the iteration condition of the loop. This instruction
739
      // evaluates to 1 if the loop should continue and 0 if it shouldn't
740
      // (due to short-circuit evaluation).
741
742
0
      pop(r2);  // min. expression - all, any, none, integer
743
0
      pop(r3);  // number of true expressions
744
0
      pop(r4);  // last expression result
745
746
      // In case of 'all' loop, end once we the body failed
747
0
      if (is_undef(r2))
748
0
      {
749
0
        r1.i = r4.i != 0 ? 1 : 0;
750
0
      }
751
      // In case of 'none' loop, end once the body succeed
752
0
      else if (r2.i == 0)
753
0
      {
754
0
        r1.i = r4.i != 1 ? 1 : 0;
755
0
      }
756
      // In case of other loops, end once we satified min. expr.
757
0
      else
758
0
      {
759
0
        r1.i = r3.i + r4.i < r2.i ? 1 : 0;
760
0
      }
761
762
      // Push whether loop should continue and repush
763
      // the last expression result
764
0
      push(r1);
765
0
      push(r4);
766
0
      break;
767
768
0
    case OP_ITER_END:
769
0
      YR_DEBUG_FPRINTF(
770
0
          2, stderr, "- case OP_ITER_END: // %s()\n", __FUNCTION__);
771
772
      // Evaluate the whole loop. Whether it was successful or not
773
      // and whether it satisfied it's quantifier.
774
775
0
      pop(r2);  // min. expression - all, any, none, integer
776
0
      pop(r3);  // number of true expressions
777
0
      pop(r4);  // number of total iterations
778
779
      // If there was 0 iterations in total, it doesn't
780
      // matter what other numbers show. We can't evaluate
781
      // the loop as true.
782
0
      if (r4.i == 0)
783
0
      {
784
0
        r1.i = 0;
785
0
      }
786
0
      else if (is_undef(r2))
787
0
      {
788
0
        r1.i = r3.i == r4.i ? 1 : 0;
789
0
      }
790
0
      else if (r2.i == 0)
791
0
      {
792
0
        r1.i = r3.i == 0 ? 1 : 0;
793
0
      }
794
0
      else
795
0
      {
796
0
        r1.i = r3.i >= r2.i ? 1 : 0;
797
0
      }
798
799
0
      push(r1);
800
0
      break;
801
802
0
    case OP_PUSH:
803
0
      YR_DEBUG_FPRINTF(2, stderr, "- case OP_PUSH: // %s()\n", __FUNCTION__);
804
0
      r1.i = yr_unaligned_u64(ip);
805
0
      ip += sizeof(uint64_t);
806
0
      push(r1);
807
0
      break;
808
809
0
    case OP_PUSH_8:
810
0
      r1.i = *ip;
811
0
      YR_DEBUG_FPRINTF(
812
0
          2,
813
0
          stderr,
814
0
          "- case OP_PUSH_8: r1.i=%" PRId64 " // %s()\n",
815
0
          r1.i,
816
0
          __FUNCTION__);
817
0
      ip += sizeof(uint8_t);
818
0
      push(r1);
819
0
      break;
820
821
0
    case OP_PUSH_16:
822
0
      r1.i = yr_unaligned_u16(ip);
823
0
      YR_DEBUG_FPRINTF(
824
0
          2,
825
0
          stderr,
826
0
          "- case OP_PUSH_16: r1.i=%" PRId64 " // %s()\n",
827
0
          r1.i,
828
0
          __FUNCTION__);
829
0
      ip += sizeof(uint16_t);
830
0
      push(r1);
831
0
      break;
832
833
0
    case OP_PUSH_32:
834
0
      r1.i = yr_unaligned_u32(ip);
835
0
      YR_DEBUG_FPRINTF(
836
0
          2,
837
0
          stderr,
838
0
          "- case OP_PUSH_32: r1.i=%" PRId64 " // %s()\n",
839
0
          r1.i,
840
0
          __FUNCTION__);
841
0
      ip += sizeof(uint32_t);
842
0
      push(r1);
843
0
      break;
844
845
0
    case OP_PUSH_U:
846
0
      YR_DEBUG_FPRINTF(2, stderr, "- case OP_PUSH_U: // %s()\n", __FUNCTION__);
847
0
      r1.i = YR_UNDEFINED;
848
0
      push(r1);
849
0
      break;
850
851
0
    case OP_POP:
852
0
      YR_DEBUG_FPRINTF(2, stderr, "- case OP_POP: // %s()\n", __FUNCTION__);
853
0
      pop(r1);
854
0
      break;
855
856
0
    case OP_CLEAR_M:
857
0
      YR_DEBUG_FPRINTF(2, stderr, "- case OP_CLEAR_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
      mem[r1.i].i = 0;
864
0
      break;
865
866
0
    case OP_ADD_M:
867
0
      YR_DEBUG_FPRINTF(2, stderr, "- case OP_ADD_M: // %s()\n", __FUNCTION__);
868
0
      r1.i = yr_unaligned_u64(ip);
869
0
      ip += sizeof(uint64_t);
870
0
#if YR_PARANOID_EXEC
871
0
      ensure_within_mem(r1.i);
872
0
#endif
873
0
      pop(r2);
874
0
      if (!is_undef(r2))
875
0
        mem[r1.i].i += r2.i;
876
0
      break;
877
878
0
    case OP_INCR_M:
879
0
      YR_DEBUG_FPRINTF(2, stderr, "- case OP_INCR_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
      mem[r1.i].i++;
886
0
      break;
887
888
0
    case OP_PUSH_M:
889
0
      YR_DEBUG_FPRINTF(2, stderr, "- case OP_PUSH_M: // %s()\n", __FUNCTION__);
890
0
      r1.i = yr_unaligned_u64(ip);
891
0
      ip += sizeof(uint64_t);
892
0
#if YR_PARANOID_EXEC
893
0
      ensure_within_mem(r1.i);
894
0
#endif
895
0
      r1 = mem[r1.i];
896
0
      push(r1);
897
0
      break;
898
899
0
    case OP_POP_M:
900
0
      YR_DEBUG_FPRINTF(2, stderr, "- case OP_POP_M: // %s()\n", __FUNCTION__);
901
0
      r1.i = yr_unaligned_u64(ip);
902
0
      ip += sizeof(uint64_t);
903
0
#if YR_PARANOID_EXEC
904
0
      ensure_within_mem(r1.i);
905
0
#endif
906
0
      pop(r2);
907
0
      mem[r1.i] = r2;
908
0
      break;
909
910
0
    case OP_SET_M:
911
0
      YR_DEBUG_FPRINTF(2, stderr, "- case OP_SET_M: // %s()\n", __FUNCTION__);
912
0
      r1.i = yr_unaligned_u64(ip);
913
0
      ip += sizeof(uint64_t);
914
0
#if YR_PARANOID_EXEC
915
0
      ensure_within_mem(r1.i);
916
0
#endif
917
0
      pop(r2);
918
0
      push(r2);
919
0
      if (!is_undef(r2))
920
0
        mem[r1.i] = r2;
921
0
      break;
922
923
0
    case OP_SWAPUNDEF:
924
0
      YR_DEBUG_FPRINTF(
925
0
          2, stderr, "- case OP_SWAPUNDEF: // %s()\n", __FUNCTION__);
926
0
      r1.i = yr_unaligned_u64(ip);
927
0
      ip += sizeof(uint64_t);
928
0
#if YR_PARANOID_EXEC
929
0
      ensure_within_mem(r1.i);
930
0
#endif
931
0
      pop(r2);
932
933
0
      if (is_undef(r2))
934
0
      {
935
0
        r1 = mem[r1.i];
936
0
        push(r1);
937
0
      }
938
0
      else
939
0
      {
940
0
        push(r2);
941
0
      }
942
0
      break;
943
944
0
    case OP_JNUNDEF:
945
      // Jump if the top the stack is not undefined without modifying the stack.
946
0
      YR_DEBUG_FPRINTF(2, stderr, "- case OP_JNUNDEF: // %s()\n", __FUNCTION__);
947
0
      pop(r1);
948
0
      push(r1);
949
0
      ip = jmp_if(!is_undef(r1), ip);
950
0
      break;
951
952
0
    case OP_JUNDEF_P:
953
      // Removes a value from the top of the stack and jump if the value is not
954
      // undefined.
955
0
      YR_DEBUG_FPRINTF(
956
0
          2, stderr, "- case OP_JUNDEF_P: // %s()\n", __FUNCTION__);
957
0
      pop(r1);
958
0
      ip = jmp_if(is_undef(r1), ip);
959
0
      break;
960
961
0
    case OP_JL_P:
962
      // Pops two values A and B from the stack and jump if A < B. B is popped
963
      // first, and then A.
964
0
      YR_DEBUG_FPRINTF(2, stderr, "- case OP_JL_P: // %s()\n", __FUNCTION__);
965
0
      pop(r2);
966
0
      pop(r1);
967
0
      ip = jmp_if(r1.i < r2.i, ip);
968
0
      break;
969
970
0
    case OP_JLE_P:
971
      // Pops two values A and B from the stack and jump if A <= B. B is popped
972
      // first, and then A.
973
0
      YR_DEBUG_FPRINTF(2, stderr, "- case OP_JLE_P: // %s()\n", __FUNCTION__);
974
0
      pop(r2);
975
0
      pop(r1);
976
0
      ip = jmp_if(r1.i <= r2.i, ip);
977
0
      break;
978
979
0
    case OP_JTRUE:
980
      // Jump if the top of the stack is true without modifying the stack. If
981
      // the top of the stack is undefined the jump is not taken.
982
0
      YR_DEBUG_FPRINTF(2, stderr, "- case OP_JTRUE: // %s()\n", __FUNCTION__);
983
0
      pop(r1);
984
0
      push(r1);
985
0
      ip = jmp_if(!is_undef(r1) && r1.i, ip);
986
0
      break;
987
988
0
    case OP_JTRUE_P:
989
      // Removes a value from the stack and jump if it is true. If the value
990
      // is undefined the jump is not taken.
991
0
      YR_DEBUG_FPRINTF(2, stderr, "- case OP_JTRUE_P: // %s()\n", __FUNCTION__);
992
0
      pop(r1);
993
0
      ip = jmp_if(!is_undef(r1) && r1.i, ip);
994
0
      break;
995
996
0
    case OP_JFALSE:
997
      // Jump if the top of the stack is false without modifying the stack. If
998
      // the top of the stack is undefined the jump is not taken.
999
0
      YR_DEBUG_FPRINTF(2, stderr, "- case OP_JFALSE: // %s()\n", __FUNCTION__);
1000
0
      pop(r1);
1001
0
      push(r1);
1002
0
      ip = jmp_if(!is_undef(r1) && !r1.i, ip);
1003
0
      break;
1004
1005
0
    case OP_JFALSE_P:
1006
      // Removes a value from the stack and jump if it is false. If the value
1007
      // is undefined the jump is not taken.
1008
0
      YR_DEBUG_FPRINTF(
1009
0
          2, stderr, "- case OP_JFALSE_P: // %s()\n", __FUNCTION__);
1010
0
      pop(r1);
1011
0
      ip = jmp_if(!is_undef(r1) && !r1.i, ip);
1012
0
      break;
1013
1014
0
    case OP_JZ:
1015
      // Jump if the value at the top of the stack is 0 without modifying the
1016
      // stack.
1017
0
      YR_DEBUG_FPRINTF(2, stderr, "- case OP_JZ: // %s()\n", __FUNCTION__);
1018
0
      pop(r1);
1019
0
      push(r1);
1020
0
      ip = jmp_if(r1.i == 0, ip);
1021
0
      break;
1022
1023
0
    case OP_JZ_P:
1024
      // Removes a value from the stack and jump if the value is 0.
1025
0
      YR_DEBUG_FPRINTF(2, stderr, "- case OP_JZ_P: // %s()\n", __FUNCTION__);
1026
0
      pop(r1);
1027
0
      ip = jmp_if(r1.i == 0, ip);
1028
0
      break;
1029
1030
0
    case OP_AND:
1031
0
      YR_DEBUG_FPRINTF(2, stderr, "- case OP_AND: // %s()\n", __FUNCTION__);
1032
0
      pop(r2);
1033
0
      pop(r1);
1034
1035
0
      if (is_undef(r1))
1036
0
        r1.i = 0;
1037
1038
0
      if (is_undef(r2))
1039
0
        r2.i = 0;
1040
1041
0
      r1.i = r1.i && r2.i;
1042
0
      push(r1);
1043
0
      break;
1044
1045
0
    case OP_OR:
1046
0
      YR_DEBUG_FPRINTF(2, stderr, "- case OP_OR: // %s()\n", __FUNCTION__);
1047
0
      pop(r2);
1048
0
      pop(r1);
1049
1050
0
      if (is_undef(r1))
1051
0
        r1.i = 0;
1052
1053
0
      if (is_undef(r2))
1054
0
        r2.i = 0;
1055
1056
0
      r1.i = r1.i || r2.i;
1057
0
      push(r1);
1058
0
      break;
1059
1060
0
    case OP_NOT:
1061
0
      YR_DEBUG_FPRINTF(2, stderr, "- case OP_NOT: // %s()\n", __FUNCTION__);
1062
0
      pop(r1);
1063
1064
0
      if (is_undef(r1))
1065
0
        r1.i = YR_UNDEFINED;
1066
0
      else
1067
0
        r1.i = !r1.i;
1068
1069
0
      push(r1);
1070
0
      break;
1071
1072
0
    case OP_DEFINED:
1073
0
      pop(r1);
1074
0
      r1.i = !is_undef(r1);
1075
0
      push(r1);
1076
0
      break;
1077
1078
0
    case OP_MOD:
1079
0
      YR_DEBUG_FPRINTF(2, stderr, "- case OP_MOD: // %s()\n", __FUNCTION__);
1080
0
      pop(r2);
1081
0
      pop(r1);
1082
0
      ensure_defined(r2);
1083
0
      ensure_defined(r1);
1084
      // If divisor is zero the result is undefined. It's also undefined
1085
      // when dividing INT64_MIN by -1.
1086
0
      if (r2.i == 0 || (r1.i == INT64_MIN && r2.i == -1))
1087
0
        r1.i = YR_UNDEFINED;
1088
0
      else
1089
0
        r1.i = r1.i % r2.i;
1090
0
      push(r1);
1091
0
      break;
1092
1093
0
    case OP_SHR:
1094
0
      YR_DEBUG_FPRINTF(2, stderr, "- case OP_SHR: // %s()\n", __FUNCTION__);
1095
0
      pop(r2);
1096
0
      pop(r1);
1097
0
      ensure_defined(r2);
1098
0
      ensure_defined(r1);
1099
0
      if (r2.i < 0)
1100
0
        r1.i = YR_UNDEFINED;
1101
0
      else if (r2.i < 64)
1102
0
        r1.i = r1.i >> r2.i;
1103
0
      else
1104
0
        r1.i = 0;
1105
0
      push(r1);
1106
0
      break;
1107
1108
0
    case OP_SHL:
1109
0
      YR_DEBUG_FPRINTF(2, stderr, "- case OP_SHL: // %s()\n", __FUNCTION__);
1110
0
      pop(r2);
1111
0
      pop(r1);
1112
0
      ensure_defined(r2);
1113
0
      ensure_defined(r1);
1114
0
      if (r2.i < 0)
1115
0
        r1.i = YR_UNDEFINED;
1116
0
      else if (r2.i < 64)
1117
0
        r1.i = r1.i << r2.i;
1118
0
      else
1119
0
        r1.i = 0;
1120
0
      push(r1);
1121
0
      break;
1122
1123
0
    case OP_BITWISE_NOT:
1124
0
      YR_DEBUG_FPRINTF(
1125
0
          2, stderr, "- case OP_BITWISE_NOT: // %s()\n", __FUNCTION__);
1126
0
      pop(r1);
1127
0
      ensure_defined(r1);
1128
0
      r1.i = ~r1.i;
1129
0
      push(r1);
1130
0
      break;
1131
1132
0
    case OP_BITWISE_AND:
1133
0
      YR_DEBUG_FPRINTF(
1134
0
          2, stderr, "- case OP_BITWISE_AND: // %s()\n", __FUNCTION__);
1135
0
      pop(r2);
1136
0
      pop(r1);
1137
0
      ensure_defined(r2);
1138
0
      ensure_defined(r1);
1139
0
      r1.i = r1.i & r2.i;
1140
0
      push(r1);
1141
0
      break;
1142
1143
0
    case OP_BITWISE_OR:
1144
0
      YR_DEBUG_FPRINTF(
1145
0
          2, stderr, "- case OP_BITWISE_OR: // %s()\n", __FUNCTION__);
1146
0
      pop(r2);
1147
0
      pop(r1);
1148
0
      ensure_defined(r2);
1149
0
      ensure_defined(r1);
1150
0
      r1.i = r1.i | r2.i;
1151
0
      push(r1);
1152
0
      break;
1153
1154
0
    case OP_BITWISE_XOR:
1155
0
      YR_DEBUG_FPRINTF(
1156
0
          2, stderr, "- case OP_BITWISE_XOR: // %s()\n", __FUNCTION__);
1157
0
      pop(r2);
1158
0
      pop(r1);
1159
0
      ensure_defined(r2);
1160
0
      ensure_defined(r1);
1161
0
      r1.i = r1.i ^ r2.i;
1162
0
      push(r1);
1163
0
      break;
1164
1165
0
    case OP_PUSH_RULE:
1166
0
      YR_DEBUG_FPRINTF(
1167
0
          2, stderr, "- case OP_PUSH_RULE: // %s()\n", __FUNCTION__);
1168
0
      r1.i = yr_unaligned_u64(ip);
1169
0
      ip += sizeof(uint64_t);
1170
1171
0
      rule = &context->rules->rules_table[r1.i];
1172
1173
0
#if YR_PARANOID_EXEC
1174
0
      ensure_within_rules_arena(rule);
1175
0
#endif
1176
1177
0
      if (RULE_IS_DISABLED(rule))
1178
0
      {
1179
0
        r2.i = YR_UNDEFINED;
1180
0
      }
1181
0
      else
1182
0
      {
1183
0
        if (yr_bitmask_is_set(context->rule_matches_flags, r1.i))
1184
0
          r2.i = 1;
1185
0
        else
1186
0
          r2.i = 0;
1187
0
      }
1188
1189
0
      push(r2);
1190
0
      break;
1191
1192
0
    case OP_INIT_RULE:
1193
0
      YR_DEBUG_FPRINTF(
1194
0
          2, stderr, "- case OP_INIT_RULE: // %s()\n", __FUNCTION__);
1195
1196
      // After the opcode there's an int32_t corresponding to the jump's
1197
      // offset and an uint32_t corresponding to the rule's index.
1198
0
      current_rule_idx = yr_unaligned_u32(ip + sizeof(int32_t));
1199
1200
      // The curent rule index can't be larger than the number of rules.
1201
0
      assert(current_rule_idx < context->rules->num_rules);
1202
1203
0
      current_rule = &context->rules->rules_table[current_rule_idx];
1204
1205
0
#if YR_PARANOID_EXEC
1206
0
      ensure_within_rules_arena(current_rule);
1207
0
#endif
1208
1209
      // If the rule is disabled, let's skip its code.
1210
0
      bool skip_rule = RULE_IS_DISABLED(current_rule);
1211
1212
      // The rule is also skipped if it is not required to be evaluated.
1213
0
      skip_rule |= yr_bitmask_is_not_set(
1214
0
          context->required_eval, current_rule_idx);
1215
1216
0
      ip = jmp_if(skip_rule, ip);
1217
1218
0
      if (skip_rule)
1219
0
      {
1220
        // If the rule is skipped it is false, and if a global rule is false
1221
        // we must mark its namespace as unsatisfied.
1222
0
        if (RULE_IS_GLOBAL(current_rule))
1223
0
          yr_bitmask_set(context->ns_unsatisfied_flags, current_rule->ns->idx);
1224
0
      }
1225
0
      else
1226
0
      {
1227
        // If not taking the jump, skip the bytes corresponding to the
1228
        // rule's index.
1229
0
        ip += sizeof(uint32_t);
1230
0
      }
1231
1232
0
      break;
1233
1234
0
    case OP_MATCH_RULE:
1235
0
      YR_DEBUG_FPRINTF(
1236
0
          2, stderr, "- case OP_MATCH_RULE: // %s()\n", __FUNCTION__);
1237
0
      pop(r1);
1238
1239
0
      r2.i = yr_unaligned_u64(ip);
1240
0
      ip += sizeof(uint64_t);
1241
1242
0
      rule = &context->rules->rules_table[r2.i];
1243
1244
0
#if YR_PARANOID_EXEC
1245
0
      ensure_within_rules_arena(rule);
1246
0
#endif
1247
1248
0
      if (!is_undef(r1) && r1.i)
1249
0
        yr_bitmask_set(context->rule_matches_flags, r2.i);
1250
0
      else if (RULE_IS_GLOBAL(rule))
1251
0
        yr_bitmask_set(context->ns_unsatisfied_flags, rule->ns->idx);
1252
1253
#ifdef YR_PROFILING_ENABLED
1254
      elapsed_time = yr_stopwatch_elapsed_ns(&context->stopwatch);
1255
      context->profiling_info[r2.i].exec_time += (elapsed_time - start_time);
1256
      start_time = elapsed_time;
1257
#endif
1258
1259
0
      assert(stack.sp == 0);  // at this point the stack should be empty.
1260
0
      break;
1261
1262
0
    case OP_OBJ_LOAD:
1263
0
      YR_DEBUG_FPRINTF(
1264
0
          2, stderr, "- case OP_OBJ_LOAD: // %s()\n", __FUNCTION__);
1265
1266
0
      identifier = yr_unaligned_char_ptr(ip);
1267
0
      ip += sizeof(uint64_t);
1268
1269
0
#if YR_PARANOID_EXEC
1270
0
      ensure_within_rules_arena(identifier);
1271
0
#endif
1272
1273
0
      r1.o = (YR_OBJECT*) yr_hash_table_lookup(
1274
0
          context->objects_table, identifier, NULL);
1275
1276
0
      assert(r1.o != NULL);
1277
0
      push(r1);
1278
0
      break;
1279
1280
0
    case OP_OBJ_FIELD:
1281
0
      YR_DEBUG_FPRINTF(
1282
0
          2, stderr, "- case OP_OBJ_FIELD: // %s()\n", __FUNCTION__);
1283
1284
0
      identifier = yr_unaligned_char_ptr(ip);
1285
0
      ip += sizeof(uint64_t);
1286
1287
0
#if YR_PARANOID_EXEC
1288
0
      ensure_within_rules_arena(identifier);
1289
0
#endif
1290
1291
0
      pop(r1);
1292
0
      ensure_defined(r1);
1293
1294
0
      r1.o = yr_object_lookup_field(r1.o, identifier);
1295
1296
0
      if (r1.o == NULL)
1297
0
      {
1298
0
        result = ERROR_INVALID_FIELD_NAME;
1299
0
        stop = true;
1300
0
        break;
1301
0
      }
1302
1303
0
      push(r1);
1304
0
      break;
1305
1306
0
    case OP_OBJ_VALUE:
1307
0
      YR_DEBUG_FPRINTF(
1308
0
          2, stderr, "- case OP_OBJ_VALUE: // %s()\n", __FUNCTION__);
1309
0
      pop(r1);
1310
0
      ensure_defined(r1);
1311
1312
0
#if YR_PARANOID_EXEC
1313
0
      check_object_canary(r1.o);
1314
0
#endif
1315
1316
0
      switch (r1.o->type)
1317
0
      {
1318
0
      case OBJECT_TYPE_INTEGER:
1319
0
        r1.i = r1.o->value.i;
1320
0
        break;
1321
1322
0
      case OBJECT_TYPE_FLOAT:
1323
0
        if (yr_isnan(r1.o->value.d))
1324
0
          r1.i = YR_UNDEFINED;
1325
0
        else
1326
0
          r1.d = r1.o->value.d;
1327
0
        break;
1328
1329
0
      case OBJECT_TYPE_STRING:
1330
0
        if (r1.o->value.ss == NULL)
1331
0
          r1.i = YR_UNDEFINED;
1332
0
        else
1333
0
          r1.ss = r1.o->value.ss;
1334
0
        break;
1335
1336
0
      default:
1337
0
        assert(false);
1338
0
      }
1339
1340
0
      push(r1);
1341
0
      break;
1342
1343
0
    case OP_INDEX_ARRAY:
1344
0
      YR_DEBUG_FPRINTF(
1345
0
          2, stderr, "- case OP_INDEX_ARRAY: // %s()\n", __FUNCTION__);
1346
0
      pop(r1);  // index
1347
0
      pop(r2);  // array
1348
1349
0
      ensure_defined(r1);
1350
0
      ensure_defined(r2);
1351
1352
0
      assert(r2.o->type == OBJECT_TYPE_ARRAY);
1353
1354
0
#if YR_PARANOID_EXEC
1355
0
      check_object_canary(r2.o);
1356
0
#endif
1357
1358
0
      r1.o = yr_object_array_get_item(r2.o, 0, (int) r1.i);
1359
1360
0
      if (r1.o == NULL)
1361
0
        r1.i = YR_UNDEFINED;
1362
1363
0
      push(r1);
1364
0
      break;
1365
1366
0
    case OP_LOOKUP_DICT:
1367
0
      YR_DEBUG_FPRINTF(
1368
0
          2, stderr, "- case OP_LOOKUP_DICT: // %s()\n", __FUNCTION__);
1369
0
      pop(r1);  // key
1370
0
      pop(r2);  // dictionary
1371
1372
0
      ensure_defined(r1);
1373
0
      ensure_defined(r2);
1374
1375
0
      assert(r2.o->type == OBJECT_TYPE_DICTIONARY);
1376
1377
0
#if YR_PARANOID_EXEC
1378
0
      check_object_canary(r2.o);
1379
0
#endif
1380
1381
0
      r1.o = yr_object_dict_get_item(r2.o, 0, r1.ss->c_string);
1382
1383
0
      if (r1.o == NULL)
1384
0
        r1.i = YR_UNDEFINED;
1385
1386
0
      push(r1);
1387
0
      break;
1388
1389
0
    case OP_CALL:
1390
0
      YR_DEBUG_FPRINTF(2, stderr, "- case OP_CALL: // %s()\n", __FUNCTION__);
1391
1392
0
      args_fmt = yr_unaligned_char_ptr(ip);
1393
0
      ip += sizeof(uint64_t);
1394
1395
0
      int i = (int) strlen(args_fmt);
1396
0
      count = 0;
1397
1398
0
#if YR_PARANOID_EXEC
1399
0
      if (i > YR_MAX_FUNCTION_ARGS)
1400
0
      {
1401
0
        stop = true;
1402
0
        result = ERROR_INTERNAL_FATAL_ERROR;
1403
0
        break;
1404
0
      }
1405
0
#endif
1406
1407
      // pop arguments from stack and copy them to args array
1408
1409
0
      while (i > 0)
1410
0
      {
1411
0
        pop(r1);
1412
1413
0
        if (is_undef(r1))  // count the number of undefined args
1414
0
          count++;
1415
1416
0
        args[i - 1] = r1;
1417
0
        i--;
1418
0
      }
1419
1420
0
      pop(r2);
1421
0
      ensure_defined(r2);
1422
1423
0
#if YR_PARANOID_EXEC
1424
0
      check_object_canary(r2.o);
1425
0
#endif
1426
1427
0
      if (count > 0)
1428
0
      {
1429
        // If there are undefined args, result for function call
1430
        // is undefined as well.
1431
1432
0
        r1.i = YR_UNDEFINED;
1433
0
        push(r1);
1434
0
        break;
1435
0
      }
1436
1437
0
      function = object_as_function(r2.o);
1438
0
      result = ERROR_INTERNAL_FATAL_ERROR;
1439
1440
0
      for (i = 0; i < YR_MAX_OVERLOADED_FUNCTIONS; i++)
1441
0
      {
1442
0
        if (function->prototypes[i].arguments_fmt == NULL)
1443
0
          break;
1444
1445
0
        if (strcmp(function->prototypes[i].arguments_fmt, args_fmt) == 0)
1446
0
        {
1447
0
          result = function->prototypes[i].code(args, context, function);
1448
0
          break;
1449
0
        }
1450
0
      }
1451
1452
      // If i == YR_MAX_OVERLOADED_FUNCTIONS at this point no matching
1453
      // prototype was found, but this shouldn't happen.
1454
0
      assert(i < YR_MAX_OVERLOADED_FUNCTIONS);
1455
1456
      // Make a copy of the returned object and push the copy into the stack,
1457
      // function->return_obj can't be pushed because it can change in
1458
      // subsequent calls to the same function.
1459
0
      if (result == ERROR_SUCCESS)
1460
0
        result = yr_object_copy(function->return_obj, &r1.o);
1461
1462
      // A pointer to the copied object is stored in a arena in order to
1463
      // free the object before exiting yr_execute_code, obj_count tracks
1464
      // the number of objects written.
1465
0
      if (result == ERROR_SUCCESS)
1466
0
      {
1467
0
        result = yr_arena_write_data(obj_arena, 0, &r1.o, sizeof(r1.o), NULL);
1468
0
        obj_count++;
1469
0
      }
1470
0
      else
1471
0
      {
1472
0
        r1.i = YR_UNDEFINED;
1473
0
      }
1474
1475
0
      stop = (result != ERROR_SUCCESS);
1476
0
      push(r1);
1477
0
      break;
1478
1479
0
    case OP_FOUND:
1480
0
      pop(r1);
1481
0
      r2.i = context->matches[r1.s->idx].tail != NULL ? 1 : 0;
1482
0
      YR_DEBUG_FPRINTF(
1483
0
          2,
1484
0
          stderr,
1485
0
          "- case OP_FOUND: r2.i=%" PRId64 " // %s()\n",
1486
0
          r2.i,
1487
0
          __FUNCTION__);
1488
0
      push(r2);
1489
0
      break;
1490
1491
0
    case OP_FOUND_AT:
1492
0
      YR_DEBUG_FPRINTF(
1493
0
          2, stderr, "- case OP_FOUND_AT: // %s()\n", __FUNCTION__);
1494
0
      pop(r2);
1495
0
      pop(r1);
1496
1497
0
      ensure_defined(r1);
1498
1499
0
#if YR_PARANOID_EXEC
1500
0
      ensure_within_rules_arena(r2.p);
1501
0
#endif
1502
1503
0
      match = context->matches[r2.s->idx].head;
1504
0
      r3.i = false;
1505
1506
0
      while (match != NULL)
1507
0
      {
1508
0
        if (r1.i == match->base + match->offset)
1509
0
        {
1510
0
          r3.i = true;
1511
0
          break;
1512
0
        }
1513
1514
0
        if (r1.i < match->base + match->offset)
1515
0
          break;
1516
1517
0
        match = match->next;
1518
0
      }
1519
1520
0
      push(r3);
1521
0
      break;
1522
1523
0
    case OP_FOUND_IN:
1524
0
      YR_DEBUG_FPRINTF(
1525
0
          2, stderr, "- case OP_FOUND_IN: // %s()\n", __FUNCTION__);
1526
0
      pop(r3);
1527
0
      pop(r2);
1528
0
      pop(r1);
1529
1530
0
      ensure_defined(r1);
1531
0
      ensure_defined(r2);
1532
1533
0
#if YR_PARANOID_EXEC
1534
0
      ensure_within_rules_arena(r3.p);
1535
0
#endif
1536
1537
0
      match = context->matches[r3.s->idx].head;
1538
0
      r4.i = false;
1539
1540
0
      while (match != NULL && !r4.i)
1541
0
      {
1542
0
        if (match->base + match->offset >= r1.i &&
1543
0
            match->base + match->offset <= r2.i)
1544
0
        {
1545
0
          r4.i = true;
1546
0
        }
1547
1548
0
        if (match->base + match->offset > r2.i)
1549
0
          break;
1550
1551
0
        match = match->next;
1552
0
      }
1553
1554
0
      push(r4);
1555
0
      break;
1556
1557
0
    case OP_COUNT:
1558
0
      YR_DEBUG_FPRINTF(2, stderr, "- case OP_COUNT: // %s()\n", __FUNCTION__);
1559
0
      pop(r1);
1560
1561
0
#if YR_PARANOID_EXEC
1562
0
      ensure_within_rules_arena(r1.p);
1563
0
#endif
1564
1565
0
      r2.i = context->matches[r1.s->idx].count;
1566
0
      push(r2);
1567
0
      break;
1568
1569
0
    case OP_COUNT_IN:
1570
0
      YR_DEBUG_FPRINTF(
1571
0
          2, stderr, "- case OP_COUNT_IN: // %s()\n", __FUNCTION__);
1572
0
      pop(r3);
1573
0
      pop(r2);
1574
0
      pop(r1);
1575
1576
0
      ensure_defined(r1);
1577
0
      ensure_defined(r2);
1578
1579
0
#if YR_PARANOID_EXEC
1580
0
      ensure_within_rules_arena(r3.p);
1581
0
#endif
1582
1583
0
      match = context->matches[r3.s->idx].head;
1584
0
      r4.i = 0;
1585
1586
0
      while (match != NULL)
1587
0
      {
1588
0
        if (match->base + match->offset >= r1.i &&
1589
0
            match->base + match->offset <= r2.i)
1590
0
        {
1591
0
          r4.i++;
1592
0
        }
1593
1594
0
        if (match->base + match->offset > r2.i)
1595
0
          break;
1596
1597
0
        match = match->next;
1598
0
      }
1599
1600
0
      push(r4);
1601
0
      break;
1602
1603
0
    case OP_OFFSET:
1604
0
      YR_DEBUG_FPRINTF(2, stderr, "- case OP_OFFSET: // %s()\n", __FUNCTION__);
1605
0
      pop(r2);
1606
0
      pop(r1);
1607
1608
0
      ensure_defined(r1);
1609
1610
0
#if YR_PARANOID_EXEC
1611
0
      ensure_within_rules_arena(r2.p);
1612
0
#endif
1613
1614
0
      match = context->matches[r2.s->idx].head;
1615
1616
0
      i = 1;
1617
0
      r3.i = YR_UNDEFINED;
1618
1619
0
      while (match != NULL && r3.i == YR_UNDEFINED)
1620
0
      {
1621
0
        if (r1.i == i)
1622
0
          r3.i = match->base + match->offset;
1623
1624
0
        i++;
1625
0
        match = match->next;
1626
0
      }
1627
1628
0
      push(r3);
1629
0
      break;
1630
1631
0
    case OP_LENGTH:
1632
0
      YR_DEBUG_FPRINTF(2, stderr, "- case OP_LENGTH: // %s()\n", __FUNCTION__);
1633
0
      pop(r2);
1634
0
      pop(r1);
1635
1636
0
      ensure_defined(r1);
1637
1638
0
#if YR_PARANOID_EXEC
1639
0
      ensure_within_rules_arena(r2.p);
1640
0
#endif
1641
1642
0
      match = context->matches[r2.s->idx].head;
1643
1644
0
      i = 1;
1645
0
      r3.i = YR_UNDEFINED;
1646
1647
0
      while (match != NULL && r3.i == YR_UNDEFINED)
1648
0
      {
1649
0
        if (r1.i == i)
1650
0
          r3.i = match->match_length;
1651
1652
0
        i++;
1653
0
        match = match->next;
1654
0
      }
1655
1656
0
      push(r3);
1657
0
      break;
1658
1659
0
    case OP_OF:
1660
0
    case OP_OF_PERCENT:
1661
0
      r2.i = yr_unaligned_u64(ip);
1662
0
      ip += sizeof(uint64_t);
1663
0
      assert(r2.i == OF_STRING_SET || r2.i == OF_RULE_SET);
1664
0
      found = 0;
1665
0
      count = 0;
1666
0
      pop(r1);
1667
1668
0
      while (!is_undef(r1))
1669
0
      {
1670
0
        if (r2.i == OF_STRING_SET)
1671
0
        {
1672
0
          if (context->matches[r1.s->idx].tail != NULL)
1673
0
          {
1674
0
            found++;
1675
0
          }
1676
0
        }
1677
0
        else
1678
0
        {
1679
          // r1.i is 1 if the rule has already matched and zero otherwise.
1680
0
          found += r1.i;
1681
0
        }
1682
0
        count++;
1683
0
        pop(r1);
1684
0
      }
1685
1686
0
      pop(r2);
1687
1688
0
      if (opcode == OP_OF)
1689
0
      {
1690
0
        YR_DEBUG_FPRINTF(2, stderr, "- case OP_OF: // %s()\n", __FUNCTION__);
1691
1692
        // Quantifier is "all"
1693
0
        if (is_undef(r2))
1694
0
        {
1695
0
          r1.i = found >= count ? 1 : 0;
1696
0
        }
1697
        // Quantifier is 0 or none. This is a special case in which we want
1698
        // exactly 0 strings matching. More information at:
1699
        // https://github.com/VirusTotal/yara/issues/1695
1700
0
        else if (r2.i == 0)
1701
0
        {
1702
0
          r1.i = found == 0 ? 1 : 0;
1703
0
        }
1704
        // In all other cases the number of strings matching should be at
1705
        // least the amount specified by the quantifier.
1706
0
        else
1707
0
        {
1708
0
          r1.i = found >= r2.i ? 1 : 0;
1709
0
        }
1710
0
      }
1711
0
      else  // OP_OF_PERCENT
1712
0
      {
1713
0
        YR_DEBUG_FPRINTF(
1714
0
            2, stderr, "- case OP_OF_PERCENT: // %s()\n", __FUNCTION__);
1715
1716
        // If, by some weird reason, we manage to get an undefined string
1717
        // reference as the first thing on the stack then count would be zero.
1718
        // I don't know how this could ever happen but better to check for it.
1719
0
        if (is_undef(r2) || count == 0)
1720
0
          r1.i = YR_UNDEFINED;
1721
0
        else
1722
0
          r1.i = (((double) found / count) * 100) >= r2.i ? 1 : 0;
1723
0
      }
1724
1725
0
      push(r1);
1726
0
      break;
1727
1728
0
    case OP_OF_FOUND_IN:
1729
0
      YR_DEBUG_FPRINTF(
1730
0
          2, stderr, "- case OP_OF_FOUND_IN: // %s()\n", __FUNCTION__);
1731
1732
0
      found = 0;
1733
0
      count = 0;
1734
1735
0
      pop(r2);  // Offset range end
1736
0
      pop(r1);  // Offset range start
1737
0
      pop(r3);  // First string
1738
1739
      // If any of the range boundaries are undefined the result is also
1740
      // undefined, be we need to unwind the stack first.
1741
0
      if (is_undef(r1) || is_undef(r2))
1742
0
      {
1743
        // Remove all the strings.
1744
0
        while (!is_undef(r3)) pop(r3);
1745
        // Remove the quantifier at the bottom of the stack.
1746
0
        pop(r3);
1747
0
        r1.i = YR_UNDEFINED;
1748
0
        push(r1);
1749
0
        break;
1750
0
      }
1751
1752
0
      while (!is_undef(r3))
1753
0
      {
1754
0
#if YR_PARANOID_EXEC
1755
0
        ensure_within_rules_arena(r3.p);
1756
0
#endif
1757
0
        match = context->matches[r3.s->idx].head;
1758
1759
0
        while (match != NULL)
1760
0
        {
1761
          // String match within range start and range end?
1762
0
          if (match->base + match->offset >= r1.i &&
1763
0
              match->base + match->offset <= r2.i)
1764
0
          {
1765
0
            found++;
1766
0
            break;
1767
0
          }
1768
1769
          // If current match is past range end, we can stop as matches
1770
          // are sorted by offset in increasing order, so all remaining
1771
          // matches are part the range end too.
1772
0
          if (match->base + match->offset > r1.i)
1773
0
            break;
1774
1775
0
          match = match->next;
1776
0
        }
1777
1778
0
        count++;
1779
0
        pop(r3);
1780
0
      }
1781
1782
0
      pop(r2);  // Quantifier X in expressions like "X of string_set in range"
1783
1784
      // Quantifier is "all".
1785
0
      if (is_undef(r2))
1786
0
      {
1787
0
        r1.i = found >= count ? 1 : 0;
1788
0
      }
1789
      // Quantifier is 0 or none. This is a special case in which we want
1790
      // exactly 0 strings matching. More information at:
1791
      // https://github.com/VirusTotal/yara/issues/1695
1792
0
      else if (r2.i == 0)
1793
0
      {
1794
0
        r1.i = found == 0 ? 1 : 0;
1795
0
      }
1796
      // In all other cases the number of strings matching should be at least
1797
      // the amount specified by the quantifier.
1798
0
      else
1799
0
      {
1800
0
        r1.i = found >= r2.i ? 1 : 0;
1801
0
      }
1802
1803
0
      push(r1);
1804
0
      break;
1805
1806
0
    case OP_OF_FOUND_AT:
1807
0
      YR_DEBUG_FPRINTF(
1808
0
          2, stderr, "- case OP_OF_FOUND_AT: // %s()\n", __FUNCTION__);
1809
1810
0
      found = 0;
1811
0
      count = 0;
1812
1813
0
      pop(r2);  // Match location
1814
0
      pop(r1);  // First string
1815
1816
      // Match location must be defined.
1817
0
      if (is_undef(r2))
1818
0
      {
1819
        // Remove all the strings.
1820
0
        while (!is_undef(r1)) pop(r1);
1821
        // Remove the quantifier at the bottom of the stack.
1822
0
        pop(r1);
1823
0
        r1.i = YR_UNDEFINED;
1824
0
        push(r1);
1825
0
        break;
1826
0
      }
1827
1828
0
      while (!is_undef(r1))
1829
0
      {
1830
0
#if YR_PARANOID_EXEC
1831
0
        ensure_within_rules_arena(r1.p);
1832
0
#endif
1833
0
        match = context->matches[r1.s->idx].head;
1834
1835
0
        while (match != NULL)
1836
0
        {
1837
          // String match at the desired location?
1838
0
          if (match->base + match->offset == r2.i)
1839
0
          {
1840
0
            found++;
1841
0
            break;
1842
0
          }
1843
1844
          // If current match is past desired location, we can stop as matches
1845
          // are sorted by offset in increasing order, so all remaining
1846
          // matches are past it.
1847
0
          if (match->base + match->offset > r2.i)
1848
0
            break;
1849
1850
0
          match = match->next;
1851
0
        }
1852
1853
0
        count++;
1854
0
        pop(r1);
1855
0
      }
1856
1857
0
      pop(r2);  // Quantifier X in expressions like "X of string_set in range"
1858
1859
      // Quantifier is "all".
1860
0
      if (is_undef(r2))
1861
0
      {
1862
0
        r1.i = found >= count ? 1 : 0;
1863
0
      }
1864
      // Quantifier is 0 or none. This is a special case in which we want
1865
      // exactly 0 strings matching. More information at:
1866
      // https://github.com/VirusTotal/yara/issues/1695
1867
0
      else if (r2.i == 0)
1868
0
      {
1869
0
        r1.i = found == 0 ? 1 : 0;
1870
0
      }
1871
      // In all other cases the number of strings matching should be at least
1872
      // the amount specified by the quantifier.
1873
0
      else
1874
0
      {
1875
0
        r1.i = found >= r2.i ? 1 : 0;
1876
0
      }
1877
1878
0
      push(r1);
1879
0
      break;
1880
1881
0
    case OP_FILESIZE:
1882
0
      r1.i = context->file_size;
1883
0
      YR_DEBUG_FPRINTF(
1884
0
          2,
1885
0
          stderr,
1886
0
          "- case OP_FILESIZE: r1.i=%" PRId64 "%s // %s()\n",
1887
0
          r1.i,
1888
0
          r1.i == YR_UNDEFINED ? " AKA YR_UNDEFINED" : "",
1889
0
          __FUNCTION__);
1890
0
      push(r1);
1891
0
      break;
1892
1893
0
    case OP_ENTRYPOINT:
1894
0
      YR_DEBUG_FPRINTF(
1895
0
          2, stderr, "- case OP_ENTRYPOINT: // %s()\n", __FUNCTION__);
1896
0
      r1.i = context->entry_point;
1897
0
      push(r1);
1898
0
      break;
1899
1900
0
    case OP_INT8:
1901
0
      YR_DEBUG_FPRINTF(2, stderr, "- case OP_INT8: // %s()\n", __FUNCTION__);
1902
0
      pop(r1);
1903
0
      r1.i = read_int8_t_little_endian(context->iterator, (size_t) r1.i);
1904
0
      push(r1);
1905
0
      break;
1906
1907
0
    case OP_INT16:
1908
0
      YR_DEBUG_FPRINTF(2, stderr, "- case OP_INT16: // %s()\n", __FUNCTION__);
1909
0
      pop(r1);
1910
0
      r1.i = read_int16_t_little_endian(context->iterator, (size_t) r1.i);
1911
0
      push(r1);
1912
0
      break;
1913
1914
0
    case OP_INT32:
1915
0
      YR_DEBUG_FPRINTF(2, stderr, "- case OP_INT32: // %s()\n", __FUNCTION__);
1916
0
      pop(r1);
1917
0
      r1.i = read_int32_t_little_endian(context->iterator, (size_t) r1.i);
1918
0
      push(r1);
1919
0
      break;
1920
1921
0
    case OP_UINT8:
1922
0
      YR_DEBUG_FPRINTF(2, stderr, "- case OP_UINT8: // %s()\n", __FUNCTION__);
1923
0
      pop(r1);
1924
0
      r1.i = read_uint8_t_little_endian(context->iterator, (size_t) r1.i);
1925
0
      push(r1);
1926
0
      break;
1927
1928
0
    case OP_UINT16:
1929
0
      YR_DEBUG_FPRINTF(2, stderr, "- case OP_UINT16: // %s()\n", __FUNCTION__);
1930
0
      pop(r1);
1931
0
      r1.i = read_uint16_t_little_endian(context->iterator, (size_t) r1.i);
1932
0
      push(r1);
1933
0
      break;
1934
1935
0
    case OP_UINT32:
1936
0
      YR_DEBUG_FPRINTF(2, stderr, "- case OP_UINT32: // %s()\n", __FUNCTION__);
1937
0
      pop(r1);
1938
0
      r1.i = read_uint32_t_little_endian(context->iterator, (size_t) r1.i);
1939
0
      push(r1);
1940
0
      break;
1941
1942
0
    case OP_INT8BE:
1943
0
      YR_DEBUG_FPRINTF(2, stderr, "- case OP_INT8BE: // %s()\n", __FUNCTION__);
1944
0
      pop(r1);
1945
0
      r1.i = read_int8_t_big_endian(context->iterator, (size_t) r1.i);
1946
0
      push(r1);
1947
0
      break;
1948
1949
0
    case OP_INT16BE:
1950
0
      YR_DEBUG_FPRINTF(2, stderr, "- case OP_INT16BE: // %s()\n", __FUNCTION__);
1951
0
      pop(r1);
1952
0
      r1.i = read_int16_t_big_endian(context->iterator, (size_t) r1.i);
1953
0
      push(r1);
1954
0
      break;
1955
1956
0
    case OP_INT32BE:
1957
0
      YR_DEBUG_FPRINTF(2, stderr, "- case OP_INT32BE: // %s()\n", __FUNCTION__);
1958
0
      pop(r1);
1959
0
      r1.i = read_int32_t_big_endian(context->iterator, (size_t) r1.i);
1960
0
      push(r1);
1961
0
      break;
1962
1963
0
    case OP_UINT8BE:
1964
0
      YR_DEBUG_FPRINTF(2, stderr, "- case OP_UINT8BE: // %s()\n", __FUNCTION__);
1965
0
      pop(r1);
1966
0
      r1.i = read_uint8_t_big_endian(context->iterator, (size_t) r1.i);
1967
0
      push(r1);
1968
0
      break;
1969
1970
0
    case OP_UINT16BE:
1971
0
      YR_DEBUG_FPRINTF(
1972
0
          2, stderr, "- case OP_UINT16BE: // %s()\n", __FUNCTION__);
1973
0
      pop(r1);
1974
0
      r1.i = read_uint16_t_big_endian(context->iterator, (size_t) r1.i);
1975
0
      push(r1);
1976
0
      break;
1977
1978
0
    case OP_UINT32BE:
1979
0
      YR_DEBUG_FPRINTF(
1980
0
          2, stderr, "- case OP_UINT32BE: // %s()\n", __FUNCTION__);
1981
0
      pop(r1);
1982
0
      r1.i = read_uint32_t_big_endian(context->iterator, (size_t) r1.i);
1983
0
      push(r1);
1984
0
      break;
1985
1986
7.62k
    case OP_IMPORT:
1987
7.62k
      YR_DEBUG_FPRINTF(2, stderr, "- case OP_IMPORT: // %s()\n", __FUNCTION__);
1988
7.62k
      r1.i = yr_unaligned_u64(ip);
1989
7.62k
      ip += sizeof(uint64_t);
1990
1991
7.62k
#if YR_PARANOID_EXEC
1992
7.62k
      ensure_within_rules_arena(r1.p);
1993
7.62k
#endif
1994
1995
7.62k
      result = yr_modules_load((char*) r1.p, context);
1996
1997
7.62k
      if (result != ERROR_SUCCESS)
1998
0
        stop = true;
1999
2000
7.62k
      break;
2001
2002
0
    case OP_MATCHES:
2003
0
      YR_DEBUG_FPRINTF(2, stderr, "- case OP_MATCHES: // %s()\n", __FUNCTION__);
2004
0
      pop(r2);
2005
0
      pop(r1);
2006
2007
0
      ensure_defined(r2);
2008
0
      ensure_defined(r1);
2009
2010
0
      result = yr_re_exec(
2011
0
          context,
2012
0
          (uint8_t*) r2.re->code,
2013
0
          (uint8_t*) r1.ss->c_string,
2014
0
          r1.ss->length,
2015
0
          0,
2016
0
          r2.re->flags | RE_FLAGS_SCAN,
2017
0
          NULL,
2018
0
          NULL,
2019
0
          &found);
2020
2021
0
      if (result != ERROR_SUCCESS)
2022
0
        stop = true;
2023
2024
0
      r1.i = found >= 0;
2025
0
      push(r1);
2026
0
      break;
2027
2028
0
    case OP_INT_TO_DBL:
2029
0
      YR_DEBUG_FPRINTF(
2030
0
          2, stderr, "- case OP_INT_TO_DBL: // %s()\n", __FUNCTION__);
2031
0
      r1.i = yr_unaligned_u64(ip);
2032
0
      ip += sizeof(uint64_t);
2033
2034
0
#if YR_PARANOID_EXEC
2035
0
      if (r1.i > stack.sp || stack.sp - r1.i >= stack.capacity)
2036
0
      {
2037
0
        stop = true;
2038
0
        result = ERROR_INTERNAL_FATAL_ERROR;
2039
0
        break;
2040
0
      }
2041
0
#endif
2042
2043
0
      r2 = stack.items[stack.sp - r1.i];
2044
2045
0
      if (is_undef(r2))
2046
0
        stack.items[stack.sp - r1.i].i = YR_UNDEFINED;
2047
0
      else
2048
0
        stack.items[stack.sp - r1.i].d = (double) r2.i;
2049
0
      break;
2050
2051
0
    case OP_STR_TO_BOOL:
2052
0
      YR_DEBUG_FPRINTF(
2053
0
          2, stderr, "- case OP_STR_TO_BOOL: // %s()\n", __FUNCTION__);
2054
0
      pop(r1);
2055
0
      ensure_defined(r1);
2056
0
      r1.i = r1.ss->length > 0;
2057
0
      push(r1);
2058
0
      break;
2059
2060
0
    case OP_INT_EQ:
2061
0
      YR_DEBUG_FPRINTF(2, stderr, "- case OP_INT_EQ: // %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_NEQ:
2071
0
      YR_DEBUG_FPRINTF(2, stderr, "- case OP_INT_NEQ: // %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_LT:
2081
0
      YR_DEBUG_FPRINTF(2, stderr, "- case OP_INT_LT: // %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_GT:
2091
0
      YR_DEBUG_FPRINTF(2, stderr, "- case OP_INT_GT: // %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_LE:
2101
0
      YR_DEBUG_FPRINTF(2, stderr, "- case OP_INT_LE: // %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_GE:
2111
0
      YR_DEBUG_FPRINTF(2, stderr, "- case OP_INT_GE: // %s()\n", __FUNCTION__);
2112
0
      pop(r2);
2113
0
      pop(r1);
2114
0
      ensure_defined(r2);
2115
0
      ensure_defined(r1);
2116
0
      r1.i = r1.i >= r2.i;
2117
0
      push(r1);
2118
0
      break;
2119
2120
0
    case OP_INT_ADD:
2121
0
      YR_DEBUG_FPRINTF(2, stderr, "- case OP_INT_ADD: // %s()\n", __FUNCTION__);
2122
0
      pop(r2);
2123
0
      pop(r1);
2124
0
      ensure_defined(r2);
2125
0
      ensure_defined(r1);
2126
0
      r1.i = r1.i + r2.i;
2127
0
      push(r1);
2128
0
      break;
2129
2130
0
    case OP_INT_SUB:
2131
0
      YR_DEBUG_FPRINTF(2, stderr, "- case OP_INT_SUB: // %s()\n", __FUNCTION__);
2132
0
      pop(r2);
2133
0
      pop(r1);
2134
0
      ensure_defined(r2);
2135
0
      ensure_defined(r1);
2136
0
      r1.i = r1.i - r2.i;
2137
0
      push(r1);
2138
0
      break;
2139
2140
0
    case OP_INT_MUL:
2141
0
      YR_DEBUG_FPRINTF(2, stderr, "- case OP_INT_MUL: // %s()\n", __FUNCTION__);
2142
0
      pop(r2);
2143
0
      pop(r1);
2144
0
      ensure_defined(r2);
2145
0
      ensure_defined(r1);
2146
0
      r1.i = r1.i * r2.i;
2147
0
      push(r1);
2148
0
      break;
2149
2150
0
    case OP_INT_DIV:
2151
0
      YR_DEBUG_FPRINTF(2, stderr, "- case OP_INT_DIV: // %s()\n", __FUNCTION__);
2152
0
      pop(r2);
2153
0
      pop(r1);
2154
0
      ensure_defined(r2);
2155
0
      ensure_defined(r1);
2156
      // If divisor is zero the result is undefined. It's also undefined
2157
      // when dividing INT64_MIN by -1.
2158
0
      if (r2.i == 0 || (r1.i == INT64_MIN && r2.i == -1))
2159
0
        r1.i = YR_UNDEFINED;
2160
0
      else
2161
0
        r1.i = r1.i / r2.i;
2162
0
      push(r1);
2163
0
      break;
2164
2165
0
    case OP_INT_MINUS:
2166
0
      YR_DEBUG_FPRINTF(
2167
0
          2, stderr, "- case OP_INT_MINUS: // %s()\n", __FUNCTION__);
2168
0
      pop(r1);
2169
0
      ensure_defined(r1);
2170
0
      r1.i = -r1.i;
2171
0
      push(r1);
2172
0
      break;
2173
2174
0
    case OP_DBL_LT:
2175
0
      YR_DEBUG_FPRINTF(2, stderr, "- case OP_DBL_LT: // %s()\n", __FUNCTION__);
2176
0
      pop(r2);
2177
0
      pop(r1);
2178
0
      if (is_undef(r1) || is_undef(r2))
2179
0
        r1.i = false;
2180
0
      else
2181
0
        r1.i = r1.d < r2.d;
2182
0
      push(r1);
2183
0
      break;
2184
2185
0
    case OP_DBL_GT:
2186
0
      YR_DEBUG_FPRINTF(2, stderr, "- case OP_DBL_GT: // %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 = r1.d > r2.d;
2192
0
      push(r1);
2193
0
      break;
2194
2195
0
    case OP_DBL_LE:
2196
0
      YR_DEBUG_FPRINTF(2, stderr, "- case OP_DBL_LE: // %s()\n", __FUNCTION__);
2197
0
      pop(r2);
2198
0
      pop(r1);
2199
0
      ensure_defined(r2);
2200
0
      ensure_defined(r1);
2201
0
      r1.i = r1.d <= r2.d;
2202
0
      push(r1);
2203
0
      break;
2204
2205
0
    case OP_DBL_GE:
2206
0
      YR_DEBUG_FPRINTF(2, stderr, "- case OP_DBL_GE: // %s()\n", __FUNCTION__);
2207
0
      pop(r2);
2208
0
      pop(r1);
2209
0
      ensure_defined(r2);
2210
0
      ensure_defined(r1);
2211
0
      r1.i = r1.d >= r2.d;
2212
0
      push(r1);
2213
0
      break;
2214
2215
0
    case OP_DBL_EQ:
2216
0
      YR_DEBUG_FPRINTF(2, stderr, "- case OP_DBL_EQ: // %s()\n", __FUNCTION__);
2217
0
      pop(r2);
2218
0
      pop(r1);
2219
0
      ensure_defined(r2);
2220
0
      ensure_defined(r1);
2221
0
      r1.i = fabs(r1.d - r2.d) < DBL_EPSILON;
2222
0
      push(r1);
2223
0
      break;
2224
2225
0
    case OP_DBL_NEQ:
2226
0
      YR_DEBUG_FPRINTF(2, stderr, "- case OP_DBL_NEQ: // %s()\n", __FUNCTION__);
2227
0
      pop(r2);
2228
0
      pop(r1);
2229
0
      ensure_defined(r2);
2230
0
      ensure_defined(r1);
2231
0
      r1.i = fabs(r1.d - r2.d) >= DBL_EPSILON;
2232
0
      push(r1);
2233
0
      break;
2234
2235
0
    case OP_DBL_ADD:
2236
0
      YR_DEBUG_FPRINTF(2, stderr, "- case OP_DBL_ADD: // %s()\n", __FUNCTION__);
2237
0
      pop(r2);
2238
0
      pop(r1);
2239
0
      ensure_defined(r2);
2240
0
      ensure_defined(r1);
2241
0
      r1.d = r1.d + r2.d;
2242
0
      push(r1);
2243
0
      break;
2244
2245
0
    case OP_DBL_SUB:
2246
0
      YR_DEBUG_FPRINTF(2, stderr, "- case OP_DBL_SUB: // %s()\n", __FUNCTION__);
2247
0
      pop(r2);
2248
0
      pop(r1);
2249
0
      ensure_defined(r2);
2250
0
      ensure_defined(r1);
2251
0
      r1.d = r1.d - r2.d;
2252
0
      push(r1);
2253
0
      break;
2254
2255
0
    case OP_DBL_MUL:
2256
0
      YR_DEBUG_FPRINTF(2, stderr, "- case OP_DBL_MUL: // %s()\n", __FUNCTION__);
2257
0
      pop(r2);
2258
0
      pop(r1);
2259
0
      ensure_defined(r2);
2260
0
      ensure_defined(r1);
2261
0
      r1.d = r1.d * r2.d;
2262
0
      push(r1);
2263
0
      break;
2264
2265
0
    case OP_DBL_DIV:
2266
0
      YR_DEBUG_FPRINTF(2, stderr, "- case OP_DBL_DIV: // %s()\n", __FUNCTION__);
2267
0
      pop(r2);
2268
0
      pop(r1);
2269
0
      ensure_defined(r2);
2270
0
      ensure_defined(r1);
2271
0
      r1.d = r1.d / r2.d;
2272
0
      push(r1);
2273
0
      break;
2274
2275
0
    case OP_DBL_MINUS:
2276
0
      YR_DEBUG_FPRINTF(
2277
0
          2, stderr, "- case OP_DBL_MINUS: // %s()\n", __FUNCTION__);
2278
0
      pop(r1);
2279
0
      ensure_defined(r1);
2280
0
      r1.d = -r1.d;
2281
0
      push(r1);
2282
0
      break;
2283
2284
0
    case OP_STR_EQ:
2285
0
    case OP_STR_NEQ:
2286
0
    case OP_STR_LT:
2287
0
    case OP_STR_LE:
2288
0
    case OP_STR_GT:
2289
0
    case OP_STR_GE:
2290
0
      pop(r2);
2291
0
      pop(r1);
2292
2293
0
      ensure_defined(r2);
2294
0
      ensure_defined(r1);
2295
2296
0
      switch (opcode)
2297
0
      {
2298
0
      case OP_STR_EQ:
2299
0
        YR_DEBUG_FPRINTF(
2300
0
            2, stderr, "- case OP_STR_EQ: // %s()\n", __FUNCTION__);
2301
0
        r1.i = (ss_compare(r1.ss, r2.ss) == 0);
2302
0
        break;
2303
0
      case OP_STR_NEQ:
2304
0
        YR_DEBUG_FPRINTF(
2305
0
            2, stderr, "- case OP_STR_NEQ: // %s()\n", __FUNCTION__);
2306
0
        r1.i = (ss_compare(r1.ss, r2.ss) != 0);
2307
0
        break;
2308
0
      case OP_STR_LT:
2309
0
        YR_DEBUG_FPRINTF(
2310
0
            2, stderr, "- case OP_STR_LT: // %s()\n", __FUNCTION__);
2311
0
        r1.i = (ss_compare(r1.ss, r2.ss) < 0);
2312
0
        break;
2313
0
      case OP_STR_LE:
2314
0
        YR_DEBUG_FPRINTF(
2315
0
            2, stderr, "- case OP_STR_LE: // %s()\n", __FUNCTION__);
2316
0
        r1.i = (ss_compare(r1.ss, r2.ss) <= 0);
2317
0
        break;
2318
0
      case OP_STR_GT:
2319
0
        YR_DEBUG_FPRINTF(
2320
0
            2, stderr, "- case OP_STR_GT: // %s()\n", __FUNCTION__);
2321
0
        r1.i = (ss_compare(r1.ss, r2.ss) > 0);
2322
0
        break;
2323
0
      case OP_STR_GE:
2324
0
        YR_DEBUG_FPRINTF(
2325
0
            2, stderr, "- case OP_STR_GE: // %s()\n", __FUNCTION__);
2326
0
        r1.i = (ss_compare(r1.ss, r2.ss) >= 0);
2327
0
        break;
2328
0
      }
2329
2330
0
      push(r1);
2331
0
      break;
2332
2333
0
    case OP_CONTAINS:
2334
0
    case OP_ICONTAINS:
2335
0
    case OP_STARTSWITH:
2336
0
    case OP_ISTARTSWITH:
2337
0
    case OP_ENDSWITH:
2338
0
    case OP_IENDSWITH:
2339
0
    case OP_IEQUALS:
2340
0
      pop(r2);
2341
0
      pop(r1);
2342
2343
0
      ensure_defined(r1);
2344
0
      ensure_defined(r2);
2345
2346
0
      switch (opcode)
2347
0
      {
2348
0
      case OP_CONTAINS:
2349
0
        YR_DEBUG_FPRINTF(
2350
0
            2, stderr, "- case OP_CONTAINS: // %s()\n", __FUNCTION__);
2351
0
        r1.i = ss_contains(r1.ss, r2.ss);
2352
0
        break;
2353
0
      case OP_ICONTAINS:
2354
0
        YR_DEBUG_FPRINTF(
2355
0
            2, stderr, "- case OP_ICONTAINS: // %s()\n", __FUNCTION__);
2356
0
        r1.i = ss_icontains(r1.ss, r2.ss);
2357
0
        break;
2358
0
      case OP_STARTSWITH:
2359
0
        YR_DEBUG_FPRINTF(
2360
0
            2, stderr, "- case OP_STARTSWITH: // %s()\n", __FUNCTION__);
2361
0
        r1.i = ss_startswith(r1.ss, r2.ss);
2362
0
        break;
2363
0
      case OP_ISTARTSWITH:
2364
0
        YR_DEBUG_FPRINTF(
2365
0
            2, stderr, "- case OP_ISTARTSWITH: // %s()\n", __FUNCTION__);
2366
0
        r1.i = ss_istartswith(r1.ss, r2.ss);
2367
0
        break;
2368
0
      case OP_ENDSWITH:
2369
0
        YR_DEBUG_FPRINTF(
2370
0
            2, stderr, "- case OP_ENDSWITH: // %s()\n", __FUNCTION__);
2371
0
        r1.i = ss_endswith(r1.ss, r2.ss);
2372
0
        break;
2373
0
      case OP_IENDSWITH:
2374
0
        YR_DEBUG_FPRINTF(
2375
0
            2, stderr, "- case OP_IENDSWITH: // %s()\n", __FUNCTION__);
2376
0
        r1.i = ss_iendswith(r1.ss, r2.ss);
2377
0
        break;
2378
0
      case OP_IEQUALS:
2379
0
        YR_DEBUG_FPRINTF(
2380
0
            2, stderr, "- case OP_IEQUALS: // %s()\n", __FUNCTION__);
2381
0
        r1.i = ss_icompare(r1.ss, r2.ss) == 0;
2382
0
        break;
2383
0
      }
2384
2385
0
      push(r1);
2386
0
      break;
2387
2388
0
    default:
2389
0
      YR_DEBUG_FPRINTF(
2390
0
          2, stderr, "- case <unknown instruction>: // %s()\n", __FUNCTION__);
2391
      // Unknown instruction, this shouldn't happen.
2392
0
      assert(false);
2393
15.2k
    }
2394
2395
    // Check for timeout every 100 instruction cycles. If timeout == 0 it means
2396
    // no timeout at all.
2397
2398
15.2k
    if (context->timeout > 0ULL && ++cycle == 100)
2399
0
    {
2400
0
      elapsed_time = yr_stopwatch_elapsed_ns(&context->stopwatch);
2401
2402
0
      if (elapsed_time > context->timeout)
2403
0
      {
2404
#ifdef YR_PROFILING_ENABLED
2405
        context->profiling_info[current_rule_idx].exec_time +=
2406
            (elapsed_time - start_time);
2407
#endif
2408
0
        result = ERROR_SCAN_TIMEOUT;
2409
0
        stop = true;
2410
0
      }
2411
2412
0
      cycle = 0;
2413
0
    }
2414
15.2k
  }
2415
2416
7.62k
  obj_ptr = yr_arena_get_ptr(obj_arena, 0, 0);
2417
2418
7.62k
  for (int i = 0; i < obj_count; i++) yr_object_destroy(obj_ptr[i]);
2419
2420
7.62k
  yr_arena_release(obj_arena);
2421
7.62k
  yr_notebook_destroy(it_notebook);
2422
7.62k
  yr_modules_unload_all(context);
2423
7.62k
  yr_free(stack.items);
2424
2425
7.62k
  YR_DEBUG_FPRINTF(
2426
7.62k
      2,
2427
7.62k
      stderr,
2428
7.62k
      "} = %d AKA %s // %s()\n",
2429
7.62k
      result,
2430
7.62k
      yr_debug_error_as_string(result),
2431
7.62k
      __FUNCTION__);
2432
2433
7.62k
  return result;
2434
7.62k
}