Coverage Report

Created: 2025-07-23 06:46

/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
54.0M
{
57
54.0M
  YR_OBJECT* obj;
58
54.0M
  size_t object_size = 0;
59
60
54.0M
  assert(parent != NULL || object != NULL);
61
54.0M
  assert(identifier != NULL);
62
63
54.0M
  switch (type)
64
54.0M
  {
65
11.3M
  case OBJECT_TYPE_STRUCTURE:
66
11.3M
    object_size = sizeof(YR_OBJECT_STRUCTURE);
67
11.3M
    break;
68
141k
  case OBJECT_TYPE_ARRAY:
69
141k
    object_size = sizeof(YR_OBJECT_ARRAY);
70
141k
    break;
71
7.62k
  case OBJECT_TYPE_DICTIONARY:
72
7.62k
    object_size = sizeof(YR_OBJECT_DICTIONARY);
73
7.62k
    break;
74
28.7M
  case OBJECT_TYPE_INTEGER:
75
28.7M
    object_size = sizeof(YR_OBJECT);
76
28.7M
    break;
77
0
  case OBJECT_TYPE_FLOAT:
78
0
    object_size = sizeof(YR_OBJECT);
79
0
    break;
80
13.6M
  case OBJECT_TYPE_STRING:
81
13.6M
    object_size = sizeof(YR_OBJECT);
82
13.6M
    break;
83
114k
  case OBJECT_TYPE_FUNCTION:
84
114k
    object_size = sizeof(YR_OBJECT_FUNCTION);
85
114k
    break;
86
0
  default:
87
0
    assert(false);
88
54.0M
  }
89
90
54.0M
  obj = (YR_OBJECT*) yr_malloc(object_size);
91
92
54.0M
  if (obj == NULL)
93
0
    return ERROR_INSUFFICIENT_MEMORY;
94
95
54.0M
  obj->type = type;
96
54.0M
  obj->identifier = yr_strdup(identifier);
97
54.0M
  obj->parent = parent;
98
54.0M
  obj->data = NULL;
99
100
54.0M
  switch (type)
101
54.0M
  {
102
28.7M
  case OBJECT_TYPE_INTEGER:
103
28.7M
    obj->value.i = YR_UNDEFINED;
104
28.7M
    break;
105
0
  case OBJECT_TYPE_FLOAT:
106
0
    obj->value.d = NAN;
107
0
    break;
108
13.6M
  case OBJECT_TYPE_STRING:
109
13.6M
    obj->value.ss = NULL;
110
13.6M
    break;
111
11.3M
  case OBJECT_TYPE_STRUCTURE:
112
11.3M
    object_as_structure(obj)->members = NULL;
113
11.3M
    break;
114
141k
  case OBJECT_TYPE_ARRAY:
115
141k
    object_as_array(obj)->items = NULL;
116
141k
    object_as_array(obj)->prototype_item = NULL;
117
141k
    break;
118
7.62k
  case OBJECT_TYPE_DICTIONARY:
119
7.62k
    object_as_dictionary(obj)->items = NULL;
120
7.62k
    object_as_dictionary(obj)->prototype_item = NULL;
121
7.62k
    break;
122
114k
  case OBJECT_TYPE_FUNCTION:
123
114k
    object_as_function(obj)->return_obj = NULL;
124
1.25M
    for (int i = 0; i < YR_MAX_OVERLOADED_FUNCTIONS; i++)
125
1.14M
    {
126
1.14M
      object_as_function(obj)->prototypes[i].arguments_fmt = NULL;
127
1.14M
      object_as_function(obj)->prototypes[i].code = NULL;
128
1.14M
    }
129
114k
    break;
130
54.0M
  }
131
132
54.0M
  if (obj->identifier == NULL)
133
0
  {
134
0
    yr_free(obj);
135
0
    return ERROR_INSUFFICIENT_MEMORY;
136
0
  }
137
138
54.0M
  if (parent != NULL)
139
2.49M
  {
140
2.49M
    assert(
141
2.49M
        parent->type == OBJECT_TYPE_STRUCTURE ||
142
2.49M
        parent->type == OBJECT_TYPE_ARRAY ||
143
2.49M
        parent->type == OBJECT_TYPE_DICTIONARY ||
144
2.49M
        parent->type == OBJECT_TYPE_FUNCTION);
145
146
    // Objects with a parent take the canary from it.
147
2.49M
    obj->canary = parent->canary;
148
149
2.49M
    switch (parent->type)
150
2.49M
    {
151
2.30M
    case OBJECT_TYPE_STRUCTURE:
152
2.30M
      FAIL_ON_ERROR_WITH_CLEANUP(yr_object_structure_set_member(parent, obj), {
153
2.30M
        yr_free((void*) obj->identifier);
154
2.30M
        yr_free(obj);
155
2.30M
      });
156
2.30M
      break;
157
158
68.6k
    case OBJECT_TYPE_ARRAY:
159
68.6k
      object_as_array(parent)->prototype_item = obj;
160
68.6k
      break;
161
162
7.62k
    case OBJECT_TYPE_DICTIONARY:
163
7.62k
      object_as_dictionary(parent)->prototype_item = obj;
164
7.62k
      break;
165
166
114k
    case OBJECT_TYPE_FUNCTION:
167
114k
      object_as_function(parent)->return_obj = obj;
168
114k
      break;
169
2.49M
    }
170
2.49M
  }
171
172
54.0M
  if (object != NULL)
173
51.9M
    *object = obj;
174
175
54.0M
  return ERROR_SUCCESS;
176
54.0M
}
177
178
void yr_object_set_canary(YR_OBJECT* object, int canary)
179
7.62k
{
180
7.62k
  object->canary = canary;
181
7.62k
}
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
236k
{
191
236k
  YR_OBJECT* return_obj;
192
236k
  YR_OBJECT* o = NULL;
193
236k
  YR_OBJECT_FUNCTION* f = NULL;
194
195
236k
  int8_t return_type;
196
197
  // The parent of a function must be a structure.
198
236k
  assert(parent != NULL && parent->type == OBJECT_TYPE_STRUCTURE);
199
200
236k
  switch (*return_fmt)
201
236k
  {
202
236k
  case 'i':
203
236k
    return_type = OBJECT_TYPE_INTEGER;
204
236k
    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
236k
  }
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
236k
  f = object_as_function(yr_object_lookup_field(parent, identifier));
218
219
  // Overloaded functions must have the same return type.
220
236k
  if (f != NULL && return_type != f->return_obj->type)
221
0
    return ERROR_WRONG_RETURN_TYPE;
222
223
236k
  if (f == NULL)  // Function doesn't exist yet
224
114k
  {
225
114k
    FAIL_ON_ERROR(
226
114k
        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
114k
    FAIL_ON_ERROR(yr_object_create(return_type, "result", o, &return_obj));
232
233
114k
    f = object_as_function(o);
234
114k
  }
235
236
533k
  for (int i = 0; i < YR_MAX_OVERLOADED_FUNCTIONS; i++)
237
533k
  {
238
533k
    if (f->prototypes[i].arguments_fmt == NULL)
239
236k
    {
240
236k
      f->prototypes[i].arguments_fmt = arguments_fmt;
241
236k
      f->prototypes[i].code = code;
242
243
236k
      break;
244
236k
    }
245
533k
  }
246
247
236k
  if (function != NULL)
248
236k
    *function = (YR_OBJECT*) f;
249
250
236k
  return ERROR_SUCCESS;
251
236k
}
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
54.0M
{
322
54.0M
  YR_STRUCTURE_MEMBER* member;
323
54.0M
  YR_STRUCTURE_MEMBER* next_member;
324
54.0M
  YR_ARRAY_ITEMS* array_items;
325
54.0M
  YR_DICTIONARY_ITEMS* dict_items;
326
327
54.0M
  if (object == NULL)
328
0
    return;
329
330
54.0M
  switch (object->type)
331
54.0M
  {
332
11.3M
  case OBJECT_TYPE_STRUCTURE:
333
11.3M
    member = object_as_structure(object)->members;
334
335
53.9M
    while (member != NULL)
336
42.5M
    {
337
42.5M
      next_member = member->next;
338
42.5M
      yr_object_destroy(member->object);
339
42.5M
      yr_free(member);
340
42.5M
      member = next_member;
341
42.5M
    }
342
11.3M
    break;
343
344
13.6M
  case OBJECT_TYPE_STRING:
345
13.6M
    if (object->value.ss != NULL)
346
10.1M
      yr_free(object->value.ss);
347
13.6M
    break;
348
349
141k
  case OBJECT_TYPE_ARRAY:
350
141k
    if (object_as_array(object)->prototype_item != NULL)
351
141k
      yr_object_destroy(object_as_array(object)->prototype_item);
352
353
141k
    array_items = object_as_array(object)->items;
354
355
141k
    if (array_items != NULL)
356
85.0k
    {
357
11.2M
      for (int i = 0; i < array_items->length; i++)
358
11.1M
        if (array_items->objects[i] != NULL)
359
11.1M
          yr_object_destroy(array_items->objects[i]);
360
85.0k
    }
361
362
141k
    yr_free(array_items);
363
141k
    break;
364
365
7.62k
  case OBJECT_TYPE_DICTIONARY:
366
7.62k
    if (object_as_dictionary(object)->prototype_item != NULL)
367
7.62k
      yr_object_destroy(object_as_dictionary(object)->prototype_item);
368
369
7.62k
    dict_items = object_as_dictionary(object)->items;
370
371
7.62k
    if (dict_items != NULL)
372
182
    {
373
2.61k
      for (int i = 0; i < dict_items->used; i++)
374
2.43k
      {
375
2.43k
        if (dict_items->objects[i].key != NULL)
376
2.43k
          yr_free(dict_items->objects[i].key);
377
378
2.43k
        if (dict_items->objects[i].obj != NULL)
379
2.43k
          yr_object_destroy(dict_items->objects[i].obj);
380
2.43k
      }
381
182
    }
382
383
7.62k
    yr_free(dict_items);
384
7.62k
    break;
385
386
114k
  case OBJECT_TYPE_FUNCTION:
387
114k
    yr_object_destroy(object_as_function(object)->return_obj);
388
114k
    break;
389
54.0M
  }
390
391
54.0M
  yr_free((void*) object->identifier);
392
54.0M
  yr_free(object);
393
54.0M
}
394
395
YR_OBJECT* yr_object_lookup_field(YR_OBJECT* object, const char* field_name)
396
145M
{
397
145M
  YR_STRUCTURE_MEMBER* member;
398
399
145M
  assert(object != NULL);
400
145M
  assert(object->type == OBJECT_TYPE_STRUCTURE);
401
402
145M
  member = object_as_structure(object)->members;
403
404
993M
  while (member != NULL)
405
951M
  {
406
951M
    if (strcmp(member->object->identifier, field_name) == 0)
407
103M
      return member->object;
408
409
848M
    member = member->next;
410
848M
  }
411
412
42.6M
  return NULL;
413
145M
}
414
415
static YR_OBJECT* _yr_object_lookup(
416
    YR_OBJECT* object,
417
    int flags,
418
    const char* pattern,
419
    va_list args)
420
37.8M
{
421
37.8M
  YR_OBJECT* obj = object;
422
423
37.8M
  const char* p = pattern;
424
37.8M
  const char* key = NULL;
425
426
37.8M
  char str[256];
427
428
37.8M
  int i;
429
37.8M
  int index = -1;
430
431
102M
  while (obj != NULL)
432
102M
  {
433
102M
    i = 0;
434
435
1.25G
    while (*p != '\0' && *p != '.' && *p != '[' && i < sizeof(str) - 1)
436
1.15G
    {
437
1.15G
      str[i++] = *p++;
438
1.15G
    }
439
440
102M
    str[i] = '\0';
441
442
102M
    if (obj->type != OBJECT_TYPE_STRUCTURE)
443
0
      return NULL;
444
445
102M
    obj = yr_object_lookup_field(obj, str);
446
447
102M
    if (obj == NULL)
448
0
      return NULL;
449
450
102M
    if (*p == '[')
451
64.9M
    {
452
64.9M
      p++;
453
454
64.9M
      if (*p == '%')
455
64.9M
      {
456
64.9M
        p++;
457
458
64.9M
        switch (*p++)
459
64.9M
        {
460
64.9M
        case 'i':
461
64.9M
          index = va_arg(args, int);
462
64.9M
          break;
463
8.09k
        case 's':
464
8.09k
          key = va_arg(args, const char*);
465
8.09k
          break;
466
467
0
        default:
468
0
          return NULL;
469
64.9M
        }
470
64.9M
      }
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
64.9M
      assert(*p == ']');
492
64.9M
      p++;
493
64.9M
      assert(*p == '.' || *p == '\0');
494
495
64.9M
      switch (obj->type)
496
64.9M
      {
497
64.9M
      case OBJECT_TYPE_ARRAY:
498
64.9M
        assert(index != -1);
499
64.9M
        obj = yr_object_array_get_item(obj, flags, index);
500
64.9M
        break;
501
502
8.09k
      case OBJECT_TYPE_DICTIONARY:
503
8.09k
        assert(key != NULL);
504
8.09k
        obj = yr_object_dict_get_item(obj, flags, key);
505
8.09k
        break;
506
64.9M
      }
507
64.9M
    }
508
509
102M
    if (*p == '\0')
510
37.8M
      break;
511
512
65.0M
    p++;
513
65.0M
  }
514
515
37.8M
  return obj;
516
37.8M
}
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
51.5M
{
538
51.5M
  YR_OBJECT* copy;
539
51.5M
  YR_OBJECT* o;
540
541
51.5M
  YR_STRUCTURE_MEMBER* structure_member;
542
543
51.5M
  *object_copy = NULL;
544
545
51.5M
  FAIL_ON_ERROR(
546
51.5M
      yr_object_create(object->type, object->identifier, NULL, &copy));
547
548
51.5M
  copy->canary = object->canary;
549
550
51.5M
  switch (object->type)
551
51.5M
  {
552
26.6M
  case OBJECT_TYPE_INTEGER:
553
26.6M
    copy->value.i = object->value.i;
554
26.6M
    break;
555
556
0
  case OBJECT_TYPE_FLOAT:
557
0
    copy->value.d = object->value.d;
558
0
    break;
559
560
13.5M
  case OBJECT_TYPE_STRING:
561
562
13.5M
    if (object->value.ss != NULL)
563
0
      copy->value.ss = ss_dup(object->value.ss);
564
13.5M
    else
565
13.5M
      copy->value.ss = NULL;
566
567
13.5M
    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
11.2M
  case OBJECT_TYPE_STRUCTURE:
585
586
11.2M
    structure_member = object_as_structure(object)->members;
587
588
51.5M
    while (structure_member != NULL)
589
40.2M
    {
590
40.2M
      FAIL_ON_ERROR_WITH_CLEANUP(
591
40.2M
          yr_object_copy(structure_member->object, &o),
592
40.2M
          yr_object_destroy(copy));
593
594
40.2M
      FAIL_ON_ERROR_WITH_CLEANUP(yr_object_structure_set_member(copy, o),
595
                                 // cleanup
596
40.2M
                                 yr_free(o);
597
40.2M
                                 yr_object_destroy(copy));
598
599
40.2M
      structure_member = structure_member->next;
600
40.2M
    }
601
602
11.2M
    break;
603
604
11.2M
  case OBJECT_TYPE_ARRAY:
605
606
72.8k
    FAIL_ON_ERROR_WITH_CLEANUP(
607
72.8k
        yr_object_copy(object_as_array(object)->prototype_item, &o),
608
72.8k
        yr_object_destroy(copy));
609
610
72.8k
    object_as_array(copy)->prototype_item = o;
611
612
72.8k
    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
51.5M
  }
627
628
51.5M
  *object_copy = copy;
629
630
51.5M
  return ERROR_SUCCESS;
631
51.5M
}
632
633
int yr_object_structure_set_member(YR_OBJECT* object, YR_OBJECT* member)
634
42.5M
{
635
42.5M
  YR_STRUCTURE_MEMBER* sm;
636
637
42.5M
  assert(object->type == OBJECT_TYPE_STRUCTURE);
638
639
  // Check if the object already have a member with the same identifier
640
641
42.5M
  if (yr_object_lookup_field(object, member->identifier) != NULL)
642
0
    return ERROR_DUPLICATED_STRUCTURE_MEMBER;
643
644
42.5M
  sm = (YR_STRUCTURE_MEMBER*) yr_malloc(sizeof(YR_STRUCTURE_MEMBER));
645
646
42.5M
  if (sm == NULL)
647
0
    return ERROR_INSUFFICIENT_MEMORY;
648
649
42.5M
  member->parent = object;
650
42.5M
  sm->object = member;
651
42.5M
  sm->next = object_as_structure(object)->members;
652
653
42.5M
  object_as_structure(object)->members = sm;
654
655
42.5M
  return ERROR_SUCCESS;
656
42.5M
}
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
64.9M
{
674
64.9M
  YR_OBJECT* result = NULL;
675
64.9M
  YR_OBJECT_ARRAY* array;
676
677
64.9M
  assert(object->type == OBJECT_TYPE_ARRAY);
678
679
64.9M
  if (index < 0)
680
0
    return NULL;
681
682
64.9M
  array = object_as_array(object);
683
684
64.9M
  if (array->items != NULL && array->items->capacity > index)
685
64.8M
    result = array->items->objects[index];
686
687
64.9M
  if (result == NULL && flags & OBJECT_CREATE)
688
11.1M
  {
689
11.1M
    yr_object_copy(array->prototype_item, &result);
690
691
11.1M
    if (result != NULL)
692
11.1M
      yr_object_array_set_item(object, result, index);
693
11.1M
  }
694
695
64.9M
  return result;
696
64.9M
}
697
698
int yr_object_array_set_item(YR_OBJECT* object, YR_OBJECT* item, int index)
699
11.1M
{
700
11.1M
  YR_OBJECT_ARRAY* array;
701
702
11.1M
  int capacity;
703
704
11.1M
  assert(index >= 0);
705
11.1M
  assert(object->type == OBJECT_TYPE_ARRAY);
706
707
11.1M
  array = object_as_array(object);
708
709
11.1M
  if (array->items == NULL)
710
85.0k
  {
711
85.0k
    capacity = 64;
712
713
85.0k
    while (capacity <= index) capacity *= 2;
714
715
85.0k
    array->items = (YR_ARRAY_ITEMS*) yr_malloc(
716
85.0k
        sizeof(YR_ARRAY_ITEMS) + capacity * sizeof(YR_OBJECT*));
717
718
85.0k
    if (array->items == NULL)
719
0
      return ERROR_INSUFFICIENT_MEMORY;
720
721
85.0k
    memset(array->items->objects, 0, capacity * sizeof(YR_OBJECT*));
722
723
85.0k
    array->items->capacity = capacity;
724
85.0k
    array->items->length = 0;
725
85.0k
  }
726
11.0M
  else if (index >= array->items->capacity)
727
21.5k
  {
728
21.5k
    capacity = array->items->capacity * 2;
729
730
21.5k
    while (capacity <= index) capacity *= 2;
731
732
21.5k
    array->items = (YR_ARRAY_ITEMS*) yr_realloc(
733
21.5k
        array->items, sizeof(YR_ARRAY_ITEMS) + capacity * sizeof(YR_OBJECT*));
734
735
21.5k
    if (array->items == NULL)
736
0
      return ERROR_INSUFFICIENT_MEMORY;
737
738
14.7M
    for (int i = array->items->capacity; i < capacity; i++)
739
14.7M
      array->items->objects[i] = NULL;
740
741
21.5k
    array->items->capacity = capacity;
742
21.5k
  }
743
744
11.1M
  item->parent = object;
745
11.1M
  array->items->objects[index] = item;
746
747
11.1M
  if (index >= array->items->length)
748
11.1M
    array->items->length = index + 1;
749
750
11.1M
  return ERROR_SUCCESS;
751
11.1M
}
752
753
YR_OBJECT* yr_object_dict_get_item(
754
    YR_OBJECT* object,
755
    int flags,
756
    const char* key)
757
8.09k
{
758
8.09k
  YR_OBJECT* result = NULL;
759
8.09k
  YR_OBJECT_DICTIONARY* dict;
760
761
8.09k
  assert(object->type == OBJECT_TYPE_DICTIONARY);
762
763
8.09k
  dict = object_as_dictionary(object);
764
765
8.09k
  if (dict->items != NULL)
766
7.91k
  {
767
522k
    for (int i = 0; i < dict->items->used; i++)
768
514k
    {
769
514k
      if (strcmp(dict->items->objects[i].key->c_string, key) == 0)
770
5.66k
        result = dict->items->objects[i].obj;
771
514k
    }
772
7.91k
  }
773
774
8.09k
  if (result == NULL && flags & OBJECT_CREATE)
775
2.43k
  {
776
2.43k
    yr_object_copy(dict->prototype_item, &result);
777
778
2.43k
    if (result != NULL)
779
2.43k
      yr_object_dict_set_item(object, result, key);
780
2.43k
  }
781
782
8.09k
  return result;
783
8.09k
}
784
785
int yr_object_dict_set_item(YR_OBJECT* object, YR_OBJECT* item, const char* key)
786
2.43k
{
787
2.43k
  YR_OBJECT_DICTIONARY* dict;
788
789
2.43k
  int count;
790
791
2.43k
  assert(object->type == OBJECT_TYPE_DICTIONARY);
792
793
2.43k
  dict = object_as_dictionary(object);
794
795
2.43k
  if (dict->items == NULL)
796
182
  {
797
182
    count = 64;
798
799
182
    dict->items = (YR_DICTIONARY_ITEMS*) yr_malloc(
800
182
        sizeof(YR_DICTIONARY_ITEMS) + count * sizeof(dict->items->objects[0]));
801
802
182
    if (dict->items == NULL)
803
0
      return ERROR_INSUFFICIENT_MEMORY;
804
805
182
    memset(dict->items->objects, 0, count * sizeof(dict->items->objects[0]));
806
807
182
    dict->items->free = count;
808
182
    dict->items->used = 0;
809
182
  }
810
2.24k
  else if (dict->items->free == 0)
811
15
  {
812
15
    count = dict->items->used * 2;
813
15
    dict->items = (YR_DICTIONARY_ITEMS*) yr_realloc(
814
15
        dict->items,
815
15
        sizeof(YR_DICTIONARY_ITEMS) + count * sizeof(dict->items->objects[0]));
816
817
15
    if (dict->items == NULL)
818
0
      return ERROR_INSUFFICIENT_MEMORY;
819
820
1.42k
    for (int i = dict->items->used; i < count; i++)
821
1.40k
    {
822
1.40k
      dict->items->objects[i].key = NULL;
823
1.40k
      dict->items->objects[i].obj = NULL;
824
1.40k
    }
825
826
15
    dict->items->free = dict->items->used;
827
15
  }
828
829
2.43k
  item->parent = object;
830
831
2.43k
  dict->items->objects[dict->items->used].key = ss_new(key);
832
2.43k
  dict->items->objects[dict->items->used].obj = item;
833
834
2.43k
  dict->items->used++;
835
2.43k
  dict->items->free--;
836
837
2.43k
  return ERROR_SUCCESS;
838
2.43k
}
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
27.7M
{
951
27.7M
  YR_OBJECT* integer_obj;
952
953
27.7M
  va_list args;
954
27.7M
  va_start(args, field);
955
956
27.7M
  if (field != NULL)
957
27.7M
    integer_obj = _yr_object_lookup(object, OBJECT_CREATE, field, args);
958
2.72k
  else
959
2.72k
    integer_obj = object;
960
961
27.7M
  va_end(args);
962
963
27.7M
  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
27.7M
  assert(integer_obj->type == OBJECT_TYPE_INTEGER);
972
973
27.7M
  integer_obj->value.i = value;
974
975
27.7M
  return ERROR_SUCCESS;
976
27.7M
}
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
10.1M
{
1014
10.1M
  YR_OBJECT* string_obj;
1015
1016
10.1M
  va_list args;
1017
10.1M
  va_start(args, field);
1018
1019
10.1M
  if (field != NULL)
1020
10.1M
    string_obj = _yr_object_lookup(object, OBJECT_CREATE, field, args);
1021
0
  else
1022
0
    string_obj = object;
1023
1024
10.1M
  va_end(args);
1025
1026
10.1M
  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
10.1M
  assert(string_obj->type == OBJECT_TYPE_STRING);
1035
1036
10.1M
  if (string_obj->value.ss != NULL)
1037
5.66k
    yr_free(string_obj->value.ss);
1038
1039
10.1M
  if (value != NULL)
1040
10.1M
  {
1041
10.1M
    string_obj->value.ss = (SIZED_STRING*) yr_malloc(
1042
10.1M
        len + sizeof(SIZED_STRING));
1043
1044
10.1M
    if (string_obj->value.ss == NULL)
1045
0
      return ERROR_INSUFFICIENT_MEMORY;
1046
1047
10.1M
    string_obj->value.ss->length = (uint32_t) len;
1048
10.1M
    string_obj->value.ss->flags = 0;
1049
1050
10.1M
    memcpy(string_obj->value.ss->c_string, value, len);
1051
10.1M
    string_obj->value.ss->c_string[len] = '\0';
1052
10.1M
  }
1053
713
  else
1054
713
  {
1055
713
    string_obj->value.ss = NULL;
1056
713
  }
1057
1058
10.1M
  return ERROR_SUCCESS;
1059
10.1M
}
1060
1061
YR_OBJECT* yr_object_get_root(YR_OBJECT* object)
1062
2.72k
{
1063
2.72k
  YR_OBJECT* o = object;
1064
1065
5.45k
  while (o->parent != NULL) o = o->parent;
1066
1067
2.72k
  return o;
1068
2.72k
}
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
}