Coverage Report

Created: 2023-06-07 07:19

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