Coverage Report

Created: 2026-08-13 06:11

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/yara/libyara/object.c
Line
Count
Source
1
/*
2
Copyright (c) 2014. 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 <ctype.h>
32
#include <math.h>
33
#include <stdarg.h>
34
#include <stdio.h>
35
#include <stdlib.h>
36
#include <string.h>
37
#include <yara/error.h>
38
#include <yara/exec.h>
39
#include <yara/globals.h>
40
#include <yara/mem.h>
41
#include <yara/object.h>
42
#include <yara/strutils.h>
43
#include <yara/utils.h>
44
45
////////////////////////////////////////////////////////////////////////////////
46
// Creates a new object with the given type and identifier. If a parent is
47
// specified the new object is owned by the parent and it will be destroyed when
48
// the parent is destroyed. You must not call yr_object_destroy on an objected
49
// that has a parent, you should destroy the parent instead.
50
//
51
int yr_object_create(
52
    int8_t type,
53
    const char* identifier,
54
    YR_OBJECT* parent,
55
    YR_OBJECT** object)
56
11.6M
{
57
11.6M
  YR_OBJECT* obj;
58
11.6M
  size_t object_size = 0;
59
60
11.6M
  assert(parent != NULL || object != NULL);
61
11.6M
  assert(identifier != NULL);
62
63
11.6M
  switch (type)
64
11.6M
  {
65
1.41M
  case OBJECT_TYPE_STRUCTURE:
66
1.41M
    object_size = sizeof(YR_OBJECT_STRUCTURE);
67
1.41M
    break;
68
1.49M
  case OBJECT_TYPE_ARRAY:
69
1.49M
    object_size = sizeof(YR_OBJECT_ARRAY);
70
1.49M
    break;
71
0
  case OBJECT_TYPE_DICTIONARY:
72
0
    object_size = sizeof(YR_OBJECT_DICTIONARY);
73
0
    break;
74
4.31M
  case OBJECT_TYPE_INTEGER:
75
4.31M
    object_size = sizeof(YR_OBJECT);
76
4.31M
    break;
77
0
  case OBJECT_TYPE_FLOAT:
78
0
    object_size = sizeof(YR_OBJECT);
79
0
    break;
80
4.41M
  case OBJECT_TYPE_STRING:
81
4.41M
    object_size = sizeof(YR_OBJECT);
82
4.41M
    break;
83
0
  case OBJECT_TYPE_FUNCTION:
84
0
    object_size = sizeof(YR_OBJECT_FUNCTION);
85
0
    break;
86
0
  default:
87
0
    assert(false);
88
0
    return ERROR_INVALID_ARGUMENT;
89
11.6M
  }
90
91
11.6M
  obj = (YR_OBJECT*) yr_malloc(object_size);
92
93
11.6M
  if (obj == NULL)
94
0
    return ERROR_INSUFFICIENT_MEMORY;
95
96
11.6M
  obj->type = type;
97
11.6M
  obj->identifier = yr_strdup(identifier);
98
11.6M
  obj->parent = parent;
99
11.6M
  obj->data = NULL;
100
101
11.6M
  switch (type)
102
11.6M
  {
103
4.31M
  case OBJECT_TYPE_INTEGER:
104
4.31M
    obj->value.i = YR_UNDEFINED;
105
4.31M
    break;
106
0
  case OBJECT_TYPE_FLOAT:
107
0
    obj->value.d = NAN;
108
0
    break;
109
4.41M
  case OBJECT_TYPE_STRING:
110
4.41M
    obj->value.ss = NULL;
111
4.41M
    break;
112
1.41M
  case OBJECT_TYPE_STRUCTURE:
113
1.41M
    object_as_structure(obj)->members = NULL;
114
1.41M
    break;
115
1.49M
  case OBJECT_TYPE_ARRAY:
116
1.49M
    object_as_array(obj)->items = NULL;
117
1.49M
    object_as_array(obj)->prototype_item = NULL;
118
1.49M
    break;
119
0
  case OBJECT_TYPE_DICTIONARY:
120
0
    object_as_dictionary(obj)->items = NULL;
121
0
    object_as_dictionary(obj)->prototype_item = NULL;
122
0
    break;
123
0
  case OBJECT_TYPE_FUNCTION:
124
0
    object_as_function(obj)->return_obj = NULL;
125
0
    for (int i = 0; i < YR_MAX_OVERLOADED_FUNCTIONS; i++)
126
0
    {
127
0
      object_as_function(obj)->prototypes[i].arguments_fmt = NULL;
128
0
      object_as_function(obj)->prototypes[i].code = NULL;
129
0
    }
130
0
    break;
131
11.6M
  }
132
133
11.6M
  if (obj->identifier == NULL)
134
0
  {
135
0
    yr_free(obj);
136
0
    return ERROR_INSUFFICIENT_MEMORY;
137
0
  }
138
139
11.6M
  if (parent != NULL)
140
606k
  {
141
606k
    assert(
142
606k
        parent->type == OBJECT_TYPE_STRUCTURE ||
143
606k
        parent->type == OBJECT_TYPE_ARRAY ||
144
606k
        parent->type == OBJECT_TYPE_DICTIONARY ||
145
606k
        parent->type == OBJECT_TYPE_FUNCTION);
146
147
    // Objects with a parent take the canary from it.
148
606k
    obj->canary = parent->canary;
149
150
606k
    switch (parent->type)
151
606k
    {
152
504k
    case OBJECT_TYPE_STRUCTURE:
153
504k
      FAIL_ON_ERROR_WITH_CLEANUP(yr_object_structure_set_member(parent, obj), {
154
504k
        yr_free((void*) obj->identifier);
155
504k
        yr_free(obj);
156
504k
      });
157
504k
      break;
158
159
102k
    case OBJECT_TYPE_ARRAY:
160
102k
      object_as_array(parent)->prototype_item = obj;
161
102k
      break;
162
163
0
    case OBJECT_TYPE_DICTIONARY:
164
0
      object_as_dictionary(parent)->prototype_item = obj;
165
0
      break;
166
167
0
    case OBJECT_TYPE_FUNCTION:
168
0
      object_as_function(parent)->return_obj = obj;
169
0
      break;
170
606k
    }
171
606k
  }
172
173
11.6M
  if (object != NULL)
174
11.2M
    *object = obj;
175
176
11.6M
  return ERROR_SUCCESS;
177
11.6M
}
178
179
void yr_object_set_canary(YR_OBJECT* object, int canary)
180
7.30k
{
181
7.30k
  object->canary = canary;
182
7.30k
}
183
184
int yr_object_function_create(
185
    const char* identifier,
186
    const char* arguments_fmt,
187
    const char* return_fmt,
188
    YR_MODULE_FUNC code,
189
    YR_OBJECT* parent,
190
    YR_OBJECT** function)
191
0
{
192
0
  YR_OBJECT* return_obj;
193
0
  YR_OBJECT* o = NULL;
194
0
  YR_OBJECT_FUNCTION* f = NULL;
195
196
0
  int8_t return_type;
197
198
  // The parent of a function must be a structure.
199
0
  assert(parent != NULL && parent->type == OBJECT_TYPE_STRUCTURE);
200
201
0
  switch (*return_fmt)
202
0
  {
203
0
  case 'i':
204
0
    return_type = OBJECT_TYPE_INTEGER;
205
0
    break;
206
0
  case 's':
207
0
    return_type = OBJECT_TYPE_STRING;
208
0
    break;
209
0
  case 'f':
210
0
    return_type = OBJECT_TYPE_FLOAT;
211
0
    break;
212
0
  default:
213
0
    return ERROR_INVALID_FORMAT;
214
0
  }
215
216
  // Try to find if the structure already has a function
217
  // with that name. In that case this is a function overload.
218
0
  f = object_as_function(yr_object_lookup_field(parent, identifier));
219
220
  // Overloaded functions must have the same return type.
221
0
  if (f != NULL && return_type != f->return_obj->type)
222
0
    return ERROR_WRONG_RETURN_TYPE;
223
224
0
  if (f == NULL)  // Function doesn't exist yet
225
0
  {
226
0
    FAIL_ON_ERROR(
227
0
        yr_object_create(OBJECT_TYPE_FUNCTION, identifier, parent, &o));
228
229
    // In case of failure while creating return_obj we don't need to free the
230
    // previously created "o" object, as it is already associated with its
231
    // parent and will be destroyed when the parent is destroyed.
232
0
    FAIL_ON_ERROR(yr_object_create(return_type, "result", o, &return_obj));
233
234
0
    f = object_as_function(o);
235
0
  }
236
237
0
  for (int i = 0; i < YR_MAX_OVERLOADED_FUNCTIONS; i++)
238
0
  {
239
0
    if (f->prototypes[i].arguments_fmt == NULL)
240
0
    {
241
0
      f->prototypes[i].arguments_fmt = arguments_fmt;
242
0
      f->prototypes[i].code = code;
243
244
0
      break;
245
0
    }
246
0
  }
247
248
0
  if (function != NULL)
249
0
    *function = (YR_OBJECT*) f;
250
251
0
  return ERROR_SUCCESS;
252
0
}
253
254
int yr_object_from_external_variable(
255
    YR_EXTERNAL_VARIABLE* external,
256
    YR_OBJECT** object)
257
0
{
258
0
  YR_OBJECT* obj;
259
0
  int result;
260
0
  uint8_t obj_type = 0;
261
262
0
  switch (external->type)
263
0
  {
264
0
  case EXTERNAL_VARIABLE_TYPE_INTEGER:
265
0
  case EXTERNAL_VARIABLE_TYPE_BOOLEAN:
266
0
    obj_type = OBJECT_TYPE_INTEGER;
267
0
    break;
268
269
0
  case EXTERNAL_VARIABLE_TYPE_FLOAT:
270
0
    obj_type = OBJECT_TYPE_FLOAT;
271
0
    break;
272
273
0
  case EXTERNAL_VARIABLE_TYPE_STRING:
274
0
  case EXTERNAL_VARIABLE_TYPE_MALLOC_STRING:
275
0
    obj_type = OBJECT_TYPE_STRING;
276
0
    break;
277
278
0
  default:
279
    // The type comes from the compiled rules file, a corrupt or hand-crafted
280
    // one can carry a value that is not any of the EXTERNAL_VARIABLE_TYPE_X.
281
0
    return ERROR_CORRUPT_FILE;
282
0
  }
283
284
0
  result = yr_object_create(obj_type, external->identifier, NULL, &obj);
285
286
0
  if (result == ERROR_SUCCESS)
287
0
  {
288
0
    switch (external->type)
289
0
    {
290
0
    case EXTERNAL_VARIABLE_TYPE_INTEGER:
291
0
    case EXTERNAL_VARIABLE_TYPE_BOOLEAN:
292
0
      result = yr_object_set_integer(external->value.i, obj, NULL);
293
0
      break;
294
295
0
    case EXTERNAL_VARIABLE_TYPE_FLOAT:
296
0
      result = yr_object_set_float(external->value.f, obj, NULL);
297
0
      break;
298
299
0
    case EXTERNAL_VARIABLE_TYPE_STRING:
300
0
    case EXTERNAL_VARIABLE_TYPE_MALLOC_STRING:
301
0
      result = yr_object_set_string(
302
0
          external->value.s, strlen(external->value.s), obj, NULL);
303
0
      break;
304
0
    }
305
306
0
    if (result == ERROR_SUCCESS)
307
0
    {
308
0
      *object = obj;
309
0
    }
310
0
    else
311
0
    {
312
0
      yr_object_destroy(obj);
313
0
    }
314
0
  }
315
316
0
  return result;
317
0
}
318
319
////////////////////////////////////////////////////////////////////////////////
320
// Destroy an objects, and any other object that is a child of it. For example,
321
// destroying a struct will destroy all its members.
322
//
323
void yr_object_destroy(YR_OBJECT* object)
324
11.6M
{
325
11.6M
  YR_STRUCTURE_MEMBER* member;
326
11.6M
  YR_STRUCTURE_MEMBER* next_member;
327
11.6M
  YR_ARRAY_ITEMS* array_items;
328
11.6M
  YR_DICTIONARY_ITEMS* dict_items;
329
330
11.6M
  if (object == NULL)
331
0
    return;
332
333
11.6M
  switch (object->type)
334
11.6M
  {
335
1.41M
  case OBJECT_TYPE_STRUCTURE:
336
1.41M
    member = object_as_structure(object)->members;
337
338
10.8M
    while (member != NULL)
339
9.42M
    {
340
9.42M
      next_member = member->next;
341
9.42M
      yr_object_destroy(member->object);
342
9.42M
      yr_free(member);
343
9.42M
      member = next_member;
344
9.42M
    }
345
1.41M
    break;
346
347
4.41M
  case OBJECT_TYPE_STRING:
348
4.41M
    if (object->value.ss != NULL)
349
1.73M
      yr_free(object->value.ss);
350
4.41M
    break;
351
352
1.49M
  case OBJECT_TYPE_ARRAY:
353
1.49M
    if (object_as_array(object)->prototype_item != NULL)
354
1.49M
      yr_object_destroy(object_as_array(object)->prototype_item);
355
356
1.49M
    array_items = object_as_array(object)->items;
357
358
1.49M
    if (array_items != NULL)
359
52.0k
    {
360
858k
      for (int i = 0; i < array_items->length; i++)
361
806k
        if (array_items->objects[i] != NULL)
362
724k
          yr_object_destroy(array_items->objects[i]);
363
52.0k
    }
364
365
1.49M
    yr_free(array_items);
366
1.49M
    break;
367
368
0
  case OBJECT_TYPE_DICTIONARY:
369
0
    if (object_as_dictionary(object)->prototype_item != NULL)
370
0
      yr_object_destroy(object_as_dictionary(object)->prototype_item);
371
372
0
    dict_items = object_as_dictionary(object)->items;
373
374
0
    if (dict_items != NULL)
375
0
    {
376
0
      for (int i = 0; i < dict_items->used; i++)
377
0
      {
378
0
        if (dict_items->objects[i].key != NULL)
379
0
          yr_free(dict_items->objects[i].key);
380
381
0
        if (dict_items->objects[i].obj != NULL)
382
0
          yr_object_destroy(dict_items->objects[i].obj);
383
0
      }
384
0
    }
385
386
0
    yr_free(dict_items);
387
0
    break;
388
389
0
  case OBJECT_TYPE_FUNCTION:
390
0
    yr_object_destroy(object_as_function(object)->return_obj);
391
0
    break;
392
11.6M
  }
393
394
11.6M
  yr_free((void*) object->identifier);
395
11.6M
  yr_free(object);
396
11.6M
}
397
398
YR_OBJECT* yr_object_lookup_field(YR_OBJECT* object, const char* field_name)
399
18.1M
{
400
18.1M
  YR_STRUCTURE_MEMBER* member;
401
402
18.1M
  assert(object != NULL);
403
18.1M
  assert(object->type == OBJECT_TYPE_STRUCTURE);
404
405
18.1M
  member = object_as_structure(object)->members;
406
407
129M
  while (member != NULL)
408
119M
  {
409
119M
    if (strcmp(member->object->identifier, field_name) == 0)
410
8.69M
      return member->object;
411
412
111M
    member = member->next;
413
111M
  }
414
415
9.42M
  return NULL;
416
18.1M
}
417
418
static YR_OBJECT* _yr_object_lookup(
419
    YR_OBJECT* object,
420
    int flags,
421
    const char* pattern,
422
    va_list args)
423
3.97M
{
424
3.97M
  YR_OBJECT* obj = object;
425
426
3.97M
  const char* p = pattern;
427
3.97M
  const char* key = NULL;
428
429
3.97M
  char str[256];
430
431
3.97M
  int i;
432
3.97M
  int index = -1;
433
434
8.68M
  while (obj != NULL)
435
8.68M
  {
436
8.68M
    i = 0;
437
438
87.0M
    while (*p != '\0' && *p != '.' && *p != '[' && i < sizeof(str) - 1)
439
78.3M
    {
440
78.3M
      str[i++] = *p++;
441
78.3M
    }
442
443
8.68M
    str[i] = '\0';
444
445
8.68M
    if (obj->type != OBJECT_TYPE_STRUCTURE)
446
0
      return NULL;
447
448
8.68M
    obj = yr_object_lookup_field(obj, str);
449
450
8.68M
    if (obj == NULL)
451
0
      return NULL;
452
453
8.68M
    if (*p == '[')
454
4.20M
    {
455
4.20M
      p++;
456
457
4.20M
      if (*p == '%')
458
4.20M
      {
459
4.20M
        p++;
460
461
4.20M
        switch (*p++)
462
4.20M
        {
463
4.20M
        case 'i':
464
4.20M
          index = va_arg(args, int);
465
4.20M
          break;
466
0
        case 's':
467
0
          key = va_arg(args, const char*);
468
0
          break;
469
470
0
        default:
471
0
          return NULL;
472
4.20M
        }
473
4.20M
      }
474
0
      else if (*p >= '0' && *p <= '9')
475
0
      {
476
0
        index = (int) strtol(p, (char**) &p, 10);
477
0
      }
478
0
      else if (*p == '"')
479
0
      {
480
0
        i = 0;
481
0
        p++;  // skip the opening quotation mark
482
483
0
        while (*p != '"' && *p != '\0' && i < sizeof(str) - 1) str[i++] = *p++;
484
485
0
        str[i] = '\0';
486
0
        p++;  // skip the closing quotation mark
487
0
        key = str;
488
0
      }
489
0
      else
490
0
      {
491
0
        return NULL;
492
0
      }
493
494
4.20M
      assert(*p == ']');
495
4.20M
      p++;
496
4.20M
      assert(*p == '.' || *p == '\0');
497
498
4.20M
      switch (obj->type)
499
4.20M
      {
500
4.20M
      case OBJECT_TYPE_ARRAY:
501
4.20M
        assert(index != -1);
502
4.20M
        obj = yr_object_array_get_item(obj, flags, index);
503
4.20M
        break;
504
505
0
      case OBJECT_TYPE_DICTIONARY:
506
0
        assert(key != NULL);
507
0
        obj = yr_object_dict_get_item(obj, flags, key);
508
0
        break;
509
4.20M
      }
510
4.20M
    }
511
512
8.68M
    if (*p == '\0')
513
3.97M
      break;
514
515
4.71M
    p++;
516
4.71M
  }
517
518
3.97M
  return obj;
519
3.97M
}
520
521
YR_OBJECT* yr_object_lookup(
522
    YR_OBJECT* object,
523
    int flags,
524
    const char* pattern,
525
    ...)
526
0
{
527
0
  YR_OBJECT* result;
528
529
0
  va_list args;
530
0
  va_start(args, pattern);
531
532
0
  result = _yr_object_lookup(object, flags, pattern, args);
533
534
0
  va_end(args);
535
536
0
  return result;
537
0
}
538
539
int yr_object_copy(YR_OBJECT* object, YR_OBJECT** object_copy)
540
11.0M
{
541
11.0M
  YR_OBJECT* copy;
542
11.0M
  YR_OBJECT* o;
543
544
11.0M
  YR_STRUCTURE_MEMBER* structure_member;
545
546
11.0M
  *object_copy = NULL;
547
548
11.0M
  FAIL_ON_ERROR(
549
11.0M
      yr_object_create(object->type, object->identifier, NULL, &copy));
550
551
11.0M
  copy->canary = object->canary;
552
553
11.0M
  switch (object->type)
554
11.0M
  {
555
4.07M
  case OBJECT_TYPE_INTEGER:
556
4.07M
    copy->value.i = object->value.i;
557
4.07M
    break;
558
559
0
  case OBJECT_TYPE_FLOAT:
560
0
    copy->value.d = object->value.d;
561
0
    break;
562
563
4.22M
  case OBJECT_TYPE_STRING:
564
565
4.22M
    if (object->value.ss != NULL)
566
0
      copy->value.ss = ss_dup(object->value.ss);
567
4.22M
    else
568
4.22M
      copy->value.ss = NULL;
569
570
4.22M
    break;
571
572
0
  case OBJECT_TYPE_FUNCTION:
573
574
0
    FAIL_ON_ERROR_WITH_CLEANUP(
575
0
        yr_object_copy(
576
0
            object_as_function(object)->return_obj,
577
0
            &object_as_function(copy)->return_obj),
578
        // cleanup
579
0
        yr_object_destroy(copy));
580
581
0
    for (int i = 0; i < YR_MAX_OVERLOADED_FUNCTIONS; i++)
582
0
      object_as_function(copy)->prototypes[i] =
583
0
          object_as_function(object)->prototypes[i];
584
585
0
    break;
586
587
1.34M
  case OBJECT_TYPE_STRUCTURE:
588
589
1.34M
    structure_member = object_as_structure(object)->members;
590
591
10.2M
    while (structure_member != NULL)
592
8.91M
    {
593
8.91M
      FAIL_ON_ERROR_WITH_CLEANUP(
594
8.91M
          yr_object_copy(structure_member->object, &o),
595
8.91M
          yr_object_destroy(copy));
596
597
8.91M
      FAIL_ON_ERROR_WITH_CLEANUP(yr_object_structure_set_member(copy, o),
598
                                 // cleanup
599
8.91M
                                 yr_free(o);
600
8.91M
                                 yr_object_destroy(copy));
601
602
8.91M
      structure_member = structure_member->next;
603
8.91M
    }
604
605
1.34M
    break;
606
607
1.39M
  case OBJECT_TYPE_ARRAY:
608
609
1.39M
    FAIL_ON_ERROR_WITH_CLEANUP(
610
1.39M
        yr_object_copy(object_as_array(object)->prototype_item, &o),
611
1.39M
        yr_object_destroy(copy));
612
613
1.39M
    object_as_array(copy)->prototype_item = o;
614
615
1.39M
    break;
616
617
0
  case OBJECT_TYPE_DICTIONARY:
618
619
0
    FAIL_ON_ERROR_WITH_CLEANUP(
620
0
        yr_object_copy(object_as_dictionary(object)->prototype_item, &o),
621
0
        yr_object_destroy(copy));
622
623
0
    object_as_dictionary(copy)->prototype_item = o;
624
625
0
    break;
626
627
0
  default:
628
0
    assert(false);
629
11.0M
  }
630
631
11.0M
  *object_copy = copy;
632
633
11.0M
  return ERROR_SUCCESS;
634
11.0M
}
635
636
int yr_object_structure_set_member(YR_OBJECT* object, YR_OBJECT* member)
637
9.42M
{
638
9.42M
  YR_STRUCTURE_MEMBER* sm;
639
640
9.42M
  assert(object->type == OBJECT_TYPE_STRUCTURE);
641
642
  // Check if the object already have a member with the same identifier
643
644
9.42M
  if (yr_object_lookup_field(object, member->identifier) != NULL)
645
0
    return ERROR_DUPLICATED_STRUCTURE_MEMBER;
646
647
9.42M
  sm = (YR_STRUCTURE_MEMBER*) yr_malloc(sizeof(YR_STRUCTURE_MEMBER));
648
649
9.42M
  if (sm == NULL)
650
0
    return ERROR_INSUFFICIENT_MEMORY;
651
652
9.42M
  member->parent = object;
653
9.42M
  sm->object = member;
654
9.42M
  sm->next = object_as_structure(object)->members;
655
656
9.42M
  object_as_structure(object)->members = sm;
657
658
9.42M
  return ERROR_SUCCESS;
659
9.42M
}
660
661
YR_API int yr_object_array_length(YR_OBJECT* object)
662
0
{
663
0
  YR_OBJECT_ARRAY* array;
664
665
0
  assert(object->type == OBJECT_TYPE_ARRAY);
666
0
  array = object_as_array(object);
667
668
0
  if (array->items == NULL)
669
0
    return 0;
670
671
0
  return array->items->length;
672
0
}
673
674
YR_API YR_OBJECT* yr_object_array_get_item(YR_OBJECT* object, int flags,
675
                                           int index)
676
4.20M
{
677
4.20M
  YR_OBJECT* result = NULL;
678
4.20M
  YR_OBJECT_ARRAY* array;
679
680
4.20M
  assert(object->type == OBJECT_TYPE_ARRAY);
681
682
4.20M
  if (index < 0)
683
0
    return NULL;
684
685
4.20M
  array = object_as_array(object);
686
687
4.20M
  if (array->items != NULL && array->items->capacity > index)
688
4.14M
    result = array->items->objects[index];
689
690
4.20M
  if (result == NULL && flags & OBJECT_CREATE)
691
724k
  {
692
724k
    yr_object_copy(array->prototype_item, &result);
693
694
724k
    if (result != NULL)
695
724k
      yr_object_array_set_item(object, result, index);
696
724k
  }
697
698
4.20M
  return result;
699
4.20M
}
700
701
int yr_object_array_set_item(YR_OBJECT* object, YR_OBJECT* item, int index)
702
724k
{
703
724k
  YR_OBJECT_ARRAY* array;
704
705
724k
  int capacity;
706
707
724k
  assert(index >= 0);
708
724k
  assert(object->type == OBJECT_TYPE_ARRAY);
709
710
724k
  array = object_as_array(object);
711
712
724k
  if (array->items == NULL)
713
52.0k
  {
714
52.0k
    capacity = 64;
715
716
52.1k
    while (capacity <= index) capacity *= 2;
717
718
52.0k
    array->items = (YR_ARRAY_ITEMS*) yr_malloc(
719
52.0k
        sizeof(YR_ARRAY_ITEMS) + capacity * sizeof(YR_OBJECT*));
720
721
52.0k
    if (array->items == NULL)
722
0
      return ERROR_INSUFFICIENT_MEMORY;
723
724
52.0k
    memset(array->items->objects, 0, capacity * sizeof(YR_OBJECT*));
725
726
52.0k
    array->items->capacity = capacity;
727
52.0k
    array->items->length = 0;
728
52.0k
  }
729
672k
  else if (index >= array->items->capacity)
730
2.82k
  {
731
2.82k
    capacity = array->items->capacity * 2;
732
733
2.85k
    while (capacity <= index) capacity *= 2;
734
735
2.82k
    array->items = (YR_ARRAY_ITEMS*) yr_realloc(
736
2.82k
        array->items, sizeof(YR_ARRAY_ITEMS) + capacity * sizeof(YR_OBJECT*));
737
738
2.82k
    if (array->items == NULL)
739
0
      return ERROR_INSUFFICIENT_MEMORY;
740
741
814k
    for (int i = array->items->capacity; i < capacity; i++)
742
811k
      array->items->objects[i] = NULL;
743
744
2.82k
    array->items->capacity = capacity;
745
2.82k
  }
746
747
724k
  item->parent = object;
748
724k
  array->items->objects[index] = item;
749
750
724k
  if (index >= array->items->length)
751
724k
    array->items->length = index + 1;
752
753
724k
  return ERROR_SUCCESS;
754
724k
}
755
756
YR_OBJECT* yr_object_dict_get_item(
757
    YR_OBJECT* object,
758
    int flags,
759
    const char* key)
760
0
{
761
0
  YR_OBJECT* result = NULL;
762
0
  YR_OBJECT_DICTIONARY* dict;
763
764
0
  assert(object->type == OBJECT_TYPE_DICTIONARY);
765
766
0
  dict = object_as_dictionary(object);
767
768
0
  if (dict->items != NULL)
769
0
  {
770
0
    for (int i = 0; i < dict->items->used; i++)
771
0
    {
772
0
      if (strcmp(dict->items->objects[i].key->c_string, key) == 0)
773
0
        result = dict->items->objects[i].obj;
774
0
    }
775
0
  }
776
777
0
  if (result == NULL && flags & OBJECT_CREATE)
778
0
  {
779
0
    yr_object_copy(dict->prototype_item, &result);
780
781
0
    if (result != NULL)
782
0
      yr_object_dict_set_item(object, result, key);
783
0
  }
784
785
0
  return result;
786
0
}
787
788
int yr_object_dict_set_item(YR_OBJECT* object, YR_OBJECT* item, const char* key)
789
0
{
790
0
  YR_OBJECT_DICTIONARY* dict;
791
792
0
  int count;
793
794
0
  assert(object->type == OBJECT_TYPE_DICTIONARY);
795
796
0
  dict = object_as_dictionary(object);
797
798
0
  if (dict->items == NULL)
799
0
  {
800
0
    count = 64;
801
802
0
    dict->items = (YR_DICTIONARY_ITEMS*) yr_malloc(
803
0
        sizeof(YR_DICTIONARY_ITEMS) + count * sizeof(dict->items->objects[0]));
804
805
0
    if (dict->items == NULL)
806
0
      return ERROR_INSUFFICIENT_MEMORY;
807
808
0
    memset(dict->items->objects, 0, count * sizeof(dict->items->objects[0]));
809
810
0
    dict->items->free = count;
811
0
    dict->items->used = 0;
812
0
  }
813
0
  else if (dict->items->free == 0)
814
0
  {
815
0
    count = dict->items->used * 2;
816
0
    dict->items = (YR_DICTIONARY_ITEMS*) yr_realloc(
817
0
        dict->items,
818
0
        sizeof(YR_DICTIONARY_ITEMS) + count * sizeof(dict->items->objects[0]));
819
820
0
    if (dict->items == NULL)
821
0
      return ERROR_INSUFFICIENT_MEMORY;
822
823
0
    for (int i = dict->items->used; i < count; i++)
824
0
    {
825
0
      dict->items->objects[i].key = NULL;
826
0
      dict->items->objects[i].obj = NULL;
827
0
    }
828
829
0
    dict->items->free = dict->items->used;
830
0
  }
831
832
0
  item->parent = object;
833
834
0
  dict->items->objects[dict->items->used].key = ss_new(key);
835
0
  dict->items->objects[dict->items->used].obj = item;
836
837
0
  dict->items->used++;
838
0
  dict->items->free--;
839
840
0
  return ERROR_SUCCESS;
841
0
}
842
843
bool yr_object_has_undefined_value(YR_OBJECT* object, const char* field, ...)
844
0
{
845
0
  YR_OBJECT* field_obj;
846
847
0
  va_list args;
848
0
  va_start(args, field);
849
850
0
  if (field != NULL)
851
0
    field_obj = _yr_object_lookup(object, 0, field, args);
852
0
  else
853
0
    field_obj = object;
854
855
0
  va_end(args);
856
857
0
  if (field_obj == NULL)
858
0
    return true;
859
860
0
  switch (field_obj->type)
861
0
  {
862
0
  case OBJECT_TYPE_FLOAT:
863
0
    return yr_isnan(field_obj->value.d);
864
0
  case OBJECT_TYPE_STRING:
865
0
    return field_obj->value.ss == NULL;
866
0
  case OBJECT_TYPE_INTEGER:
867
0
    return field_obj->value.i == YR_UNDEFINED;
868
0
  }
869
870
0
  return false;
871
0
}
872
873
int64_t yr_object_get_integer(YR_OBJECT* object, const char* field, ...)
874
0
{
875
0
  YR_OBJECT* integer_obj;
876
877
0
  va_list args;
878
0
  va_start(args, field);
879
880
0
  if (field != NULL)
881
0
    integer_obj = _yr_object_lookup(object, 0, field, args);
882
0
  else
883
0
    integer_obj = object;
884
885
0
  va_end(args);
886
887
0
  if (integer_obj == NULL)
888
0
    return YR_UNDEFINED;
889
890
0
  assertf(
891
0
      integer_obj->type == OBJECT_TYPE_INTEGER,
892
0
      "type of \"%s\" is not integer\n",
893
0
      field);
894
895
0
  return integer_obj->value.i;
896
0
}
897
898
double yr_object_get_float(YR_OBJECT* object, const char* field, ...)
899
0
{
900
0
  YR_OBJECT* double_obj;
901
902
0
  va_list args;
903
0
  va_start(args, field);
904
905
0
  if (field != NULL)
906
0
    double_obj = _yr_object_lookup(object, 0, field, args);
907
0
  else
908
0
    double_obj = object;
909
910
0
  va_end(args);
911
912
0
  if (double_obj == NULL)
913
0
    return NAN;
914
915
0
  assertf(
916
0
      double_obj->type == OBJECT_TYPE_FLOAT,
917
0
      "type of \"%s\" is not double\n",
918
0
      field);
919
920
0
  return double_obj->value.d;
921
0
}
922
923
SIZED_STRING* yr_object_get_string(YR_OBJECT* object, const char* field, ...)
924
0
{
925
0
  YR_OBJECT* string_obj;
926
927
0
  va_list args;
928
0
  va_start(args, field);
929
930
0
  if (field != NULL)
931
0
    string_obj = _yr_object_lookup(object, 0, field, args);
932
0
  else
933
0
    string_obj = object;
934
935
0
  va_end(args);
936
937
0
  if (string_obj == NULL)
938
0
    return NULL;
939
940
0
  assertf(
941
0
      string_obj->type == OBJECT_TYPE_STRING,
942
0
      "type of \"%s\" is not string\n",
943
0
      field);
944
945
0
  return string_obj->value.ss;
946
0
}
947
948
int yr_object_set_integer(
949
    int64_t value,
950
    YR_OBJECT* object,
951
    const char* field,
952
    ...)
953
2.16M
{
954
2.16M
  YR_OBJECT* integer_obj;
955
956
2.16M
  va_list args;
957
2.16M
  va_start(args, field);
958
959
2.16M
  if (field != NULL)
960
2.16M
    integer_obj = _yr_object_lookup(object, OBJECT_CREATE, field, args);
961
0
  else
962
0
    integer_obj = object;
963
964
2.16M
  va_end(args);
965
966
2.16M
  if (integer_obj == NULL)
967
0
  {
968
0
    if (field != NULL)
969
0
      return ERROR_INSUFFICIENT_MEMORY;
970
0
    else
971
0
      return ERROR_INVALID_ARGUMENT;
972
0
  }
973
974
2.16M
  assert(integer_obj->type == OBJECT_TYPE_INTEGER);
975
976
2.16M
  integer_obj->value.i = value;
977
978
2.16M
  return ERROR_SUCCESS;
979
2.16M
}
980
981
int yr_object_set_float(double value, YR_OBJECT* object, const char* field, ...)
982
0
{
983
0
  YR_OBJECT* double_obj;
984
985
0
  va_list args;
986
0
  va_start(args, field);
987
988
0
  if (field != NULL)
989
0
    double_obj = _yr_object_lookup(object, OBJECT_CREATE, field, args);
990
0
  else
991
0
    double_obj = object;
992
993
0
  va_end(args);
994
995
0
  if (double_obj == NULL)
996
0
  {
997
0
    if (field != NULL)
998
0
      return ERROR_INSUFFICIENT_MEMORY;
999
0
    else
1000
0
      return ERROR_INVALID_ARGUMENT;
1001
0
  }
1002
1003
0
  assert(double_obj->type == OBJECT_TYPE_FLOAT);
1004
1005
0
  double_obj->value.d = value;
1006
1007
0
  return ERROR_SUCCESS;
1008
0
}
1009
1010
int yr_object_set_string(
1011
    const char* value,
1012
    size_t len,
1013
    YR_OBJECT* object,
1014
    const char* field,
1015
    ...)
1016
1.81M
{
1017
1.81M
  YR_OBJECT* string_obj;
1018
1019
1.81M
  va_list args;
1020
1.81M
  va_start(args, field);
1021
1022
1.81M
  if (field != NULL)
1023
1.81M
    string_obj = _yr_object_lookup(object, OBJECT_CREATE, field, args);
1024
0
  else
1025
0
    string_obj = object;
1026
1027
1.81M
  va_end(args);
1028
1029
1.81M
  if (string_obj == NULL)
1030
0
  {
1031
0
    if (field != NULL)
1032
0
      return ERROR_INSUFFICIENT_MEMORY;
1033
0
    else
1034
0
      return ERROR_INVALID_ARGUMENT;
1035
0
  }
1036
1037
1.81M
  assert(string_obj->type == OBJECT_TYPE_STRING);
1038
1039
1.81M
  if (string_obj->value.ss != NULL)
1040
681
    yr_free(string_obj->value.ss);
1041
1042
1.81M
  if (value != NULL)
1043
1.73M
  {
1044
1.73M
    string_obj->value.ss = (SIZED_STRING*) yr_malloc(
1045
1.73M
        len + sizeof(SIZED_STRING));
1046
1047
1.73M
    if (string_obj->value.ss == NULL)
1048
0
      return ERROR_INSUFFICIENT_MEMORY;
1049
1050
1.73M
    string_obj->value.ss->length = (uint32_t) len;
1051
1.73M
    string_obj->value.ss->flags = 0;
1052
1053
1.73M
    memcpy(string_obj->value.ss->c_string, value, len);
1054
1.73M
    string_obj->value.ss->c_string[len] = '\0';
1055
1.73M
  }
1056
80.0k
  else
1057
80.0k
  {
1058
80.0k
    string_obj->value.ss = NULL;
1059
80.0k
  }
1060
1061
1.81M
  return ERROR_SUCCESS;
1062
1.81M
}
1063
1064
YR_OBJECT* yr_object_get_root(YR_OBJECT* object)
1065
0
{
1066
0
  YR_OBJECT* o = object;
1067
1068
0
  while (o->parent != NULL) o = o->parent;
1069
1070
0
  return o;
1071
0
}
1072
1073
YR_API void yr_object_print_data(
1074
    YR_OBJECT* object,
1075
    int indent,
1076
    int print_identifier)
1077
0
{
1078
0
  YR_DICTIONARY_ITEMS* dict_items;
1079
0
  YR_STRUCTURE_MEMBER* member;
1080
1081
0
  char indent_spaces[32];
1082
1083
0
  indent = yr_min(indent, sizeof(indent_spaces) - 1);
1084
1085
0
  memset(indent_spaces, '\t', indent);
1086
0
  indent_spaces[indent] = '\0';
1087
1088
0
  if (print_identifier && object->type != OBJECT_TYPE_FUNCTION)
1089
0
    printf("%s%s", indent_spaces, object->identifier);
1090
1091
0
  switch (object->type)
1092
0
  {
1093
0
  case OBJECT_TYPE_FLOAT:
1094
0
    if (object->value.i != YR_UNDEFINED)
1095
0
      printf(" = %f", object->value.d);
1096
0
    else
1097
0
      printf(" = YR_UNDEFINED");
1098
1099
0
    break;
1100
1101
0
  case OBJECT_TYPE_INTEGER:
1102
1103
0
    if (object->value.i != YR_UNDEFINED)
1104
0
      printf(" = %" PRId64, object->value.i);
1105
0
    else
1106
0
      printf(" = YR_UNDEFINED");
1107
1108
0
    break;
1109
1110
0
  case OBJECT_TYPE_STRING:
1111
1112
0
    if (object->value.ss != NULL)
1113
0
    {
1114
0
      printf(" = \"");
1115
1116
0
      for (size_t l = 0; l < object->value.ss->length; l++)
1117
0
      {
1118
0
        char c = object->value.ss->c_string[l];
1119
1120
0
        if (isprint((unsigned char) c))
1121
0
          printf("%c", c);
1122
0
        else
1123
0
          printf("\\x%02x", (unsigned char) c);
1124
0
      }
1125
1126
0
      printf("\"");
1127
0
    }
1128
0
    else
1129
0
    {
1130
0
      printf(" = YR_UNDEFINED");
1131
0
    }
1132
1133
0
    break;
1134
1135
0
  case OBJECT_TYPE_STRUCTURE:
1136
1137
0
    member = object_as_structure(object)->members;
1138
1139
0
    while (member != NULL)
1140
0
    {
1141
0
      if (member->object->type != OBJECT_TYPE_FUNCTION)
1142
0
      {
1143
0
        printf("\n");
1144
0
        yr_object_print_data(member->object, indent + 1, 1);
1145
0
      }
1146
0
      member = member->next;
1147
0
    }
1148
1149
0
    break;
1150
1151
0
  case OBJECT_TYPE_ARRAY:
1152
0
    for (int i = 0; i < yr_object_array_length(object); i++)
1153
0
    {
1154
0
      YR_OBJECT* o = yr_object_array_get_item(object, 0, i);
1155
1156
0
      if (o != NULL)
1157
0
      {
1158
0
        printf("\n%s\t[%d]", indent_spaces, i);
1159
0
        yr_object_print_data(o, indent + 1, 0);
1160
0
      }
1161
0
    }
1162
0
    break;
1163
1164
0
  case OBJECT_TYPE_DICTIONARY:
1165
1166
0
    dict_items = object_as_dictionary(object)->items;
1167
1168
0
    if (dict_items != NULL)
1169
0
    {
1170
0
      for (int i = 0; i < dict_items->used; i++)
1171
0
      {
1172
0
        printf("\n%s\t%s", indent_spaces, dict_items->objects[i].key->c_string);
1173
1174
0
        yr_object_print_data(dict_items->objects[i].obj, indent + 1, 0);
1175
0
      }
1176
0
    }
1177
1178
0
    break;
1179
0
  }
1180
0
}