Coverage Report

Created: 2026-07-16 06:11

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