Coverage Report

Created: 2023-09-25 07:12

/src/yara/libyara/compiler.c
Line
Count
Source (jump to first uncovered line)
1
/*
2
Copyright (c) 2013-2018. 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 <fcntl.h>
32
#include <stddef.h>
33
#include <stdio.h>
34
#include <string.h>
35
#include <sys/stat.h>
36
37
#ifdef _MSC_VER
38
#include <io.h>
39
#include <share.h>
40
#else
41
#include <unistd.h>
42
#endif
43
44
#include <yara/compiler.h>
45
#include <yara/error.h>
46
#include <yara/exec.h>
47
#include <yara/lexer.h>
48
#include <yara/libyara.h>
49
#include <yara/mem.h>
50
#include <yara/object.h>
51
#include <yara/strutils.h>
52
#include <yara/utils.h>
53
54
static void _yr_compiler_default_include_free(
55
    const char* callback_result_ptr,
56
    void* user_data)
57
0
{
58
0
  if (callback_result_ptr != NULL)
59
0
  {
60
0
    yr_free((void*) callback_result_ptr);
61
0
  }
62
0
}
63
64
const char* _yr_compiler_default_include_callback(
65
    const char* include_name,
66
    const char* calling_rule_filename,
67
    const char* calling_rule_namespace,
68
    void* user_data)
69
0
{
70
0
#ifndef _MSC_VER
71
0
  struct stat stbuf;
72
0
#endif
73
74
0
  char* file_buffer;
75
76
#ifdef _MSC_VER
77
  long file_size;
78
#else
79
0
  off_t file_size;
80
0
#endif
81
82
0
  int fd = -1;
83
84
#if defined(_MSC_VER)
85
  _sopen_s(&fd, include_name, _O_RDONLY | _O_BINARY, _SH_DENYWR, _S_IREAD);
86
#elif defined(_WIN32) || defined(__CYGWIN__)
87
  fd = open(include_name, O_RDONLY | O_BINARY);
88
#else
89
0
  fd = open(include_name, O_RDONLY);
90
0
#endif
91
92
0
  if (fd == -1)
93
0
    return NULL;
94
95
#ifdef _MSC_VER
96
  file_size = _filelength(fd);
97
  if (file_size == -1)
98
  {
99
    _close(fd);
100
    return NULL;
101
  }
102
#else
103
0
  if ((fstat(fd, &stbuf) != 0) || (!S_ISREG(stbuf.st_mode)))
104
0
  {
105
0
    close(fd);
106
0
    return NULL;
107
0
  }
108
0
  file_size = stbuf.st_size;
109
0
#endif
110
111
0
  file_buffer = (char*) yr_malloc((size_t) file_size + 1);
112
113
0
  if (file_buffer == NULL)
114
0
  {
115
#ifdef _MSC_VER
116
    _close(fd);
117
#else
118
0
    close(fd);
119
0
#endif
120
121
0
    return NULL;
122
0
  }
123
124
0
  if (file_size != read(fd, file_buffer, (size_t) file_size))
125
0
  {
126
0
    yr_free(file_buffer);
127
128
#ifdef _MSC_VER
129
    _close(fd);
130
#else
131
0
    close(fd);
132
0
#endif
133
134
0
    return NULL;
135
0
  }
136
0
  else
137
0
  {
138
0
    file_buffer[file_size] = '\0';
139
0
  }
140
141
#ifdef _MSC_VER
142
  _close(fd);
143
#else
144
0
  close(fd);
145
0
#endif
146
147
0
  return file_buffer;
148
0
}
149
150
////////////////////////////////////////////////////////////////////////////////
151
// Returns a rule given its index in the rules table.
152
//
153
// The returned pointer is valid as long as no other rule is written to the
154
// table. This is because the write operation may cause the table to be moved to
155
// a different location in memory. Use the pointer only in a limited scope where
156
// you can be sure that no other rule is being written during the pointer's
157
// lifetime.
158
//
159
YR_RULE* _yr_compiler_get_rule_by_idx(YR_COMPILER* compiler, uint32_t rule_idx)
160
0
{
161
0
  return (YR_RULE*) yr_arena_get_ptr(
162
0
      compiler->arena, YR_RULES_TABLE, rule_idx * sizeof(YR_RULE));
163
0
}
164
165
////////////////////////////////////////////////////////////////////////////////
166
// Stores some data in the YR_SZ_POOL and returns a reference to it.
167
//
168
// If the same data was already stored in a previous call to this function the
169
// data is not written again, a reference to the existing data is returned
170
// instead.
171
//
172
int _yr_compiler_store_data(
173
    YR_COMPILER* compiler,
174
    const void* data,
175
    size_t data_length,
176
    YR_ARENA_REF* ref)
177
12
{
178
  // Check if the data is already in YR_SZ_POOL by using a hash table.
179
12
  uint32_t offset = yr_hash_table_lookup_uint32_raw_key(
180
12
      compiler->sz_table, data, data_length, NULL);
181
182
12
  if (offset == UINT32_MAX)
183
10
  {
184
    // The data was not previously written to YR_SZ_POOL, write it and store
185
    // the reference's offset in the hash table. Storing the buffer number
186
    // is not necessary, it's always YR_SZ_POOL.
187
10
    FAIL_ON_ERROR(yr_arena_write_data(
188
10
        compiler->arena, YR_SZ_POOL, data, data_length, ref));
189
190
10
    FAIL_ON_ERROR(yr_hash_table_add_uint32_raw_key(
191
10
        compiler->sz_table, data, data_length, NULL, ref->offset));
192
10
  }
193
2
  else
194
2
  {
195
2
    ref->buffer_id = YR_SZ_POOL;
196
2
    ref->offset = offset;
197
2
  }
198
199
12
  return ERROR_SUCCESS;
200
12
}
201
202
////////////////////////////////////////////////////////////////////////////////
203
// Similar to _yr_compiler_store_data, but receives a null-terminated string.
204
//
205
int _yr_compiler_store_string(
206
    YR_COMPILER* compiler,
207
    const char* string,
208
    YR_ARENA_REF* ref)
209
10
{
210
10
  return _yr_compiler_store_data(
211
10
      compiler,
212
10
      (void*) string,
213
10
      strlen(string) + 1,  // include the null terminator
214
10
      ref);
215
10
}
216
217
YR_API int yr_compiler_create(YR_COMPILER** compiler)
218
2
{
219
2
  int result;
220
2
  YR_COMPILER* new_compiler;
221
222
2
  new_compiler = (YR_COMPILER*) yr_calloc(1, sizeof(YR_COMPILER));
223
224
2
  if (new_compiler == NULL)
225
0
    return ERROR_INSUFFICIENT_MEMORY;
226
227
2
  new_compiler->current_rule_idx = UINT32_MAX;
228
2
  new_compiler->next_rule_idx = 0;
229
2
  new_compiler->current_string_idx = 0;
230
2
  new_compiler->current_namespace_idx = 0;
231
2
  new_compiler->current_meta_idx = 0;
232
2
  new_compiler->num_namespaces = 0;
233
2
  new_compiler->errors = 0;
234
2
  new_compiler->callback = NULL;
235
2
  new_compiler->rules = NULL;
236
2
  new_compiler->include_callback = _yr_compiler_default_include_callback;
237
2
  new_compiler->incl_clbk_user_data = NULL;
238
2
  new_compiler->include_free = _yr_compiler_default_include_free;
239
2
  new_compiler->re_ast_callback = NULL;
240
2
  new_compiler->re_ast_clbk_user_data = NULL;
241
2
  new_compiler->last_error = ERROR_SUCCESS;
242
2
  new_compiler->last_error_line = 0;
243
2
  new_compiler->strict_escape = false;
244
2
  new_compiler->current_line = 0;
245
2
  new_compiler->file_name_stack_ptr = 0;
246
2
  new_compiler->fixup_stack_head = NULL;
247
2
  new_compiler->loop_index = -1;
248
2
  new_compiler->loop_for_of_var_index = -1;
249
250
2
  new_compiler->atoms_config.get_atom_quality = yr_atoms_heuristic_quality;
251
2
  new_compiler->atoms_config.quality_warning_threshold =
252
2
      YR_ATOM_QUALITY_WARNING_THRESHOLD;
253
254
2
  result = yr_hash_table_create(5000, &new_compiler->rules_table);
255
256
2
  if (result == ERROR_SUCCESS)
257
2
    result = yr_hash_table_create(1000, &new_compiler->objects_table);
258
259
2
  if (result == ERROR_SUCCESS)
260
2
    result = yr_hash_table_create(10000, &new_compiler->strings_table);
261
262
2
  if (result == ERROR_SUCCESS)
263
2
    result = yr_hash_table_create(
264
2
        1000, &new_compiler->wildcard_identifiers_table);
265
266
2
  if (result == ERROR_SUCCESS)
267
2
    result = yr_hash_table_create(10000, &new_compiler->sz_table);
268
269
2
  if (result == ERROR_SUCCESS)
270
2
    result = yr_arena_create(YR_NUM_SECTIONS, 1048576, &new_compiler->arena);
271
272
2
  if (result == ERROR_SUCCESS)
273
2
    result = yr_ac_automaton_create(
274
2
        new_compiler->arena, &new_compiler->automaton);
275
276
2
  if (result == ERROR_SUCCESS)
277
2
  {
278
2
    *compiler = new_compiler;
279
2
  }
280
0
  else  // if error, do cleanup
281
0
  {
282
0
    yr_compiler_destroy(new_compiler);
283
0
  }
284
285
2
  return result;
286
2
}
287
288
YR_API void yr_compiler_destroy(YR_COMPILER* compiler)
289
2
{
290
2
  if (compiler->arena != NULL)
291
2
    yr_arena_release(compiler->arena);
292
293
2
  if (compiler->automaton != NULL)
294
2
    yr_ac_automaton_destroy(compiler->automaton);
295
296
2
  if (compiler->rules_table != NULL)
297
2
    yr_hash_table_destroy(compiler->rules_table, NULL);
298
299
2
  if (compiler->strings_table != NULL)
300
2
    yr_hash_table_destroy(compiler->strings_table, NULL);
301
302
2
  if (compiler->wildcard_identifiers_table != NULL)
303
2
    yr_hash_table_destroy(compiler->wildcard_identifiers_table, NULL);
304
305
2
  if (compiler->sz_table != NULL)
306
2
    yr_hash_table_destroy(compiler->sz_table, NULL);
307
308
2
  if (compiler->objects_table != NULL)
309
2
    yr_hash_table_destroy(
310
2
        compiler->objects_table,
311
2
        (YR_HASH_TABLE_FREE_VALUE_FUNC) yr_object_destroy);
312
313
2
  if (compiler->atoms_config.free_quality_table)
314
0
    yr_free(compiler->atoms_config.quality_table);
315
316
2
  for (int i = 0; i < compiler->file_name_stack_ptr; i++)
317
0
    yr_free(compiler->file_name_stack[i]);
318
319
2
  YR_FIXUP* fixup = compiler->fixup_stack_head;
320
321
2
  while (fixup != NULL)
322
0
  {
323
0
    YR_FIXUP* next_fixup = fixup->next;
324
0
    yr_free(fixup);
325
0
    fixup = next_fixup;
326
0
  }
327
328
2
  yr_free(compiler);
329
2
}
330
331
YR_API void yr_compiler_set_callback(
332
    YR_COMPILER* compiler,
333
    YR_COMPILER_CALLBACK_FUNC callback,
334
    void* user_data)
335
0
{
336
0
  compiler->callback = callback;
337
0
  compiler->user_data = user_data;
338
0
}
339
340
YR_API void yr_compiler_set_include_callback(
341
    YR_COMPILER* compiler,
342
    YR_COMPILER_INCLUDE_CALLBACK_FUNC include_callback,
343
    YR_COMPILER_INCLUDE_FREE_FUNC include_free,
344
    void* user_data)
345
0
{
346
0
  compiler->include_callback = include_callback;
347
0
  compiler->include_free = include_free;
348
0
  compiler->incl_clbk_user_data = user_data;
349
0
}
350
351
YR_API void yr_compiler_set_re_ast_callback(
352
    YR_COMPILER* compiler,
353
    YR_COMPILER_RE_AST_CALLBACK_FUNC re_ast_callback,
354
    void* user_data)
355
0
{
356
0
  compiler->re_ast_callback = re_ast_callback;
357
0
  compiler->re_ast_clbk_user_data = user_data;
358
0
}
359
360
////////////////////////////////////////////////////////////////////////////////
361
// This function allows to specify an atom quality table to be used by the
362
// compiler for choosing the best atoms from regular expressions and strings.
363
// When a quality table is set, the compiler uses yr_atoms_table_quality
364
// instead of yr_atoms_heuristic_quality for computing atom quality. The table
365
// has an arbitrary number of entries, each composed of YR_MAX_ATOM_LENGTH + 1
366
// bytes. The first YR_MAX_ATOM_LENGTH bytes from each entry are the atom's
367
// ones, and the remaining byte is a value in the range 0-255 determining the
368
// atom's quality. Entries must be lexicographically sorted by atom in ascending
369
// order.
370
//
371
//  [ atom (YR_MAX_ATOM_LENGTH bytes) ] [ quality (1 byte) ]
372
//
373
//  [ 00 00 .. 00 00 ] [ 00 ]
374
//  [ 00 00 .. 00 01 ] [ 45 ]
375
//  [ 00 00 .. 00 02 ] [ 13 ]
376
//  ...
377
//  [ FF FF .. FF FF ] [ 03 ]
378
//
379
// The "table" argument must point to a buffer containing the quality in
380
// the format explained above, and "entries" must contain the number of entries
381
// in the table. The table can not be freed while the compiler is in use, the
382
// caller is responsible for freeing the table.
383
//
384
// The "warning_threshold" argument must be a number between 0 and 255, if some
385
// atom chosen for a string have a quality below the specified threshold a
386
// warning like "<string> is slowing down scanning" is shown.
387
//
388
YR_API void yr_compiler_set_atom_quality_table(
389
    YR_COMPILER* compiler,
390
    const void* table,
391
    int entries,
392
    unsigned char warning_threshold)
393
0
{
394
0
  compiler->atoms_config.free_quality_table = false;
395
0
  compiler->atoms_config.quality_warning_threshold = warning_threshold;
396
0
  compiler->atoms_config.get_atom_quality = yr_atoms_table_quality;
397
0
  compiler->atoms_config.quality_table_entries = entries;
398
0
  compiler->atoms_config.quality_table = (YR_ATOM_QUALITY_TABLE_ENTRY*) table;
399
0
}
400
401
////////////////////////////////////////////////////////////////////////////////
402
// Load an atom quality table from a file. The file's content must have the
403
// format explained in the description for yr_compiler_set_atom_quality_table.
404
//
405
YR_API int yr_compiler_load_atom_quality_table(
406
    YR_COMPILER* compiler,
407
    const char* filename,
408
    unsigned char warning_threshold)
409
0
{
410
0
  long file_size;
411
0
  int entries;
412
0
  void* table;
413
414
0
  FILE* fh = fopen(filename, "rb");
415
416
0
  if (fh == NULL)
417
0
    return ERROR_COULD_NOT_OPEN_FILE;
418
419
0
  fseek(fh, 0L, SEEK_END);
420
0
  file_size = ftell(fh);
421
0
  fseek(fh, 0L, SEEK_SET);
422
423
0
  if (file_size == -1L)
424
0
  {
425
0
    fclose(fh);
426
0
    return ERROR_COULD_NOT_READ_FILE;
427
0
  }
428
429
0
  table = yr_malloc(file_size);
430
431
0
  if (table == NULL)
432
0
  {
433
0
    fclose(fh);
434
0
    return ERROR_INSUFFICIENT_MEMORY;
435
0
  }
436
437
0
  entries = (int) file_size / sizeof(YR_ATOM_QUALITY_TABLE_ENTRY);
438
439
0
  if (fread(table, sizeof(YR_ATOM_QUALITY_TABLE_ENTRY), entries, fh) != entries)
440
0
  {
441
0
    fclose(fh);
442
0
    yr_free(table);
443
0
    return ERROR_COULD_NOT_READ_FILE;
444
0
  }
445
446
0
  fclose(fh);
447
448
0
  yr_compiler_set_atom_quality_table(
449
0
      compiler, table, entries, warning_threshold);
450
451
0
  compiler->atoms_config.free_quality_table = true;
452
453
0
  return ERROR_SUCCESS;
454
0
}
455
456
int _yr_compiler_push_file_name(YR_COMPILER* compiler, const char* file_name)
457
0
{
458
0
  char* str;
459
0
  int i;
460
461
0
  for (i = 0; i < compiler->file_name_stack_ptr; i++)
462
0
  {
463
0
    if (strcmp(file_name, compiler->file_name_stack[i]) == 0)
464
0
      return ERROR_INCLUDES_CIRCULAR_REFERENCE;
465
0
  }
466
467
0
  if (compiler->file_name_stack_ptr == YR_MAX_INCLUDE_DEPTH)
468
0
    return ERROR_INCLUDE_DEPTH_EXCEEDED;
469
470
0
  str = yr_strdup(file_name);
471
472
0
  if (str == NULL)
473
0
    return ERROR_INSUFFICIENT_MEMORY;
474
475
0
  compiler->file_name_stack[compiler->file_name_stack_ptr] = str;
476
0
  compiler->file_name_stack_ptr++;
477
478
0
  return ERROR_SUCCESS;
479
0
}
480
481
void _yr_compiler_pop_file_name(YR_COMPILER* compiler)
482
0
{
483
0
  if (compiler->file_name_stack_ptr > 0)
484
0
  {
485
0
    compiler->file_name_stack_ptr--;
486
0
    yr_free(compiler->file_name_stack[compiler->file_name_stack_ptr]);
487
0
    compiler->file_name_stack[compiler->file_name_stack_ptr] = NULL;
488
0
  }
489
0
}
490
491
int _yr_compiler_get_var_frame(YR_COMPILER* compiler)
492
0
{
493
0
  int i, result = 0;
494
495
0
  for (i = 0; i < compiler->loop_index; i++)
496
0
  {
497
0
    result += compiler->loop[i].vars_count +
498
0
              compiler->loop[i].vars_internal_count;
499
0
  }
500
501
0
  return result;
502
0
}
503
504
YR_API char* yr_compiler_get_current_file_name(YR_COMPILER* compiler)
505
0
{
506
0
  if (compiler->file_name_stack_ptr > 0)
507
0
  {
508
0
    return compiler->file_name_stack[compiler->file_name_stack_ptr - 1];
509
0
  }
510
0
  else
511
0
  {
512
0
    return NULL;
513
0
  }
514
0
}
515
516
static int _yr_compiler_set_namespace(
517
    YR_COMPILER* compiler,
518
    const char* namespace_)
519
2
{
520
2
  YR_NAMESPACE* ns = (YR_NAMESPACE*) yr_arena_get_ptr(
521
2
      compiler->arena, YR_NAMESPACES_TABLE, 0);
522
523
2
  bool found = false;
524
525
2
  for (int i = 0; i < compiler->num_namespaces; i++, ns++)
526
0
  {
527
0
    if (strcmp(ns->name, namespace_) == 0)
528
0
    {
529
0
      found = true;
530
0
      compiler->current_namespace_idx = i;
531
0
      break;
532
0
    }
533
0
  }
534
535
2
  if (!found)
536
2
  {
537
2
    YR_ARENA_REF ref;
538
539
2
    FAIL_ON_ERROR(yr_arena_allocate_struct(
540
2
        compiler->arena,
541
2
        YR_NAMESPACES_TABLE,
542
2
        sizeof(YR_NAMESPACE),
543
2
        &ref,
544
2
        offsetof(YR_NAMESPACE, name),
545
2
        EOL));
546
547
2
    ns = (YR_NAMESPACE*) yr_arena_ref_to_ptr(compiler->arena, &ref);
548
549
2
    FAIL_ON_ERROR(_yr_compiler_store_string(compiler, namespace_, &ref));
550
551
2
    ns->name = (const char*) yr_arena_ref_to_ptr(compiler->arena, &ref);
552
2
    ns->idx = compiler->num_namespaces;
553
554
2
    compiler->current_namespace_idx = compiler->num_namespaces;
555
2
    compiler->num_namespaces++;
556
2
  }
557
558
2
  return ERROR_SUCCESS;
559
2
}
560
561
YR_API int yr_compiler_add_file(
562
    YR_COMPILER* compiler,
563
    FILE* rules_file,
564
    const char* namespace_,
565
    const char* file_name)
566
0
{
567
0
  int result;
568
569
  // Don't allow yr_compiler_add_file() after
570
  // yr_compiler_get_rules() has been called.
571
572
0
  assert(compiler->rules == NULL);
573
574
  // Don't allow calls to yr_compiler_add_file() if a previous call to
575
  // yr_compiler_add_XXXX failed.
576
577
0
  assert(compiler->errors == 0);
578
579
0
  if (namespace_ != NULL)
580
0
    compiler->last_error = _yr_compiler_set_namespace(compiler, namespace_);
581
0
  else
582
0
    compiler->last_error = _yr_compiler_set_namespace(compiler, "default");
583
584
0
  if (compiler->last_error == ERROR_SUCCESS && file_name != NULL)
585
0
    compiler->last_error = _yr_compiler_push_file_name(compiler, file_name);
586
587
0
  if (compiler->last_error != ERROR_SUCCESS)
588
0
    return ++compiler->errors;
589
590
0
  result = yr_lex_parse_rules_file(rules_file, compiler);
591
592
0
  if (file_name != NULL)
593
0
    _yr_compiler_pop_file_name(compiler);
594
595
0
  return result;
596
0
}
597
598
YR_API int yr_compiler_add_fd(
599
    YR_COMPILER* compiler,
600
    YR_FILE_DESCRIPTOR rules_fd,
601
    const char* namespace_,
602
    const char* file_name)
603
0
{
604
0
  int result;
605
606
  // Don't allow yr_compiler_add_fd() after
607
  // yr_compiler_get_rules() has been called.
608
0
  assert(compiler->rules == NULL);
609
610
  // Don't allow calls to yr_compiler_add_fd() if a previous call to
611
  // yr_compiler_add_XXXX failed.
612
0
  assert(compiler->errors == 0);
613
614
0
  if (namespace_ != NULL)
615
0
    compiler->last_error = _yr_compiler_set_namespace(compiler, namespace_);
616
0
  else
617
0
    compiler->last_error = _yr_compiler_set_namespace(compiler, "default");
618
619
0
  if (compiler->last_error == ERROR_SUCCESS && file_name != NULL)
620
0
    compiler->last_error = _yr_compiler_push_file_name(compiler, file_name);
621
622
0
  if (compiler->last_error != ERROR_SUCCESS)
623
0
    return ++compiler->errors;
624
625
0
  result = yr_lex_parse_rules_fd(rules_fd, compiler);
626
627
0
  if (file_name != NULL)
628
0
    _yr_compiler_pop_file_name(compiler);
629
630
0
  return result;
631
0
}
632
633
YR_API int yr_compiler_add_bytes(
634
    YR_COMPILER* compiler,
635
    const void* rules_data,
636
    size_t rules_size,
637
    const char* namespace_)
638
0
{
639
  // Don't allow calls to yr_compiler_add_bytes() after
640
  // yr_compiler_get_rules() has been called.
641
0
  assert(compiler->rules == NULL);
642
643
  // Don't allow calls to yr_compiler_add_bytes() if a previous call to
644
  // yr_compiler_add_XXXX failed.
645
0
  assert(compiler->errors == 0);
646
647
0
  if (namespace_ != NULL)
648
0
    compiler->last_error = _yr_compiler_set_namespace(compiler, namespace_);
649
0
  else
650
0
    compiler->last_error = _yr_compiler_set_namespace(compiler, "default");
651
652
0
  if (compiler->last_error != ERROR_SUCCESS)
653
0
    return ++compiler->errors;
654
655
0
  return yr_lex_parse_rules_bytes(rules_data, rules_size, compiler);
656
0
}
657
658
YR_API int yr_compiler_add_string(
659
    YR_COMPILER* compiler,
660
    const char* rules_string,
661
    const char* namespace_)
662
2
{
663
  // Don't allow calls to yr_compiler_add_string() after
664
  // yr_compiler_get_rules() has been called.
665
2
  assert(compiler->rules == NULL);
666
667
  // Don't allow calls to yr_compiler_add_string() if a previous call to
668
  // yr_compiler_add_XXXX failed.
669
2
  assert(compiler->errors == 0);
670
671
2
  if (namespace_ != NULL)
672
0
    compiler->last_error = _yr_compiler_set_namespace(compiler, namespace_);
673
2
  else
674
2
    compiler->last_error = _yr_compiler_set_namespace(compiler, "default");
675
676
2
  if (compiler->last_error != ERROR_SUCCESS)
677
0
    return ++compiler->errors;
678
679
2
  return yr_lex_parse_rules_string(rules_string, compiler);
680
2
}
681
682
static int _yr_compiler_compile_rules(YR_COMPILER* compiler)
683
2
{
684
2
  YR_RULE null_rule;
685
2
  YR_EXTERNAL_VARIABLE null_external;
686
687
2
  uint8_t halt = OP_HALT;
688
689
  // Write halt instruction at the end of code.
690
2
  FAIL_ON_ERROR(yr_arena_write_data(
691
2
      compiler->arena, YR_CODE_SECTION, &halt, sizeof(uint8_t), NULL));
692
693
  // Write a null rule indicating the end.
694
2
  memset(&null_rule, 0xFA, sizeof(YR_RULE));
695
2
  null_rule.flags = RULE_FLAGS_NULL;
696
697
2
  FAIL_ON_ERROR(yr_arena_write_data(
698
2
      compiler->arena, YR_RULES_TABLE, &null_rule, sizeof(YR_RULE), NULL));
699
700
  // Write a null external indicating the end.
701
2
  memset(&null_external, 0xFA, sizeof(YR_EXTERNAL_VARIABLE));
702
2
  null_external.type = EXTERNAL_VARIABLE_TYPE_NULL;
703
704
2
  FAIL_ON_ERROR(yr_arena_write_data(
705
2
      compiler->arena,
706
2
      YR_EXTERNAL_VARIABLES_TABLE,
707
2
      &null_external,
708
2
      sizeof(YR_EXTERNAL_VARIABLE),
709
2
      NULL));
710
711
  // Write Aho-Corasick automaton to arena.
712
2
  FAIL_ON_ERROR(yr_ac_compile(compiler->automaton, compiler->arena));
713
714
2
  YR_ARENA_REF ref;
715
716
2
  FAIL_ON_ERROR(yr_arena_allocate_struct(
717
2
      compiler->arena, YR_SUMMARY_SECTION, sizeof(YR_SUMMARY), &ref, EOL));
718
719
2
  YR_SUMMARY* summary = (YR_SUMMARY*) yr_arena_ref_to_ptr(
720
2
      compiler->arena, &ref);
721
722
2
  summary->num_namespaces = compiler->num_namespaces;
723
2
  summary->num_rules = compiler->next_rule_idx;
724
2
  summary->num_strings = compiler->current_string_idx;
725
726
2
  return yr_rules_from_arena(compiler->arena, &compiler->rules);
727
2
}
728
729
YR_API int yr_compiler_get_rules(YR_COMPILER* compiler, YR_RULES** rules)
730
2
{
731
  // Don't allow calls to yr_compiler_get_rules() if a previous call to
732
  // yr_compiler_add_XXXX failed.
733
2
  assert(compiler->errors == 0);
734
735
2
  *rules = NULL;
736
737
2
  if (compiler->rules == NULL)
738
2
    FAIL_ON_ERROR(_yr_compiler_compile_rules(compiler));
739
740
2
  *rules = compiler->rules;
741
742
2
  return ERROR_SUCCESS;
743
2
}
744
745
static int _yr_compiler_define_variable(
746
    YR_COMPILER* compiler,
747
    YR_EXTERNAL_VARIABLE* external)
748
0
{
749
0
  YR_EXTERNAL_VARIABLE* ext;
750
0
  YR_OBJECT* object;
751
752
0
  if (external->identifier == NULL)
753
0
    return ERROR_INVALID_ARGUMENT;
754
755
0
  object = (YR_OBJECT*) yr_hash_table_lookup(
756
0
      compiler->objects_table, external->identifier, NULL);
757
758
0
  if (object != NULL)
759
0
    return ERROR_DUPLICATED_EXTERNAL_VARIABLE;
760
761
0
  YR_ARENA_REF ext_ref;
762
0
  YR_ARENA_REF ref;
763
764
0
  FAIL_ON_ERROR(yr_arena_allocate_struct(
765
0
      compiler->arena,
766
0
      YR_EXTERNAL_VARIABLES_TABLE,
767
0
      sizeof(YR_EXTERNAL_VARIABLE),
768
0
      &ext_ref,
769
0
      offsetof(YR_EXTERNAL_VARIABLE, identifier),
770
0
      EOL));
771
772
0
  ext = (YR_EXTERNAL_VARIABLE*) yr_arena_ref_to_ptr(compiler->arena, &ext_ref);
773
774
0
  FAIL_ON_ERROR(
775
0
      _yr_compiler_store_string(compiler, external->identifier, &ref));
776
777
0
  ext->identifier = (const char*) yr_arena_ref_to_ptr(compiler->arena, &ref);
778
779
0
  ext->type = external->type;
780
0
  ext->value = external->value;
781
782
0
  if (external->type == EXTERNAL_VARIABLE_TYPE_STRING)
783
0
  {
784
0
    if (external->value.s == NULL)
785
0
      return ERROR_INVALID_ARGUMENT;
786
787
0
    FAIL_ON_ERROR(_yr_compiler_store_string(compiler, external->value.s, &ref));
788
789
0
    FAIL_ON_ERROR(yr_arena_make_ptr_relocatable(
790
0
        compiler->arena,
791
0
        YR_EXTERNAL_VARIABLES_TABLE,
792
0
        ext_ref.offset + offsetof(YR_EXTERNAL_VARIABLE, value.s),
793
0
        EOL));
794
795
0
    ext->value.s = (char*) yr_arena_ref_to_ptr(compiler->arena, &ref);
796
0
  }
797
798
0
  FAIL_ON_ERROR(yr_object_from_external_variable(external, &object));
799
800
0
  FAIL_ON_ERROR_WITH_CLEANUP(
801
0
      yr_hash_table_add(
802
0
          compiler->objects_table, external->identifier, NULL, (void*) object),
803
0
      yr_object_destroy(object));
804
805
0
  return ERROR_SUCCESS;
806
0
}
807
808
YR_API int yr_compiler_define_integer_variable(
809
    YR_COMPILER* compiler,
810
    const char* identifier,
811
    int64_t value)
812
0
{
813
0
  YR_EXTERNAL_VARIABLE external;
814
815
0
  external.type = EXTERNAL_VARIABLE_TYPE_INTEGER;
816
0
  external.identifier = identifier;
817
0
  external.value.i = value;
818
819
0
  FAIL_ON_ERROR(_yr_compiler_define_variable(compiler, &external));
820
821
0
  return ERROR_SUCCESS;
822
0
}
823
824
YR_API int yr_compiler_define_boolean_variable(
825
    YR_COMPILER* compiler,
826
    const char* identifier,
827
    int value)
828
0
{
829
0
  YR_EXTERNAL_VARIABLE external;
830
831
0
  external.type = EXTERNAL_VARIABLE_TYPE_BOOLEAN;
832
0
  external.identifier = identifier;
833
0
  external.value.i = value;
834
835
0
  FAIL_ON_ERROR(_yr_compiler_define_variable(compiler, &external));
836
837
0
  return ERROR_SUCCESS;
838
0
}
839
840
YR_API int yr_compiler_define_float_variable(
841
    YR_COMPILER* compiler,
842
    const char* identifier,
843
    double value)
844
0
{
845
0
  YR_EXTERNAL_VARIABLE external;
846
847
0
  external.type = EXTERNAL_VARIABLE_TYPE_FLOAT;
848
0
  external.identifier = identifier;
849
0
  external.value.f = value;
850
851
0
  FAIL_ON_ERROR(_yr_compiler_define_variable(compiler, &external));
852
853
0
  return ERROR_SUCCESS;
854
0
}
855
856
YR_API int yr_compiler_define_string_variable(
857
    YR_COMPILER* compiler,
858
    const char* identifier,
859
    const char* value)
860
0
{
861
0
  YR_EXTERNAL_VARIABLE external;
862
863
0
  external.type = EXTERNAL_VARIABLE_TYPE_STRING;
864
0
  external.identifier = identifier;
865
0
  external.value.s = (char*) value;
866
867
0
  FAIL_ON_ERROR(_yr_compiler_define_variable(compiler, &external));
868
869
0
  return ERROR_SUCCESS;
870
0
}
871
872
YR_API char* yr_compiler_get_error_message(
873
    YR_COMPILER* compiler,
874
    char* buffer,
875
    int buffer_size)
876
0
{
877
0
  uint32_t max_strings_per_rule;
878
879
0
  switch (compiler->last_error)
880
0
  {
881
0
  case ERROR_INSUFFICIENT_MEMORY:
882
0
    snprintf(buffer, buffer_size, "not enough memory");
883
0
    break;
884
0
  case ERROR_DUPLICATED_IDENTIFIER:
885
0
    snprintf(
886
0
        buffer,
887
0
        buffer_size,
888
0
        "duplicated identifier \"%s\"",
889
0
        compiler->last_error_extra_info);
890
0
    break;
891
0
  case ERROR_DUPLICATED_STRING_IDENTIFIER:
892
0
    snprintf(
893
0
        buffer,
894
0
        buffer_size,
895
0
        "duplicated string identifier \"%s\"",
896
0
        compiler->last_error_extra_info);
897
0
    break;
898
0
  case ERROR_DUPLICATED_TAG_IDENTIFIER:
899
0
    snprintf(
900
0
        buffer,
901
0
        buffer_size,
902
0
        "duplicated tag identifier \"%s\"",
903
0
        compiler->last_error_extra_info);
904
0
    break;
905
0
  case ERROR_DUPLICATED_META_IDENTIFIER:
906
0
    snprintf(
907
0
        buffer,
908
0
        buffer_size,
909
0
        "duplicated metadata identifier \"%s\"",
910
0
        compiler->last_error_extra_info);
911
0
    break;
912
0
  case ERROR_DUPLICATED_LOOP_IDENTIFIER:
913
0
    snprintf(
914
0
        buffer,
915
0
        buffer_size,
916
0
        "duplicated loop identifier \"%s\"",
917
0
        compiler->last_error_extra_info);
918
0
    break;
919
0
  case ERROR_UNDEFINED_STRING:
920
0
    snprintf(
921
0
        buffer,
922
0
        buffer_size,
923
0
        "undefined string \"%s\"",
924
0
        compiler->last_error_extra_info);
925
0
    break;
926
0
  case ERROR_UNDEFINED_IDENTIFIER:
927
0
    snprintf(
928
0
        buffer,
929
0
        buffer_size,
930
0
        "undefined identifier \"%s\"",
931
0
        compiler->last_error_extra_info);
932
0
    break;
933
0
  case ERROR_UNREFERENCED_STRING:
934
0
    snprintf(
935
0
        buffer,
936
0
        buffer_size,
937
0
        "unreferenced string \"%s\"",
938
0
        compiler->last_error_extra_info);
939
0
    break;
940
0
  case ERROR_EMPTY_STRING:
941
0
    snprintf(
942
0
        buffer,
943
0
        buffer_size,
944
0
        "empty string \"%s\"",
945
0
        compiler->last_error_extra_info);
946
0
    break;
947
0
  case ERROR_NOT_A_STRUCTURE:
948
0
    snprintf(
949
0
        buffer,
950
0
        buffer_size,
951
0
        "\"%s\" is not a structure",
952
0
        compiler->last_error_extra_info);
953
0
    break;
954
0
  case ERROR_NOT_INDEXABLE:
955
0
    snprintf(
956
0
        buffer,
957
0
        buffer_size,
958
0
        "\"%s\" is not an array or dictionary",
959
0
        compiler->last_error_extra_info);
960
0
    break;
961
0
  case ERROR_NOT_A_FUNCTION:
962
0
    snprintf(
963
0
        buffer,
964
0
        buffer_size,
965
0
        "\"%s\" is not a function",
966
0
        compiler->last_error_extra_info);
967
0
    break;
968
0
  case ERROR_INVALID_FIELD_NAME:
969
0
    snprintf(
970
0
        buffer,
971
0
        buffer_size,
972
0
        "invalid field name \"%s\"",
973
0
        compiler->last_error_extra_info);
974
0
    break;
975
0
  case ERROR_MISPLACED_ANONYMOUS_STRING:
976
0
    snprintf(buffer, buffer_size, "wrong use of anonymous string");
977
0
    break;
978
0
  case ERROR_INCLUDES_CIRCULAR_REFERENCE:
979
0
    snprintf(buffer, buffer_size, "include circular reference");
980
0
    break;
981
0
  case ERROR_INCLUDE_DEPTH_EXCEEDED:
982
0
    snprintf(buffer, buffer_size, "too many levels of included rules");
983
0
    break;
984
0
  case ERROR_LOOP_NESTING_LIMIT_EXCEEDED:
985
0
    snprintf(buffer, buffer_size, "loop nesting limit exceeded");
986
0
    break;
987
0
  case ERROR_NESTED_FOR_OF_LOOP:
988
0
    snprintf(
989
0
        buffer,
990
0
        buffer_size,
991
0
        "'for <quantifier> of <string set>' loops can't be nested");
992
0
    break;
993
0
  case ERROR_UNKNOWN_MODULE:
994
0
    snprintf(
995
0
        buffer,
996
0
        buffer_size,
997
0
        "unknown module \"%s\"",
998
0
        compiler->last_error_extra_info);
999
0
    break;
1000
0
  case ERROR_INVALID_MODULE_NAME:
1001
0
    snprintf(
1002
0
        buffer,
1003
0
        buffer_size,
1004
0
        "invalid module name \"%s\"",
1005
0
        compiler->last_error_extra_info);
1006
0
    break;
1007
0
  case ERROR_DUPLICATED_STRUCTURE_MEMBER:
1008
0
    snprintf(buffer, buffer_size, "duplicated structure member");
1009
0
    break;
1010
0
  case ERROR_WRONG_ARGUMENTS:
1011
0
    snprintf(
1012
0
        buffer,
1013
0
        buffer_size,
1014
0
        "wrong arguments for function \"%s\"",
1015
0
        compiler->last_error_extra_info);
1016
0
    break;
1017
0
  case ERROR_WRONG_RETURN_TYPE:
1018
0
    snprintf(buffer, buffer_size, "wrong return type for overloaded function");
1019
0
    break;
1020
0
  case ERROR_INVALID_HEX_STRING:
1021
0
  case ERROR_INVALID_REGULAR_EXPRESSION:
1022
0
  case ERROR_SYNTAX_ERROR:
1023
0
  case ERROR_WRONG_TYPE:
1024
0
  case ERROR_INVALID_MODIFIER:
1025
0
  case ERROR_INVALID_PERCENTAGE:
1026
0
    snprintf(buffer, buffer_size, "%s", compiler->last_error_extra_info);
1027
0
    break;
1028
0
  case ERROR_INTERNAL_FATAL_ERROR:
1029
0
    snprintf(buffer, buffer_size, "internal fatal error");
1030
0
    break;
1031
0
  case ERROR_DIVISION_BY_ZERO:
1032
0
    snprintf(buffer, buffer_size, "division by zero");
1033
0
    break;
1034
0
  case ERROR_REGULAR_EXPRESSION_TOO_LARGE:
1035
0
    snprintf(buffer, buffer_size, "regular expression is too large");
1036
0
    break;
1037
0
  case ERROR_REGULAR_EXPRESSION_TOO_COMPLEX:
1038
0
    snprintf(buffer, buffer_size, "regular expression is too complex");
1039
0
    break;
1040
0
  case ERROR_TOO_MANY_STRINGS:
1041
0
    yr_get_configuration_uint32(
1042
0
        YR_CONFIG_MAX_STRINGS_PER_RULE, &max_strings_per_rule);
1043
0
    snprintf(
1044
0
        buffer,
1045
0
        buffer_size,
1046
0
        "too many strings in rule \"%s\" (limit: %d)",
1047
0
        compiler->last_error_extra_info,
1048
0
        max_strings_per_rule);
1049
0
    break;
1050
0
  case ERROR_INTEGER_OVERFLOW:
1051
0
    snprintf(
1052
0
        buffer,
1053
0
        buffer_size,
1054
0
        "integer overflow in \"%s\"",
1055
0
        compiler->last_error_extra_info);
1056
0
    break;
1057
0
  case ERROR_COULD_NOT_READ_FILE:
1058
0
    snprintf(buffer, buffer_size, "could not read file");
1059
0
    break;
1060
0
  case ERROR_DUPLICATED_MODIFIER:
1061
0
    snprintf(buffer, buffer_size, "duplicated modifier");
1062
0
    break;
1063
0
  case ERROR_IDENTIFIER_MATCHES_WILDCARD:
1064
0
    snprintf(
1065
0
        buffer,
1066
0
        buffer_size,
1067
0
        "rule identifier \"%s\" matches previously used wildcard rule set",
1068
0
        compiler->last_error_extra_info);
1069
0
    break;
1070
0
  case ERROR_INVALID_VALUE:
1071
0
    snprintf(
1072
0
        buffer,
1073
0
        buffer_size,
1074
0
        "invalid value in condition: \"%s\"",
1075
0
        compiler->last_error_extra_info);
1076
0
    break;
1077
0
  }
1078
1079
0
  return buffer;
1080
0
}