Coverage Report

Created: 2026-08-13 06:11

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/yara/libyara/re.c
Line
Count
Source
1
/*
2
Copyright (c) 2013. 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
/*
31
32
This module implements a regular expressions engine based on Thompson's
33
algorithm as described by Russ Cox in http://swtch.com/~rsc/regexp/regexp2.html.
34
35
What the article names a "thread" has been named a "fiber" in this code, in
36
order to avoid confusion with operating system threads.
37
38
*/
39
40
#include <assert.h>
41
#include <string.h>
42
#include <yara/arena.h>
43
#include <yara/compiler.h>
44
#include <yara/error.h>
45
#include <yara/globals.h>
46
#include <yara/hex_lexer.h>
47
#include <yara/libyara.h>
48
#include <yara/limits.h>
49
#include <yara/mem.h>
50
#include <yara/re.h>
51
#include <yara/re_lexer.h>
52
#include <yara/strutils.h>
53
#include <yara/threading.h>
54
#include <yara/unaligned.h>
55
#include <yara/utils.h>
56
57
0
#define EMIT_BACKWARDS               0x01
58
0
#define EMIT_DONT_SET_FORWARDS_CODE  0x02
59
0
#define EMIT_DONT_SET_BACKWARDS_CODE 0x04
60
61
#ifndef INT16_MAX
62
#define INT16_MAX (32767)
63
#endif
64
65
typedef uint8_t RE_SPLIT_ID_TYPE;
66
67
// RE_REPEAT_ARGS and RE_REPEAT_ANY_ARGS are structures that are embedded in
68
// the regexp's instruction stream. As such, they are not always aligned to
69
// 8-byte boundaries, so they need to be "packed" structures in order to prevent
70
// issues due to unaligned memory accesses.
71
#pragma pack(push)
72
#pragma pack(1)
73
74
typedef struct _RE_REPEAT_ARGS
75
{
76
  uint16_t min;
77
  uint16_t max;
78
  int32_t offset;
79
80
} RE_REPEAT_ARGS;
81
82
typedef struct _RE_REPEAT_ANY_ARGS
83
{
84
  uint16_t min;
85
  uint16_t max;
86
87
} RE_REPEAT_ANY_ARGS;
88
89
#pragma pack(pop)
90
91
typedef struct _RE_EMIT_CONTEXT
92
{
93
  YR_ARENA* arena;
94
  RE_SPLIT_ID_TYPE next_split_id;
95
96
} RE_EMIT_CONTEXT;
97
98
0
#define CHAR_IN_CLASS(cls, chr) ((cls)[(chr) / 8] & 1 << ((chr) % 8))
99
100
static bool _yr_re_is_char_in_class(
101
    RE_CLASS* re_class,
102
    uint8_t chr,
103
    int case_insensitive)
104
0
{
105
0
  int result = CHAR_IN_CLASS(re_class->bitmap, chr);
106
107
0
  if (case_insensitive)
108
0
    result |= CHAR_IN_CLASS(re_class->bitmap, yr_altercase[chr]);
109
110
0
  if (re_class->negated)
111
0
    result = !result;
112
113
0
  return result;
114
0
}
115
116
static bool _yr_re_is_word_char(const uint8_t* input, uint8_t character_size)
117
0
{
118
0
  int result = ((yr_isalnum(input) || (*input) == '_'));
119
120
0
  if (character_size == 2)
121
0
    result = result && (*(input + 1) == 0);
122
123
0
  return result;
124
0
}
125
126
RE_NODE* yr_re_node_create(int type)
127
0
{
128
0
  RE_NODE* result = (RE_NODE*) yr_malloc(sizeof(RE_NODE));
129
130
0
  if (result != NULL)
131
0
  {
132
0
    result->type = type;
133
0
    result->children_head = NULL;
134
0
    result->children_tail = NULL;
135
0
    result->prev_sibling = NULL;
136
0
    result->next_sibling = NULL;
137
0
    result->greedy = true;
138
0
    result->forward_code_ref = YR_ARENA_NULL_REF;
139
0
    result->backward_code_ref = YR_ARENA_NULL_REF;
140
0
  }
141
142
0
  return result;
143
0
}
144
145
void yr_re_node_destroy(RE_NODE* node)
146
0
{
147
0
  RE_NODE* child = node->children_head;
148
0
  RE_NODE* next_child;
149
150
0
  while (child != NULL)
151
0
  {
152
0
    next_child = child->next_sibling;
153
0
    yr_re_node_destroy(child);
154
0
    child = next_child;
155
0
  }
156
157
0
  if (node->type == RE_NODE_CLASS)
158
0
    yr_free(node->re_class);
159
160
0
  yr_free(node);
161
0
}
162
163
////////////////////////////////////////////////////////////////////////////////
164
// Appends a node to the end of the children list.
165
//
166
void yr_re_node_append_child(RE_NODE* node, RE_NODE* child)
167
0
{
168
0
  if (node->children_head == NULL)
169
0
    node->children_head = child;
170
171
0
  if (node->children_tail != NULL)
172
0
    node->children_tail->next_sibling = child;
173
174
0
  child->prev_sibling = node->children_tail;
175
0
  node->children_tail = child;
176
0
}
177
178
////////////////////////////////////////////////////////////////////////////////
179
// Appends a node to the beginning of the children list.
180
//
181
void yr_re_node_prepend_child(RE_NODE* node, RE_NODE* child)
182
0
{
183
0
  child->next_sibling = node->children_head;
184
185
0
  if (node->children_head != NULL)
186
0
    node->children_head->prev_sibling = child;
187
188
0
  node->children_head = child;
189
190
0
  if (node->children_tail == NULL)
191
0
    node->children_tail = child;
192
0
}
193
194
int yr_re_ast_create(RE_AST** re_ast)
195
0
{
196
0
  *re_ast = (RE_AST*) yr_malloc(sizeof(RE_AST));
197
198
0
  if (*re_ast == NULL)
199
0
    return ERROR_INSUFFICIENT_MEMORY;
200
201
0
  (*re_ast)->flags = 0;
202
0
  (*re_ast)->root_node = NULL;
203
204
0
  return ERROR_SUCCESS;
205
0
}
206
207
void yr_re_ast_destroy(RE_AST* re_ast)
208
0
{
209
0
  if (re_ast->root_node != NULL)
210
0
    yr_re_node_destroy(re_ast->root_node);
211
212
0
  yr_free(re_ast);
213
0
}
214
215
////////////////////////////////////////////////////////////////////////////////
216
// Parses a regexp but don't emit its code. A further call to
217
// yr_re_ast_emit_code is required to get the code.
218
//
219
int yr_re_parse(
220
    const char* re_string,
221
    RE_AST** re_ast,
222
    RE_ERROR* error,
223
    int flags)
224
0
{
225
0
  return yr_parse_re_string(re_string, re_ast, error, flags);
226
0
}
227
228
////////////////////////////////////////////////////////////////////////////////
229
// Parses a hex string but don't emit its code. A further call to
230
// yr_re_ast_emit_code is required to get the code.
231
//
232
int yr_re_parse_hex(const char* hex_string, RE_AST** re_ast, RE_ERROR* error)
233
0
{
234
0
  return yr_parse_hex_string(hex_string, re_ast, error);
235
0
}
236
237
////////////////////////////////////////////////////////////////////////////////
238
// Parses the regexp and emit its code to the provided to the
239
// YR_RE_CODE_SECTION in the specified arena.
240
//
241
int yr_re_compile(
242
    const char* re_string,
243
    int flags,
244
    int parser_flags,
245
    YR_ARENA* arena,
246
    YR_ARENA_REF* ref,
247
    RE_ERROR* error)
248
0
{
249
0
  RE_AST* re_ast;
250
0
  RE _re;
251
0
  int result;
252
253
0
  result = yr_re_parse(re_string, &re_ast, error, parser_flags);
254
0
  if (result != ERROR_UNKNOWN_ESCAPE_SEQUENCE)
255
0
    FAIL_ON_ERROR(result);
256
257
0
  _re.flags = flags;
258
259
0
  FAIL_ON_ERROR_WITH_CLEANUP(
260
0
      yr_arena_write_data(arena, YR_RE_CODE_SECTION, &_re, sizeof(_re), ref),
261
0
      yr_re_ast_destroy(re_ast));
262
263
0
  FAIL_ON_ERROR_WITH_CLEANUP(
264
0
      yr_re_ast_emit_code(re_ast, arena, false), yr_re_ast_destroy(re_ast));
265
266
0
  yr_re_ast_destroy(re_ast);
267
268
0
  return result;
269
0
}
270
271
////////////////////////////////////////////////////////////////////////////////
272
// Verifies if the target string matches the pattern
273
//
274
// Args:
275
//    context: Scan context
276
//    re: A pointer to a compiled regexp
277
//    target: Target string
278
//
279
// Returns:
280
//    See return codes for yr_re_exec
281
//
282
int yr_re_match(YR_SCAN_CONTEXT* context, RE* re, const char* target)
283
0
{
284
0
  int result;
285
286
0
  yr_re_exec(
287
0
      context,
288
0
      re->code,
289
0
      (uint8_t*) target,
290
0
      strlen(target),
291
0
      0,
292
0
      re->flags | RE_FLAGS_SCAN,
293
0
      NULL,
294
0
      NULL,
295
0
      &result);
296
297
0
  return result;
298
0
}
299
300
////////////////////////////////////////////////////////////////////////////////
301
// Verifies if the provided regular expression is just a literal string
302
// like "abc", "12345", without any wildcard, operator, etc. In that case
303
// returns the string as a SIZED_STRING, or returns NULL if otherwise.
304
//
305
// The caller is responsible for deallocating the returned SIZED_STRING by
306
// calling yr_free.
307
//
308
SIZED_STRING* yr_re_ast_extract_literal(RE_AST* re_ast)
309
0
{
310
0
  SIZED_STRING* string;
311
0
  RE_NODE* child;
312
313
0
  int length = 0;
314
315
0
  if (re_ast->root_node->type == RE_NODE_LITERAL)
316
0
  {
317
0
    length = 1;
318
0
  }
319
0
  else if (re_ast->root_node->type == RE_NODE_CONCAT)
320
0
  {
321
0
    child = re_ast->root_node->children_tail;
322
323
0
    while (child != NULL && child->type == RE_NODE_LITERAL)
324
0
    {
325
0
      length++;
326
0
      child = child->prev_sibling;
327
0
    }
328
329
0
    if (child != NULL)
330
0
      return NULL;
331
0
  }
332
0
  else
333
0
  {
334
0
    return NULL;
335
0
  }
336
337
0
  string = (SIZED_STRING*) yr_malloc(sizeof(SIZED_STRING) + length);
338
339
0
  if (string == NULL)
340
0
    return NULL;
341
342
0
  string->length = length;
343
0
  string->flags = 0;
344
345
0
  if (re_ast->root_node->type == RE_NODE_LITERAL)
346
0
  {
347
0
    string->c_string[0] = re_ast->root_node->value;
348
0
  }
349
0
  else
350
0
  {
351
0
    child = re_ast->root_node->children_tail;
352
353
0
    while (child != NULL)
354
0
    {
355
0
      string->c_string[--length] = child->value;
356
0
      child = child->prev_sibling;
357
0
    }
358
0
  }
359
360
0
  string->c_string[string->length] = '\0';
361
362
0
  return string;
363
0
}
364
365
int _yr_re_node_has_unbounded_quantifier_for_dot(RE_NODE* re_node)
366
0
{
367
0
  RE_NODE* child;
368
369
0
  if ((re_node->type == RE_NODE_STAR || re_node->type == RE_NODE_PLUS) &&
370
0
      re_node->children_head->type == RE_NODE_ANY)
371
0
    return true;
372
373
0
  if (re_node->type == RE_NODE_RANGE_ANY && re_node->end == RE_MAX_RANGE)
374
0
    return true;
375
376
0
  if (re_node->type == RE_NODE_CONCAT)
377
0
  {
378
0
    child = re_node->children_tail;
379
380
0
    while (child != NULL)
381
0
    {
382
0
      if (_yr_re_node_has_unbounded_quantifier_for_dot(child))
383
0
        return true;
384
385
0
      child = child->prev_sibling;
386
0
    }
387
0
  }
388
389
0
  return false;
390
0
}
391
392
////////////////////////////////////////////////////////////////////////////////
393
// Detects the use of .*, .+ or .{x,} in a regexp. The use of wildcards with
394
// quantifiers that don't have a reasonably small upper bound causes a
395
// performance penalty. This function detects such cases in order to warn the
396
// user about this.
397
//
398
int yr_re_ast_has_unbounded_quantifier_for_dot(RE_AST* re_ast)
399
0
{
400
0
  return _yr_re_node_has_unbounded_quantifier_for_dot(re_ast->root_node);
401
0
}
402
403
////////////////////////////////////////////////////////////////////////////////
404
// In some cases splitting a regular expression (or hex string) in two parts is
405
// convenient for increasing performance. This happens when the pattern contains
406
// a large gap (a.k.a jump), for example: { 01 02 03 [0-999] 04 05 06 }
407
// In this case the string is splitted in { 01 02 03 } and { 04 05 06 } where
408
// the latter is chained to the former. This means that { 01 02 03 } and
409
// { 04 05 06 } are handled as individual strings, and when both of them are
410
// found, YARA verifies if the distance between the matches complies with the
411
// [0-999] restriction.
412
//
413
// This function traverses a regexp's AST looking for nodes where it should be
414
// splitted. It must be noticed that this only applies to two-level ASTs (i.e.
415
// an AST consisting in a RE_NODE_CONCAT at the root where all the children are
416
// leaves).
417
//
418
// For example, { 01 02 03 [0-1000] 04 05 06 [500-2000] 07 08 09 } has the
419
// following AST:
420
//
421
// RE_NODE_CONCAT
422
// |
423
// |- RE_NODE_LITERAL (01)
424
// |- RE_NODE_LITERAL (02)
425
// |- RE_NODE_LITERAL (03)
426
// |- RE_NODE_RANGE_ANY (start=0, end=1000)
427
// |- RE_NODE_LITERAL (04)
428
// |- RE_NODE_LITERAL (05)
429
// |- RE_NODE_LITERAL (06)
430
// |- RE_NODE_RANGE_ANY (start=500, end=2000)
431
// |- RE_NODE_LITERAL (07)
432
// |- RE_NODE_LITERAL (08)
433
// |- RE_NODE_LITERAL (09)
434
//
435
// If the AST above is passed in the re_ast argument, it will be trimmed to:
436
//
437
// RE_NODE_CONCAT
438
// |
439
// |- RE_NODE_LITERAL (01)
440
// |- RE_NODE_LITERAL (02)
441
// |- RE_NODE_LITERAL (03)
442
//
443
// While remainder_re_ast will be:
444
//
445
// RE_NODE_CONCAT
446
// |
447
// |- RE_NODE_LITERAL (04)
448
// |- RE_NODE_LITERAL (05)
449
// |- RE_NODE_LITERAL (06)
450
// |- RE_NODE_RANGE_ANY (start=500, end=2000)
451
// |- RE_NODE_LITERAL (07)
452
// |- RE_NODE_LITERAL (08)
453
// |- RE_NODE_LITERAL (09)
454
//
455
// The caller is responsible for freeing the new AST in remainder_re_ast by
456
// calling yr_re_ast_destroy.
457
//
458
// The integers pointed to by min_gap and max_gap will be filled with the
459
// minimum and maximum gap size between the sub-strings represented by the
460
// two ASTs.
461
//
462
int yr_re_ast_split_at_chaining_point(
463
    RE_AST* re_ast,
464
    RE_AST** remainder_re_ast,
465
    int32_t* min_gap,
466
    int32_t* max_gap)
467
0
{
468
0
  RE_NODE* child;
469
0
  RE_NODE* concat;
470
471
0
  int result;
472
473
0
  *remainder_re_ast = NULL;
474
0
  *min_gap = 0;
475
0
  *max_gap = 0;
476
477
0
  if (re_ast->root_node->type != RE_NODE_CONCAT)
478
0
    return ERROR_SUCCESS;
479
480
0
  child = re_ast->root_node->children_head;
481
482
0
  while (child != NULL)
483
0
  {
484
0
    if (!child->greedy && child->type == RE_NODE_RANGE_ANY &&
485
0
        child->prev_sibling != NULL && child->next_sibling != NULL &&
486
0
        (child->start > YR_STRING_CHAINING_THRESHOLD ||
487
0
         child->end > YR_STRING_CHAINING_THRESHOLD))
488
0
    {
489
0
      result = yr_re_ast_create(remainder_re_ast);
490
491
0
      if (result != ERROR_SUCCESS)
492
0
        return result;
493
494
0
      concat = yr_re_node_create(RE_NODE_CONCAT);
495
496
0
      if (concat == NULL)
497
0
        return ERROR_INSUFFICIENT_MEMORY;
498
499
0
      concat->children_head = child->next_sibling;
500
0
      concat->children_tail = re_ast->root_node->children_tail;
501
502
0
      re_ast->root_node->children_tail = child->prev_sibling;
503
504
0
      child->prev_sibling->next_sibling = NULL;
505
0
      child->next_sibling->prev_sibling = NULL;
506
507
0
      *min_gap = child->start;
508
0
      *max_gap = child->end;
509
510
0
      (*remainder_re_ast)->root_node = concat;
511
0
      (*remainder_re_ast)->flags = re_ast->flags;
512
513
0
      yr_re_node_destroy(child);
514
515
0
      return ERROR_SUCCESS;
516
0
    }
517
518
0
    child = child->next_sibling;
519
0
  }
520
521
0
  return ERROR_SUCCESS;
522
0
}
523
524
int _yr_emit_inst(
525
    RE_EMIT_CONTEXT* emit_context,
526
    uint8_t opcode,
527
    YR_ARENA_REF* instruction_ref)
528
0
{
529
0
  FAIL_ON_ERROR(yr_arena_write_data(
530
0
      emit_context->arena,
531
0
      YR_RE_CODE_SECTION,
532
0
      &opcode,
533
0
      sizeof(uint8_t),
534
0
      instruction_ref));
535
536
0
  return ERROR_SUCCESS;
537
0
}
538
539
int _yr_emit_inst_arg_uint8(
540
    RE_EMIT_CONTEXT* emit_context,
541
    uint8_t opcode,
542
    uint8_t argument,
543
    YR_ARENA_REF* instruction_ref,
544
    YR_ARENA_REF* argument_ref)
545
0
{
546
0
  FAIL_ON_ERROR(yr_arena_write_data(
547
0
      emit_context->arena,
548
0
      YR_RE_CODE_SECTION,
549
0
      &opcode,
550
0
      sizeof(uint8_t),
551
0
      instruction_ref));
552
553
0
  FAIL_ON_ERROR(yr_arena_write_data(
554
0
      emit_context->arena,
555
0
      YR_RE_CODE_SECTION,
556
0
      &argument,
557
0
      sizeof(uint8_t),
558
0
      argument_ref));
559
560
0
  return ERROR_SUCCESS;
561
0
}
562
563
int _yr_emit_inst_arg_uint16(
564
    RE_EMIT_CONTEXT* emit_context,
565
    uint8_t opcode,
566
    uint16_t argument,
567
    YR_ARENA_REF* instruction_ref,
568
    YR_ARENA_REF* argument_ref)
569
0
{
570
0
  FAIL_ON_ERROR(yr_arena_write_data(
571
0
      emit_context->arena,
572
0
      YR_RE_CODE_SECTION,
573
0
      &opcode,
574
0
      sizeof(uint8_t),
575
0
      instruction_ref));
576
577
0
  FAIL_ON_ERROR(yr_arena_write_data(
578
0
      emit_context->arena,
579
0
      YR_RE_CODE_SECTION,
580
0
      &argument,
581
0
      sizeof(uint16_t),
582
0
      argument_ref));
583
584
0
  return ERROR_SUCCESS;
585
0
}
586
587
int _yr_emit_inst_arg_uint32(
588
    RE_EMIT_CONTEXT* emit_context,
589
    uint8_t opcode,
590
    uint32_t argument,
591
    YR_ARENA_REF* instruction_ref,
592
    YR_ARENA_REF* argument_ref)
593
0
{
594
0
  FAIL_ON_ERROR(yr_arena_write_data(
595
0
      emit_context->arena,
596
0
      YR_RE_CODE_SECTION,
597
0
      &opcode,
598
0
      sizeof(uint8_t),
599
0
      instruction_ref));
600
601
0
  FAIL_ON_ERROR(yr_arena_write_data(
602
0
      emit_context->arena,
603
0
      YR_RE_CODE_SECTION,
604
0
      &argument,
605
0
      sizeof(uint32_t),
606
0
      argument_ref));
607
608
0
  return ERROR_SUCCESS;
609
0
}
610
611
int _yr_emit_inst_arg_int16(
612
    RE_EMIT_CONTEXT* emit_context,
613
    uint8_t opcode,
614
    int16_t argument,
615
    YR_ARENA_REF* instruction_ref,
616
    YR_ARENA_REF* argument_ref)
617
0
{
618
0
  FAIL_ON_ERROR(yr_arena_write_data(
619
0
      emit_context->arena,
620
0
      YR_RE_CODE_SECTION,
621
0
      &opcode,
622
0
      sizeof(uint8_t),
623
0
      instruction_ref));
624
625
0
  FAIL_ON_ERROR(yr_arena_write_data(
626
0
      emit_context->arena,
627
0
      YR_RE_CODE_SECTION,
628
0
      &argument,
629
0
      sizeof(int16_t),
630
0
      argument_ref));
631
632
0
  return ERROR_SUCCESS;
633
0
}
634
635
int _yr_emit_inst_arg_struct(
636
    RE_EMIT_CONTEXT* emit_context,
637
    uint8_t opcode,
638
    void* structure,
639
    size_t structure_size,
640
    YR_ARENA_REF* instruction_ref,
641
    YR_ARENA_REF* argument_ref)
642
0
{
643
0
  FAIL_ON_ERROR(yr_arena_write_data(
644
0
      emit_context->arena,
645
0
      YR_RE_CODE_SECTION,
646
0
      &opcode,
647
0
      sizeof(uint8_t),
648
0
      instruction_ref));
649
650
0
  FAIL_ON_ERROR(yr_arena_write_data(
651
0
      emit_context->arena,
652
0
      YR_RE_CODE_SECTION,
653
0
      structure,
654
0
      structure_size,
655
0
      argument_ref));
656
657
0
  return ERROR_SUCCESS;
658
0
}
659
660
int _yr_emit_split(
661
    RE_EMIT_CONTEXT* emit_context,
662
    uint8_t opcode,
663
    int16_t argument,
664
    YR_ARENA_REF* instruction_ref,
665
    YR_ARENA_REF* argument_ref)
666
0
{
667
0
  assert(opcode == RE_OPCODE_SPLIT_A || opcode == RE_OPCODE_SPLIT_B);
668
669
0
  if (emit_context->next_split_id == RE_MAX_SPLIT_ID)
670
0
    return ERROR_REGULAR_EXPRESSION_TOO_COMPLEX;
671
672
0
  FAIL_ON_ERROR(yr_arena_write_data(
673
0
      emit_context->arena,
674
0
      YR_RE_CODE_SECTION,
675
0
      &opcode,
676
0
      sizeof(uint8_t),
677
0
      instruction_ref));
678
679
0
  FAIL_ON_ERROR(yr_arena_write_data(
680
0
      emit_context->arena,
681
0
      YR_RE_CODE_SECTION,
682
0
      &emit_context->next_split_id,
683
0
      sizeof(RE_SPLIT_ID_TYPE),
684
0
      NULL));
685
686
0
  emit_context->next_split_id++;
687
688
0
  FAIL_ON_ERROR(yr_arena_write_data(
689
0
      emit_context->arena,
690
0
      YR_RE_CODE_SECTION,
691
0
      &argument,
692
0
      sizeof(int16_t),
693
0
      argument_ref));
694
695
0
  return ERROR_SUCCESS;
696
0
}
697
698
static int _yr_re_emit(
699
    RE_EMIT_CONTEXT* emit_context,
700
    RE_NODE* re_node,
701
    int flags,
702
    YR_ARENA_REF* code_ref)
703
0
{
704
0
  int16_t jmp_offset;
705
706
0
  yr_arena_off_t bookmark_1 = 0;
707
0
  yr_arena_off_t bookmark_2 = 0;
708
0
  yr_arena_off_t bookmark_3 = 0;
709
0
  yr_arena_off_t bookmark_4 = 0;
710
711
0
  bool emit_split;
712
0
  bool emit_repeat;
713
0
  bool emit_prolog;
714
0
  bool emit_epilog;
715
716
0
  RE_REPEAT_ARGS repeat_args;
717
0
  RE_REPEAT_ARGS* repeat_start_args_addr;
718
0
  RE_REPEAT_ANY_ARGS repeat_any_args;
719
720
0
  RE_NODE* child;
721
722
0
  void* split_offset_addr = NULL;
723
0
  void* jmp_offset_addr = NULL;
724
725
0
  YR_ARENA_REF instruction_ref = YR_ARENA_NULL_REF;
726
0
  YR_ARENA_REF split_offset_ref;
727
0
  YR_ARENA_REF jmp_instruction_ref;
728
0
  YR_ARENA_REF jmp_offset_ref;
729
0
  YR_ARENA_REF repeat_start_args_ref;
730
731
0
  switch (re_node->type)
732
0
  {
733
0
  case RE_NODE_LITERAL:
734
0
    FAIL_ON_ERROR(_yr_emit_inst_arg_uint8(
735
0
        emit_context,
736
0
        RE_OPCODE_LITERAL,
737
0
        re_node->value,
738
0
        &instruction_ref,
739
0
        NULL));
740
0
    break;
741
742
0
  case RE_NODE_NOT_LITERAL:
743
0
    FAIL_ON_ERROR(_yr_emit_inst_arg_uint8(
744
0
        emit_context,
745
0
        RE_OPCODE_NOT_LITERAL,
746
0
        re_node->value,
747
0
        &instruction_ref,
748
0
        NULL));
749
0
    break;
750
751
0
  case RE_NODE_MASKED_LITERAL:
752
0
    FAIL_ON_ERROR(_yr_emit_inst_arg_uint16(
753
0
        emit_context,
754
0
        RE_OPCODE_MASKED_LITERAL,
755
0
        re_node->mask << 8 | re_node->value,
756
0
        &instruction_ref,
757
0
        NULL));
758
0
    break;
759
760
0
  case RE_NODE_MASKED_NOT_LITERAL:
761
0
    FAIL_ON_ERROR(_yr_emit_inst_arg_uint16(
762
0
        emit_context,
763
0
        RE_OPCODE_MASKED_NOT_LITERAL,
764
0
        re_node->mask << 8 | re_node->value,
765
0
        &instruction_ref,
766
0
        NULL));
767
0
    break;
768
769
0
  case RE_NODE_WORD_CHAR:
770
0
    FAIL_ON_ERROR(
771
0
        _yr_emit_inst(emit_context, RE_OPCODE_WORD_CHAR, &instruction_ref));
772
0
    break;
773
774
0
  case RE_NODE_NON_WORD_CHAR:
775
0
    FAIL_ON_ERROR(
776
0
        _yr_emit_inst(emit_context, RE_OPCODE_NON_WORD_CHAR, &instruction_ref));
777
0
    break;
778
779
0
  case RE_NODE_WORD_BOUNDARY:
780
0
    FAIL_ON_ERROR(
781
0
        _yr_emit_inst(emit_context, RE_OPCODE_WORD_BOUNDARY, &instruction_ref));
782
0
    break;
783
784
0
  case RE_NODE_NON_WORD_BOUNDARY:
785
0
    FAIL_ON_ERROR(_yr_emit_inst(
786
0
        emit_context, RE_OPCODE_NON_WORD_BOUNDARY, &instruction_ref));
787
0
    break;
788
789
0
  case RE_NODE_SPACE:
790
0
    FAIL_ON_ERROR(
791
0
        _yr_emit_inst(emit_context, RE_OPCODE_SPACE, &instruction_ref));
792
0
    break;
793
794
0
  case RE_NODE_NON_SPACE:
795
0
    FAIL_ON_ERROR(
796
0
        _yr_emit_inst(emit_context, RE_OPCODE_NON_SPACE, &instruction_ref));
797
0
    break;
798
799
0
  case RE_NODE_DIGIT:
800
0
    FAIL_ON_ERROR(
801
0
        _yr_emit_inst(emit_context, RE_OPCODE_DIGIT, &instruction_ref));
802
0
    break;
803
804
0
  case RE_NODE_NON_DIGIT:
805
0
    FAIL_ON_ERROR(
806
0
        _yr_emit_inst(emit_context, RE_OPCODE_NON_DIGIT, &instruction_ref));
807
0
    break;
808
809
0
  case RE_NODE_ANY:
810
0
    FAIL_ON_ERROR(_yr_emit_inst(emit_context, RE_OPCODE_ANY, &instruction_ref));
811
0
    break;
812
813
0
  case RE_NODE_CLASS:
814
0
    FAIL_ON_ERROR(
815
0
        _yr_emit_inst(emit_context, RE_OPCODE_CLASS, &instruction_ref));
816
817
0
    FAIL_ON_ERROR(yr_arena_write_data(
818
0
        emit_context->arena,
819
0
        YR_RE_CODE_SECTION,
820
0
        re_node->re_class,
821
0
        sizeof(*re_node->re_class),
822
0
        NULL));
823
0
    break;
824
825
0
  case RE_NODE_ANCHOR_START:
826
0
    FAIL_ON_ERROR(_yr_emit_inst(
827
0
        emit_context, RE_OPCODE_MATCH_AT_START, &instruction_ref));
828
0
    break;
829
830
0
  case RE_NODE_ANCHOR_END:
831
0
    FAIL_ON_ERROR(
832
0
        _yr_emit_inst(emit_context, RE_OPCODE_MATCH_AT_END, &instruction_ref));
833
0
    break;
834
835
0
  case RE_NODE_CONCAT:
836
0
    FAIL_ON_ERROR(_yr_re_emit(
837
0
        emit_context,
838
0
        (flags & EMIT_BACKWARDS) ? re_node->children_tail
839
0
                                 : re_node->children_head,
840
0
        flags,
841
0
        &instruction_ref));
842
843
0
    if (flags & EMIT_BACKWARDS)
844
0
      child = re_node->children_tail->prev_sibling;
845
0
    else
846
0
      child = re_node->children_head->next_sibling;
847
848
0
    while (child != NULL)
849
0
    {
850
0
      FAIL_ON_ERROR(_yr_re_emit(emit_context, child, flags, NULL));
851
852
0
      child = (flags & EMIT_BACKWARDS) ? child->prev_sibling
853
0
                                       : child->next_sibling;
854
0
    }
855
0
    break;
856
857
0
  case RE_NODE_PLUS:
858
    // Code for e+ looks like:
859
    //
860
    //          L1: code for e
861
    //              split L1, L2
862
    //          L2:
863
    //
864
0
    FAIL_ON_ERROR(_yr_re_emit(
865
0
        emit_context, re_node->children_head, flags, &instruction_ref));
866
867
0
    bookmark_1 = yr_arena_get_current_offset(
868
0
        emit_context->arena, YR_RE_CODE_SECTION);
869
870
0
    if (instruction_ref.offset - bookmark_1 < INT16_MIN)
871
0
      return ERROR_REGULAR_EXPRESSION_TOO_LARGE;
872
873
0
    jmp_offset = (int16_t) (instruction_ref.offset - bookmark_1);
874
875
0
    FAIL_ON_ERROR(_yr_emit_split(
876
0
        emit_context,
877
0
        re_node->greedy ? RE_OPCODE_SPLIT_B : RE_OPCODE_SPLIT_A,
878
0
        jmp_offset,
879
0
        NULL,
880
0
        NULL));
881
882
0
    break;
883
884
0
  case RE_NODE_STAR:
885
    // Code for e* looks like:
886
    //
887
    //          L1: split L1, L2
888
    //              code for e
889
    //              jmp L1
890
    //          L2:
891
0
    FAIL_ON_ERROR(_yr_emit_split(
892
0
        emit_context,
893
0
        re_node->greedy ? RE_OPCODE_SPLIT_A : RE_OPCODE_SPLIT_B,
894
0
        0,
895
0
        &instruction_ref,
896
0
        &split_offset_ref));
897
898
0
    FAIL_ON_ERROR(
899
0
        _yr_re_emit(emit_context, re_node->children_head, flags, NULL));
900
901
0
    bookmark_1 = yr_arena_get_current_offset(
902
0
        emit_context->arena, YR_RE_CODE_SECTION);
903
904
0
    if (instruction_ref.offset - bookmark_1 < INT16_MIN)
905
0
      return ERROR_REGULAR_EXPRESSION_TOO_LARGE;
906
907
0
    jmp_offset = (int16_t) (instruction_ref.offset - bookmark_1);
908
909
    // Emit jump with offset set to 0.
910
911
0
    FAIL_ON_ERROR(_yr_emit_inst_arg_int16(
912
0
        emit_context, RE_OPCODE_JUMP, jmp_offset, NULL, NULL));
913
914
0
    bookmark_1 = yr_arena_get_current_offset(
915
0
        emit_context->arena, YR_RE_CODE_SECTION);
916
917
0
    if (bookmark_1 - instruction_ref.offset > INT16_MAX)
918
0
      return ERROR_REGULAR_EXPRESSION_TOO_LARGE;
919
920
0
    jmp_offset = (int16_t) (bookmark_1 - instruction_ref.offset);
921
922
    // Update split offset.
923
0
    split_offset_addr =
924
0
        yr_arena_ref_to_ptr(emit_context->arena, &split_offset_ref);
925
926
0
    memcpy(split_offset_addr, &jmp_offset, sizeof(jmp_offset));
927
0
    break;
928
929
0
  case RE_NODE_ALT:
930
    // Code for e1|e2 looks like:
931
    //
932
    //              split L1, L2
933
    //          L1: code for e1
934
    //              jmp L3
935
    //          L2: code for e2
936
    //          L3:
937
938
    // Emit a split instruction with offset set to 0 temporarily. Offset
939
    // will be updated after we know the size of the code generated for
940
    // the left node (e1).
941
942
0
    FAIL_ON_ERROR(_yr_emit_split(
943
0
        emit_context,
944
0
        RE_OPCODE_SPLIT_A,
945
0
        0,
946
0
        &instruction_ref,
947
0
        &split_offset_ref));
948
949
0
    FAIL_ON_ERROR(
950
0
        _yr_re_emit(emit_context, re_node->children_head, flags, NULL));
951
952
    // Emit jump with offset set to 0.
953
954
0
    FAIL_ON_ERROR(_yr_emit_inst_arg_int16(
955
0
        emit_context,
956
0
        RE_OPCODE_JUMP,
957
0
        0,
958
0
        &jmp_instruction_ref,
959
0
        &jmp_offset_ref));
960
961
0
    bookmark_1 = yr_arena_get_current_offset(
962
0
        emit_context->arena, YR_RE_CODE_SECTION);
963
964
0
    if (bookmark_1 - instruction_ref.offset > INT16_MAX)
965
0
      return ERROR_REGULAR_EXPRESSION_TOO_LARGE;
966
967
0
    jmp_offset = (int16_t) (bookmark_1 - instruction_ref.offset);
968
969
    // Update split offset.
970
0
    split_offset_addr =
971
0
        yr_arena_ref_to_ptr(emit_context->arena, &split_offset_ref);
972
973
0
    memcpy(split_offset_addr, &jmp_offset, sizeof(jmp_offset));
974
975
0
    FAIL_ON_ERROR(
976
0
        _yr_re_emit(emit_context, re_node->children_tail, flags, NULL));
977
978
0
    bookmark_1 = yr_arena_get_current_offset(
979
0
        emit_context->arena, YR_RE_CODE_SECTION);
980
981
0
    if (bookmark_1 - jmp_instruction_ref.offset > INT16_MAX)
982
0
      return ERROR_REGULAR_EXPRESSION_TOO_LARGE;
983
984
0
    jmp_offset = (int16_t) (bookmark_1 - jmp_instruction_ref.offset);
985
986
    // Update offset for jmp instruction.
987
0
    jmp_offset_addr = yr_arena_ref_to_ptr(emit_context->arena, &jmp_offset_ref);
988
989
0
    memcpy(jmp_offset_addr, &jmp_offset, sizeof(jmp_offset));
990
0
    break;
991
992
0
  case RE_NODE_RANGE_ANY:
993
0
    repeat_any_args.min = re_node->start;
994
0
    repeat_any_args.max = re_node->end;
995
996
0
    FAIL_ON_ERROR(_yr_emit_inst_arg_struct(
997
0
        emit_context,
998
0
        re_node->greedy ? RE_OPCODE_REPEAT_ANY_GREEDY
999
0
                        : RE_OPCODE_REPEAT_ANY_UNGREEDY,
1000
0
        &repeat_any_args,
1001
0
        sizeof(repeat_any_args),
1002
0
        &instruction_ref,
1003
0
        NULL));
1004
1005
0
    break;
1006
1007
0
  case RE_NODE_RANGE:
1008
    // Code for e{n,m} looks like:
1009
    //
1010
    //            code for e              ---   prolog
1011
    //            repeat_start n, m, L1   --+
1012
    //        L0: code for e                |   repeat
1013
    //            repeat_end n, m, L0     --+
1014
    //        L1: split L2, L3            ---   split
1015
    //        L2: code for e              ---   epilog
1016
    //        L3:
1017
    //
1018
    // Not all sections (prolog, repeat, split and epilog) are generated in all
1019
    // cases, it depends on the values of n and m. The following table shows
1020
    // which sections are generated for the first few values of n and m.
1021
    //
1022
    //        n,m   prolog  repeat      split  epilog
1023
    //                      (min,max)
1024
    //        ---------------------------------------
1025
    //        0,0     -       -           -      -
1026
    //        0,1     -       -           X      X
1027
    //        0,2     -       0,1         X      X
1028
    //        0,3     -       0,2         X      X
1029
    //        0,M     -       0,M-1       X      X
1030
    //
1031
    //        1,1     X       -           -      -
1032
    //        1,2     X       -           X      X
1033
    //        1,3     X       0,1         X      X
1034
    //        1,4     X       1,2         X      X
1035
    //        1,M     X       1,M-2       X      X
1036
    //
1037
    //        2,2     X       -           -      X
1038
    //        2,3     X       1,1         X      X
1039
    //        2,4     X       1,2         X      X
1040
    //        2,M     X       1,M-2       X      X
1041
    //
1042
    //        3,3     X       1,1         -      X
1043
    //        3,4     X       2,2         X      X
1044
    //        3,M     X       2,M-2       X      X
1045
    //
1046
    //        4,4     X       2,2         -      X
1047
    //        4,5     X       3,3         X      X
1048
    //        4,M     X       3,M-2       X      X
1049
    //
1050
    // The code can't consists simply in the repeat section, the prolog and
1051
    // epilog are required because we can't have atoms pointing to code inside
1052
    // the repeat loop. Atoms' forwards_code will point to code in the prolog
1053
    // and backwards_code will point to code in the epilog (or in prolog if
1054
    // epilog wasn't generated, like in n=1,m=1)
1055
1056
0
    emit_prolog = re_node->start > 0;
1057
0
    emit_repeat = re_node->end > re_node->start + 1 || re_node->end > 2;
1058
0
    emit_split = re_node->end > re_node->start;
1059
0
    emit_epilog = re_node->end > re_node->start || re_node->end > 1;
1060
1061
0
    if (emit_prolog)
1062
0
    {
1063
0
      FAIL_ON_ERROR(_yr_re_emit(
1064
0
          emit_context, re_node->children_head, flags, &instruction_ref));
1065
0
    }
1066
1067
0
    if (emit_repeat)
1068
0
    {
1069
0
      repeat_args.min = re_node->start;
1070
0
      repeat_args.max = re_node->end;
1071
1072
0
      if (emit_prolog)
1073
0
      {
1074
0
        repeat_args.max--;
1075
0
        repeat_args.min--;
1076
0
      }
1077
1078
0
      if (emit_split)
1079
0
      {
1080
0
        repeat_args.max--;
1081
0
      }
1082
0
      else
1083
0
      {
1084
0
        repeat_args.min--;
1085
0
        repeat_args.max--;
1086
0
      }
1087
1088
0
      repeat_args.offset = 0;
1089
1090
0
      bookmark_1 = yr_arena_get_current_offset(
1091
0
          emit_context->arena, YR_RE_CODE_SECTION);
1092
1093
0
      FAIL_ON_ERROR(_yr_emit_inst_arg_struct(
1094
0
          emit_context,
1095
0
          re_node->greedy ? RE_OPCODE_REPEAT_START_GREEDY
1096
0
                          : RE_OPCODE_REPEAT_START_UNGREEDY,
1097
0
          &repeat_args,
1098
0
          sizeof(repeat_args),
1099
0
          emit_prolog ? NULL : &instruction_ref,
1100
0
          &repeat_start_args_ref));
1101
1102
0
      bookmark_2 = yr_arena_get_current_offset(
1103
0
          emit_context->arena, YR_RE_CODE_SECTION);
1104
1105
0
      FAIL_ON_ERROR(_yr_re_emit(
1106
0
          emit_context,
1107
0
          re_node->children_head,
1108
0
          flags | EMIT_DONT_SET_FORWARDS_CODE | EMIT_DONT_SET_BACKWARDS_CODE,
1109
0
          NULL));
1110
1111
0
      bookmark_3 = yr_arena_get_current_offset(
1112
0
          emit_context->arena, YR_RE_CODE_SECTION);
1113
1114
0
      if (bookmark_2 - bookmark_3 < INT32_MIN)
1115
0
        return ERROR_REGULAR_EXPRESSION_TOO_LARGE;
1116
1117
0
      repeat_args.offset = (int32_t) (bookmark_2 - bookmark_3);
1118
1119
0
      FAIL_ON_ERROR(_yr_emit_inst_arg_struct(
1120
0
          emit_context,
1121
0
          re_node->greedy ? RE_OPCODE_REPEAT_END_GREEDY
1122
0
                          : RE_OPCODE_REPEAT_END_UNGREEDY,
1123
0
          &repeat_args,
1124
0
          sizeof(repeat_args),
1125
0
          NULL,
1126
0
          NULL));
1127
1128
0
      bookmark_4 = yr_arena_get_current_offset(
1129
0
          emit_context->arena, YR_RE_CODE_SECTION);
1130
1131
0
      repeat_start_args_addr = (RE_REPEAT_ARGS*) yr_arena_ref_to_ptr(
1132
0
          emit_context->arena, &repeat_start_args_ref);
1133
1134
0
      if (bookmark_4 - bookmark_1 > INT32_MAX)
1135
0
        return ERROR_REGULAR_EXPRESSION_TOO_LARGE;
1136
1137
0
      repeat_start_args_addr->offset = (int32_t) (bookmark_4 - bookmark_1);
1138
0
    }
1139
1140
0
    if (emit_split)
1141
0
    {
1142
0
      bookmark_1 = yr_arena_get_current_offset(
1143
0
          emit_context->arena, YR_RE_CODE_SECTION);
1144
1145
0
      FAIL_ON_ERROR(_yr_emit_split(
1146
0
          emit_context,
1147
0
          re_node->greedy ? RE_OPCODE_SPLIT_A : RE_OPCODE_SPLIT_B,
1148
0
          0,
1149
0
          NULL,
1150
0
          &split_offset_ref));
1151
0
    }
1152
1153
0
    if (emit_epilog)
1154
0
    {
1155
0
      FAIL_ON_ERROR(_yr_re_emit(
1156
0
          emit_context,
1157
0
          re_node->children_head,
1158
0
          emit_prolog ? flags | EMIT_DONT_SET_FORWARDS_CODE : flags,
1159
0
          emit_prolog || emit_repeat ? NULL : &instruction_ref));
1160
0
    }
1161
1162
0
    if (emit_split)
1163
0
    {
1164
0
      bookmark_2 = yr_arena_get_current_offset(
1165
0
          emit_context->arena, YR_RE_CODE_SECTION);
1166
1167
0
      if (bookmark_2 - bookmark_1 > INT16_MAX)
1168
0
        return ERROR_REGULAR_EXPRESSION_TOO_LARGE;
1169
1170
0
      split_offset_addr =
1171
0
          yr_arena_ref_to_ptr(emit_context->arena, &split_offset_ref);
1172
1173
0
      jmp_offset = (int16_t) (bookmark_2 - bookmark_1);
1174
1175
0
      memcpy(split_offset_addr, &jmp_offset, sizeof(jmp_offset));
1176
0
    }
1177
1178
0
    break;
1179
0
  }
1180
1181
0
  if (flags & EMIT_BACKWARDS)
1182
0
  {
1183
0
    if (!(flags & EMIT_DONT_SET_BACKWARDS_CODE))
1184
0
    {
1185
0
      re_node->backward_code_ref.buffer_id = YR_RE_CODE_SECTION;
1186
0
      re_node->backward_code_ref.offset = yr_arena_get_current_offset(
1187
0
          emit_context->arena, YR_RE_CODE_SECTION);
1188
0
    }
1189
0
  }
1190
0
  else
1191
0
  {
1192
0
    if (!(flags & EMIT_DONT_SET_FORWARDS_CODE))
1193
0
    {
1194
0
      re_node->forward_code_ref = instruction_ref;
1195
0
    }
1196
0
  }
1197
1198
0
  if (code_ref != NULL)
1199
0
    *code_ref = instruction_ref;
1200
1201
0
  return ERROR_SUCCESS;
1202
0
}
1203
1204
int yr_re_ast_emit_code(RE_AST* re_ast, YR_ARENA* arena, int backwards_code)
1205
0
{
1206
0
  RE_EMIT_CONTEXT emit_context;
1207
1208
  // Emit code for matching the regular expressions forwards.
1209
0
  emit_context.arena = arena;
1210
0
  emit_context.next_split_id = 0;
1211
1212
0
  FAIL_ON_ERROR(_yr_re_emit(
1213
0
      &emit_context,
1214
0
      re_ast->root_node,
1215
0
      backwards_code ? EMIT_BACKWARDS : 0,
1216
0
      NULL));
1217
1218
0
  FAIL_ON_ERROR(_yr_emit_inst(&emit_context, RE_OPCODE_MATCH, NULL));
1219
1220
0
  return ERROR_SUCCESS;
1221
0
}
1222
1223
static int _yr_re_fiber_create(RE_FIBER_POOL* fiber_pool, RE_FIBER** new_fiber)
1224
0
{
1225
0
  RE_FIBER* fiber;
1226
1227
0
  if (fiber_pool->fibers.head != NULL)
1228
0
  {
1229
0
    fiber = fiber_pool->fibers.head;
1230
0
    fiber_pool->fibers.head = fiber->next;
1231
1232
0
    if (fiber_pool->fibers.tail == fiber)
1233
0
      fiber_pool->fibers.tail = NULL;
1234
0
  }
1235
0
  else
1236
0
  {
1237
0
    if (fiber_pool->fiber_count == RE_MAX_FIBERS)
1238
0
      return ERROR_TOO_MANY_RE_FIBERS;
1239
1240
0
    fiber = (RE_FIBER*) yr_malloc(sizeof(RE_FIBER));
1241
1242
0
    if (fiber == NULL)
1243
0
      return ERROR_INSUFFICIENT_MEMORY;
1244
1245
0
    fiber_pool->fiber_count++;
1246
0
  }
1247
1248
0
  fiber->ip = NULL;
1249
0
  fiber->sp = -1;
1250
0
  fiber->rc = -1;
1251
0
  fiber->next = NULL;
1252
0
  fiber->prev = NULL;
1253
1254
0
  *new_fiber = fiber;
1255
1256
0
  return ERROR_SUCCESS;
1257
0
}
1258
1259
////////////////////////////////////////////////////////////////////////////////
1260
// Appends 'fiber' to 'fiber_list'
1261
//
1262
static void _yr_re_fiber_append(RE_FIBER_LIST* fiber_list, RE_FIBER* fiber)
1263
0
{
1264
0
  assert(fiber->prev == NULL);
1265
0
  assert(fiber->next == NULL);
1266
1267
0
  fiber->prev = fiber_list->tail;
1268
1269
0
  if (fiber_list->tail != NULL)
1270
0
    fiber_list->tail->next = fiber;
1271
1272
0
  fiber_list->tail = fiber;
1273
1274
0
  if (fiber_list->head == NULL)
1275
0
    fiber_list->head = fiber;
1276
1277
0
  assert(fiber_list->tail->next == NULL);
1278
0
  assert(fiber_list->head->prev == NULL);
1279
0
}
1280
1281
////////////////////////////////////////////////////////////////////////////////
1282
// Verifies if a fiber with the same properties (ip, rc, sp, and stack values)
1283
// than 'target_fiber' exists in 'fiber_list'. The list is iterated from
1284
// the start until 'last_fiber' (inclusive). Fibers past 'last_fiber' are not
1285
// taken into account.
1286
//
1287
static int _yr_re_fiber_exists(
1288
    RE_FIBER_LIST* fiber_list,
1289
    RE_FIBER* target_fiber,
1290
    RE_FIBER* last_fiber)
1291
0
{
1292
0
  RE_FIBER* fiber = fiber_list->head;
1293
1294
0
  int equal_stacks;
1295
0
  int i;
1296
1297
0
  if (last_fiber == NULL)
1298
0
    return false;
1299
1300
0
  while (fiber != last_fiber->next)
1301
0
  {
1302
0
    if (fiber->ip == target_fiber->ip && fiber->sp == target_fiber->sp &&
1303
0
        fiber->rc == target_fiber->rc)
1304
0
    {
1305
0
      equal_stacks = true;
1306
1307
0
      for (i = 0; i <= fiber->sp; i++)
1308
0
      {
1309
0
        if (fiber->stack[i] != target_fiber->stack[i])
1310
0
        {
1311
0
          equal_stacks = false;
1312
0
          break;
1313
0
        }
1314
0
      }
1315
1316
0
      if (equal_stacks)
1317
0
        return true;
1318
0
    }
1319
1320
0
    fiber = fiber->next;
1321
0
  }
1322
1323
0
  return false;
1324
0
}
1325
1326
////////////////////////////////////////////////////////////////////////////////
1327
// Clones a fiber in fiber_list and inserts the cloned fiber just after.
1328
// the original one. If fiber_list is:
1329
//
1330
//   f1 -> f2 -> f3 -> f4
1331
//
1332
// Splitting f2 will result in:
1333
//
1334
//   f1 -> f2 -> cloned f2 -> f3 -> f4
1335
//
1336
static int _yr_re_fiber_split(
1337
    RE_FIBER_LIST* fiber_list,
1338
    RE_FIBER_POOL* fiber_pool,
1339
    RE_FIBER* fiber,
1340
    RE_FIBER** new_fiber)
1341
0
{
1342
0
  int32_t i;
1343
1344
0
  FAIL_ON_ERROR(_yr_re_fiber_create(fiber_pool, new_fiber));
1345
1346
0
  (*new_fiber)->sp = fiber->sp;
1347
0
  (*new_fiber)->ip = fiber->ip;
1348
0
  (*new_fiber)->rc = fiber->rc;
1349
1350
0
  for (i = 0; i <= fiber->sp; i++) (*new_fiber)->stack[i] = fiber->stack[i];
1351
1352
0
  (*new_fiber)->next = fiber->next;
1353
0
  (*new_fiber)->prev = fiber;
1354
1355
0
  if (fiber->next != NULL)
1356
0
    fiber->next->prev = *new_fiber;
1357
1358
0
  fiber->next = *new_fiber;
1359
1360
0
  if (fiber_list->tail == fiber)
1361
0
    fiber_list->tail = *new_fiber;
1362
1363
0
  assert(fiber_list->tail->next == NULL);
1364
0
  assert(fiber_list->head->prev == NULL);
1365
1366
0
  return ERROR_SUCCESS;
1367
0
}
1368
1369
////////////////////////////////////////////////////////////////////////////////
1370
// Kills a given fiber by removing it from the fiber list and putting it in the
1371
// fiber pool.
1372
//
1373
static RE_FIBER* _yr_re_fiber_kill(
1374
    RE_FIBER_LIST* fiber_list,
1375
    RE_FIBER_POOL* fiber_pool,
1376
    RE_FIBER* fiber)
1377
0
{
1378
0
  RE_FIBER* next_fiber = fiber->next;
1379
1380
0
  if (fiber->prev != NULL)
1381
0
    fiber->prev->next = next_fiber;
1382
1383
0
  if (next_fiber != NULL)
1384
0
    next_fiber->prev = fiber->prev;
1385
1386
0
  if (fiber_pool->fibers.tail != NULL)
1387
0
    fiber_pool->fibers.tail->next = fiber;
1388
1389
0
  if (fiber_list->tail == fiber)
1390
0
    fiber_list->tail = fiber->prev;
1391
1392
0
  if (fiber_list->head == fiber)
1393
0
    fiber_list->head = next_fiber;
1394
1395
0
  fiber->next = NULL;
1396
0
  fiber->prev = fiber_pool->fibers.tail;
1397
0
  fiber_pool->fibers.tail = fiber;
1398
1399
0
  if (fiber_pool->fibers.head == NULL)
1400
0
    fiber_pool->fibers.head = fiber;
1401
1402
0
  return next_fiber;
1403
0
}
1404
1405
////////////////////////////////////////////////////////////////////////////////
1406
// Kills all fibers from the given one up to the end of the fiber list.
1407
//
1408
static void _yr_re_fiber_kill_tail(
1409
    RE_FIBER_LIST* fiber_list,
1410
    RE_FIBER_POOL* fiber_pool,
1411
    RE_FIBER* fiber)
1412
0
{
1413
0
  RE_FIBER* prev_fiber = fiber->prev;
1414
1415
0
  if (prev_fiber != NULL)
1416
0
    prev_fiber->next = NULL;
1417
1418
0
  fiber->prev = fiber_pool->fibers.tail;
1419
1420
0
  if (fiber_pool->fibers.tail != NULL)
1421
0
    fiber_pool->fibers.tail->next = fiber;
1422
1423
0
  fiber_pool->fibers.tail = fiber_list->tail;
1424
0
  fiber_list->tail = prev_fiber;
1425
1426
0
  if (fiber_list->head == fiber)
1427
0
    fiber_list->head = NULL;
1428
1429
0
  if (fiber_pool->fibers.head == NULL)
1430
0
    fiber_pool->fibers.head = fiber;
1431
0
}
1432
1433
////////////////////////////////////////////////////////////////////////////////
1434
// Kills all fibers in the fiber list.
1435
//
1436
static void _yr_re_fiber_kill_all(
1437
    RE_FIBER_LIST* fiber_list,
1438
    RE_FIBER_POOL* fiber_pool)
1439
0
{
1440
0
  if (fiber_list->head != NULL)
1441
0
    _yr_re_fiber_kill_tail(fiber_list, fiber_pool, fiber_list->head);
1442
0
}
1443
1444
////////////////////////////////////////////////////////////////////////////////
1445
// Executes a fiber until reaching an "matching" instruction. A "matching"
1446
// instruction is one that actually reads a byte from the input and performs
1447
// some matching. If the fiber reaches a split instruction, the new fiber is
1448
// also synced.
1449
//
1450
static int _yr_re_fiber_sync(
1451
    RE_FIBER_LIST* fiber_list,
1452
    RE_FIBER_POOL* fiber_pool,
1453
    RE_FIBER* fiber_to_sync)
1454
0
{
1455
  // A array for keeping track of which split instructions has been already
1456
  // executed. Each split instruction within a regexp has an associated ID
1457
  // between 0 and RE_MAX_SPLIT_ID-1. Keeping track of executed splits is
1458
  // required to avoid infinite loops in regexps like (a*)* or (a|)*
1459
1460
0
  RE_SPLIT_ID_TYPE splits_executed[RE_MAX_SPLIT_ID];
1461
0
  RE_SPLIT_ID_TYPE splits_executed_count = 0;
1462
0
  RE_SPLIT_ID_TYPE split_id, splits_executed_idx;
1463
1464
0
  int split_already_executed;
1465
1466
0
  RE_REPEAT_ARGS* repeat_args;
1467
0
  RE_REPEAT_ANY_ARGS* repeat_any_args;
1468
1469
0
  RE_FIBER* fiber;
1470
0
  RE_FIBER* last;
1471
0
  RE_FIBER* next;
1472
0
  RE_FIBER* branch_a;
1473
0
  RE_FIBER* branch_b;
1474
1475
0
  fiber = fiber_to_sync;
1476
0
  last = fiber_to_sync->next;
1477
1478
0
  while (fiber != last)
1479
0
  {
1480
0
    int16_t jmp_len;
1481
0
    uint8_t opcode = *fiber->ip;
1482
1483
0
    switch (opcode)
1484
0
    {
1485
0
    case RE_OPCODE_SPLIT_A:
1486
0
    case RE_OPCODE_SPLIT_B:
1487
1488
0
      split_id = *(RE_SPLIT_ID_TYPE*) (fiber->ip + 1);
1489
0
      split_already_executed = false;
1490
1491
0
      for (splits_executed_idx = 0; splits_executed_idx < splits_executed_count;
1492
0
           splits_executed_idx++)
1493
0
      {
1494
0
        if (split_id == splits_executed[splits_executed_idx])
1495
0
        {
1496
0
          split_already_executed = true;
1497
0
          break;
1498
0
        }
1499
0
      }
1500
1501
0
      if (split_already_executed)
1502
0
      {
1503
0
        fiber = _yr_re_fiber_kill(fiber_list, fiber_pool, fiber);
1504
0
      }
1505
0
      else
1506
0
      {
1507
0
        branch_a = fiber;
1508
1509
0
        FAIL_ON_ERROR(
1510
0
            _yr_re_fiber_split(fiber_list, fiber_pool, branch_a, &branch_b));
1511
1512
        // With RE_OPCODE_SPLIT_A the current fiber continues at the next
1513
        // instruction in the stream (branch A), while the newly created
1514
        // fiber starts at the address indicated by the instruction (branch B)
1515
        // RE_OPCODE_SPLIT_B has the opposite behavior.
1516
1517
0
        if (opcode == RE_OPCODE_SPLIT_B)
1518
0
          yr_swap(branch_a, branch_b, RE_FIBER*);
1519
1520
        // Branch A continues at the next instruction
1521
0
        branch_a->ip += (sizeof(RE_SPLIT_ID_TYPE) + 3);
1522
1523
        // Branch B adds the offset indicated by the split instruction.
1524
0
        jmp_len = yr_unaligned_i16(branch_b->ip + 1 + sizeof(RE_SPLIT_ID_TYPE));
1525
1526
0
        branch_b->ip += jmp_len;
1527
1528
0
#if YR_PARANOID_EXEC
1529
        // In normal conditions this should never happen. But with compiled
1530
        // rules that has been hand-crafted by a malicious actor this could
1531
        // happen.
1532
0
        if (splits_executed_count >= RE_MAX_SPLIT_ID)
1533
0
          return ERROR_INTERNAL_FATAL_ERROR;
1534
0
#endif
1535
1536
0
        splits_executed[splits_executed_count] = split_id;
1537
0
        splits_executed_count++;
1538
0
      }
1539
1540
0
      break;
1541
1542
0
    case RE_OPCODE_REPEAT_START_GREEDY:
1543
0
    case RE_OPCODE_REPEAT_START_UNGREEDY:
1544
1545
0
      repeat_args = (RE_REPEAT_ARGS*) (fiber->ip + 1);
1546
0
      assert(repeat_args->max > 0);
1547
0
      branch_a = fiber;
1548
1549
0
      if (repeat_args->min == 0)
1550
0
      {
1551
0
        FAIL_ON_ERROR(
1552
0
            _yr_re_fiber_split(fiber_list, fiber_pool, branch_a, &branch_b));
1553
1554
0
        if (opcode == RE_OPCODE_REPEAT_START_UNGREEDY)
1555
0
          yr_swap(branch_a, branch_b, RE_FIBER*);
1556
1557
0
        branch_b->ip += repeat_args->offset;
1558
0
      }
1559
1560
0
#if YR_PARANOID_EXEC
1561
      // In normal conditions this should never happen. But with compiled
1562
      // rules that has been hand-crafted by a malicious actor this could
1563
      // happen.
1564
0
      if (branch_a->sp >= RE_MAX_STACK - 1)
1565
0
        return ERROR_INTERNAL_FATAL_ERROR;
1566
0
#endif
1567
1568
0
      branch_a->stack[++branch_a->sp] = 0;
1569
0
      branch_a->ip += (1 + sizeof(RE_REPEAT_ARGS));
1570
0
      break;
1571
1572
0
    case RE_OPCODE_REPEAT_END_GREEDY:
1573
0
    case RE_OPCODE_REPEAT_END_UNGREEDY:
1574
1575
0
      repeat_args = (RE_REPEAT_ARGS*) (fiber->ip + 1);
1576
0
      fiber->stack[fiber->sp]++;
1577
1578
0
      if (fiber->stack[fiber->sp] < repeat_args->min)
1579
0
      {
1580
0
        fiber->ip += repeat_args->offset;
1581
0
        break;
1582
0
      }
1583
1584
0
      branch_a = fiber;
1585
1586
0
      if (fiber->stack[fiber->sp] < repeat_args->max)
1587
0
      {
1588
0
        FAIL_ON_ERROR(
1589
0
            _yr_re_fiber_split(fiber_list, fiber_pool, branch_a, &branch_b));
1590
1591
0
        if (opcode == RE_OPCODE_REPEAT_END_GREEDY)
1592
0
          yr_swap(branch_a, branch_b, RE_FIBER*);
1593
1594
0
        branch_b->ip += repeat_args->offset;
1595
0
      }
1596
1597
0
      branch_a->sp--;
1598
0
      branch_a->ip += (1 + sizeof(RE_REPEAT_ARGS));
1599
0
      break;
1600
1601
0
    case RE_OPCODE_REPEAT_ANY_GREEDY:
1602
0
    case RE_OPCODE_REPEAT_ANY_UNGREEDY:
1603
1604
0
      repeat_any_args = (RE_REPEAT_ANY_ARGS*) (fiber->ip + 1);
1605
1606
      // If repetition counter (rc) is -1 it means that we are reaching this
1607
      // instruction from the previous one in the instructions stream. In
1608
      // this case let's initialize the counter to 0 and start looping.
1609
1610
0
      if (fiber->rc == -1)
1611
0
        fiber->rc = 0;
1612
1613
0
      if (fiber->rc < repeat_any_args->min)
1614
0
      {
1615
        // Increase repetition counter and continue with next fiber. The
1616
        // instruction pointer for this fiber is not incremented yet, this
1617
        // fiber spins in this same instruction until reaching the minimum
1618
        // number of repetitions.
1619
1620
0
        fiber->rc++;
1621
0
        fiber = fiber->next;
1622
0
      }
1623
0
      else if (fiber->rc < repeat_any_args->max)
1624
0
      {
1625
        // Once the minimum number of repetitions are matched one fiber
1626
        // remains spinning in this instruction until reaching the maximum
1627
        // number of repetitions while new fibers are created. New fibers
1628
        // start executing at the next instruction.
1629
1630
0
        next = fiber->next;
1631
0
        branch_a = fiber;
1632
1633
0
        FAIL_ON_ERROR(
1634
0
            _yr_re_fiber_split(fiber_list, fiber_pool, branch_a, &branch_b));
1635
1636
0
        if (opcode == RE_OPCODE_REPEAT_ANY_UNGREEDY)
1637
0
          yr_swap(branch_a, branch_b, RE_FIBER*);
1638
1639
0
        branch_a->rc++;
1640
0
        branch_b->ip += (1 + sizeof(RE_REPEAT_ANY_ARGS));
1641
0
        branch_b->rc = -1;
1642
1643
0
        FAIL_ON_ERROR(_yr_re_fiber_sync(fiber_list, fiber_pool, branch_b));
1644
1645
0
        fiber = next;
1646
0
      }
1647
0
      else
1648
0
      {
1649
        // When the maximum number of repetitions is reached the fiber keeps
1650
        // executing at the next instruction. The repetition counter is set
1651
        // to -1 indicating that we are not spinning in a repeat instruction
1652
        // anymore.
1653
1654
0
        fiber->ip += (1 + sizeof(RE_REPEAT_ANY_ARGS));
1655
0
        fiber->rc = -1;
1656
0
      }
1657
1658
0
      break;
1659
1660
0
    case RE_OPCODE_JUMP:
1661
0
      jmp_len = yr_unaligned_i16(fiber->ip + 1);
1662
0
      fiber->ip += jmp_len;
1663
0
      break;
1664
1665
0
    default:
1666
0
      fiber = fiber->next;
1667
0
    }
1668
0
  }
1669
1670
0
  return ERROR_SUCCESS;
1671
0
}
1672
1673
////////////////////////////////////////////////////////////////////////////////
1674
// Executes a regular expression. The specified regular expression will try to
1675
// match the data starting at the address specified by "input". The "input"
1676
// pointer can point to any address inside a memory buffer. Arguments
1677
// "input_forwards_size" and "input_backwards_size" indicate how many bytes
1678
// can be accessible starting at "input" and going forwards and backwards
1679
// respectively.
1680
//
1681
//   <--- input_backwards_size -->|<----------- input_forwards_size -------->
1682
//  |--------  memory buffer  -----------------------------------------------|
1683
//                                ^
1684
//                              input
1685
//
1686
// Args:
1687
//   YR_SCAN_CONTEXT *context         - Scan context.
1688
//   const uint8_t* code              - Regexp code be executed
1689
//   const uint8_t* input             - Pointer to input data
1690
//   size_t input_forwards_size       - Number of accessible bytes starting at
1691
//                                      "input" and going forwards.
1692
//   size_t input_backwards_size      - Number of accessible bytes starting at
1693
//                                      "input" and going backwards
1694
//   int flags                        - Flags:
1695
//      RE_FLAGS_SCAN
1696
//      RE_FLAGS_BACKWARDS
1697
//      RE_FLAGS_EXHAUSTIVE
1698
//      RE_FLAGS_WIDE
1699
//      RE_FLAGS_NO_CASE
1700
//      RE_FLAGS_DOT_ALL
1701
//   RE_MATCH_CALLBACK_FUNC callback  - Callback function
1702
//   void* callback_args              - Callback argument
1703
//   int*  matches                    - Pointer to an integer receiving the
1704
//                                      number of matching bytes. Notice that
1705
//                                      0 means a zero-length match, while no
1706
//                                      matches is -1.
1707
// Returns:
1708
//    ERROR_SUCCESS or any other error code.
1709
1710
int yr_re_exec(
1711
    YR_SCAN_CONTEXT* context,
1712
    const uint8_t* code,
1713
    const uint8_t* input_data,
1714
    size_t input_forwards_size,
1715
    size_t input_backwards_size,
1716
    int flags,
1717
    RE_MATCH_CALLBACK_FUNC callback,
1718
    void* callback_args,
1719
    int* matches)
1720
0
{
1721
0
  const uint8_t* input;
1722
0
  const uint8_t* ip;
1723
1724
0
  uint16_t opcode_args;
1725
0
  uint8_t mask;
1726
0
  uint8_t value;
1727
0
  uint8_t character_size;
1728
1729
0
  RE_FIBER_LIST fibers;
1730
0
  RE_FIBER* fiber;
1731
0
  RE_FIBER* next_fiber;
1732
1733
0
  int bytes_matched;
1734
0
  int max_bytes_matched;
1735
1736
0
  int match;
1737
0
  int input_incr;
1738
0
  int kill;
1739
0
  int action;
1740
1741
0
  bool prev_is_word_char = false;
1742
0
  bool input_is_word_char = false;
1743
1744
0
#define ACTION_NONE      0
1745
0
#define ACTION_CONTINUE  1
1746
0
#define ACTION_KILL      2
1747
0
#define ACTION_KILL_TAIL 3
1748
1749
0
#define prolog                                      \
1750
0
  {                                                 \
1751
0
    if ((bytes_matched >= max_bytes_matched) ||     \
1752
0
        (character_size == 2 && *(input + 1) != 0)) \
1753
0
    {                                               \
1754
0
      action = ACTION_KILL;                         \
1755
0
      break;                                        \
1756
0
    }                                               \
1757
0
  }
1758
1759
0
  if (matches != NULL)
1760
0
    *matches = -1;
1761
1762
0
  if (flags & RE_FLAGS_WIDE)
1763
0
    character_size = 2;
1764
0
  else
1765
0
    character_size = 1;
1766
1767
0
  input = input_data;
1768
0
  input_incr = character_size;
1769
1770
0
  if (flags & RE_FLAGS_BACKWARDS)
1771
0
  {
1772
    // Signedness conversion is sound as long as YR_RE_SCAN_LIMIT <= INT_MAX
1773
0
    max_bytes_matched = (int) yr_min(input_backwards_size, YR_RE_SCAN_LIMIT);
1774
0
    input -= character_size;
1775
0
    input_incr = -input_incr;
1776
0
  }
1777
0
  else
1778
0
  {
1779
    // Signedness conversion is sound as long as YR_RE_SCAN_LIMIT <= INT_MAX
1780
0
    max_bytes_matched = (int) yr_min(input_forwards_size, YR_RE_SCAN_LIMIT);
1781
0
  }
1782
1783
  // Round down max_bytes_matched to a multiple of character_size, this way if
1784
  // character_size is 2 and max_bytes_matched is odd we are ignoring the
1785
  // extra byte which can't match anyways.
1786
1787
0
  max_bytes_matched = max_bytes_matched - max_bytes_matched % character_size;
1788
0
  bytes_matched = 0;
1789
1790
0
  FAIL_ON_ERROR(_yr_re_fiber_create(&context->re_fiber_pool, &fiber));
1791
1792
0
  fiber->ip = code;
1793
0
  fibers.head = fiber;
1794
0
  fibers.tail = fiber;
1795
1796
0
  FAIL_ON_ERROR_WITH_CLEANUP(
1797
0
      _yr_re_fiber_sync(&fibers, &context->re_fiber_pool, fiber),
1798
0
      _yr_re_fiber_kill_all(&fibers, &context->re_fiber_pool));
1799
1800
0
  while (fibers.head != NULL)
1801
0
  {
1802
0
    fiber = fibers.head;
1803
1804
0
    while (fiber != NULL)
1805
0
    {
1806
0
      next_fiber = fiber->next;
1807
1808
0
      if (_yr_re_fiber_exists(&fibers, fiber, fiber->prev))
1809
0
        _yr_re_fiber_kill(&fibers, &context->re_fiber_pool, fiber);
1810
1811
0
      fiber = next_fiber;
1812
0
    }
1813
1814
0
    fiber = fibers.head;
1815
1816
0
    while (fiber != NULL)
1817
0
    {
1818
0
      ip = fiber->ip;
1819
0
      action = ACTION_NONE;
1820
1821
0
      switch (*ip)
1822
0
      {
1823
0
      case RE_OPCODE_ANY:
1824
0
        prolog;
1825
0
        match = (flags & RE_FLAGS_DOT_ALL) || (*input != 0x0A);
1826
0
        action = match ? ACTION_NONE : ACTION_KILL;
1827
0
        fiber->ip += 1;
1828
0
        break;
1829
1830
0
      case RE_OPCODE_REPEAT_ANY_GREEDY:
1831
0
      case RE_OPCODE_REPEAT_ANY_UNGREEDY:
1832
0
        prolog;
1833
0
        match = (flags & RE_FLAGS_DOT_ALL) || (*input != 0x0A);
1834
0
        action = match ? ACTION_NONE : ACTION_KILL;
1835
1836
        // The instruction pointer is not incremented here. The current fiber
1837
        // spins in this instruction until reaching the required number of
1838
        // repetitions. The code controlling the number of repetitions is in
1839
        // _yr_re_fiber_sync.
1840
1841
0
        break;
1842
1843
0
      case RE_OPCODE_LITERAL:
1844
0
        prolog;
1845
0
        if (flags & RE_FLAGS_NO_CASE)
1846
0
          match = yr_lowercase[*input] == yr_lowercase[*(ip + 1)];
1847
0
        else
1848
0
          match = (*input == *(ip + 1));
1849
0
        action = match ? ACTION_NONE : ACTION_KILL;
1850
0
        fiber->ip += 2;
1851
0
        break;
1852
1853
0
      case RE_OPCODE_NOT_LITERAL:
1854
0
        prolog;
1855
1856
        // We don't need to take into account the case-insensitive
1857
        // case because this opcode is only used with hex strings,
1858
        // which can't be case-insensitive.
1859
1860
0
        match = (*input != *(ip + 1));
1861
0
        action = match ? ACTION_NONE : ACTION_KILL;
1862
0
        fiber->ip += 2;
1863
0
        break;
1864
1865
0
      case RE_OPCODE_MASKED_LITERAL:
1866
0
        prolog;
1867
0
        opcode_args = yr_unaligned_u16(ip + 1);
1868
0
        mask = opcode_args >> 8;
1869
0
        value = opcode_args & 0xFF;
1870
1871
        // We don't need to take into account the case-insensitive
1872
        // case because this opcode is only used with hex strings,
1873
        // which can't be case-insensitive.
1874
1875
0
        match = ((*input & mask) == value);
1876
0
        action = match ? ACTION_NONE : ACTION_KILL;
1877
0
        fiber->ip += 3;
1878
0
        break;
1879
1880
0
      case RE_OPCODE_MASKED_NOT_LITERAL:
1881
0
        prolog;
1882
0
        opcode_args = yr_unaligned_u16(ip + 1);
1883
0
        mask = opcode_args >> 8;
1884
0
        value = opcode_args & 0xFF;
1885
1886
        // We don't need to take into account the case-insensitive
1887
        // case because this opcode is only used with hex strings,
1888
        // which can't be case-insensitive.
1889
1890
0
        match = ((*input & mask) != value);
1891
0
        action = match ? ACTION_NONE : ACTION_KILL;
1892
0
        fiber->ip += 3;
1893
0
        break;
1894
1895
0
      case RE_OPCODE_CLASS:
1896
0
        prolog;
1897
0
        match = _yr_re_is_char_in_class(
1898
0
            (RE_CLASS*) (ip + 1), *input, flags & RE_FLAGS_NO_CASE);
1899
0
        action = match ? ACTION_NONE : ACTION_KILL;
1900
0
        fiber->ip += (sizeof(RE_CLASS) + 1);
1901
0
        break;
1902
1903
0
      case RE_OPCODE_WORD_CHAR:
1904
0
        prolog;
1905
0
        match = _yr_re_is_word_char(input, character_size);
1906
0
        action = match ? ACTION_NONE : ACTION_KILL;
1907
0
        fiber->ip += 1;
1908
0
        break;
1909
1910
0
      case RE_OPCODE_NON_WORD_CHAR:
1911
0
        prolog;
1912
0
        match = !_yr_re_is_word_char(input, character_size);
1913
0
        action = match ? ACTION_NONE : ACTION_KILL;
1914
0
        fiber->ip += 1;
1915
0
        break;
1916
1917
0
      case RE_OPCODE_SPACE:
1918
0
      case RE_OPCODE_NON_SPACE:
1919
1920
0
        prolog;
1921
1922
0
        switch (*input)
1923
0
        {
1924
0
        case ' ':
1925
0
        case '\t':
1926
0
        case '\r':
1927
0
        case '\n':
1928
0
        case '\v':
1929
0
        case '\f':
1930
0
          match = true;
1931
0
          break;
1932
0
        default:
1933
0
          match = false;
1934
0
        }
1935
1936
0
        if (*ip == RE_OPCODE_NON_SPACE)
1937
0
          match = !match;
1938
1939
0
        action = match ? ACTION_NONE : ACTION_KILL;
1940
0
        fiber->ip += 1;
1941
0
        break;
1942
1943
0
      case RE_OPCODE_DIGIT:
1944
0
        prolog;
1945
0
        match = isdigit(*input);
1946
0
        action = match ? ACTION_NONE : ACTION_KILL;
1947
0
        fiber->ip += 1;
1948
0
        break;
1949
1950
0
      case RE_OPCODE_NON_DIGIT:
1951
0
        prolog;
1952
0
        match = !isdigit(*input);
1953
0
        action = match ? ACTION_NONE : ACTION_KILL;
1954
0
        fiber->ip += 1;
1955
0
        break;
1956
1957
0
      case RE_OPCODE_WORD_BOUNDARY:
1958
0
      case RE_OPCODE_NON_WORD_BOUNDARY:
1959
0
        if (input - input_incr + character_size <=
1960
0
                input_data + input_forwards_size &&
1961
0
            input - input_incr >= input_data - input_backwards_size)
1962
0
        {
1963
0
          prev_is_word_char = _yr_re_is_word_char(
1964
0
              input - input_incr, character_size);
1965
0
        }
1966
0
        else
1967
0
        {
1968
0
          prev_is_word_char = false;
1969
0
        }
1970
1971
0
        if (input + character_size <= input_data + input_forwards_size &&
1972
0
            input >= input_data - input_backwards_size)
1973
0
        {
1974
0
          input_is_word_char = _yr_re_is_word_char(input, character_size);
1975
0
        }
1976
0
        else
1977
0
        {
1978
0
          input_is_word_char = false;
1979
0
        }
1980
1981
0
        match = (prev_is_word_char && !input_is_word_char) ||
1982
0
                (!prev_is_word_char && input_is_word_char);
1983
1984
0
        if (*ip == RE_OPCODE_NON_WORD_BOUNDARY)
1985
0
          match = !match;
1986
1987
0
        action = match ? ACTION_CONTINUE : ACTION_KILL;
1988
0
        fiber->ip += 1;
1989
0
        break;
1990
1991
0
      case RE_OPCODE_MATCH_AT_START:
1992
0
        if (flags & RE_FLAGS_BACKWARDS)
1993
0
          kill = input_backwards_size > (size_t) bytes_matched;
1994
0
        else
1995
0
          kill = input_backwards_size > 0 || (bytes_matched != 0);
1996
0
        action = kill ? ACTION_KILL : ACTION_CONTINUE;
1997
0
        fiber->ip += 1;
1998
0
        break;
1999
2000
0
      case RE_OPCODE_MATCH_AT_END:
2001
0
        kill = flags & RE_FLAGS_BACKWARDS ||
2002
0
               input_forwards_size > (size_t) bytes_matched;
2003
0
        action = kill ? ACTION_KILL : ACTION_CONTINUE;
2004
0
        fiber->ip += 1;
2005
0
        break;
2006
2007
0
      case RE_OPCODE_MATCH:
2008
2009
0
        if (matches != NULL)
2010
0
          *matches = bytes_matched;
2011
2012
0
        if (flags & RE_FLAGS_EXHAUSTIVE)
2013
0
        {
2014
0
          if (callback != NULL)
2015
0
          {
2016
0
            if (flags & RE_FLAGS_BACKWARDS)
2017
0
            {
2018
0
              FAIL_ON_ERROR_WITH_CLEANUP(
2019
0
                  callback(
2020
0
                      input + character_size,
2021
0
                      bytes_matched,
2022
0
                      flags,
2023
0
                      callback_args),
2024
0
                  _yr_re_fiber_kill_all(&fibers, &context->re_fiber_pool));
2025
0
            }
2026
0
            else
2027
0
            {
2028
0
              FAIL_ON_ERROR_WITH_CLEANUP(
2029
0
                  callback(input_data, bytes_matched, flags, callback_args),
2030
0
                  _yr_re_fiber_kill_all(&fibers, &context->re_fiber_pool));
2031
0
            }
2032
0
          }
2033
2034
0
          action = ACTION_KILL;
2035
0
        }
2036
0
        else
2037
0
        {
2038
0
          action = ACTION_KILL_TAIL;
2039
0
        }
2040
2041
0
        break;
2042
2043
0
      default:
2044
0
        assert(false);
2045
0
      }
2046
2047
0
      switch (action)
2048
0
      {
2049
0
      case ACTION_KILL:
2050
0
        fiber = _yr_re_fiber_kill(&fibers, &context->re_fiber_pool, fiber);
2051
0
        break;
2052
2053
0
      case ACTION_KILL_TAIL:
2054
0
        _yr_re_fiber_kill_tail(&fibers, &context->re_fiber_pool, fiber);
2055
0
        fiber = NULL;
2056
0
        break;
2057
2058
0
      case ACTION_CONTINUE:
2059
0
        FAIL_ON_ERROR_WITH_CLEANUP(
2060
0
            _yr_re_fiber_sync(&fibers, &context->re_fiber_pool, fiber),
2061
0
            _yr_re_fiber_kill_all(&fibers, &context->re_fiber_pool));
2062
0
        break;
2063
2064
0
      default:
2065
0
        next_fiber = fiber->next;
2066
0
        FAIL_ON_ERROR_WITH_CLEANUP(
2067
0
            _yr_re_fiber_sync(&fibers, &context->re_fiber_pool, fiber),
2068
0
            _yr_re_fiber_kill_all(&fibers, &context->re_fiber_pool));
2069
0
        fiber = next_fiber;
2070
0
      }
2071
0
    }
2072
2073
0
    input += input_incr;
2074
0
    bytes_matched += character_size;
2075
2076
0
    if (flags & RE_FLAGS_SCAN && bytes_matched < max_bytes_matched)
2077
0
    {
2078
0
      FAIL_ON_ERROR_WITH_CLEANUP(
2079
0
          _yr_re_fiber_create(&context->re_fiber_pool, &fiber),
2080
0
          _yr_re_fiber_kill_all(&fibers, &context->re_fiber_pool));
2081
2082
0
      fiber->ip = code;
2083
0
      _yr_re_fiber_append(&fibers, fiber);
2084
2085
0
      FAIL_ON_ERROR_WITH_CLEANUP(
2086
0
          _yr_re_fiber_sync(&fibers, &context->re_fiber_pool, fiber),
2087
0
          _yr_re_fiber_kill_all(&fibers, &context->re_fiber_pool));
2088
0
    }
2089
0
  }
2090
2091
0
  return ERROR_SUCCESS;
2092
0
}
2093
2094
////////////////////////////////////////////////////////////////////////////////
2095
// Helper function that creates a RE_FAST_EXEC_POSITION by either allocating it
2096
// or reusing a previously allocated one from a pool.
2097
//
2098
static int _yr_re_fast_exec_position_create(
2099
    RE_FAST_EXEC_POSITION_POOL* pool,
2100
    RE_FAST_EXEC_POSITION** new_position)
2101
0
{
2102
0
  RE_FAST_EXEC_POSITION* position;
2103
2104
0
  if (pool->head != NULL)
2105
0
  {
2106
0
    position = pool->head;
2107
0
    pool->head = position->next;
2108
0
  }
2109
0
  else
2110
0
  {
2111
0
    position = (RE_FAST_EXEC_POSITION*) yr_malloc(
2112
0
        sizeof(RE_FAST_EXEC_POSITION));
2113
2114
0
    if (position == NULL)
2115
0
      return ERROR_INSUFFICIENT_MEMORY;
2116
0
  }
2117
2118
0
  position->input = NULL;
2119
0
  position->round = 0;
2120
0
  position->next = NULL;
2121
0
  position->prev = NULL;
2122
2123
0
  *new_position = position;
2124
2125
0
  return ERROR_SUCCESS;
2126
0
}
2127
2128
////////////////////////////////////////////////////////////////////////////////
2129
// Helper function that moves a list of RE_FAST_EXEC_POSITION structures to a
2130
// pool represented by a RE_FAST_EXEC_POSITION_POOL. Receives pointers to the
2131
// pool, the first item, and last item in the list.
2132
//
2133
static void _yr_re_fast_exec_destroy_position_list(
2134
    RE_FAST_EXEC_POSITION_POOL* pool,
2135
    RE_FAST_EXEC_POSITION* first,
2136
    RE_FAST_EXEC_POSITION* last)
2137
0
{
2138
0
  last->next = pool->head;
2139
2140
0
  if (pool->head != NULL)
2141
0
    pool->head->prev = last;
2142
2143
0
  pool->head = first;
2144
0
}
2145
2146
////////////////////////////////////////////////////////////////////////////////
2147
// This function replaces yr_re_exec for regular expressions marked with flag
2148
// RE_FLAGS_FAST_REGEXP. These regular expressions are derived from hex strings
2149
// that don't contain alternatives, like for example:
2150
//
2151
//   { 01 02 03 04 [0-2] 04 05 06 07 }
2152
//
2153
// The regexp's code produced by such strings can be matched by a faster, less
2154
// general algorithm, and it contains only the following opcodes:
2155
//
2156
//   * RE_OPCODE_LITERAL
2157
//   * RE_OPCODE_MASKED_LITERAL,
2158
//   * RE_OPCODE_NOT_LITERAL
2159
//   * RE_OPCODE_MASKED_NOT_LITERAL
2160
//   * RE_OPCODE_ANY
2161
//   * RE_OPCODE_REPEAT_ANY_UNGREEDY
2162
//   * RE_OPCODE_MATCH.
2163
//
2164
// The regexp's code is executed one instruction at time, and the function
2165
// maintains a list of positions within the input for tracking different
2166
// matching alternatives, these positions are described by an instance of
2167
// RE_FAST_EXEC_POSITION. With each instruction the list of positions is
2168
// updated, removing those where the input data doesn't match the current
2169
// instruction, or adding new positions if the instruction is
2170
// RE_OPCODE_REPEAT_ANY_UNGREEDY. The list of positions is maintained sorted
2171
// by the value of the pointer they hold to the input, and it doesn't contain
2172
// duplicated pointer values.
2173
//
2174
int yr_re_fast_exec(
2175
    YR_SCAN_CONTEXT* context,
2176
    const uint8_t* code,
2177
    const uint8_t* input_data,
2178
    size_t input_forwards_size,
2179
    size_t input_backwards_size,
2180
    int flags,
2181
    RE_MATCH_CALLBACK_FUNC callback,
2182
    void* callback_args,
2183
    int* matches)
2184
0
{
2185
0
  RE_REPEAT_ANY_ARGS* repeat_any_args;
2186
2187
  // Pointers to the first and last position in the list.
2188
0
  RE_FAST_EXEC_POSITION* first;
2189
0
  RE_FAST_EXEC_POSITION* last;
2190
2191
0
  int input_incr = flags & RE_FLAGS_BACKWARDS ? -1 : 1;
2192
0
  int bytes_matched;
2193
0
  int max_bytes_matched;
2194
2195
0
  if (flags & RE_FLAGS_BACKWARDS)
2196
0
    max_bytes_matched = (int) yr_min(input_backwards_size, YR_RE_SCAN_LIMIT);
2197
0
  else
2198
0
    max_bytes_matched = (int) yr_min(input_forwards_size, YR_RE_SCAN_LIMIT);
2199
2200
0
  const uint8_t* ip = code;
2201
2202
  // Create the first position in the list, which points to the start of the
2203
  // input data. Intially this is the only position, more positions will be
2204
  // created every time RE_OPCODE_REPEAT_ANY_UNGREEDY is executed.
2205
0
  FAIL_ON_ERROR(_yr_re_fast_exec_position_create(
2206
0
      &context->re_fast_exec_position_pool, &first));
2207
2208
0
  first->round = 0;
2209
0
  first->input = input_data;
2210
0
  first->prev = NULL;
2211
0
  first->next = NULL;
2212
2213
0
  if (flags & RE_FLAGS_BACKWARDS)
2214
0
    first->input--;
2215
2216
  // As we are starting with a single position, the last one and the first one
2217
  // are the same.
2218
0
  last = first;
2219
2220
  // Round is incremented with every regxp instruction.
2221
0
  int round = 0;
2222
2223
  // Keep in the loop until the list of positions gets empty. Positions are
2224
  // removed from the list when they don't match the current instruction in
2225
  // the code.
2226
0
  while (first != NULL)
2227
0
  {
2228
0
    RE_FAST_EXEC_POSITION* current = first;
2229
2230
    // Iterate over all the positions, executing the current instruction at
2231
    // all of them.
2232
0
    while (current != NULL)
2233
0
    {
2234
0
      RE_FAST_EXEC_POSITION* next = current->next;
2235
2236
      // Ignore any position in the list whose round number is different from
2237
      // the current round. This prevents new positions added to the list in
2238
      // this round from being taken into account in this same round.
2239
0
      if (current->round != round)
2240
0
      {
2241
0
        current = next;
2242
0
        continue;
2243
0
      }
2244
2245
0
      bytes_matched = flags & RE_FLAGS_BACKWARDS
2246
0
                          ? (int) (input_data - current->input - 1)
2247
0
                          : (int) (current->input - input_data);
2248
2249
0
      uint16_t opcode_args;
2250
0
      uint8_t mask;
2251
0
      uint8_t value;
2252
2253
0
      bool match = false;
2254
2255
0
      switch (*ip)
2256
0
      {
2257
0
      case RE_OPCODE_ANY:
2258
0
        if (bytes_matched >= max_bytes_matched)
2259
0
          break;
2260
2261
0
        match = true;
2262
0
        current->input += input_incr;
2263
0
        break;
2264
2265
0
      case RE_OPCODE_LITERAL:
2266
0
        if (bytes_matched >= max_bytes_matched)
2267
0
          break;
2268
2269
0
        if (*current->input == *(ip + 1))
2270
0
        {
2271
0
          match = true;
2272
0
          current->input += input_incr;
2273
0
        }
2274
0
        break;
2275
2276
0
      case RE_OPCODE_NOT_LITERAL:
2277
0
        if (bytes_matched >= max_bytes_matched)
2278
0
          break;
2279
2280
0
        if (*current->input != *(ip + 1))
2281
0
        {
2282
0
          match = true;
2283
0
          current->input += input_incr;
2284
0
        }
2285
0
        break;
2286
2287
0
      case RE_OPCODE_MASKED_LITERAL:
2288
0
        if (bytes_matched >= max_bytes_matched)
2289
0
          break;
2290
2291
0
        opcode_args = yr_unaligned_u16(ip + 1);
2292
0
        mask = opcode_args >> 8;
2293
0
        value = opcode_args & 0xFF;
2294
2295
0
        if ((*current->input & mask) == value)
2296
0
        {
2297
0
          match = true;
2298
0
          current->input += input_incr;
2299
0
        }
2300
0
        break;
2301
2302
0
      case RE_OPCODE_MASKED_NOT_LITERAL:
2303
0
        if (bytes_matched >= max_bytes_matched)
2304
0
          break;
2305
2306
0
        opcode_args = yr_unaligned_u16(ip + 1);
2307
0
        mask = opcode_args >> 8;
2308
0
        value = opcode_args & 0xFF;
2309
2310
0
        if ((*current->input & mask) != value)
2311
0
        {
2312
0
          match = true;
2313
0
          current->input += input_incr;
2314
0
        }
2315
0
        break;
2316
2317
0
      case RE_OPCODE_REPEAT_ANY_UNGREEDY:
2318
0
        repeat_any_args = (RE_REPEAT_ANY_ARGS*) (ip + 1);
2319
2320
0
        if (bytes_matched + repeat_any_args->min >= max_bytes_matched)
2321
0
          break;
2322
2323
0
        match = true;
2324
2325
0
        const uint8_t* next_opcode = ip + 1 + sizeof(RE_REPEAT_ANY_ARGS);
2326
2327
        // insertion_point indicates the item in the list of inputs after which
2328
        // the newly created inputs will be inserted.
2329
0
        RE_FAST_EXEC_POSITION* insertion_point = current;
2330
2331
0
        for (int j = repeat_any_args->min + 1; j <= repeat_any_args->max; j++)
2332
0
        {
2333
          // bytes_matched is the number of bytes matched so far, and j is the
2334
          // minimum number of bytes that are still pending to match. If these
2335
          // two numbers sum more than the maximum number of bytes that can be
2336
          // matched the loop can be aborted. The position that we were about
2337
          // to create can't lead to a match without exceeding
2338
          // max_bytes_matched.
2339
0
          if (bytes_matched + j >= max_bytes_matched)
2340
0
            break;
2341
2342
0
          const uint8_t* next_input = current->input + j * input_incr;
2343
2344
          // Find the point where next_input should be inserted. The list is
2345
          // kept sorted by pointer in increasing order, the insertion point is
2346
          // an item that has a pointer lower or equal than next_input, but
2347
          // whose next item have a pointer that is larger.
2348
0
          while (insertion_point->next != NULL &&
2349
0
                 insertion_point->next->input <= next_input)
2350
0
          {
2351
0
            insertion_point = insertion_point->next;
2352
0
          }
2353
2354
          // If the input already exists for the next round, we don't need to
2355
          // insert it.
2356
0
          if (insertion_point->round == round + 1 &&
2357
0
              insertion_point->input == next_input)
2358
0
            continue;
2359
2360
          // The next opcode is RE_OPCODE_LITERAL, but the literal doesn't
2361
          // match with the byte at next_input, we don't need to add this
2362
          // input to the list as we already know that it won't match in the
2363
          // next round and will be deleted from the list anyways.
2364
0
          if (*(next_opcode) == RE_OPCODE_LITERAL &&
2365
0
              *(next_opcode + 1) != *next_input)
2366
0
            continue;
2367
2368
0
          RE_FAST_EXEC_POSITION* new_input;
2369
2370
0
          FAIL_ON_ERROR_WITH_CLEANUP(
2371
0
              _yr_re_fast_exec_position_create(
2372
0
                  &context->re_fast_exec_position_pool, &new_input),
2373
              // Cleanup
2374
0
              _yr_re_fast_exec_destroy_position_list(
2375
0
                  &context->re_fast_exec_position_pool, first, last));
2376
2377
0
          new_input->input = next_input;
2378
0
          new_input->round = round + 1;
2379
0
          new_input->prev = insertion_point;
2380
0
          new_input->next = insertion_point->next;
2381
0
          insertion_point->next = new_input;
2382
2383
0
          if (new_input->next != NULL)
2384
0
            new_input->next->prev = new_input;
2385
2386
0
          if (insertion_point == last)
2387
0
            last = new_input;
2388
0
        }
2389
2390
0
        current->input += input_incr * repeat_any_args->min;
2391
0
        break;
2392
2393
0
      case RE_OPCODE_MATCH:
2394
2395
0
        if (flags & RE_FLAGS_EXHAUSTIVE)
2396
0
        {
2397
0
          FAIL_ON_ERROR_WITH_CLEANUP(
2398
0
              callback(
2399
                  // When matching forwards the matching data always starts at
2400
                  // input_data, when matching backwards it starts at input + 1
2401
                  // or input_data - input_backwards_size if input + 1 is
2402
                  // outside the buffer.
2403
0
                  flags & RE_FLAGS_BACKWARDS
2404
0
                      ? yr_max(
2405
0
                            current->input + 1,
2406
0
                            input_data - input_backwards_size)
2407
0
                      : input_data,
2408
                  // The number of matched bytes should not be larger than
2409
                  // max_bytes_matched.
2410
0
                  yr_min(bytes_matched, max_bytes_matched),
2411
0
                  flags,
2412
0
                  callback_args),
2413
              // Cleanup
2414
0
              _yr_re_fast_exec_destroy_position_list(
2415
0
                  &context->re_fast_exec_position_pool, first, last));
2416
0
        }
2417
0
        else
2418
0
        {
2419
0
          if (matches != NULL)
2420
0
            *matches = bytes_matched;
2421
2422
0
          _yr_re_fast_exec_destroy_position_list(
2423
0
              &context->re_fast_exec_position_pool, first, last);
2424
2425
0
          return ERROR_SUCCESS;
2426
0
        }
2427
0
        break;
2428
2429
0
      default:
2430
0
        printf("non-supported opcode: %d\n", *ip);
2431
0
        assert(false);
2432
0
      }
2433
2434
0
      if (match)
2435
0
      {
2436
0
        current->round = round + 1;
2437
0
      }
2438
0
      else
2439
0
      {
2440
        // Remove current from the list. If the item being removed is the first
2441
        // one or the last one, the first and last pointers should be updated.
2442
        // The removed item is put into the pool for later reuse.
2443
2444
0
        if (current == first)
2445
0
          first = current->next;
2446
2447
0
        if (current == last)
2448
0
          last = current->prev;
2449
2450
0
        if (current->prev != NULL)
2451
0
          current->prev->next = current->next;
2452
2453
0
        if (current->next != NULL)
2454
0
          current->next->prev = current->prev;
2455
2456
0
        current->prev = NULL;
2457
0
        current->next = context->re_fast_exec_position_pool.head;
2458
2459
0
        if (current->next != NULL)
2460
0
          current->next->prev = current;
2461
2462
0
        context->re_fast_exec_position_pool.head = current;
2463
0
      }
2464
2465
0
      current = next;
2466
2467
0
    }  // while (current != NULL)
2468
2469
    // Move instruction pointer (ip) to next instruction. Each opcode has
2470
    // a different size.
2471
0
    switch (*ip)
2472
0
    {
2473
0
    case RE_OPCODE_ANY:
2474
0
      ip += 1;
2475
0
      break;
2476
0
    case RE_OPCODE_LITERAL:
2477
0
    case RE_OPCODE_NOT_LITERAL:
2478
0
      ip += 2;
2479
0
      break;
2480
0
    case RE_OPCODE_MASKED_LITERAL:
2481
0
    case RE_OPCODE_MASKED_NOT_LITERAL:
2482
0
      ip += 3;
2483
0
      break;
2484
0
    case RE_OPCODE_REPEAT_ANY_UNGREEDY:
2485
0
      ip += 1 + sizeof(RE_REPEAT_ANY_ARGS);
2486
0
      break;
2487
0
    case RE_OPCODE_MATCH:
2488
0
      break;
2489
0
    default:
2490
0
      assert(false);
2491
0
    }
2492
2493
0
    round++;
2494
0
  }
2495
2496
  // If this point is reached no matches were found.
2497
2498
0
  if (matches != NULL)
2499
0
    *matches = -1;
2500
2501
0
  return ERROR_SUCCESS;
2502
0
}
2503
2504
static void _yr_re_print_node(RE_NODE* re_node, uint32_t indent)
2505
0
{
2506
0
  RE_NODE* child;
2507
0
  int i;
2508
2509
0
  if (re_node == NULL)
2510
0
    return;
2511
2512
0
  if (indent > 0)
2513
0
    printf("\n%*s", indent, " ");
2514
0
  switch (re_node->type)
2515
0
  {
2516
0
  case RE_NODE_ALT:
2517
0
    printf("Alt(");
2518
0
    _yr_re_print_node(re_node->children_head, indent + 4);
2519
0
    printf(",");
2520
0
    _yr_re_print_node(re_node->children_tail, indent + 4);
2521
0
    printf("\n%*s%s", indent, " ", ")");
2522
0
    break;
2523
2524
0
  case RE_NODE_CONCAT:
2525
0
    printf("Cat(");
2526
0
    child = re_node->children_head;
2527
0
    while (child != NULL)
2528
0
    {
2529
0
      _yr_re_print_node(child, indent + 4);
2530
0
      printf(",");
2531
0
      child = child->next_sibling;
2532
0
    }
2533
0
    printf("\n%*s%s", indent, " ", ")");
2534
0
    break;
2535
2536
0
  case RE_NODE_STAR:
2537
0
    printf("Star(");
2538
0
    _yr_re_print_node(re_node->children_head, indent + 4);
2539
0
    printf(")");
2540
0
    break;
2541
2542
0
  case RE_NODE_PLUS:
2543
0
    printf("Plus(");
2544
0
    _yr_re_print_node(re_node->children_head, indent + 4);
2545
0
    printf(")");
2546
0
    break;
2547
2548
0
  case RE_NODE_LITERAL:
2549
0
    printf("Lit(%c)", re_node->value);
2550
0
    break;
2551
2552
0
  case RE_NODE_NOT_LITERAL:
2553
0
    printf("NotLit(%c)", re_node->value);
2554
0
    break;
2555
2556
0
  case RE_NODE_MASKED_LITERAL:
2557
0
    printf("MaskedLit(%02X,%02X)", re_node->value, re_node->mask);
2558
0
    break;
2559
2560
0
  case RE_NODE_WORD_CHAR:
2561
0
    printf("WordChar");
2562
0
    break;
2563
2564
0
  case RE_NODE_NON_WORD_CHAR:
2565
0
    printf("NonWordChar");
2566
0
    break;
2567
2568
0
  case RE_NODE_SPACE:
2569
0
    printf("Space");
2570
0
    break;
2571
2572
0
  case RE_NODE_NON_SPACE:
2573
0
    printf("NonSpace");
2574
0
    break;
2575
2576
0
  case RE_NODE_DIGIT:
2577
0
    printf("Digit");
2578
0
    break;
2579
2580
0
  case RE_NODE_NON_DIGIT:
2581
0
    printf("NonDigit");
2582
0
    break;
2583
2584
0
  case RE_NODE_ANY:
2585
0
    printf("Any");
2586
0
    break;
2587
2588
0
  case RE_NODE_RANGE:
2589
0
    printf("Range(%d-%d, ", re_node->start, re_node->end);
2590
0
    _yr_re_print_node(re_node->children_head, indent + 4);
2591
0
    printf("\n%*s%s", indent, " ", ")");
2592
0
    break;
2593
2594
0
  case RE_NODE_CLASS:
2595
0
    printf("Class(");
2596
0
    for (i = 0; i < 256; i++)
2597
0
      if (_yr_re_is_char_in_class(re_node->re_class, i, false))
2598
0
        printf("%02X,", i);
2599
0
    printf(")");
2600
0
    break;
2601
2602
0
  case RE_NODE_EMPTY:
2603
0
    printf("Empty");
2604
0
    break;
2605
2606
0
  case RE_NODE_ANCHOR_START:
2607
0
    printf("AnchorStart");
2608
0
    break;
2609
2610
0
  case RE_NODE_ANCHOR_END:
2611
0
    printf("AnchorEnd");
2612
0
    break;
2613
2614
0
  case RE_NODE_WORD_BOUNDARY:
2615
0
    printf("WordBoundary");
2616
0
    break;
2617
2618
0
  case RE_NODE_NON_WORD_BOUNDARY:
2619
0
    printf("NonWordBoundary");
2620
0
    break;
2621
2622
0
  case RE_NODE_RANGE_ANY:
2623
0
    printf("RangeAny");
2624
0
    break;
2625
2626
0
  default:
2627
0
    printf("???");
2628
0
    break;
2629
0
  }
2630
0
}
2631
2632
void yr_re_print(RE_AST* re_ast)
2633
0
{
2634
0
  _yr_re_print_node(re_ast->root_node, 0);
2635
0
}