Coverage Report

Created: 2023-09-25 07:13

/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
613
{
70
613
#ifndef _MSC_VER
71
613
  struct stat stbuf;
72
613
#endif
73
74
613
  char* file_buffer;
75
76
#ifdef _MSC_VER
77
  long file_size;
78
#else
79
613
  off_t file_size;
80
613
#endif
81
82
613
  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
613
  fd = open(include_name, O_RDONLY);
90
613
#endif
91
92
613
  if (fd == -1)
93
347
    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
266
  if ((fstat(fd, &stbuf) != 0) || (!S_ISREG(stbuf.st_mode)))
104
266
  {
105
266
    close(fd);
106
266
    return NULL;
107
266
  }
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
42.4k
{
161
42.4k
  return (YR_RULE*) yr_arena_get_ptr(
162
42.4k
      compiler->arena, YR_RULES_TABLE, rule_idx * sizeof(YR_RULE));
163
42.4k
}
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
48.8k
{
178
  // Check if the data is already in YR_SZ_POOL by using a hash table.
179
48.8k
  uint32_t offset = yr_hash_table_lookup_uint32_raw_key(
180
48.8k
      compiler->sz_table, data, data_length, NULL);
181
182
48.8k
  if (offset == UINT32_MAX)
183
12.7k
  {
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
12.7k
    FAIL_ON_ERROR(yr_arena_write_data(
188
12.7k
        compiler->arena, YR_SZ_POOL, data, data_length, ref));
189
190
12.7k
    FAIL_ON_ERROR(yr_hash_table_add_uint32_raw_key(
191
12.7k
        compiler->sz_table, data, data_length, NULL, ref->offset));
192
12.7k
  }
193
36.1k
  else
194
36.1k
  {
195
36.1k
    ref->buffer_id = YR_SZ_POOL;
196
36.1k
    ref->offset = offset;
197
36.1k
  }
198
199
48.8k
  return ERROR_SUCCESS;
200
48.8k
}
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
32.7k
{
210
32.7k
  return _yr_compiler_store_data(
211
32.7k
      compiler,
212
32.7k
      (void*) string,
213
32.7k
      strlen(string) + 1,  // include the null terminator
214
32.7k
      ref);
215
32.7k
}
216
217
YR_API int yr_compiler_create(YR_COMPILER** compiler)
218
1.35k
{
219
1.35k
  int result;
220
1.35k
  YR_COMPILER* new_compiler;
221
222
1.35k
  new_compiler = (YR_COMPILER*) yr_calloc(1, sizeof(YR_COMPILER));
223
224
1.35k
  if (new_compiler == NULL)
225
0
    return ERROR_INSUFFICIENT_MEMORY;
226
227
1.35k
  new_compiler->current_rule_idx = UINT32_MAX;
228
1.35k
  new_compiler->next_rule_idx = 0;
229
1.35k
  new_compiler->current_string_idx = 0;
230
1.35k
  new_compiler->current_namespace_idx = 0;
231
1.35k
  new_compiler->current_meta_idx = 0;
232
1.35k
  new_compiler->num_namespaces = 0;
233
1.35k
  new_compiler->errors = 0;
234
1.35k
  new_compiler->callback = NULL;
235
1.35k
  new_compiler->rules = NULL;
236
1.35k
  new_compiler->include_callback = _yr_compiler_default_include_callback;
237
1.35k
  new_compiler->incl_clbk_user_data = NULL;
238
1.35k
  new_compiler->include_free = _yr_compiler_default_include_free;
239
1.35k
  new_compiler->re_ast_callback = NULL;
240
1.35k
  new_compiler->re_ast_clbk_user_data = NULL;
241
1.35k
  new_compiler->last_error = ERROR_SUCCESS;
242
1.35k
  new_compiler->last_error_line = 0;
243
1.35k
  new_compiler->strict_escape = false;
244
1.35k
  new_compiler->current_line = 0;
245
1.35k
  new_compiler->file_name_stack_ptr = 0;
246
1.35k
  new_compiler->fixup_stack_head = NULL;
247
1.35k
  new_compiler->loop_index = -1;
248
1.35k
  new_compiler->loop_for_of_var_index = -1;
249
250
1.35k
  new_compiler->atoms_config.get_atom_quality = yr_atoms_heuristic_quality;
251
1.35k
  new_compiler->atoms_config.quality_warning_threshold =
252
1.35k
      YR_ATOM_QUALITY_WARNING_THRESHOLD;
253
254
1.35k
  result = yr_hash_table_create(5000, &new_compiler->rules_table);
255
256
1.35k
  if (result == ERROR_SUCCESS)
257
1.35k
    result = yr_hash_table_create(1000, &new_compiler->objects_table);
258
259
1.35k
  if (result == ERROR_SUCCESS)
260
1.35k
    result = yr_hash_table_create(10000, &new_compiler->strings_table);
261
262
1.35k
  if (result == ERROR_SUCCESS)
263
1.35k
    result = yr_hash_table_create(
264
1.35k
        1000, &new_compiler->wildcard_identifiers_table);
265
266
1.35k
  if (result == ERROR_SUCCESS)
267
1.35k
    result = yr_hash_table_create(10000, &new_compiler->sz_table);
268
269
1.35k
  if (result == ERROR_SUCCESS)
270
1.35k
    result = yr_arena_create(YR_NUM_SECTIONS, 1048576, &new_compiler->arena);
271
272
1.35k
  if (result == ERROR_SUCCESS)
273
1.35k
    result = yr_ac_automaton_create(
274
1.35k
        new_compiler->arena, &new_compiler->automaton);
275
276
1.35k
  if (result == ERROR_SUCCESS)
277
1.35k
  {
278
1.35k
    *compiler = new_compiler;
279
1.35k
  }
280
0
  else  // if error, do cleanup
281
0
  {
282
0
    yr_compiler_destroy(new_compiler);
283
0
  }
284
285
1.35k
  return result;
286
1.35k
}
287
288
YR_API void yr_compiler_destroy(YR_COMPILER* compiler)
289
1.35k
{
290
1.35k
  if (compiler->arena != NULL)
291
1.35k
    yr_arena_release(compiler->arena);
292
293
1.35k
  if (compiler->automaton != NULL)
294
1.35k
    yr_ac_automaton_destroy(compiler->automaton);
295
296
1.35k
  if (compiler->rules_table != NULL)
297
1.35k
    yr_hash_table_destroy(compiler->rules_table, NULL);
298
299
1.35k
  if (compiler->strings_table != NULL)
300
1.35k
    yr_hash_table_destroy(compiler->strings_table, NULL);
301
302
1.35k
  if (compiler->wildcard_identifiers_table != NULL)
303
1.35k
    yr_hash_table_destroy(compiler->wildcard_identifiers_table, NULL);
304
305
1.35k
  if (compiler->sz_table != NULL)
306
1.35k
    yr_hash_table_destroy(compiler->sz_table, NULL);
307
308
1.35k
  if (compiler->objects_table != NULL)
309
1.35k
    yr_hash_table_destroy(
310
1.35k
        compiler->objects_table,
311
1.35k
        (YR_HASH_TABLE_FREE_VALUE_FUNC) yr_object_destroy);
312
313
1.35k
  if (compiler->atoms_config.free_quality_table)
314
0
    yr_free(compiler->atoms_config.quality_table);
315
316
1.35k
  for (int i = 0; i < compiler->file_name_stack_ptr; i++)
317
0
    yr_free(compiler->file_name_stack[i]);
318
319
1.35k
  YR_FIXUP* fixup = compiler->fixup_stack_head;
320
321
16.1k
  while (fixup != NULL)
322
14.7k
  {
323
14.7k
    YR_FIXUP* next_fixup = fixup->next;
324
14.7k
    yr_free(fixup);
325
14.7k
    fixup = next_fixup;
326
14.7k
  }
327
328
1.35k
  yr_free(compiler);
329
1.35k
}
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
2.39k
{
493
2.39k
  int i, result = 0;
494
495
3.63k
  for (i = 0; i < compiler->loop_index; i++)
496
1.24k
  {
497
1.24k
    result += compiler->loop[i].vars_count +
498
1.24k
              compiler->loop[i].vars_internal_count;
499
1.24k
  }
500
501
2.39k
  return result;
502
2.39k
}
503
504
YR_API char* yr_compiler_get_current_file_name(YR_COMPILER* compiler)
505
613
{
506
613
  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
613
  else
511
613
  {
512
613
    return NULL;
513
613
  }
514
613
}
515
516
static int _yr_compiler_set_namespace(
517
    YR_COMPILER* compiler,
518
    const char* namespace_)
519
1.35k
{
520
1.35k
  YR_NAMESPACE* ns = (YR_NAMESPACE*) yr_arena_get_ptr(
521
1.35k
      compiler->arena, YR_NAMESPACES_TABLE, 0);
522
523
1.35k
  bool found = false;
524
525
1.35k
  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
1.35k
  if (!found)
536
1.35k
  {
537
1.35k
    YR_ARENA_REF ref;
538
539
1.35k
    FAIL_ON_ERROR(yr_arena_allocate_struct(
540
1.35k
        compiler->arena,
541
1.35k
        YR_NAMESPACES_TABLE,
542
1.35k
        sizeof(YR_NAMESPACE),
543
1.35k
        &ref,
544
1.35k
        offsetof(YR_NAMESPACE, name),
545
1.35k
        EOL));
546
547
1.35k
    ns = (YR_NAMESPACE*) yr_arena_ref_to_ptr(compiler->arena, &ref);
548
549
1.35k
    FAIL_ON_ERROR(_yr_compiler_store_string(compiler, namespace_, &ref));
550
551
1.35k
    ns->name = (const char*) yr_arena_ref_to_ptr(compiler->arena, &ref);
552
1.35k
    ns->idx = compiler->num_namespaces;
553
554
1.35k
    compiler->current_namespace_idx = compiler->num_namespaces;
555
1.35k
    compiler->num_namespaces++;
556
1.35k
  }
557
558
1.35k
  return ERROR_SUCCESS;
559
1.35k
}
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
1.35k
{
663
  // Don't allow calls to yr_compiler_add_string() after
664
  // yr_compiler_get_rules() has been called.
665
1.35k
  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
1.35k
  assert(compiler->errors == 0);
670
671
1.35k
  if (namespace_ != NULL)
672
0
    compiler->last_error = _yr_compiler_set_namespace(compiler, namespace_);
673
1.35k
  else
674
1.35k
    compiler->last_error = _yr_compiler_set_namespace(compiler, "default");
675
676
1.35k
  if (compiler->last_error != ERROR_SUCCESS)
677
0
    return ++compiler->errors;
678
679
1.35k
  return yr_lex_parse_rules_string(rules_string, compiler);
680
1.35k
}
681
682
static int _yr_compiler_compile_rules(YR_COMPILER* compiler)
683
97
{
684
97
  YR_RULE null_rule;
685
97
  YR_EXTERNAL_VARIABLE null_external;
686
687
97
  uint8_t halt = OP_HALT;
688
689
  // Write halt instruction at the end of code.
690
97
  FAIL_ON_ERROR(yr_arena_write_data(
691
97
      compiler->arena, YR_CODE_SECTION, &halt, sizeof(uint8_t), NULL));
692
693
  // Write a null rule indicating the end.
694
97
  memset(&null_rule, 0xFA, sizeof(YR_RULE));
695
97
  null_rule.flags = RULE_FLAGS_NULL;
696
697
97
  FAIL_ON_ERROR(yr_arena_write_data(
698
97
      compiler->arena, YR_RULES_TABLE, &null_rule, sizeof(YR_RULE), NULL));
699
700
  // Write a null external indicating the end.
701
97
  memset(&null_external, 0xFA, sizeof(YR_EXTERNAL_VARIABLE));
702
97
  null_external.type = EXTERNAL_VARIABLE_TYPE_NULL;
703
704
97
  FAIL_ON_ERROR(yr_arena_write_data(
705
97
      compiler->arena,
706
97
      YR_EXTERNAL_VARIABLES_TABLE,
707
97
      &null_external,
708
97
      sizeof(YR_EXTERNAL_VARIABLE),
709
97
      NULL));
710
711
  // Write Aho-Corasick automaton to arena.
712
97
  FAIL_ON_ERROR(yr_ac_compile(compiler->automaton, compiler->arena));
713
714
97
  YR_ARENA_REF ref;
715
716
97
  FAIL_ON_ERROR(yr_arena_allocate_struct(
717
97
      compiler->arena, YR_SUMMARY_SECTION, sizeof(YR_SUMMARY), &ref, EOL));
718
719
97
  YR_SUMMARY* summary = (YR_SUMMARY*) yr_arena_ref_to_ptr(
720
97
      compiler->arena, &ref);
721
722
97
  summary->num_namespaces = compiler->num_namespaces;
723
97
  summary->num_rules = compiler->next_rule_idx;
724
97
  summary->num_strings = compiler->current_string_idx;
725
726
97
  return yr_rules_from_arena(compiler->arena, &compiler->rules);
727
97
}
728
729
YR_API int yr_compiler_get_rules(YR_COMPILER* compiler, YR_RULES** rules)
730
97
{
731
  // Don't allow calls to yr_compiler_get_rules() if a previous call to
732
  // yr_compiler_add_XXXX failed.
733
97
  assert(compiler->errors == 0);
734
735
97
  *rules = NULL;
736
737
97
  if (compiler->rules == NULL)
738
97
    FAIL_ON_ERROR(_yr_compiler_compile_rules(compiler));
739
740
97
  *rules = compiler->rules;
741
742
97
  return ERROR_SUCCESS;
743
97
}
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
}