Coverage Report

Created: 2026-05-30 06:36

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
35.5M
{
57
35.5M
  YR_OBJECT* obj;
58
35.5M
  size_t object_size = 0;
59
60
35.5M
  assert(parent != NULL || object != NULL);
61
35.5M
  assert(identifier != NULL);
62
63
35.5M
  switch (type)
64
35.5M
  {
65
5.98M
  case OBJECT_TYPE_STRUCTURE:
66
5.98M
    object_size = sizeof(YR_OBJECT_STRUCTURE);
67
5.98M
    break;
68
1.45M
  case OBJECT_TYPE_ARRAY:
69
1.45M
    object_size = sizeof(YR_OBJECT_ARRAY);
70
1.45M
    break;
71
178
  case OBJECT_TYPE_DICTIONARY:
72
178
    object_size = sizeof(YR_OBJECT_DICTIONARY);
73
178
    break;
74
22.6M
  case OBJECT_TYPE_INTEGER:
75
22.6M
    object_size = sizeof(YR_OBJECT);
76
22.6M
    break;
77
22.2k
  case OBJECT_TYPE_FLOAT:
78
22.2k
    object_size = sizeof(YR_OBJECT);
79
22.2k
    break;
80
5.37M
  case OBJECT_TYPE_STRING:
81
5.37M
    object_size = sizeof(YR_OBJECT);
82
5.37M
    break;
83
33.9k
  case OBJECT_TYPE_FUNCTION:
84
33.9k
    object_size = sizeof(YR_OBJECT_FUNCTION);
85
33.9k
    break;
86
0
  default:
87
0
    assert(false);
88
35.5M
  }
89
90
35.5M
  obj = (YR_OBJECT*) yr_malloc(object_size);
91
92
35.5M
  if (obj == NULL)
93
0
    return ERROR_INSUFFICIENT_MEMORY;
94
95
35.5M
  obj->type = type;
96
35.5M
  obj->identifier = yr_strdup(identifier);
97
35.5M
  obj->parent = parent;
98
35.5M
  obj->data = NULL;
99
100
35.5M
  switch (type)
101
35.5M
  {
102
22.6M
  case OBJECT_TYPE_INTEGER:
103
22.6M
    obj->value.i = YR_UNDEFINED;
104
22.6M
    break;
105
22.2k
  case OBJECT_TYPE_FLOAT:
106
22.2k
    obj->value.d = NAN;
107
22.2k
    break;
108
5.37M
  case OBJECT_TYPE_STRING:
109
5.37M
    obj->value.ss = NULL;
110
5.37M
    break;
111
5.98M
  case OBJECT_TYPE_STRUCTURE:
112
5.98M
    object_as_structure(obj)->members = NULL;
113
5.98M
    break;
114
1.45M
  case OBJECT_TYPE_ARRAY:
115
1.45M
    object_as_array(obj)->items = NULL;
116
1.45M
    object_as_array(obj)->prototype_item = NULL;
117
1.45M
    break;
118
178
  case OBJECT_TYPE_DICTIONARY:
119
178
    object_as_dictionary(obj)->items = NULL;
120
178
    object_as_dictionary(obj)->prototype_item = NULL;
121
178
    break;
122
33.9k
  case OBJECT_TYPE_FUNCTION:
123
33.9k
    object_as_function(obj)->return_obj = NULL;
124
373k
    for (int i = 0; i < YR_MAX_OVERLOADED_FUNCTIONS; i++)
125
339k
    {
126
339k
      object_as_function(obj)->prototypes[i].arguments_fmt = NULL;
127
339k
      object_as_function(obj)->prototypes[i].code = NULL;
128
339k
    }
129
33.9k
    break;
130
35.5M
  }
131
132
35.5M
  if (obj->identifier == NULL)
133
0
  {
134
0
    yr_free(obj);
135
0
    return ERROR_INSUFFICIENT_MEMORY;
136
0
  }
137
138
35.5M
  if (parent != NULL)
139
1.76M
  {
140
1.76M
    assert(
141
1.76M
        parent->type == OBJECT_TYPE_STRUCTURE ||
142
1.76M
        parent->type == OBJECT_TYPE_ARRAY ||
143
1.76M
        parent->type == OBJECT_TYPE_DICTIONARY ||
144
1.76M
        parent->type == OBJECT_TYPE_FUNCTION);
145
146
    // Objects with a parent take the canary from it.
147
1.76M
    obj->canary = parent->canary;
148
149
1.76M
    switch (parent->type)
150
1.76M
    {
151
1.58M
    case OBJECT_TYPE_STRUCTURE:
152
1.58M
      FAIL_ON_ERROR_WITH_CLEANUP(yr_object_structure_set_member(parent, obj), {
153
1.58M
        yr_free((void*) obj->identifier);
154
1.58M
        yr_free(obj);
155
1.58M
      });
156
1.58M
      break;
157
158
140k
    case OBJECT_TYPE_ARRAY:
159
140k
      object_as_array(parent)->prototype_item = obj;
160
140k
      break;
161
162
178
    case OBJECT_TYPE_DICTIONARY:
163
178
      object_as_dictionary(parent)->prototype_item = obj;
164
178
      break;
165
166
33.9k
    case OBJECT_TYPE_FUNCTION:
167
33.9k
      object_as_function(parent)->return_obj = obj;
168
33.9k
      break;
169
1.76M
    }
170
1.76M
  }
171
172
35.5M
  if (object != NULL)
173
34.0M
    *object = obj;
174
175
35.5M
  return ERROR_SUCCESS;
176
35.5M
}
177
178
void yr_object_set_canary(YR_OBJECT* object, int canary)
179
16.4k
{
180
16.4k
  object->canary = canary;
181
16.4k
}
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
51.8k
{
191
51.8k
  YR_OBJECT* return_obj;
192
51.8k
  YR_OBJECT* o = NULL;
193
51.8k
  YR_OBJECT_FUNCTION* f = NULL;
194
195
51.8k
  int8_t return_type;
196
197
  // The parent of a function must be a structure.
198
51.8k
  assert(parent != NULL && parent->type == OBJECT_TYPE_STRUCTURE);
199
200
51.8k
  switch (*return_fmt)
201
51.8k
  {
202
20.1k
  case 'i':
203
20.1k
    return_type = OBJECT_TYPE_INTEGER;
204
20.1k
    break;
205
11.0k
  case 's':
206
11.0k
    return_type = OBJECT_TYPE_STRING;
207
11.0k
    break;
208
20.7k
  case 'f':
209
20.7k
    return_type = OBJECT_TYPE_FLOAT;
210
20.7k
    break;
211
0
  default:
212
0
    return ERROR_INVALID_FORMAT;
213
51.8k
  }
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
51.8k
  f = object_as_function(yr_object_lookup_field(parent, identifier));
218
219
  // Overloaded functions must have the same return type.
220
51.8k
  if (f != NULL && return_type != f->return_obj->type)
221
0
    return ERROR_WRONG_RETURN_TYPE;
222
223
51.8k
  if (f == NULL)  // Function doesn't exist yet
224
33.9k
  {
225
33.9k
    FAIL_ON_ERROR(
226
33.9k
        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
33.9k
    FAIL_ON_ERROR(yr_object_create(return_type, "result", o, &return_obj));
232
233
33.9k
    f = object_as_function(o);
234
33.9k
  }
235
236
73.1k
  for (int i = 0; i < YR_MAX_OVERLOADED_FUNCTIONS; i++)
237
73.1k
  {
238
73.1k
    if (f->prototypes[i].arguments_fmt == NULL)
239
51.8k
    {
240
51.8k
      f->prototypes[i].arguments_fmt = arguments_fmt;
241
51.8k
      f->prototypes[i].code = code;
242
243
51.8k
      break;
244
51.8k
    }
245
73.1k
  }
246
247
51.8k
  if (function != NULL)
248
51.8k
    *function = (YR_OBJECT*) f;
249
250
51.8k
  return ERROR_SUCCESS;
251
51.8k
}
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
35.5M
{
322
35.5M
  YR_STRUCTURE_MEMBER* member;
323
35.5M
  YR_STRUCTURE_MEMBER* next_member;
324
35.5M
  YR_ARRAY_ITEMS* array_items;
325
35.5M
  YR_DICTIONARY_ITEMS* dict_items;
326
327
35.5M
  if (object == NULL)
328
0
    return;
329
330
35.5M
  switch (object->type)
331
35.5M
  {
332
5.98M
  case OBJECT_TYPE_STRUCTURE:
333
5.98M
    member = object_as_structure(object)->members;
334
335
34.6M
    while (member != NULL)
336
28.7M
    {
337
28.7M
      next_member = member->next;
338
28.7M
      yr_object_destroy(member->object);
339
28.7M
      yr_free(member);
340
28.7M
      member = next_member;
341
28.7M
    }
342
5.98M
    break;
343
344
5.37M
  case OBJECT_TYPE_STRING:
345
5.37M
    if (object->value.ss != NULL)
346
1.82M
      yr_free(object->value.ss);
347
5.37M
    break;
348
349
1.45M
  case OBJECT_TYPE_ARRAY:
350
1.45M
    if (object_as_array(object)->prototype_item != NULL)
351
1.45M
      yr_object_destroy(object_as_array(object)->prototype_item);
352
353
1.45M
    array_items = object_as_array(object)->items;
354
355
1.45M
    if (array_items != NULL)
356
63.7k
    {
357
5.44M
      for (int i = 0; i < array_items->length; i++)
358
5.38M
        if (array_items->objects[i] != NULL)
359
5.30M
          yr_object_destroy(array_items->objects[i]);
360
63.7k
    }
361
362
1.45M
    yr_free(array_items);
363
1.45M
    break;
364
365
178
  case OBJECT_TYPE_DICTIONARY:
366
178
    if (object_as_dictionary(object)->prototype_item != NULL)
367
178
      yr_object_destroy(object_as_dictionary(object)->prototype_item);
368
369
178
    dict_items = object_as_dictionary(object)->items;
370
371
178
    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
178
    yr_free(dict_items);
384
178
    break;
385
386
33.9k
  case OBJECT_TYPE_FUNCTION:
387
33.9k
    yr_object_destroy(object_as_function(object)->return_obj);
388
33.9k
    break;
389
35.5M
  }
390
391
35.5M
  yr_free((void*) object->identifier);
392
35.5M
  yr_free(object);
393
35.5M
}
394
395
YR_OBJECT* yr_object_lookup_field(YR_OBJECT* object, const char* field_name)
396
83.9M
{
397
83.9M
  YR_STRUCTURE_MEMBER* member;
398
399
83.9M
  assert(object != NULL);
400
83.9M
  assert(object->type == OBJECT_TYPE_STRUCTURE);
401
402
83.9M
  member = object_as_structure(object)->members;
403
404
737M
  while (member != NULL)
405
708M
  {
406
708M
    if (strcmp(member->object->identifier, field_name) == 0)
407
55.2M
      return member->object;
408
409
653M
    member = member->next;
410
653M
  }
411
412
28.7M
  return NULL;
413
83.9M
}
414
415
static YR_OBJECT* _yr_object_lookup(
416
    YR_OBJECT* object,
417
    int flags,
418
    const char* pattern,
419
    va_list args)
420
27.5M
{
421
27.5M
  YR_OBJECT* obj = object;
422
423
27.5M
  const char* p = pattern;
424
27.5M
  const char* key = NULL;
425
426
27.5M
  char str[256];
427
428
27.5M
  int i;
429
27.5M
  int index = -1;
430
431
55.1M
  while (obj != NULL)
432
55.1M
  {
433
55.1M
    i = 0;
434
435
434M
    while (*p != '\0' && *p != '.' && *p != '[' && i < sizeof(str) - 1)
436
379M
    {
437
379M
      str[i++] = *p++;
438
379M
    }
439
440
55.1M
    str[i] = '\0';
441
442
55.1M
    if (obj->type != OBJECT_TYPE_STRUCTURE)
443
0
      return NULL;
444
445
55.1M
    obj = yr_object_lookup_field(obj, str);
446
447
55.1M
    if (obj == NULL)
448
0
      return NULL;
449
450
55.1M
    if (*p == '[')
451
27.2M
    {
452
27.2M
      p++;
453
454
27.2M
      if (*p == '%')
455
27.2M
      {
456
27.2M
        p++;
457
458
27.2M
        switch (*p++)
459
27.2M
        {
460
27.2M
        case 'i':
461
27.2M
          index = va_arg(args, int);
462
27.2M
          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
27.2M
        }
470
27.2M
      }
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
27.2M
      assert(*p == ']');
492
27.2M
      p++;
493
27.2M
      assert(*p == '.' || *p == '\0');
494
495
27.2M
      switch (obj->type)
496
27.2M
      {
497
27.2M
      case OBJECT_TYPE_ARRAY:
498
27.2M
        assert(index != -1);
499
27.2M
        obj = yr_object_array_get_item(obj, flags, index);
500
27.2M
        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
27.2M
      }
507
27.2M
    }
508
509
55.1M
    if (*p == '\0')
510
27.5M
      break;
511
512
27.6M
    p++;
513
27.6M
  }
514
515
27.5M
  return obj;
516
27.5M
}
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
33.7M
{
538
33.7M
  YR_OBJECT* copy;
539
33.7M
  YR_OBJECT* o;
540
541
33.7M
  YR_STRUCTURE_MEMBER* structure_member;
542
543
33.7M
  *object_copy = NULL;
544
545
33.7M
  FAIL_ON_ERROR(
546
33.7M
      yr_object_create(object->type, object->identifier, NULL, &copy));
547
548
33.7M
  copy->canary = object->canary;
549
550
33.7M
  switch (object->type)
551
33.7M
  {
552
21.4M
  case OBJECT_TYPE_INTEGER:
553
21.4M
    copy->value.i = object->value.i;
554
21.4M
    break;
555
556
10.0k
  case OBJECT_TYPE_FLOAT:
557
10.0k
    copy->value.d = object->value.d;
558
10.0k
    break;
559
560
5.15M
  case OBJECT_TYPE_STRING:
561
562
5.15M
    if (object->value.ss != NULL)
563
0
      copy->value.ss = ss_dup(object->value.ss);
564
5.15M
    else
565
5.15M
      copy->value.ss = NULL;
566
567
5.15M
    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
5.86M
  case OBJECT_TYPE_STRUCTURE:
585
586
5.86M
    structure_member = object_as_structure(object)->members;
587
588
32.9M
    while (structure_member != NULL)
589
27.1M
    {
590
27.1M
      FAIL_ON_ERROR_WITH_CLEANUP(
591
27.1M
          yr_object_copy(structure_member->object, &o),
592
27.1M
          yr_object_destroy(copy));
593
594
27.1M
      FAIL_ON_ERROR_WITH_CLEANUP(yr_object_structure_set_member(copy, o),
595
                                 // cleanup
596
27.1M
                                 yr_free(o);
597
27.1M
                                 yr_object_destroy(copy));
598
599
27.1M
      structure_member = structure_member->next;
600
27.1M
    }
601
602
5.86M
    break;
603
604
5.86M
  case OBJECT_TYPE_ARRAY:
605
606
1.31M
    FAIL_ON_ERROR_WITH_CLEANUP(
607
1.31M
        yr_object_copy(object_as_array(object)->prototype_item, &o),
608
1.31M
        yr_object_destroy(copy));
609
610
1.31M
    object_as_array(copy)->prototype_item = o;
611
612
1.31M
    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
33.7M
  }
627
628
33.7M
  *object_copy = copy;
629
630
33.7M
  return ERROR_SUCCESS;
631
33.7M
}
632
633
int yr_object_structure_set_member(YR_OBJECT* object, YR_OBJECT* member)
634
28.7M
{
635
28.7M
  YR_STRUCTURE_MEMBER* sm;
636
637
28.7M
  assert(object->type == OBJECT_TYPE_STRUCTURE);
638
639
  // Check if the object already have a member with the same identifier
640
641
28.7M
  if (yr_object_lookup_field(object, member->identifier) != NULL)
642
0
    return ERROR_DUPLICATED_STRUCTURE_MEMBER;
643
644
28.7M
  sm = (YR_STRUCTURE_MEMBER*) yr_malloc(sizeof(YR_STRUCTURE_MEMBER));
645
646
28.7M
  if (sm == NULL)
647
0
    return ERROR_INSUFFICIENT_MEMORY;
648
649
28.7M
  member->parent = object;
650
28.7M
  sm->object = member;
651
28.7M
  sm->next = object_as_structure(object)->members;
652
653
28.7M
  object_as_structure(object)->members = sm;
654
655
28.7M
  return ERROR_SUCCESS;
656
28.7M
}
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
27.2M
{
674
27.2M
  YR_OBJECT* result = NULL;
675
27.2M
  YR_OBJECT_ARRAY* array;
676
677
27.2M
  assert(object->type == OBJECT_TYPE_ARRAY);
678
679
27.2M
  if (index < 0)
680
0
    return NULL;
681
682
27.2M
  array = object_as_array(object);
683
684
27.2M
  if (array->items != NULL && array->items->capacity > index)
685
27.1M
    result = array->items->objects[index];
686
687
27.2M
  if (result == NULL && flags & OBJECT_CREATE)
688
5.30M
  {
689
5.30M
    yr_object_copy(array->prototype_item, &result);
690
691
5.30M
    if (result != NULL)
692
5.30M
      yr_object_array_set_item(object, result, index);
693
5.30M
  }
694
695
27.2M
  return result;
696
27.2M
}
697
698
int yr_object_array_set_item(YR_OBJECT* object, YR_OBJECT* item, int index)
699
5.30M
{
700
5.30M
  YR_OBJECT_ARRAY* array;
701
702
5.30M
  int capacity;
703
704
5.30M
  assert(index >= 0);
705
5.30M
  assert(object->type == OBJECT_TYPE_ARRAY);
706
707
5.30M
  array = object_as_array(object);
708
709
5.30M
  if (array->items == NULL)
710
63.7k
  {
711
63.7k
    capacity = 64;
712
713
63.8k
    while (capacity <= index) capacity *= 2;
714
715
63.7k
    array->items = (YR_ARRAY_ITEMS*) yr_malloc(
716
63.7k
        sizeof(YR_ARRAY_ITEMS) + capacity * sizeof(YR_OBJECT*));
717
718
63.7k
    if (array->items == NULL)
719
0
      return ERROR_INSUFFICIENT_MEMORY;
720
721
63.7k
    memset(array->items->objects, 0, capacity * sizeof(YR_OBJECT*));
722
723
63.7k
    array->items->capacity = capacity;
724
63.7k
    array->items->length = 0;
725
63.7k
  }
726
5.24M
  else if (index >= array->items->capacity)
727
5.88k
  {
728
5.88k
    capacity = array->items->capacity * 2;
729
730
5.90k
    while (capacity <= index) capacity *= 2;
731
732
5.88k
    array->items = (YR_ARRAY_ITEMS*) yr_realloc(
733
5.88k
        array->items, sizeof(YR_ARRAY_ITEMS) + capacity * sizeof(YR_OBJECT*));
734
735
5.88k
    if (array->items == NULL)
736
0
      return ERROR_INSUFFICIENT_MEMORY;
737
738
5.98M
    for (int i = array->items->capacity; i < capacity; i++)
739
5.97M
      array->items->objects[i] = NULL;
740
741
5.88k
    array->items->capacity = capacity;
742
5.88k
  }
743
744
5.30M
  item->parent = object;
745
5.30M
  array->items->objects[index] = item;
746
747
5.30M
  if (index >= array->items->length)
748
5.30M
    array->items->length = index + 1;
749
750
5.30M
  return ERROR_SUCCESS;
751
5.30M
}
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
25.6M
{
951
25.6M
  YR_OBJECT* integer_obj;
952
953
25.6M
  va_list args;
954
25.6M
  va_start(args, field);
955
956
25.6M
  if (field != NULL)
957
25.6M
    integer_obj = _yr_object_lookup(object, OBJECT_CREATE, field, args);
958
4.85k
  else
959
4.85k
    integer_obj = object;
960
961
25.6M
  va_end(args);
962
963
25.6M
  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
25.6M
  assert(integer_obj->type == OBJECT_TYPE_INTEGER);
972
973
25.6M
  integer_obj->value.i = value;
974
975
25.6M
  return ERROR_SUCCESS;
976
25.6M
}
977
978
int yr_object_set_float(double value, YR_OBJECT* object, const char* field, ...)
979
11.8k
{
980
11.8k
  YR_OBJECT* double_obj;
981
982
11.8k
  va_list args;
983
11.8k
  va_start(args, field);
984
985
11.8k
  if (field != NULL)
986
1.71k
    double_obj = _yr_object_lookup(object, OBJECT_CREATE, field, args);
987
10.0k
  else
988
10.0k
    double_obj = object;
989
990
11.8k
  va_end(args);
991
992
11.8k
  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
11.8k
  assert(double_obj->type == OBJECT_TYPE_FLOAT);
1001
1002
11.8k
  double_obj->value.d = value;
1003
1004
11.8k
  return ERROR_SUCCESS;
1005
11.8k
}
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.90M
{
1014
1.90M
  YR_OBJECT* string_obj;
1015
1016
1.90M
  va_list args;
1017
1.90M
  va_start(args, field);
1018
1019
1.90M
  if (field != NULL)
1020
1.90M
    string_obj = _yr_object_lookup(object, OBJECT_CREATE, field, args);
1021
0
  else
1022
0
    string_obj = object;
1023
1024
1.90M
  va_end(args);
1025
1026
1.90M
  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.90M
  assert(string_obj->type == OBJECT_TYPE_STRING);
1035
1036
1.90M
  if (string_obj->value.ss != NULL)
1037
787
    yr_free(string_obj->value.ss);
1038
1039
1.90M
  if (value != NULL)
1040
1.82M
  {
1041
1.82M
    string_obj->value.ss = (SIZED_STRING*) yr_malloc(
1042
1.82M
        len + sizeof(SIZED_STRING));
1043
1044
1.82M
    if (string_obj->value.ss == NULL)
1045
0
      return ERROR_INSUFFICIENT_MEMORY;
1046
1047
1.82M
    string_obj->value.ss->length = (uint32_t) len;
1048
1.82M
    string_obj->value.ss->flags = 0;
1049
1050
1.82M
    memcpy(string_obj->value.ss->c_string, value, len);
1051
1.82M
    string_obj->value.ss->c_string[len] = '\0';
1052
1.82M
  }
1053
77.1k
  else
1054
77.1k
  {
1055
77.1k
    string_obj->value.ss = NULL;
1056
77.1k
  }
1057
1058
1.90M
  return ERROR_SUCCESS;
1059
1.90M
}
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
}