Coverage Report

Created: 2026-08-28 06:16

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
0
{
57
0
  YR_OBJECT* obj;
58
0
  size_t object_size = 0;
59
60
0
  assert(parent != NULL || object != NULL);
61
0
  assert(identifier != NULL);
62
63
0
  switch (type)
64
0
  {
65
0
  case OBJECT_TYPE_STRUCTURE:
66
0
    object_size = sizeof(YR_OBJECT_STRUCTURE);
67
0
    break;
68
0
  case OBJECT_TYPE_ARRAY:
69
0
    object_size = sizeof(YR_OBJECT_ARRAY);
70
0
    break;
71
0
  case OBJECT_TYPE_DICTIONARY:
72
0
    object_size = sizeof(YR_OBJECT_DICTIONARY);
73
0
    break;
74
0
  case OBJECT_TYPE_INTEGER:
75
0
    object_size = sizeof(YR_OBJECT);
76
0
    break;
77
0
  case OBJECT_TYPE_FLOAT:
78
0
    object_size = sizeof(YR_OBJECT);
79
0
    break;
80
0
  case OBJECT_TYPE_STRING:
81
0
    object_size = sizeof(YR_OBJECT);
82
0
    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
0
  }
90
91
0
  obj = (YR_OBJECT*) yr_malloc(object_size);
92
93
0
  if (obj == NULL)
94
0
    return ERROR_INSUFFICIENT_MEMORY;
95
96
0
  obj->type = type;
97
0
  obj->identifier = yr_strdup(identifier);
98
0
  obj->parent = parent;
99
0
  obj->data = NULL;
100
101
0
  switch (type)
102
0
  {
103
0
  case OBJECT_TYPE_INTEGER:
104
0
    obj->value.i = YR_UNDEFINED;
105
0
    break;
106
0
  case OBJECT_TYPE_FLOAT:
107
0
    obj->value.d = NAN;
108
0
    break;
109
0
  case OBJECT_TYPE_STRING:
110
0
    obj->value.ss = NULL;
111
0
    break;
112
0
  case OBJECT_TYPE_STRUCTURE:
113
0
    object_as_structure(obj)->members = NULL;
114
0
    break;
115
0
  case OBJECT_TYPE_ARRAY:
116
0
    object_as_array(obj)->items = NULL;
117
0
    object_as_array(obj)->prototype_item = NULL;
118
0
    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
0
  }
132
133
0
  if (obj->identifier == NULL)
134
0
  {
135
0
    yr_free(obj);
136
0
    return ERROR_INSUFFICIENT_MEMORY;
137
0
  }
138
139
0
  if (parent != NULL)
140
0
  {
141
0
    assert(
142
0
        parent->type == OBJECT_TYPE_STRUCTURE ||
143
0
        parent->type == OBJECT_TYPE_ARRAY ||
144
0
        parent->type == OBJECT_TYPE_DICTIONARY ||
145
0
        parent->type == OBJECT_TYPE_FUNCTION);
146
147
    // Objects with a parent take the canary from it.
148
0
    obj->canary = parent->canary;
149
150
0
    switch (parent->type)
151
0
    {
152
0
    case OBJECT_TYPE_STRUCTURE:
153
0
      FAIL_ON_ERROR_WITH_CLEANUP(yr_object_structure_set_member(parent, obj), {
154
0
        yr_free((void*) obj->identifier);
155
0
        yr_free(obj);
156
0
      });
157
0
      break;
158
159
0
    case OBJECT_TYPE_ARRAY:
160
0
      object_as_array(parent)->prototype_item = obj;
161
0
      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
0
    }
171
0
  }
172
173
0
  if (object != NULL)
174
0
    *object = obj;
175
176
0
  return ERROR_SUCCESS;
177
0
}
178
179
void yr_object_set_canary(YR_OBJECT* object, int canary)
180
0
{
181
0
  object->canary = canary;
182
0
}
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
0
{
325
0
  YR_STRUCTURE_MEMBER* member;
326
0
  YR_STRUCTURE_MEMBER* next_member;
327
0
  YR_ARRAY_ITEMS* array_items;
328
0
  YR_DICTIONARY_ITEMS* dict_items;
329
330
0
  if (object == NULL)
331
0
    return;
332
333
0
  switch (object->type)
334
0
  {
335
0
  case OBJECT_TYPE_STRUCTURE:
336
0
    member = object_as_structure(object)->members;
337
338
0
    while (member != NULL)
339
0
    {
340
0
      next_member = member->next;
341
0
      yr_object_destroy(member->object);
342
0
      yr_free(member);
343
0
      member = next_member;
344
0
    }
345
0
    break;
346
347
0
  case OBJECT_TYPE_STRING:
348
0
    if (object->value.ss != NULL)
349
0
      yr_free(object->value.ss);
350
0
    break;
351
352
0
  case OBJECT_TYPE_ARRAY:
353
0
    if (object_as_array(object)->prototype_item != NULL)
354
0
      yr_object_destroy(object_as_array(object)->prototype_item);
355
356
0
    array_items = object_as_array(object)->items;
357
358
0
    if (array_items != NULL)
359
0
    {
360
0
      for (int i = 0; i < array_items->length; i++)
361
0
        if (array_items->objects[i] != NULL)
362
0
          yr_object_destroy(array_items->objects[i]);
363
0
    }
364
365
0
    yr_free(array_items);
366
0
    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
0
  }
393
394
0
  yr_free((void*) object->identifier);
395
0
  yr_free(object);
396
0
}
397
398
YR_OBJECT* yr_object_lookup_field(YR_OBJECT* object, const char* field_name)
399
0
{
400
0
  YR_STRUCTURE_MEMBER* member;
401
402
0
  assert(object != NULL);
403
0
  assert(object->type == OBJECT_TYPE_STRUCTURE);
404
405
0
  member = object_as_structure(object)->members;
406
407
0
  while (member != NULL)
408
0
  {
409
0
    if (strcmp(member->object->identifier, field_name) == 0)
410
0
      return member->object;
411
412
0
    member = member->next;
413
0
  }
414
415
0
  return NULL;
416
0
}
417
418
static YR_OBJECT* _yr_object_lookup(
419
    YR_OBJECT* object,
420
    int flags,
421
    const char* pattern,
422
    va_list args)
423
0
{
424
0
  YR_OBJECT* obj = object;
425
426
0
  const char* p = pattern;
427
0
  const char* key = NULL;
428
429
0
  char str[256];
430
431
0
  int i;
432
0
  int index = -1;
433
434
0
  while (obj != NULL)
435
0
  {
436
0
    i = 0;
437
438
0
    while (*p != '\0' && *p != '.' && *p != '[' && i < sizeof(str) - 1)
439
0
    {
440
0
      str[i++] = *p++;
441
0
    }
442
443
0
    str[i] = '\0';
444
445
0
    if (obj->type != OBJECT_TYPE_STRUCTURE)
446
0
      return NULL;
447
448
0
    obj = yr_object_lookup_field(obj, str);
449
450
0
    if (obj == NULL)
451
0
      return NULL;
452
453
0
    if (*p == '[')
454
0
    {
455
0
      p++;
456
457
0
      if (*p == '%')
458
0
      {
459
0
        p++;
460
461
0
        switch (*p++)
462
0
        {
463
0
        case 'i':
464
0
          index = va_arg(args, int);
465
0
          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
0
        }
473
0
      }
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
0
      assert(*p == ']');
495
0
      p++;
496
0
      assert(*p == '.' || *p == '\0');
497
498
0
      switch (obj->type)
499
0
      {
500
0
      case OBJECT_TYPE_ARRAY:
501
0
        assert(index != -1);
502
0
        obj = yr_object_array_get_item(obj, flags, index);
503
0
        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
0
      }
510
0
    }
511
512
0
    if (*p == '\0')
513
0
      break;
514
515
0
    p++;
516
0
  }
517
518
0
  return obj;
519
0
}
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
0
{
541
0
  YR_OBJECT* copy;
542
0
  YR_OBJECT* o;
543
544
0
  YR_STRUCTURE_MEMBER* structure_member;
545
546
0
  *object_copy = NULL;
547
548
0
  FAIL_ON_ERROR(
549
0
      yr_object_create(object->type, object->identifier, NULL, &copy));
550
551
0
  copy->canary = object->canary;
552
553
0
  switch (object->type)
554
0
  {
555
0
  case OBJECT_TYPE_INTEGER:
556
0
    copy->value.i = object->value.i;
557
0
    break;
558
559
0
  case OBJECT_TYPE_FLOAT:
560
0
    copy->value.d = object->value.d;
561
0
    break;
562
563
0
  case OBJECT_TYPE_STRING:
564
565
0
    if (object->value.ss != NULL)
566
0
      copy->value.ss = ss_dup(object->value.ss);
567
0
    else
568
0
      copy->value.ss = NULL;
569
570
0
    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
0
  case OBJECT_TYPE_STRUCTURE:
588
589
0
    structure_member = object_as_structure(object)->members;
590
591
0
    while (structure_member != NULL)
592
0
    {
593
0
      FAIL_ON_ERROR_WITH_CLEANUP(
594
0
          yr_object_copy(structure_member->object, &o),
595
0
          yr_object_destroy(copy));
596
597
0
      FAIL_ON_ERROR_WITH_CLEANUP(yr_object_structure_set_member(copy, o),
598
                                 // cleanup
599
0
                                 yr_free(o);
600
0
                                 yr_object_destroy(copy));
601
602
0
      structure_member = structure_member->next;
603
0
    }
604
605
0
    break;
606
607
0
  case OBJECT_TYPE_ARRAY:
608
609
0
    FAIL_ON_ERROR_WITH_CLEANUP(
610
0
        yr_object_copy(object_as_array(object)->prototype_item, &o),
611
0
        yr_object_destroy(copy));
612
613
0
    object_as_array(copy)->prototype_item = o;
614
615
0
    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
0
  }
630
631
0
  *object_copy = copy;
632
633
0
  return ERROR_SUCCESS;
634
0
}
635
636
int yr_object_structure_set_member(YR_OBJECT* object, YR_OBJECT* member)
637
0
{
638
0
  YR_STRUCTURE_MEMBER* sm;
639
640
0
  assert(object->type == OBJECT_TYPE_STRUCTURE);
641
642
  // Check if the object already have a member with the same identifier
643
644
0
  if (yr_object_lookup_field(object, member->identifier) != NULL)
645
0
    return ERROR_DUPLICATED_STRUCTURE_MEMBER;
646
647
0
  sm = (YR_STRUCTURE_MEMBER*) yr_malloc(sizeof(YR_STRUCTURE_MEMBER));
648
649
0
  if (sm == NULL)
650
0
    return ERROR_INSUFFICIENT_MEMORY;
651
652
0
  member->parent = object;
653
0
  sm->object = member;
654
0
  sm->next = object_as_structure(object)->members;
655
656
0
  object_as_structure(object)->members = sm;
657
658
0
  return ERROR_SUCCESS;
659
0
}
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
0
{
677
0
  YR_OBJECT* result = NULL;
678
0
  YR_OBJECT_ARRAY* array;
679
680
0
  assert(object->type == OBJECT_TYPE_ARRAY);
681
682
0
  if (index < 0)
683
0
    return NULL;
684
685
0
  array = object_as_array(object);
686
687
0
  if (array->items != NULL && array->items->capacity > index)
688
0
    result = array->items->objects[index];
689
690
0
  if (result == NULL && flags & OBJECT_CREATE)
691
0
  {
692
0
    yr_object_copy(array->prototype_item, &result);
693
694
0
    if (result != NULL)
695
0
      yr_object_array_set_item(object, result, index);
696
0
  }
697
698
0
  return result;
699
0
}
700
701
int yr_object_array_set_item(YR_OBJECT* object, YR_OBJECT* item, int index)
702
0
{
703
0
  YR_OBJECT_ARRAY* array;
704
705
0
  int capacity;
706
707
0
  assert(index >= 0);
708
0
  assert(object->type == OBJECT_TYPE_ARRAY);
709
710
0
  array = object_as_array(object);
711
712
0
  if (array->items == NULL)
713
0
  {
714
0
    capacity = 64;
715
716
0
    while (capacity <= index) capacity *= 2;
717
718
0
    array->items = (YR_ARRAY_ITEMS*) yr_malloc(
719
0
        sizeof(YR_ARRAY_ITEMS) + capacity * sizeof(YR_OBJECT*));
720
721
0
    if (array->items == NULL)
722
0
      return ERROR_INSUFFICIENT_MEMORY;
723
724
0
    memset(array->items->objects, 0, capacity * sizeof(YR_OBJECT*));
725
726
0
    array->items->capacity = capacity;
727
0
    array->items->length = 0;
728
0
  }
729
0
  else if (index >= array->items->capacity)
730
0
  {
731
0
    capacity = array->items->capacity * 2;
732
733
0
    while (capacity <= index) capacity *= 2;
734
735
0
    array->items = (YR_ARRAY_ITEMS*) yr_realloc(
736
0
        array->items, sizeof(YR_ARRAY_ITEMS) + capacity * sizeof(YR_OBJECT*));
737
738
0
    if (array->items == NULL)
739
0
      return ERROR_INSUFFICIENT_MEMORY;
740
741
0
    for (int i = array->items->capacity; i < capacity; i++)
742
0
      array->items->objects[i] = NULL;
743
744
0
    array->items->capacity = capacity;
745
0
  }
746
747
0
  item->parent = object;
748
0
  array->items->objects[index] = item;
749
750
0
  if (index >= array->items->length)
751
0
    array->items->length = index + 1;
752
753
0
  return ERROR_SUCCESS;
754
0
}
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
0
{
954
0
  YR_OBJECT* integer_obj;
955
956
0
  va_list args;
957
0
  va_start(args, field);
958
959
0
  if (field != NULL)
960
0
    integer_obj = _yr_object_lookup(object, OBJECT_CREATE, field, args);
961
0
  else
962
0
    integer_obj = object;
963
964
0
  va_end(args);
965
966
0
  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
0
  assert(integer_obj->type == OBJECT_TYPE_INTEGER);
975
976
0
  integer_obj->value.i = value;
977
978
0
  return ERROR_SUCCESS;
979
0
}
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
0
{
1017
0
  YR_OBJECT* string_obj;
1018
1019
0
  va_list args;
1020
0
  va_start(args, field);
1021
1022
0
  if (field != NULL)
1023
0
    string_obj = _yr_object_lookup(object, OBJECT_CREATE, field, args);
1024
0
  else
1025
0
    string_obj = object;
1026
1027
0
  va_end(args);
1028
1029
0
  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
0
  assert(string_obj->type == OBJECT_TYPE_STRING);
1038
1039
0
  if (string_obj->value.ss != NULL)
1040
0
    yr_free(string_obj->value.ss);
1041
1042
0
  if (value != NULL)
1043
0
  {
1044
0
    string_obj->value.ss = (SIZED_STRING*) yr_malloc(
1045
0
        len + sizeof(SIZED_STRING));
1046
1047
0
    if (string_obj->value.ss == NULL)
1048
0
      return ERROR_INSUFFICIENT_MEMORY;
1049
1050
0
    string_obj->value.ss->length = (uint32_t) len;
1051
0
    string_obj->value.ss->flags = 0;
1052
1053
0
    memcpy(string_obj->value.ss->c_string, value, len);
1054
0
    string_obj->value.ss->c_string[len] = '\0';
1055
0
  }
1056
0
  else
1057
0
  {
1058
0
    string_obj->value.ss = NULL;
1059
0
  }
1060
1061
0
  return ERROR_SUCCESS;
1062
0
}
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
}