Coverage Report

Created: 2025-09-05 06:54

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