Coverage Report

Created: 2026-01-09 06:04

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
30.1M
{
57
30.1M
  YR_OBJECT* obj;
58
30.1M
  size_t object_size = 0;
59
60
30.1M
  assert(parent != NULL || object != NULL);
61
30.1M
  assert(identifier != NULL);
62
63
30.1M
  switch (type)
64
30.1M
  {
65
2.63M
  case OBJECT_TYPE_STRUCTURE:
66
2.63M
    object_size = sizeof(YR_OBJECT_STRUCTURE);
67
2.63M
    break;
68
1.21M
  case OBJECT_TYPE_ARRAY:
69
1.21M
    object_size = sizeof(YR_OBJECT_ARRAY);
70
1.21M
    break;
71
0
  case OBJECT_TYPE_DICTIONARY:
72
0
    object_size = sizeof(YR_OBJECT_DICTIONARY);
73
0
    break;
74
23.2M
  case OBJECT_TYPE_INTEGER:
75
23.2M
    object_size = sizeof(YR_OBJECT);
76
23.2M
    break;
77
0
  case OBJECT_TYPE_FLOAT:
78
0
    object_size = sizeof(YR_OBJECT);
79
0
    break;
80
3.07M
  case OBJECT_TYPE_STRING:
81
3.07M
    object_size = sizeof(YR_OBJECT);
82
3.07M
    break;
83
8.12k
  case OBJECT_TYPE_FUNCTION:
84
8.12k
    object_size = sizeof(YR_OBJECT_FUNCTION);
85
8.12k
    break;
86
0
  default:
87
0
    assert(false);
88
30.1M
  }
89
90
30.1M
  obj = (YR_OBJECT*) yr_malloc(object_size);
91
92
30.1M
  if (obj == NULL)
93
0
    return ERROR_INSUFFICIENT_MEMORY;
94
95
30.1M
  obj->type = type;
96
30.1M
  obj->identifier = yr_strdup(identifier);
97
30.1M
  obj->parent = parent;
98
30.1M
  obj->data = NULL;
99
100
30.1M
  switch (type)
101
30.1M
  {
102
23.2M
  case OBJECT_TYPE_INTEGER:
103
23.2M
    obj->value.i = YR_UNDEFINED;
104
23.2M
    break;
105
0
  case OBJECT_TYPE_FLOAT:
106
0
    obj->value.d = NAN;
107
0
    break;
108
3.07M
  case OBJECT_TYPE_STRING:
109
3.07M
    obj->value.ss = NULL;
110
3.07M
    break;
111
2.63M
  case OBJECT_TYPE_STRUCTURE:
112
2.63M
    object_as_structure(obj)->members = NULL;
113
2.63M
    break;
114
1.21M
  case OBJECT_TYPE_ARRAY:
115
1.21M
    object_as_array(obj)->items = NULL;
116
1.21M
    object_as_array(obj)->prototype_item = NULL;
117
1.21M
    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
8.12k
  case OBJECT_TYPE_FUNCTION:
123
8.12k
    object_as_function(obj)->return_obj = NULL;
124
89.3k
    for (int i = 0; i < YR_MAX_OVERLOADED_FUNCTIONS; i++)
125
81.2k
    {
126
81.2k
      object_as_function(obj)->prototypes[i].arguments_fmt = NULL;
127
81.2k
      object_as_function(obj)->prototypes[i].code = NULL;
128
81.2k
    }
129
8.12k
    break;
130
30.1M
  }
131
132
30.1M
  if (obj->identifier == NULL)
133
0
  {
134
0
    yr_free(obj);
135
0
    return ERROR_INSUFFICIENT_MEMORY;
136
0
  }
137
138
30.1M
  if (parent != NULL)
139
962k
  {
140
962k
    assert(
141
962k
        parent->type == OBJECT_TYPE_STRUCTURE ||
142
962k
        parent->type == OBJECT_TYPE_ARRAY ||
143
962k
        parent->type == OBJECT_TYPE_DICTIONARY ||
144
962k
        parent->type == OBJECT_TYPE_FUNCTION);
145
146
    // Objects with a parent take the canary from it.
147
962k
    obj->canary = parent->canary;
148
149
962k
    switch (parent->type)
150
962k
    {
151
930k
    case OBJECT_TYPE_STRUCTURE:
152
930k
      FAIL_ON_ERROR_WITH_CLEANUP(yr_object_structure_set_member(parent, obj), {
153
930k
        yr_free((void*) obj->identifier);
154
930k
        yr_free(obj);
155
930k
      });
156
930k
      break;
157
158
24.3k
    case OBJECT_TYPE_ARRAY:
159
24.3k
      object_as_array(parent)->prototype_item = obj;
160
24.3k
      break;
161
162
0
    case OBJECT_TYPE_DICTIONARY:
163
0
      object_as_dictionary(parent)->prototype_item = obj;
164
0
      break;
165
166
8.12k
    case OBJECT_TYPE_FUNCTION:
167
8.12k
      object_as_function(parent)->return_obj = obj;
168
8.12k
      break;
169
962k
    }
170
962k
  }
171
172
30.1M
  if (object != NULL)
173
29.2M
    *object = obj;
174
175
30.1M
  return ERROR_SUCCESS;
176
30.1M
}
177
178
void yr_object_set_canary(YR_OBJECT* object, int canary)
179
4.06k
{
180
4.06k
  object->canary = canary;
181
4.06k
}
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
16.2k
{
191
16.2k
  YR_OBJECT* return_obj;
192
16.2k
  YR_OBJECT* o = NULL;
193
16.2k
  YR_OBJECT_FUNCTION* f = NULL;
194
195
16.2k
  int8_t return_type;
196
197
  // The parent of a function must be a structure.
198
16.2k
  assert(parent != NULL && parent->type == OBJECT_TYPE_STRUCTURE);
199
200
16.2k
  switch (*return_fmt)
201
16.2k
  {
202
16.2k
  case 'i':
203
16.2k
    return_type = OBJECT_TYPE_INTEGER;
204
16.2k
    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
16.2k
  }
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
16.2k
  f = object_as_function(yr_object_lookup_field(parent, identifier));
218
219
  // Overloaded functions must have the same return type.
220
16.2k
  if (f != NULL && return_type != f->return_obj->type)
221
0
    return ERROR_WRONG_RETURN_TYPE;
222
223
16.2k
  if (f == NULL)  // Function doesn't exist yet
224
8.12k
  {
225
8.12k
    FAIL_ON_ERROR(
226
8.12k
        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
8.12k
    FAIL_ON_ERROR(yr_object_create(return_type, "result", o, &return_obj));
232
233
8.12k
    f = object_as_function(o);
234
8.12k
  }
235
236
24.3k
  for (int i = 0; i < YR_MAX_OVERLOADED_FUNCTIONS; i++)
237
24.3k
  {
238
24.3k
    if (f->prototypes[i].arguments_fmt == NULL)
239
16.2k
    {
240
16.2k
      f->prototypes[i].arguments_fmt = arguments_fmt;
241
16.2k
      f->prototypes[i].code = code;
242
243
16.2k
      break;
244
16.2k
    }
245
24.3k
  }
246
247
16.2k
  if (function != NULL)
248
16.2k
    *function = (YR_OBJECT*) f;
249
250
16.2k
  return ERROR_SUCCESS;
251
16.2k
}
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
30.1M
{
322
30.1M
  YR_STRUCTURE_MEMBER* member;
323
30.1M
  YR_STRUCTURE_MEMBER* next_member;
324
30.1M
  YR_ARRAY_ITEMS* array_items;
325
30.1M
  YR_DICTIONARY_ITEMS* dict_items;
326
327
30.1M
  if (object == NULL)
328
0
    return;
329
330
30.1M
  switch (object->type)
331
30.1M
  {
332
2.63M
  case OBJECT_TYPE_STRUCTURE:
333
2.63M
    member = object_as_structure(object)->members;
334
335
30.1M
    while (member != NULL)
336
27.4M
    {
337
27.4M
      next_member = member->next;
338
27.4M
      yr_object_destroy(member->object);
339
27.4M
      yr_free(member);
340
27.4M
      member = next_member;
341
27.4M
    }
342
2.63M
    break;
343
344
3.07M
  case OBJECT_TYPE_STRING:
345
3.07M
    if (object->value.ss != NULL)
346
871k
      yr_free(object->value.ss);
347
3.07M
    break;
348
349
1.21M
  case OBJECT_TYPE_ARRAY:
350
1.21M
    if (object_as_array(object)->prototype_item != NULL)
351
1.21M
      yr_object_destroy(object_as_array(object)->prototype_item);
352
353
1.21M
    array_items = object_as_array(object)->items;
354
355
1.21M
    if (array_items != NULL)
356
9.20k
    {
357
1.60M
      for (int i = 0; i < array_items->length; i++)
358
1.59M
        if (array_items->objects[i] != NULL)
359
1.41M
          yr_object_destroy(array_items->objects[i]);
360
9.20k
    }
361
362
1.21M
    yr_free(array_items);
363
1.21M
    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
8.12k
  case OBJECT_TYPE_FUNCTION:
387
8.12k
    yr_object_destroy(object_as_function(object)->return_obj);
388
8.12k
    break;
389
30.1M
  }
390
391
30.1M
  yr_free((void*) object->identifier);
392
30.1M
  yr_free(object);
393
30.1M
}
394
395
YR_OBJECT* yr_object_lookup_field(YR_OBJECT* object, const char* field_name)
396
56.3M
{
397
56.3M
  YR_STRUCTURE_MEMBER* member;
398
399
56.3M
  assert(object != NULL);
400
56.3M
  assert(object->type == OBJECT_TYPE_STRUCTURE);
401
402
56.3M
  member = object_as_structure(object)->members;
403
404
455M
  while (member != NULL)
405
427M
  {
406
427M
    if (strcmp(member->object->identifier, field_name) == 0)
407
28.4M
      return member->object;
408
409
399M
    member = member->next;
410
399M
  }
411
412
27.8M
  return NULL;
413
56.3M
}
414
415
static YR_OBJECT* _yr_object_lookup(
416
    YR_OBJECT* object,
417
    int flags,
418
    const char* pattern,
419
    va_list args)
420
15.1M
{
421
15.1M
  YR_OBJECT* obj = object;
422
423
15.1M
  const char* p = pattern;
424
15.1M
  const char* key = NULL;
425
426
15.1M
  char str[256];
427
428
15.1M
  int i;
429
15.1M
  int index = -1;
430
431
28.8M
  while (obj != NULL)
432
28.8M
  {
433
28.8M
    i = 0;
434
435
238M
    while (*p != '\0' && *p != '.' && *p != '[' && i < sizeof(str) - 1)
436
209M
    {
437
209M
      str[i++] = *p++;
438
209M
    }
439
440
28.8M
    str[i] = '\0';
441
442
28.8M
    if (obj->type != OBJECT_TYPE_STRUCTURE)
443
0
      return NULL;
444
445
28.8M
    obj = yr_object_lookup_field(obj, str);
446
447
28.8M
    if (obj == NULL)
448
384k
      return NULL;
449
450
28.4M
    if (*p == '[')
451
13.8M
    {
452
13.8M
      p++;
453
454
13.8M
      if (*p == '%')
455
13.8M
      {
456
13.8M
        p++;
457
458
13.8M
        switch (*p++)
459
13.8M
        {
460
13.8M
        case 'i':
461
13.8M
          index = va_arg(args, int);
462
13.8M
          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
13.8M
        }
470
13.8M
      }
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
13.8M
      assert(*p == ']');
492
13.8M
      p++;
493
13.8M
      assert(*p == '.' || *p == '\0');
494
495
13.8M
      switch (obj->type)
496
13.8M
      {
497
13.8M
      case OBJECT_TYPE_ARRAY:
498
13.8M
        assert(index != -1);
499
13.8M
        obj = yr_object_array_get_item(obj, flags, index);
500
13.8M
        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
13.8M
      }
507
13.8M
    }
508
509
28.4M
    if (*p == '\0')
510
14.8M
      break;
511
512
13.6M
    p++;
513
13.6M
  }
514
515
14.8M
  return obj;
516
15.1M
}
517
518
YR_OBJECT* yr_object_lookup(
519
    YR_OBJECT* object,
520
    int flags,
521
    const char* pattern,
522
    ...)
523
194k
{
524
194k
  YR_OBJECT* result;
525
526
194k
  va_list args;
527
194k
  va_start(args, pattern);
528
529
194k
  result = _yr_object_lookup(object, flags, pattern, args);
530
531
194k
  va_end(args);
532
533
194k
  return result;
534
194k
}
535
536
int yr_object_copy(YR_OBJECT* object, YR_OBJECT** object_copy)
537
29.1M
{
538
29.1M
  YR_OBJECT* copy;
539
29.1M
  YR_OBJECT* o;
540
541
29.1M
  YR_STRUCTURE_MEMBER* structure_member;
542
543
29.1M
  *object_copy = NULL;
544
545
29.1M
  FAIL_ON_ERROR(
546
29.1M
      yr_object_create(object->type, object->identifier, NULL, &copy));
547
548
29.1M
  copy->canary = object->canary;
549
550
29.1M
  switch (object->type)
551
29.1M
  {
552
22.3M
  case OBJECT_TYPE_INTEGER:
553
22.3M
    copy->value.i = object->value.i;
554
22.3M
    break;
555
556
0
  case OBJECT_TYPE_FLOAT:
557
0
    copy->value.d = object->value.d;
558
0
    break;
559
560
3.05M
  case OBJECT_TYPE_STRING:
561
562
3.05M
    if (object->value.ss != NULL)
563
0
      copy->value.ss = ss_dup(object->value.ss);
564
3.05M
    else
565
3.05M
      copy->value.ss = NULL;
566
567
3.05M
    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
2.60M
  case OBJECT_TYPE_STRUCTURE:
585
586
2.60M
    structure_member = object_as_structure(object)->members;
587
588
29.1M
    while (structure_member != NULL)
589
26.5M
    {
590
26.5M
      FAIL_ON_ERROR_WITH_CLEANUP(
591
26.5M
          yr_object_copy(structure_member->object, &o),
592
26.5M
          yr_object_destroy(copy));
593
594
26.5M
      FAIL_ON_ERROR_WITH_CLEANUP(yr_object_structure_set_member(copy, o),
595
                                 // cleanup
596
26.5M
                                 yr_free(o);
597
26.5M
                                 yr_object_destroy(copy));
598
599
26.5M
      structure_member = structure_member->next;
600
26.5M
    }
601
602
2.60M
    break;
603
604
2.60M
  case OBJECT_TYPE_ARRAY:
605
606
1.18M
    FAIL_ON_ERROR_WITH_CLEANUP(
607
1.18M
        yr_object_copy(object_as_array(object)->prototype_item, &o),
608
1.18M
        yr_object_destroy(copy));
609
610
1.18M
    object_as_array(copy)->prototype_item = o;
611
612
1.18M
    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
29.1M
  }
627
628
29.1M
  *object_copy = copy;
629
630
29.1M
  return ERROR_SUCCESS;
631
29.1M
}
632
633
int yr_object_structure_set_member(YR_OBJECT* object, YR_OBJECT* member)
634
27.4M
{
635
27.4M
  YR_STRUCTURE_MEMBER* sm;
636
637
27.4M
  assert(object->type == OBJECT_TYPE_STRUCTURE);
638
639
  // Check if the object already have a member with the same identifier
640
641
27.4M
  if (yr_object_lookup_field(object, member->identifier) != NULL)
642
0
    return ERROR_DUPLICATED_STRUCTURE_MEMBER;
643
644
27.4M
  sm = (YR_STRUCTURE_MEMBER*) yr_malloc(sizeof(YR_STRUCTURE_MEMBER));
645
646
27.4M
  if (sm == NULL)
647
0
    return ERROR_INSUFFICIENT_MEMORY;
648
649
27.4M
  member->parent = object;
650
27.4M
  sm->object = member;
651
27.4M
  sm->next = object_as_structure(object)->members;
652
653
27.4M
  object_as_structure(object)->members = sm;
654
655
27.4M
  return ERROR_SUCCESS;
656
27.4M
}
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
13.8M
{
674
13.8M
  YR_OBJECT* result = NULL;
675
13.8M
  YR_OBJECT_ARRAY* array;
676
677
13.8M
  assert(object->type == OBJECT_TYPE_ARRAY);
678
679
13.8M
  if (index < 0)
680
0
    return NULL;
681
682
13.8M
  array = object_as_array(object);
683
684
13.8M
  if (array->items != NULL && array->items->capacity > index)
685
13.8M
    result = array->items->objects[index];
686
687
13.8M
  if (result == NULL && flags & OBJECT_CREATE)
688
1.41M
  {
689
1.41M
    yr_object_copy(array->prototype_item, &result);
690
691
1.41M
    if (result != NULL)
692
1.41M
      yr_object_array_set_item(object, result, index);
693
1.41M
  }
694
695
13.8M
  return result;
696
13.8M
}
697
698
int yr_object_array_set_item(YR_OBJECT* object, YR_OBJECT* item, int index)
699
1.41M
{
700
1.41M
  YR_OBJECT_ARRAY* array;
701
702
1.41M
  int capacity;
703
704
1.41M
  assert(index >= 0);
705
1.41M
  assert(object->type == OBJECT_TYPE_ARRAY);
706
707
1.41M
  array = object_as_array(object);
708
709
1.41M
  if (array->items == NULL)
710
9.20k
  {
711
9.20k
    capacity = 64;
712
713
9.23k
    while (capacity <= index) capacity *= 2;
714
715
9.20k
    array->items = (YR_ARRAY_ITEMS*) yr_malloc(
716
9.20k
        sizeof(YR_ARRAY_ITEMS) + capacity * sizeof(YR_OBJECT*));
717
718
9.20k
    if (array->items == NULL)
719
0
      return ERROR_INSUFFICIENT_MEMORY;
720
721
9.20k
    memset(array->items->objects, 0, capacity * sizeof(YR_OBJECT*));
722
723
9.20k
    array->items->capacity = capacity;
724
9.20k
    array->items->length = 0;
725
9.20k
  }
726
1.40M
  else if (index >= array->items->capacity)
727
3.31k
  {
728
3.31k
    capacity = array->items->capacity * 2;
729
730
3.36k
    while (capacity <= index) capacity *= 2;
731
732
3.31k
    array->items = (YR_ARRAY_ITEMS*) yr_realloc(
733
3.31k
        array->items, sizeof(YR_ARRAY_ITEMS) + capacity * sizeof(YR_OBJECT*));
734
735
3.31k
    if (array->items == NULL)
736
0
      return ERROR_INSUFFICIENT_MEMORY;
737
738
2.30M
    for (int i = array->items->capacity; i < capacity; i++)
739
2.30M
      array->items->objects[i] = NULL;
740
741
3.31k
    array->items->capacity = capacity;
742
3.31k
  }
743
744
1.41M
  item->parent = object;
745
1.41M
  array->items->objects[index] = item;
746
747
1.41M
  if (index >= array->items->length)
748
1.41M
    array->items->length = index + 1;
749
750
1.41M
  return ERROR_SUCCESS;
751
1.41M
}
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
3.95M
{
872
3.95M
  YR_OBJECT* integer_obj;
873
874
3.95M
  va_list args;
875
3.95M
  va_start(args, field);
876
877
3.95M
  if (field != NULL)
878
3.95M
    integer_obj = _yr_object_lookup(object, 0, field, args);
879
0
  else
880
0
    integer_obj = object;
881
882
3.95M
  va_end(args);
883
884
3.95M
  if (integer_obj == NULL)
885
2.30k
    return YR_UNDEFINED;
886
887
3.94M
  assertf(
888
3.94M
      integer_obj->type == OBJECT_TYPE_INTEGER,
889
3.94M
      "type of \"%s\" is not integer\n",
890
3.94M
      field);
891
892
3.94M
  return integer_obj->value.i;
893
3.94M
}
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
10.1M
{
951
10.1M
  YR_OBJECT* integer_obj;
952
953
10.1M
  va_list args;
954
10.1M
  va_start(args, field);
955
956
10.1M
  if (field != NULL)
957
10.1M
    integer_obj = _yr_object_lookup(object, OBJECT_CREATE, field, args);
958
0
  else
959
0
    integer_obj = object;
960
961
10.1M
  va_end(args);
962
963
10.1M
  if (integer_obj == NULL)
964
384k
  {
965
384k
    if (field != NULL)
966
384k
      return ERROR_INSUFFICIENT_MEMORY;
967
0
    else
968
0
      return ERROR_INVALID_ARGUMENT;
969
384k
  }
970
971
10.1M
  assert(integer_obj->type == OBJECT_TYPE_INTEGER);
972
973
9.78M
  integer_obj->value.i = value;
974
975
9.78M
  return ERROR_SUCCESS;
976
9.78M
}
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
871k
{
1014
871k
  YR_OBJECT* string_obj;
1015
1016
871k
  va_list args;
1017
871k
  va_start(args, field);
1018
1019
871k
  if (field != NULL)
1020
871k
    string_obj = _yr_object_lookup(object, OBJECT_CREATE, field, args);
1021
0
  else
1022
0
    string_obj = object;
1023
1024
871k
  va_end(args);
1025
1026
871k
  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
871k
  assert(string_obj->type == OBJECT_TYPE_STRING);
1035
1036
871k
  if (string_obj->value.ss != NULL)
1037
0
    yr_free(string_obj->value.ss);
1038
1039
871k
  if (value != NULL)
1040
871k
  {
1041
871k
    string_obj->value.ss = (SIZED_STRING*) yr_malloc(
1042
871k
        len + sizeof(SIZED_STRING));
1043
1044
871k
    if (string_obj->value.ss == NULL)
1045
0
      return ERROR_INSUFFICIENT_MEMORY;
1046
1047
871k
    string_obj->value.ss->length = (uint32_t) len;
1048
871k
    string_obj->value.ss->flags = 0;
1049
1050
871k
    memcpy(string_obj->value.ss->c_string, value, len);
1051
871k
    string_obj->value.ss->c_string[len] = '\0';
1052
871k
  }
1053
0
  else
1054
0
  {
1055
0
    string_obj->value.ss = NULL;
1056
0
  }
1057
1058
871k
  return ERROR_SUCCESS;
1059
871k
}
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
}