Coverage Report

Created: 2023-03-26 07:37

/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
4
{
178
  // Check if the data is already in YR_SZ_POOL by using a hash table.
179
4
  uint32_t offset = yr_hash_table_lookup_uint32_raw_key(
180
4
      compiler->sz_table, data, data_length, NULL);
181
182
4
  if (offset == UINT32_MAX)
183
4
  {
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
4
    FAIL_ON_ERROR(yr_arena_write_data(
188
4
        compiler->arena, YR_SZ_POOL, data, data_length, ref));
189
190
4
    FAIL_ON_ERROR(yr_hash_table_add_uint32_raw_key(
191
4
        compiler->sz_table, data, data_length, NULL, ref->offset));
192
4
  }
193
0
  else
194
0
  {
195
0
    ref->buffer_id = YR_SZ_POOL;
196
0
    ref->offset = offset;
197
0
  }
198
199
4
  return ERROR_SUCCESS;
200
4
}
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
4
{
210
4
  return _yr_compiler_store_data(
211
4
      compiler,
212
4
      (void*) string,
213
4
      strlen(string) + 1,  // include the null terminator
214
4
      ref);
215
4
}
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->current_line = 0;
244
2
  new_compiler->file_name_stack_ptr = 0;
245
2
  new_compiler->fixup_stack_head = NULL;
246
2
  new_compiler->loop_index = -1;
247
2
  new_compiler->loop_for_of_var_index = -1;
248
249
2
  new_compiler->atoms_config.get_atom_quality = yr_atoms_heuristic_quality;
250
2
  new_compiler->atoms_config.quality_warning_threshold =
251
2
      YR_ATOM_QUALITY_WARNING_THRESHOLD;
252
253
2
  result = yr_hash_table_create(5000, &new_compiler->rules_table);
254
255
2
  if (result == ERROR_SUCCESS)
256
2
    result = yr_hash_table_create(1000, &new_compiler->objects_table);
257
258
2
  if (result == ERROR_SUCCESS)
259
2
    result = yr_hash_table_create(10000, &new_compiler->strings_table);
260
261
2
  if (result == ERROR_SUCCESS)
262
2
    result = yr_hash_table_create(
263
2
        1000, &new_compiler->wildcard_identifiers_table);
264
265
2
  if (result == ERROR_SUCCESS)
266
2
    result = yr_hash_table_create(10000, &new_compiler->sz_table);
267
268
2
  if (result == ERROR_SUCCESS)
269
2
    result = yr_arena_create(YR_NUM_SECTIONS, 1048576, &new_compiler->arena);
270
271
2
  if (result == ERROR_SUCCESS)
272
2
    result = yr_ac_automaton_create(
273
2
        new_compiler->arena, &new_compiler->automaton);
274
275
2
  if (result == ERROR_SUCCESS)
276
2
  {
277
2
    *compiler = new_compiler;
278
2
  }
279
0
  else  // if error, do cleanup
280
0
  {
281
0
    yr_compiler_destroy(new_compiler);
282
0
  }
283
284
2
  return result;
285
2
}
286
287
YR_API void yr_compiler_destroy(YR_COMPILER* compiler)
288
2
{
289
2
  if (compiler->arena != NULL)
290
2
    yr_arena_release(compiler->arena);
291
292
2
  if (compiler->automaton != NULL)
293
2
    yr_ac_automaton_destroy(compiler->automaton);
294
295
2
  if (compiler->rules_table != NULL)
296
2
    yr_hash_table_destroy(compiler->rules_table, NULL);
297
298
2
  if (compiler->strings_table != NULL)
299
2
    yr_hash_table_destroy(compiler->strings_table, NULL);
300
301
2
  if (compiler->wildcard_identifiers_table != NULL)
302
2
    yr_hash_table_destroy(compiler->wildcard_identifiers_table, NULL);
303
304
2
  if (compiler->sz_table != NULL)
305
2
    yr_hash_table_destroy(compiler->sz_table, NULL);
306
307
2
  if (compiler->objects_table != NULL)
308
2
    yr_hash_table_destroy(
309
2
        compiler->objects_table,
310
2
        (YR_HASH_TABLE_FREE_VALUE_FUNC) yr_object_destroy);
311
312
2
  if (compiler->atoms_config.free_quality_table)
313
0
    yr_free(compiler->atoms_config.quality_table);
314
315
2
  for (int i = 0; i < compiler->file_name_stack_ptr; i++)
316
0
    yr_free(compiler->file_name_stack[i]);
317
318
2
  YR_FIXUP* fixup = compiler->fixup_stack_head;
319
320
2
  while (fixup != NULL)
321
0
  {
322
0
    YR_FIXUP* next_fixup = fixup->next;
323
0
    yr_free(fixup);
324
0
    fixup = next_fixup;
325
0
  }
326
327
2
  yr_free(compiler);
328
2
}
329
330
YR_API void yr_compiler_set_callback(
331
    YR_COMPILER* compiler,
332
    YR_COMPILER_CALLBACK_FUNC callback,
333
    void* user_data)
334
0
{
335
0
  compiler->callback = callback;
336
0
  compiler->user_data = user_data;
337
0
}
338
339
YR_API void yr_compiler_set_include_callback(
340
    YR_COMPILER* compiler,
341
    YR_COMPILER_INCLUDE_CALLBACK_FUNC include_callback,
342
    YR_COMPILER_INCLUDE_FREE_FUNC include_free,
343
    void* user_data)
344
0
{
345
0
  compiler->include_callback = include_callback;
346
0
  compiler->include_free = include_free;
347
0
  compiler->incl_clbk_user_data = user_data;
348
0
}
349
350
YR_API void yr_compiler_set_re_ast_callback(
351
    YR_COMPILER* compiler,
352
    YR_COMPILER_RE_AST_CALLBACK_FUNC re_ast_callback,
353
    void* user_data)
354
0
{
355
0
  compiler->re_ast_callback = re_ast_callback;
356
0
  compiler->re_ast_clbk_user_data = user_data;
357
0
}
358
359
////////////////////////////////////////////////////////////////////////////////
360
// This function allows to specify an atom quality table to be used by the
361
// compiler for choosing the best atoms from regular expressions and strings.
362
// When a quality table is set, the compiler uses yr_atoms_table_quality
363
// instead of yr_atoms_heuristic_quality for computing atom quality. The table
364
// has an arbitrary number of entries, each composed of YR_MAX_ATOM_LENGTH + 1
365
// bytes. The first YR_MAX_ATOM_LENGTH bytes from each entry are the atom's
366
// ones, and the remaining byte is a value in the range 0-255 determining the
367
// atom's quality. Entries must be lexicographically sorted by atom in ascending
368
// order.
369
//
370
//  [ atom (YR_MAX_ATOM_LENGTH bytes) ] [ quality (1 byte) ]
371
//
372
//  [ 00 00 .. 00 00 ] [ 00 ]
373
//  [ 00 00 .. 00 01 ] [ 45 ]
374
//  [ 00 00 .. 00 02 ] [ 13 ]
375
//  ...
376
//  [ FF FF .. FF FF ] [ 03 ]
377
//
378
// The "table" argument must point to a buffer containing the quality in
379
// the format explained above, and "entries" must contain the number of entries
380
// in the table. The table can not be freed while the compiler is in use, the
381
// caller is responsible for freeing the table.
382
//
383
// The "warning_threshold" argument must be a number between 0 and 255, if some
384
// atom chosen for a string have a quality below the specified threshold a
385
// warning like "<string> is slowing down scanning" is shown.
386
//
387
YR_API void yr_compiler_set_atom_quality_table(
388
    YR_COMPILER* compiler,
389
    const void* table,
390
    int entries,
391
    unsigned char warning_threshold)
392
0
{
393
0
  compiler->atoms_config.free_quality_table = false;
394
0
  compiler->atoms_config.quality_warning_threshold = warning_threshold;
395
0
  compiler->atoms_config.get_atom_quality = yr_atoms_table_quality;
396
0
  compiler->atoms_config.quality_table_entries = entries;
397
0
  compiler->atoms_config.quality_table = (YR_ATOM_QUALITY_TABLE_ENTRY*) table;
398
0
}
399
400
////////////////////////////////////////////////////////////////////////////////
401
// Load an atom quality table from a file. The file's content must have the
402
// format explained in the description for yr_compiler_set_atom_quality_table.
403
//
404
YR_API int yr_compiler_load_atom_quality_table(
405
    YR_COMPILER* compiler,
406
    const char* filename,
407
    unsigned char warning_threshold)
408
0
{
409
0
  long file_size;
410
0
  int entries;
411
0
  void* table;
412
413
0
  FILE* fh = fopen(filename, "rb");
414
415
0
  if (fh == NULL)
416
0
    return ERROR_COULD_NOT_OPEN_FILE;
417
418
0
  fseek(fh, 0L, SEEK_END);
419
0
  file_size = ftell(fh);
420
0
  fseek(fh, 0L, SEEK_SET);
421
422
0
  if (file_size == -1L)
423
0
  {
424
0
    fclose(fh);
425
0
    return ERROR_COULD_NOT_READ_FILE;
426
0
  }
427
428
0
  table = yr_malloc(file_size);
429
430
0
  if (table == NULL)
431
0
  {
432
0
    fclose(fh);
433
0
    return ERROR_INSUFFICIENT_MEMORY;
434
0
  }
435
436
0
  entries = (int) file_size / sizeof(YR_ATOM_QUALITY_TABLE_ENTRY);
437
438
0
  if (fread(table, sizeof(YR_ATOM_QUALITY_TABLE_ENTRY), entries, fh) != entries)
439
0
  {
440
0
    fclose(fh);
441
0
    yr_free(table);
442
0
    return ERROR_COULD_NOT_READ_FILE;
443
0
  }
444
445
0
  fclose(fh);
446
447
0
  yr_compiler_set_atom_quality_table(
448
0
      compiler, table, entries, warning_threshold);
449
450
0
  compiler->atoms_config.free_quality_table = true;
451
452
0
  return ERROR_SUCCESS;
453
0
}
454
455
int _yr_compiler_push_file_name(YR_COMPILER* compiler, const char* file_name)
456
0
{
457
0
  char* str;
458
0
  int i;
459
460
0
  for (i = 0; i < compiler->file_name_stack_ptr; i++)
461
0
  {
462
0
    if (strcmp(file_name, compiler->file_name_stack[i]) == 0)
463
0
      return ERROR_INCLUDES_CIRCULAR_REFERENCE;
464
0
  }
465
466
0
  if (compiler->file_name_stack_ptr == YR_MAX_INCLUDE_DEPTH)
467
0
    return ERROR_INCLUDE_DEPTH_EXCEEDED;
468
469
0
  str = yr_strdup(file_name);
470
471
0
  if (str == NULL)
472
0
    return ERROR_INSUFFICIENT_MEMORY;
473
474
0
  compiler->file_name_stack[compiler->file_name_stack_ptr] = str;
475
0
  compiler->file_name_stack_ptr++;
476
477
0
  return ERROR_SUCCESS;
478
0
}
479
480
void _yr_compiler_pop_file_name(YR_COMPILER* compiler)
481
0
{
482
0
  if (compiler->file_name_stack_ptr > 0)
483
0
  {
484
0
    compiler->file_name_stack_ptr--;
485
0
    yr_free(compiler->file_name_stack[compiler->file_name_stack_ptr]);
486
0
    compiler->file_name_stack[compiler->file_name_stack_ptr] = NULL;
487
0
  }
488
0
}
489
490
int _yr_compiler_get_var_frame(YR_COMPILER* compiler)
491
0
{
492
0
  int i, result = 0;
493
494
0
  for (i = 0; i < compiler->loop_index; i++)
495
0
  {
496
0
    result += compiler->loop[i].vars_count +
497
0
              compiler->loop[i].vars_internal_count;
498
0
  }
499
500
0
  return result;
501
0
}
502
503
YR_API char* yr_compiler_get_current_file_name(YR_COMPILER* compiler)
504
0
{
505
0
  if (compiler->file_name_stack_ptr > 0)
506
0
  {
507
0
    return compiler->file_name_stack[compiler->file_name_stack_ptr - 1];
508
0
  }
509
0
  else
510
0
  {
511
0
    return NULL;
512
0
  }
513
0
}
514
515
static int _yr_compiler_set_namespace(
516
    YR_COMPILER* compiler,
517
    const char* namespace_)
518
2
{
519
2
  YR_NAMESPACE* ns = (YR_NAMESPACE*) yr_arena_get_ptr(
520
2
      compiler->arena, YR_NAMESPACES_TABLE, 0);
521
522
2
  bool found = false;
523
524
2
  for (int i = 0; i < compiler->num_namespaces; i++, ns++)
525
0
  {
526
0
    if (strcmp(ns->name, namespace_) == 0)
527
0
    {
528
0
      found = true;
529
0
      compiler->current_namespace_idx = i;
530
0
      break;
531
0
    }
532
0
  }
533
534
2
  if (!found)
535
2
  {
536
2
    YR_ARENA_REF ref;
537
538
2
    FAIL_ON_ERROR(yr_arena_allocate_struct(
539
2
        compiler->arena,
540
2
        YR_NAMESPACES_TABLE,
541
2
        sizeof(YR_NAMESPACE),
542
2
        &ref,
543
2
        offsetof(YR_NAMESPACE, name),
544
2
        EOL));
545
546
2
    ns = (YR_NAMESPACE*) yr_arena_ref_to_ptr(compiler->arena, &ref);
547
548
2
    FAIL_ON_ERROR(_yr_compiler_store_string(compiler, namespace_, &ref));
549
550
2
    ns->name = (const char*) yr_arena_ref_to_ptr(compiler->arena, &ref);
551
2
    ns->idx = compiler->num_namespaces;
552
553
2
    compiler->current_namespace_idx = compiler->num_namespaces;
554
2
    compiler->num_namespaces++;
555
2
  }
556
557
2
  return ERROR_SUCCESS;
558
2
}
559
560
YR_API int yr_compiler_add_file(
561
    YR_COMPILER* compiler,
562
    FILE* rules_file,
563
    const char* namespace_,
564
    const char* file_name)
565
0
{
566
0
  int result;
567
568
  // Don't allow yr_compiler_add_file() after
569
  // yr_compiler_get_rules() has been called.
570
571
0
  assert(compiler->rules == NULL);
572
573
  // Don't allow calls to yr_compiler_add_file() if a previous call to
574
  // yr_compiler_add_XXXX failed.
575
576
0
  assert(compiler->errors == 0);
577
578
0
  if (namespace_ != NULL)
579
0
    compiler->last_error = _yr_compiler_set_namespace(compiler, namespace_);
580
0
  else
581
0
    compiler->last_error = _yr_compiler_set_namespace(compiler, "default");
582
583
0
  if (compiler->last_error == ERROR_SUCCESS && file_name != NULL)
584
0
    compiler->last_error = _yr_compiler_push_file_name(compiler, file_name);
585
586
0
  if (compiler->last_error != ERROR_SUCCESS)
587
0
    return ++compiler->errors;
588
589
0
  result = yr_lex_parse_rules_file(rules_file, compiler);
590
591
0
  if (file_name != NULL)
592
0
    _yr_compiler_pop_file_name(compiler);
593
594
0
  return result;
595
0
}
596
597
YR_API int yr_compiler_add_fd(
598
    YR_COMPILER* compiler,
599
    YR_FILE_DESCRIPTOR rules_fd,
600
    const char* namespace_,
601
    const char* file_name)
602
0
{
603
0
  int result;
604
605
  // Don't allow yr_compiler_add_fd() after
606
  // yr_compiler_get_rules() has been called.
607
0
  assert(compiler->rules == NULL);
608
609
  // Don't allow calls to yr_compiler_add_fd() if a previous call to
610
  // yr_compiler_add_XXXX failed.
611
0
  assert(compiler->errors == 0);
612
613
0
  if (namespace_ != NULL)
614
0
    compiler->last_error = _yr_compiler_set_namespace(compiler, namespace_);
615
0
  else
616
0
    compiler->last_error = _yr_compiler_set_namespace(compiler, "default");
617
618
0
  if (compiler->last_error == ERROR_SUCCESS && file_name != NULL)
619
0
    compiler->last_error = _yr_compiler_push_file_name(compiler, file_name);
620
621
0
  if (compiler->last_error != ERROR_SUCCESS)
622
0
    return ++compiler->errors;
623
624
0
  result = yr_lex_parse_rules_fd(rules_fd, compiler);
625
626
0
  if (file_name != NULL)
627
0
    _yr_compiler_pop_file_name(compiler);
628
629
0
  return result;
630
0
}
631
632
YR_API int yr_compiler_add_string(
633
    YR_COMPILER* compiler,
634
    const char* rules_string,
635
    const char* namespace_)
636
2
{
637
  // Don't allow calls to yr_compiler_add_string() after
638
  // yr_compiler_get_rules() has been called.
639
2
  assert(compiler->rules == NULL);
640
641
  // Don't allow calls to yr_compiler_add_string() if a previous call to
642
  // yr_compiler_add_XXXX failed.
643
2
  assert(compiler->errors == 0);
644
645
2
  if (namespace_ != NULL)
646
0
    compiler->last_error = _yr_compiler_set_namespace(compiler, namespace_);
647
2
  else
648
2
    compiler->last_error = _yr_compiler_set_namespace(compiler, "default");
649
650
2
  if (compiler->last_error != ERROR_SUCCESS)
651
0
    return ++compiler->errors;
652
653
2
  return yr_lex_parse_rules_string(rules_string, compiler);
654
2
}
655
656
static int _yr_compiler_compile_rules(YR_COMPILER* compiler)
657
2
{
658
2
  YR_RULE null_rule;
659
2
  YR_EXTERNAL_VARIABLE null_external;
660
661
2
  uint8_t halt = OP_HALT;
662
663
  // Write halt instruction at the end of code.
664
2
  FAIL_ON_ERROR(yr_arena_write_data(
665
2
      compiler->arena, YR_CODE_SECTION, &halt, sizeof(uint8_t), NULL));
666
667
  // Write a null rule indicating the end.
668
2
  memset(&null_rule, 0xFA, sizeof(YR_RULE));
669
2
  null_rule.flags = RULE_FLAGS_NULL;
670
671
2
  FAIL_ON_ERROR(yr_arena_write_data(
672
2
      compiler->arena, YR_RULES_TABLE, &null_rule, sizeof(YR_RULE), NULL));
673
674
  // Write a null external indicating the end.
675
2
  memset(&null_external, 0xFA, sizeof(YR_EXTERNAL_VARIABLE));
676
2
  null_external.type = EXTERNAL_VARIABLE_TYPE_NULL;
677
678
2
  FAIL_ON_ERROR(yr_arena_write_data(
679
2
      compiler->arena,
680
2
      YR_EXTERNAL_VARIABLES_TABLE,
681
2
      &null_external,
682
2
      sizeof(YR_EXTERNAL_VARIABLE),
683
2
      NULL));
684
685
  // Write Aho-Corasick automaton to arena.
686
2
  FAIL_ON_ERROR(yr_ac_compile(compiler->automaton, compiler->arena));
687
688
2
  YR_ARENA_REF ref;
689
690
2
  FAIL_ON_ERROR(yr_arena_allocate_struct(
691
2
      compiler->arena, YR_SUMMARY_SECTION, sizeof(YR_SUMMARY), &ref, EOL));
692
693
2
  YR_SUMMARY* summary = (YR_SUMMARY*) yr_arena_ref_to_ptr(
694
2
      compiler->arena, &ref);
695
696
2
  summary->num_namespaces = compiler->num_namespaces;
697
2
  summary->num_rules = compiler->next_rule_idx;
698
2
  summary->num_strings = compiler->current_string_idx;
699
700
2
  return yr_rules_from_arena(compiler->arena, &compiler->rules);
701
2
}
702
703
YR_API int yr_compiler_get_rules(YR_COMPILER* compiler, YR_RULES** rules)
704
2
{
705
  // Don't allow calls to yr_compiler_get_rules() if a previous call to
706
  // yr_compiler_add_XXXX failed.
707
2
  assert(compiler->errors == 0);
708
709
2
  *rules = NULL;
710
711
2
  if (compiler->rules == NULL)
712
2
    FAIL_ON_ERROR(_yr_compiler_compile_rules(compiler));
713
714
2
  *rules = compiler->rules;
715
716
2
  return ERROR_SUCCESS;
717
2
}
718
719
static int _yr_compiler_define_variable(
720
    YR_COMPILER* compiler,
721
    YR_EXTERNAL_VARIABLE* external)
722
0
{
723
0
  YR_EXTERNAL_VARIABLE* ext;
724
0
  YR_OBJECT* object;
725
726
0
  if (external->identifier == NULL)
727
0
    return ERROR_INVALID_ARGUMENT;
728
729
0
  object = (YR_OBJECT*) yr_hash_table_lookup(
730
0
      compiler->objects_table, external->identifier, NULL);
731
732
0
  if (object != NULL)
733
0
    return ERROR_DUPLICATED_EXTERNAL_VARIABLE;
734
735
0
  YR_ARENA_REF ext_ref;
736
0
  YR_ARENA_REF ref;
737
738
0
  FAIL_ON_ERROR(yr_arena_allocate_struct(
739
0
      compiler->arena,
740
0
      YR_EXTERNAL_VARIABLES_TABLE,
741
0
      sizeof(YR_EXTERNAL_VARIABLE),
742
0
      &ext_ref,
743
0
      offsetof(YR_EXTERNAL_VARIABLE, identifier),
744
0
      EOL));
745
746
0
  ext = (YR_EXTERNAL_VARIABLE*) yr_arena_ref_to_ptr(compiler->arena, &ext_ref);
747
748
0
  FAIL_ON_ERROR(
749
0
      _yr_compiler_store_string(compiler, external->identifier, &ref));
750
751
0
  ext->identifier = (const char*) yr_arena_ref_to_ptr(compiler->arena, &ref);
752
753
0
  ext->type = external->type;
754
0
  ext->value = external->value;
755
756
0
  if (external->type == EXTERNAL_VARIABLE_TYPE_STRING)
757
0
  {
758
0
    if (external->value.s == NULL)
759
0
      return ERROR_INVALID_ARGUMENT;
760
761
0
    FAIL_ON_ERROR(_yr_compiler_store_string(compiler, external->value.s, &ref));
762
763
0
    FAIL_ON_ERROR(yr_arena_make_ptr_relocatable(
764
0
        compiler->arena,
765
0
        YR_EXTERNAL_VARIABLES_TABLE,
766
0
        ext_ref.offset + offsetof(YR_EXTERNAL_VARIABLE, value.s),
767
0
        EOL));
768
769
0
    ext->value.s = (char*) yr_arena_ref_to_ptr(compiler->arena, &ref);
770
0
  }
771
772
0
  FAIL_ON_ERROR(yr_object_from_external_variable(external, &object));
773
774
0
  FAIL_ON_ERROR_WITH_CLEANUP(
775
0
      yr_hash_table_add(
776
0
          compiler->objects_table, external->identifier, NULL, (void*) object),
777
0
      yr_object_destroy(object));
778
779
0
  return ERROR_SUCCESS;
780
0
}
781
782
YR_API int yr_compiler_define_integer_variable(
783
    YR_COMPILER* compiler,
784
    const char* identifier,
785
    int64_t value)
786
0
{
787
0
  YR_EXTERNAL_VARIABLE external;
788
789
0
  external.type = EXTERNAL_VARIABLE_TYPE_INTEGER;
790
0
  external.identifier = identifier;
791
0
  external.value.i = value;
792
793
0
  FAIL_ON_ERROR(_yr_compiler_define_variable(compiler, &external));
794
795
0
  return ERROR_SUCCESS;
796
0
}
797
798
YR_API int yr_compiler_define_boolean_variable(
799
    YR_COMPILER* compiler,
800
    const char* identifier,
801
    int value)
802
0
{
803
0
  YR_EXTERNAL_VARIABLE external;
804
805
0
  external.type = EXTERNAL_VARIABLE_TYPE_BOOLEAN;
806
0
  external.identifier = identifier;
807
0
  external.value.i = value;
808
809
0
  FAIL_ON_ERROR(_yr_compiler_define_variable(compiler, &external));
810
811
0
  return ERROR_SUCCESS;
812
0
}
813
814
YR_API int yr_compiler_define_float_variable(
815
    YR_COMPILER* compiler,
816
    const char* identifier,
817
    double value)
818
0
{
819
0
  YR_EXTERNAL_VARIABLE external;
820
821
0
  external.type = EXTERNAL_VARIABLE_TYPE_FLOAT;
822
0
  external.identifier = identifier;
823
0
  external.value.f = value;
824
825
0
  FAIL_ON_ERROR(_yr_compiler_define_variable(compiler, &external));
826
827
0
  return ERROR_SUCCESS;
828
0
}
829
830
YR_API int yr_compiler_define_string_variable(
831
    YR_COMPILER* compiler,
832
    const char* identifier,
833
    const char* value)
834
0
{
835
0
  YR_EXTERNAL_VARIABLE external;
836
837
0
  external.type = EXTERNAL_VARIABLE_TYPE_STRING;
838
0
  external.identifier = identifier;
839
0
  external.value.s = (char*) value;
840
841
0
  FAIL_ON_ERROR(_yr_compiler_define_variable(compiler, &external));
842
843
0
  return ERROR_SUCCESS;
844
0
}
845
846
YR_API char* yr_compiler_get_error_message(
847
    YR_COMPILER* compiler,
848
    char* buffer,
849
    int buffer_size)
850
0
{
851
0
  uint32_t max_strings_per_rule;
852
853
0
  switch (compiler->last_error)
854
0
  {
855
0
  case ERROR_INSUFFICIENT_MEMORY:
856
0
    snprintf(buffer, buffer_size, "not enough memory");
857
0
    break;
858
0
  case ERROR_DUPLICATED_IDENTIFIER:
859
0
    snprintf(
860
0
        buffer,
861
0
        buffer_size,
862
0
        "duplicated identifier \"%s\"",
863
0
        compiler->last_error_extra_info);
864
0
    break;
865
0
  case ERROR_DUPLICATED_STRING_IDENTIFIER:
866
0
    snprintf(
867
0
        buffer,
868
0
        buffer_size,
869
0
        "duplicated string identifier \"%s\"",
870
0
        compiler->last_error_extra_info);
871
0
    break;
872
0
  case ERROR_DUPLICATED_TAG_IDENTIFIER:
873
0
    snprintf(
874
0
        buffer,
875
0
        buffer_size,
876
0
        "duplicated tag identifier \"%s\"",
877
0
        compiler->last_error_extra_info);
878
0
    break;
879
0
  case ERROR_DUPLICATED_META_IDENTIFIER:
880
0
    snprintf(
881
0
        buffer,
882
0
        buffer_size,
883
0
        "duplicated metadata identifier \"%s\"",
884
0
        compiler->last_error_extra_info);
885
0
    break;
886
0
  case ERROR_DUPLICATED_LOOP_IDENTIFIER:
887
0
    snprintf(
888
0
        buffer,
889
0
        buffer_size,
890
0
        "duplicated loop identifier \"%s\"",
891
0
        compiler->last_error_extra_info);
892
0
    break;
893
0
  case ERROR_UNDEFINED_STRING:
894
0
    snprintf(
895
0
        buffer,
896
0
        buffer_size,
897
0
        "undefined string \"%s\"",
898
0
        compiler->last_error_extra_info);
899
0
    break;
900
0
  case ERROR_UNDEFINED_IDENTIFIER:
901
0
    snprintf(
902
0
        buffer,
903
0
        buffer_size,
904
0
        "undefined identifier \"%s\"",
905
0
        compiler->last_error_extra_info);
906
0
    break;
907
0
  case ERROR_UNREFERENCED_STRING:
908
0
    snprintf(
909
0
        buffer,
910
0
        buffer_size,
911
0
        "unreferenced string \"%s\"",
912
0
        compiler->last_error_extra_info);
913
0
    break;
914
0
  case ERROR_EMPTY_STRING:
915
0
    snprintf(
916
0
        buffer,
917
0
        buffer_size,
918
0
        "empty string \"%s\"",
919
0
        compiler->last_error_extra_info);
920
0
    break;
921
0
  case ERROR_NOT_A_STRUCTURE:
922
0
    snprintf(
923
0
        buffer,
924
0
        buffer_size,
925
0
        "\"%s\" is not a structure",
926
0
        compiler->last_error_extra_info);
927
0
    break;
928
0
  case ERROR_NOT_INDEXABLE:
929
0
    snprintf(
930
0
        buffer,
931
0
        buffer_size,
932
0
        "\"%s\" is not an array or dictionary",
933
0
        compiler->last_error_extra_info);
934
0
    break;
935
0
  case ERROR_NOT_A_FUNCTION:
936
0
    snprintf(
937
0
        buffer,
938
0
        buffer_size,
939
0
        "\"%s\" is not a function",
940
0
        compiler->last_error_extra_info);
941
0
    break;
942
0
  case ERROR_INVALID_FIELD_NAME:
943
0
    snprintf(
944
0
        buffer,
945
0
        buffer_size,
946
0
        "invalid field name \"%s\"",
947
0
        compiler->last_error_extra_info);
948
0
    break;
949
0
  case ERROR_MISPLACED_ANONYMOUS_STRING:
950
0
    snprintf(buffer, buffer_size, "wrong use of anonymous string");
951
0
    break;
952
0
  case ERROR_INCLUDES_CIRCULAR_REFERENCE:
953
0
    snprintf(buffer, buffer_size, "include circular reference");
954
0
    break;
955
0
  case ERROR_INCLUDE_DEPTH_EXCEEDED:
956
0
    snprintf(buffer, buffer_size, "too many levels of included rules");
957
0
    break;
958
0
  case ERROR_LOOP_NESTING_LIMIT_EXCEEDED:
959
0
    snprintf(buffer, buffer_size, "loop nesting limit exceeded");
960
0
    break;
961
0
  case ERROR_NESTED_FOR_OF_LOOP:
962
0
    snprintf(
963
0
        buffer,
964
0
        buffer_size,
965
0
        "'for <quantifier> of <string set>' loops can't be nested");
966
0
    break;
967
0
  case ERROR_UNKNOWN_MODULE:
968
0
    snprintf(
969
0
        buffer,
970
0
        buffer_size,
971
0
        "unknown module \"%s\"",
972
0
        compiler->last_error_extra_info);
973
0
    break;
974
0
  case ERROR_INVALID_MODULE_NAME:
975
0
    snprintf(
976
0
        buffer,
977
0
        buffer_size,
978
0
        "invalid module name \"%s\"",
979
0
        compiler->last_error_extra_info);
980
0
    break;
981
0
  case ERROR_DUPLICATED_STRUCTURE_MEMBER:
982
0
    snprintf(buffer, buffer_size, "duplicated structure member");
983
0
    break;
984
0
  case ERROR_WRONG_ARGUMENTS:
985
0
    snprintf(
986
0
        buffer,
987
0
        buffer_size,
988
0
        "wrong arguments for function \"%s\"",
989
0
        compiler->last_error_extra_info);
990
0
    break;
991
0
  case ERROR_WRONG_RETURN_TYPE:
992
0
    snprintf(buffer, buffer_size, "wrong return type for overloaded function");
993
0
    break;
994
0
  case ERROR_INVALID_HEX_STRING:
995
0
  case ERROR_INVALID_REGULAR_EXPRESSION:
996
0
  case ERROR_SYNTAX_ERROR:
997
0
  case ERROR_WRONG_TYPE:
998
0
  case ERROR_INVALID_MODIFIER:
999
0
  case ERROR_INVALID_PERCENTAGE:
1000
0
    snprintf(buffer, buffer_size, "%s", compiler->last_error_extra_info);
1001
0
    break;
1002
0
  case ERROR_INTERNAL_FATAL_ERROR:
1003
0
    snprintf(buffer, buffer_size, "internal fatal error");
1004
0
    break;
1005
0
  case ERROR_DIVISION_BY_ZERO:
1006
0
    snprintf(buffer, buffer_size, "division by zero");
1007
0
    break;
1008
0
  case ERROR_REGULAR_EXPRESSION_TOO_LARGE:
1009
0
    snprintf(buffer, buffer_size, "regular expression is too large");
1010
0
    break;
1011
0
  case ERROR_REGULAR_EXPRESSION_TOO_COMPLEX:
1012
0
    snprintf(buffer, buffer_size, "regular expression is too complex");
1013
0
    break;
1014
0
  case ERROR_TOO_MANY_STRINGS:
1015
0
    yr_get_configuration_uint32(
1016
0
        YR_CONFIG_MAX_STRINGS_PER_RULE, &max_strings_per_rule);
1017
0
    snprintf(
1018
0
        buffer,
1019
0
        buffer_size,
1020
0
        "too many strings in rule \"%s\" (limit: %d)",
1021
0
        compiler->last_error_extra_info,
1022
0
        max_strings_per_rule);
1023
0
    break;
1024
0
  case ERROR_INTEGER_OVERFLOW:
1025
0
    snprintf(
1026
0
        buffer,
1027
0
        buffer_size,
1028
0
        "integer overflow in \"%s\"",
1029
0
        compiler->last_error_extra_info);
1030
0
    break;
1031
0
  case ERROR_COULD_NOT_READ_FILE:
1032
0
    snprintf(buffer, buffer_size, "could not read file");
1033
0
    break;
1034
0
  case ERROR_DUPLICATED_MODIFIER:
1035
0
    snprintf(buffer, buffer_size, "duplicated modifier");
1036
0
    break;
1037
0
  case ERROR_IDENTIFIER_MATCHES_WILDCARD:
1038
0
    snprintf(
1039
0
        buffer,
1040
0
        buffer_size,
1041
0
        "rule identifier \"%s\" matches previously used wildcard rule set",
1042
0
        compiler->last_error_extra_info);
1043
0
    break;
1044
0
  case ERROR_INVALID_VALUE:
1045
0
    snprintf(
1046
0
        buffer,
1047
0
        buffer_size,
1048
0
        "invalid value in condition: \"%s\"",
1049
0
        compiler->last_error_extra_info);
1050
0
    break;
1051
0
  }
1052
1053
0
  return buffer;
1054
0
}