Coverage Report

Created: 2025-11-11 06:56

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