Coverage Report

Created: 2025-07-11 06:08

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