Coverage Report

Created: 2026-06-07 07:09

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/fluent-bit/lib/cprofiles/cprof_decode_opentelemetry.c
Line
Count
Source
1
/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2
3
/*  CProfiles
4
 *  =========
5
 *  Copyright (C) 2024 The CProfiles Authors
6
 *
7
 *  Licensed under the Apache License, Version 2.0 (the "License");
8
 *  you may not use this file except in compliance with the License.
9
 *  You may obtain a copy of the License at
10
 *
11
 *      http://www.apache.org/licenses/LICENSE-2.0
12
 *
13
 *  Unless required by applicable law or agreed to in writing, software
14
 *  distributed under the License is distributed on an "AS IS" BASIS,
15
 *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16
 *  See the License for the specific language governing permissions and
17
 *  limitations under the License.
18
 */
19
20
21
#include <cprofiles/cprof_decode_opentelemetry.h>
22
#include <cfl/cfl_sds.h>
23
24
#include "cprof_opentelemetry_variant_helpers.c"
25
26
static int decode_resource(struct cprof_resource **output_resource,
27
                           Opentelemetry__Proto__Resource__V1__Resource *input_resource,
28
                           Opentelemetry__Proto__Profiles__V1development__ProfilesDictionary *dictionary)
29
0
{
30
0
    struct cfl_kvlist *attributes;
31
0
    int                result;
32
33
0
    *output_resource = NULL;
34
35
0
    if (input_resource == NULL) {
36
0
        *output_resource = cprof_resource_create(NULL);
37
0
        if (*output_resource != NULL) {
38
0
            (*output_resource)->dropped_attributes_count = 0;
39
40
0
            return CPROF_DECODE_OPENTELEMETRY_SUCCESS;
41
0
        }
42
43
0
        return CPROF_DECODE_OPENTELEMETRY_ALLOCATION_ERROR;
44
0
    }
45
46
0
    attributes = cfl_kvlist_create();
47
48
0
    if (attributes == NULL) {
49
0
        return CPROF_DECODE_OPENTELEMETRY_ALLOCATION_ERROR;
50
0
    }
51
52
0
    result = convert_kvarray_to_kvlist(attributes,
53
0
                                       input_resource->attributes,
54
0
                                       input_resource->n_attributes,
55
0
                                       dictionary != NULL ? dictionary->string_table : NULL,
56
0
                                       dictionary != NULL ? dictionary->n_string_table : 0);
57
58
0
    if (result != CPROF_DECODE_OPENTELEMETRY_SUCCESS) {
59
0
        cfl_kvlist_destroy(attributes);
60
0
        return result;
61
0
    }
62
63
0
    *output_resource = cprof_resource_create(attributes);
64
65
0
    if (*output_resource == NULL) {
66
0
        cfl_kvlist_destroy(attributes);
67
68
0
        return CPROF_DECODE_OPENTELEMETRY_ALLOCATION_ERROR;
69
0
    }
70
71
0
    (*output_resource)->dropped_attributes_count = input_resource->dropped_attributes_count;
72
73
0
    return CPROF_DECODE_OPENTELEMETRY_SUCCESS;
74
0
}
75
76
77
static int decode_instrumentation_scope(
78
    struct cprof_instrumentation_scope **instrumentation_scope,
79
    Opentelemetry__Proto__Common__V1__InstrumentationScope *input_instrumentation_scope,
80
    Opentelemetry__Proto__Profiles__V1development__ProfilesDictionary *dictionary)
81
0
{
82
0
    int result;
83
84
0
    *instrumentation_scope = NULL;
85
86
0
    *instrumentation_scope = cprof_instrumentation_scope_create(
87
0
        input_instrumentation_scope->name,
88
0
        input_instrumentation_scope->version,
89
0
        NULL,
90
0
        input_instrumentation_scope->dropped_attributes_count);
91
92
0
    if (*instrumentation_scope == NULL) {
93
0
        return CPROF_DECODE_OPENTELEMETRY_ALLOCATION_ERROR;
94
0
    }
95
96
0
    result = convert_kvarray_to_kvlist((*instrumentation_scope)->attributes,
97
0
                                       input_instrumentation_scope->attributes,
98
0
                                       input_instrumentation_scope->n_attributes,
99
0
                                       dictionary != NULL ? dictionary->string_table : NULL,
100
0
                                       dictionary != NULL ? dictionary->n_string_table : 0);
101
102
0
    if (result != CPROF_DECODE_OPENTELEMETRY_SUCCESS) {
103
0
        cprof_instrumentation_scope_destroy(*instrumentation_scope);
104
0
        *instrumentation_scope = NULL;
105
106
0
        return result;
107
0
    }
108
109
0
    return CPROF_DECODE_OPENTELEMETRY_SUCCESS;
110
0
}
111
112
113
static int decode_profile_sample_entry(struct cprof_sample *sample,
114
    Opentelemetry__Proto__Profiles__V1development__Sample *input_sample,
115
    Opentelemetry__Proto__Profiles__V1development__ProfilesDictionary *dictionary)
116
0
{
117
0
    int32_t location_index;
118
0
    int    result;
119
0
    size_t index;
120
0
    Opentelemetry__Proto__Profiles__V1development__Stack *stack;
121
122
    /* Resolve stack_index to location indices from dictionary.stack_table */
123
0
    if (input_sample->stack_index >= 0) {
124
0
        if (dictionary == NULL ||
125
0
            dictionary->stack_table == NULL ||
126
0
            (size_t) input_sample->stack_index >= dictionary->n_stack_table) {
127
0
            return CPROF_DECODE_OPENTELEMETRY_INVALID_ARGUMENT_ERROR;
128
0
        }
129
130
0
        stack = dictionary->stack_table[input_sample->stack_index];
131
0
        if (stack == NULL) {
132
0
            return CPROF_DECODE_OPENTELEMETRY_INVALID_ARGUMENT_ERROR;
133
0
        }
134
135
0
        if (stack != NULL && stack->location_indices != NULL) {
136
0
            for (index = 0; index < stack->n_location_indices; index++) {
137
0
                location_index = stack->location_indices[index];
138
139
0
                if (location_index < 0 ||
140
0
                    dictionary->location_table == NULL ||
141
0
                    (size_t) location_index >= dictionary->n_location_table) {
142
0
                    return CPROF_DECODE_OPENTELEMETRY_INVALID_ARGUMENT_ERROR;
143
0
                }
144
145
0
                result = cprof_sample_add_location_index(sample,
146
0
                    (uint64_t) location_index);
147
0
                if (result != 0) {
148
0
                    return CPROF_DECODE_OPENTELEMETRY_INVALID_ARGUMENT_ERROR;
149
0
                }
150
0
            }
151
0
        }
152
0
    }
153
154
0
    for (index = 0; index < input_sample->n_values; index++) {
155
0
        result = cprof_sample_add_value(sample, input_sample->values[index]);
156
0
        if (result != 0) {
157
0
            return CPROF_DECODE_OPENTELEMETRY_INVALID_ARGUMENT_ERROR;
158
0
        }
159
0
    }
160
161
0
    for (index = 0; index < input_sample->n_attribute_indices; index++) {
162
0
        if (dictionary == NULL ||
163
0
            dictionary->attribute_table == NULL ||
164
0
            input_sample->attribute_indices[index] < 0 ||
165
0
            (size_t) input_sample->attribute_indices[index] >= dictionary->n_attribute_table) {
166
0
            return CPROF_DECODE_OPENTELEMETRY_INVALID_ARGUMENT_ERROR;
167
0
        }
168
169
0
        result = cprof_sample_add_attribute(sample,
170
0
            (uint64_t)input_sample->attribute_indices[index]);
171
0
        if (result != 0) {
172
0
            return CPROF_DECODE_OPENTELEMETRY_INVALID_ARGUMENT_ERROR;
173
0
        }
174
0
    }
175
176
0
    for (index = 0; index < input_sample->n_timestamps_unix_nano; index++) {
177
0
        result = cprof_sample_add_timestamp(sample,
178
0
            input_sample->timestamps_unix_nano[index]);
179
0
        if (result != 0) {
180
0
            return CPROF_DECODE_OPENTELEMETRY_INVALID_ARGUMENT_ERROR;
181
0
        }
182
0
    }
183
184
0
    if (input_sample->link_index >= 0) {
185
0
        if (dictionary == NULL ||
186
0
            dictionary->link_table == NULL ||
187
0
            (size_t) input_sample->link_index >= dictionary->n_link_table) {
188
0
            return CPROF_DECODE_OPENTELEMETRY_INVALID_ARGUMENT_ERROR;
189
0
        }
190
191
0
        sample->link = (uint64_t) input_sample->link_index;
192
0
    }
193
0
    else {
194
0
        sample->link = 0;
195
0
    }
196
197
0
    return CPROF_DECODE_OPENTELEMETRY_SUCCESS;
198
0
}
199
200
201
202
203
static int decode_mapping_entry(struct cprof_mapping *mapping,
204
    Opentelemetry__Proto__Profiles__V1development__Mapping *input_mapping)
205
0
{
206
0
    int     result;
207
0
    int32_t raw_attribute_index;
208
0
    size_t  index;
209
210
0
    mapping->id = 0;
211
0
    mapping->memory_start = input_mapping->memory_start;
212
0
    mapping->memory_limit = input_mapping->memory_limit;
213
0
    mapping->file_offset = input_mapping->file_offset;
214
0
    mapping->filename = (int64_t)input_mapping->filename_strindex;
215
0
    mapping->has_functions = 0;
216
0
    mapping->has_filenames = 0;
217
0
    mapping->has_line_numbers = 0;
218
0
    mapping->has_inline_frames = 0;
219
220
0
    for (index = 0; index < input_mapping->n_attribute_indices; index++) {
221
0
        raw_attribute_index = input_mapping->attribute_indices[index];
222
223
0
        if (raw_attribute_index < 0) {
224
0
            return CPROF_DECODE_OPENTELEMETRY_INVALID_ARGUMENT_ERROR;
225
0
        }
226
227
0
        result = cprof_mapping_add_attribute(mapping,
228
0
            (uint64_t) raw_attribute_index);
229
0
        if (result != 0) {
230
0
            return CPROF_DECODE_OPENTELEMETRY_INVALID_ARGUMENT_ERROR;
231
0
        }
232
0
    }
233
234
0
    return CPROF_DECODE_OPENTELEMETRY_SUCCESS;
235
0
}
236
237
static int decode_line_entry(struct cprof_line *line,
238
    Opentelemetry__Proto__Profiles__V1development__Line *input_line,
239
    Opentelemetry__Proto__Profiles__V1development__ProfilesDictionary *dictionary)
240
0
{
241
0
    if (input_line->function_index < 0 ||
242
0
        dictionary == NULL ||
243
0
        dictionary->function_table == NULL ||
244
0
        (size_t) input_line->function_index >= dictionary->n_function_table) {
245
0
        return CPROF_DECODE_OPENTELEMETRY_INVALID_ARGUMENT_ERROR;
246
0
    }
247
248
0
    line->function_index = (uint64_t)input_line->function_index;
249
0
    line->line = input_line->line;
250
0
    line->column = input_line->column;
251
252
0
    return CPROF_DECODE_OPENTELEMETRY_SUCCESS;
253
0
}
254
255
static int decode_location_entry(struct cprof_location *location,
256
    Opentelemetry__Proto__Profiles__V1development__Location *input_location,
257
    Opentelemetry__Proto__Profiles__V1development__ProfilesDictionary *dictionary)
258
0
{
259
0
    int                result;
260
0
    int32_t            raw_attribute_index;
261
0
    size_t             index;
262
0
    struct cprof_line *line;
263
264
0
    if (input_location->mapping_index < 0 ||
265
0
        dictionary == NULL ||
266
0
        dictionary->mapping_table == NULL ||
267
0
        (size_t) input_location->mapping_index >= dictionary->n_mapping_table) {
268
0
        return CPROF_DECODE_OPENTELEMETRY_INVALID_ARGUMENT_ERROR;
269
0
    }
270
271
0
    location->id = 0;
272
0
    location->mapping_index = (uint64_t)input_location->mapping_index;
273
0
    location->address = input_location->address;
274
0
    location->is_folded = 0;
275
276
0
    for (index = 0; index < input_location->n_lines; index++) {
277
0
        line = cprof_line_create(location);
278
0
        if (line == NULL) {
279
0
            return CPROF_DECODE_OPENTELEMETRY_ALLOCATION_ERROR;
280
0
        }
281
0
        result = decode_line_entry(line, input_location->lines[index], dictionary);
282
0
        if (result != CPROF_DECODE_OPENTELEMETRY_SUCCESS) {
283
0
            return CPROF_DECODE_OPENTELEMETRY_INVALID_ARGUMENT_ERROR;
284
0
        }
285
0
    }
286
287
0
    for (index = 0; index < input_location->n_attribute_indices; index++) {
288
0
        raw_attribute_index = input_location->attribute_indices[index];
289
290
0
        if (raw_attribute_index < 0) {
291
0
            return CPROF_DECODE_OPENTELEMETRY_INVALID_ARGUMENT_ERROR;
292
0
        }
293
294
0
        result = cprof_location_add_attribute(location,
295
0
            (uint64_t) raw_attribute_index);
296
0
        if (result != 0) {
297
0
            return CPROF_DECODE_OPENTELEMETRY_INVALID_ARGUMENT_ERROR;
298
0
        }
299
0
    }
300
301
0
    return CPROF_DECODE_OPENTELEMETRY_SUCCESS;
302
0
}
303
304
static int decode_function_entry(struct cprof_function *function,
305
    Opentelemetry__Proto__Profiles__V1development__Function *input_function)
306
0
{
307
0
    function->id = 0;
308
0
    function->name = (int64_t)input_function->name_strindex;
309
0
    function->system_name = (int64_t)input_function->system_name_strindex;
310
0
    function->filename = (int64_t)input_function->filename_strindex;
311
0
    function->start_line = input_function->start_line;
312
313
0
    return CPROF_DECODE_OPENTELEMETRY_SUCCESS;
314
0
}
315
316
static int decode_keyvalueandunit_entry(struct cprof_attribute_unit *attribute_unit,
317
    Opentelemetry__Proto__Profiles__V1development__KeyValueAndUnit *input_kv)
318
0
{
319
0
    attribute_unit->attribute_key = (int64_t)input_kv->key_strindex;
320
0
    attribute_unit->unit = (int64_t)input_kv->unit_strindex;
321
322
0
    return CPROF_DECODE_OPENTELEMETRY_SUCCESS;
323
0
}
324
325
static int decode_link_table_entry(struct cprof_link *link,
326
    Opentelemetry__Proto__Profiles__V1development__Link *input_link)
327
0
{
328
0
    if (input_link->trace_id.data != NULL ||
329
0
        input_link->trace_id.len > 0) {
330
0
        if (input_link->trace_id.data == NULL ||
331
0
            input_link->trace_id.len != sizeof(link->trace_id)) {
332
0
            return CPROF_DECODE_OPENTELEMETRY_INVALID_ARGUMENT_ERROR;
333
0
        }
334
335
0
        memcpy(link->trace_id,
336
0
               input_link->trace_id.data,
337
0
               sizeof(link->trace_id));
338
0
    }
339
340
0
    if (input_link->span_id.data != NULL ||
341
0
        input_link->span_id.len > 0) {
342
0
        if (input_link->span_id.data == NULL ||
343
0
            input_link->span_id.len != sizeof(link->span_id)) {
344
0
            return CPROF_DECODE_OPENTELEMETRY_INVALID_ARGUMENT_ERROR;
345
0
        }
346
347
0
        memcpy(link->span_id,
348
0
               input_link->span_id.data,
349
0
               sizeof(link->span_id));
350
0
    }
351
352
0
    return CPROF_DECODE_OPENTELEMETRY_SUCCESS;
353
0
}
354
355
356
static int decode_profile_entry(struct cprof_profile *profile,
357
    Opentelemetry__Proto__Profiles__V1development__Profile *input_profile,
358
    Opentelemetry__Proto__Profiles__V1development__ProfilesDictionary *dictionary)
359
0
{
360
0
    Opentelemetry__Proto__Profiles__V1development__KeyValueAndUnit *indexed_attribute_entry;
361
0
    struct cprof_attribute_unit *attribute_unit;
362
0
    struct cprof_value_type     *sample_type;
363
0
    struct cprof_location       *location;
364
0
    struct cprof_function       *function;
365
0
    struct cprof_mapping        *mapping;
366
0
    struct cprof_sample         *sample;
367
0
    struct cprof_link           *link;
368
0
    struct cfl_variant          *indexed_attribute_value;
369
0
    int32_t                      indexed_attribute_key_index;
370
0
    int32_t                      indexed_attribute_table_index;
371
0
    char                        *indexed_attribute_key;
372
0
    int                          result;
373
0
    size_t                       index;
374
375
    /* Copy dictionary tables into profile when dictionary is present */
376
0
    if (dictionary != NULL) {
377
        /* String table */
378
0
        if (dictionary->string_table != NULL) {
379
0
            size_t table_size;
380
381
0
            table_size = dictionary->n_string_table;
382
383
0
            if (table_size == 0) {
384
0
                table_size = 1;
385
0
            }
386
387
0
            profile->string_table = calloc(table_size, sizeof(cfl_sds_t));
388
0
            if (profile->string_table == NULL) {
389
0
                return CPROF_DECODE_OPENTELEMETRY_ALLOCATION_ERROR;
390
0
            }
391
392
0
            profile->string_table_size = table_size;
393
0
            profile->string_table_count = table_size;
394
395
0
            for (index = 0; index < table_size; index++) {
396
0
                const char *s;
397
398
0
                if (index < dictionary->n_string_table) {
399
0
                    s = dictionary->string_table[index];
400
0
                }
401
0
                else {
402
0
                    s = "";
403
0
                }
404
405
0
                profile->string_table[index] = cfl_sds_create(s != NULL ? s : "");
406
0
                if (profile->string_table[index] == NULL) {
407
0
                    return CPROF_DECODE_OPENTELEMETRY_ALLOCATION_ERROR;
408
0
                }
409
0
            }
410
0
        }
411
412
        /* Mappings */
413
0
        if (dictionary->mapping_table != NULL) {
414
0
            for (index = 0; index < dictionary->n_mapping_table; index++) {
415
0
                if (dictionary->mapping_table[index] == NULL) {
416
0
                    return CPROF_DECODE_OPENTELEMETRY_INVALID_ARGUMENT_ERROR;
417
0
                }
418
419
0
                mapping = cprof_mapping_create(profile);
420
0
                if (mapping == NULL) {
421
0
                    return CPROF_DECODE_OPENTELEMETRY_ALLOCATION_ERROR;
422
0
                }
423
0
                result = decode_mapping_entry(mapping, dictionary->mapping_table[index]);
424
0
                if (result != CPROF_DECODE_OPENTELEMETRY_SUCCESS) {
425
0
                    return result;
426
0
                }
427
0
            }
428
0
        }
429
430
        /* Locations */
431
0
        if (dictionary->location_table != NULL) {
432
0
            for (index = 0; index < dictionary->n_location_table; index++) {
433
0
                if (dictionary->location_table[index] == NULL) {
434
0
                    return CPROF_DECODE_OPENTELEMETRY_INVALID_ARGUMENT_ERROR;
435
0
                }
436
437
0
                location = cprof_location_create(profile);
438
0
                if (location == NULL) {
439
0
                    return CPROF_DECODE_OPENTELEMETRY_ALLOCATION_ERROR;
440
0
                }
441
0
                result = decode_location_entry(location,
442
0
                                              dictionary->location_table[index],
443
0
                                              dictionary);
444
0
                if (result != CPROF_DECODE_OPENTELEMETRY_SUCCESS) {
445
0
                    return result;
446
0
                }
447
0
            }
448
0
        }
449
450
        /* Functions */
451
0
        if (dictionary->function_table != NULL) {
452
0
            for (index = 0; index < dictionary->n_function_table; index++) {
453
0
                if (dictionary->function_table[index] == NULL) {
454
0
                    return CPROF_DECODE_OPENTELEMETRY_INVALID_ARGUMENT_ERROR;
455
0
                }
456
457
0
                function = cprof_function_create(profile);
458
0
                if (function == NULL) {
459
0
                    return CPROF_DECODE_OPENTELEMETRY_ALLOCATION_ERROR;
460
0
                }
461
0
                result = decode_function_entry(function, dictionary->function_table[index]);
462
0
                if (result != CPROF_DECODE_OPENTELEMETRY_SUCCESS) {
463
0
                    return result;
464
0
                }
465
0
            }
466
0
        }
467
468
        /* Attribute table (KeyValueAndUnit) and attribute_units */
469
0
        if (dictionary->attribute_table != NULL && dictionary->n_attribute_table > 0) {
470
0
            result = convert_keyvalueandunit_array_to_kvlist(profile->attribute_table,
471
0
                dictionary->attribute_table,
472
0
                dictionary->n_attribute_table,
473
0
                dictionary->string_table,
474
0
                dictionary->n_string_table);
475
0
            if (result != CPROF_DECODE_OPENTELEMETRY_SUCCESS) {
476
0
                return result;
477
0
            }
478
0
            for (index = 0; index < dictionary->n_attribute_table; index++) {
479
0
                if (dictionary->attribute_table[index] == NULL) {
480
0
                    return CPROF_DECODE_OPENTELEMETRY_INVALID_ARGUMENT_ERROR;
481
0
                }
482
483
0
                attribute_unit = cprof_attribute_unit_create(profile);
484
0
                if (attribute_unit == NULL) {
485
0
                    return CPROF_DECODE_OPENTELEMETRY_ALLOCATION_ERROR;
486
0
                }
487
0
                result = decode_keyvalueandunit_entry(attribute_unit,
488
0
                    dictionary->attribute_table[index]);
489
0
                if (result != CPROF_DECODE_OPENTELEMETRY_SUCCESS) {
490
0
                    return result;
491
0
                }
492
0
            }
493
0
        }
494
495
        /* Link table */
496
0
        if (dictionary->link_table != NULL) {
497
0
            for (index = 0; index < dictionary->n_link_table; index++) {
498
0
                if (dictionary->link_table[index] == NULL) {
499
0
                    return CPROF_DECODE_OPENTELEMETRY_INVALID_ARGUMENT_ERROR;
500
0
                }
501
502
0
                link = cprof_link_create(profile);
503
0
                if (link == NULL) {
504
0
                    return CPROF_DECODE_OPENTELEMETRY_ALLOCATION_ERROR;
505
0
                }
506
0
                result = decode_link_table_entry(link, dictionary->link_table[index]);
507
0
                if (result != CPROF_DECODE_OPENTELEMETRY_SUCCESS) {
508
0
                    return result;
509
0
                }
510
0
            }
511
0
        }
512
513
        /* Profile attributes reference dictionary.attribute_table by index */
514
0
        if (input_profile->attribute_indices != NULL &&
515
0
            input_profile->n_attribute_indices > 0) {
516
0
            for (index = 0; index < input_profile->n_attribute_indices; index++) {
517
0
                indexed_attribute_table_index = input_profile->attribute_indices[index];
518
519
0
                if (indexed_attribute_table_index < 0 ||
520
0
                    (size_t) indexed_attribute_table_index >= dictionary->n_attribute_table) {
521
0
                    return CPROF_DECODE_OPENTELEMETRY_INVALID_ARGUMENT_ERROR;
522
0
                }
523
524
0
                indexed_attribute_entry = dictionary->attribute_table[indexed_attribute_table_index];
525
526
0
                if (indexed_attribute_entry == NULL) {
527
0
                    return CPROF_DECODE_OPENTELEMETRY_INVALID_ARGUMENT_ERROR;
528
0
                }
529
530
0
                indexed_attribute_key_index = indexed_attribute_entry->key_strindex;
531
532
0
                if (dictionary->string_table != NULL &&
533
0
                    indexed_attribute_key_index >= 0 &&
534
0
                    (size_t) indexed_attribute_key_index < dictionary->n_string_table &&
535
0
                    dictionary->string_table[indexed_attribute_key_index] != NULL) {
536
0
                    indexed_attribute_key = dictionary->string_table[indexed_attribute_key_index];
537
0
                }
538
0
                else {
539
0
                    return CPROF_DECODE_OPENTELEMETRY_INVALID_ARGUMENT_ERROR;
540
0
                }
541
542
0
                result = clone_variant(&indexed_attribute_value,
543
0
                                       indexed_attribute_entry->value,
544
0
                                       dictionary->string_table,
545
0
                                       dictionary->n_string_table);
546
547
0
                if (result != CPROF_DECODE_OPENTELEMETRY_SUCCESS) {
548
0
                    return result;
549
0
                }
550
551
0
                if (cfl_kvlist_insert(profile->attributes,
552
0
                                      indexed_attribute_key,
553
0
                                      indexed_attribute_value) != 0) {
554
0
                    cfl_variant_destroy(indexed_attribute_value);
555
556
0
                    return CPROF_DECODE_OPENTELEMETRY_ALLOCATION_ERROR;
557
0
                }
558
0
            }
559
0
        }
560
0
    }
561
562
    /* Profile sample_type (single ValueType in new proto) */
563
0
    if (input_profile->sample_type != NULL) {
564
0
        sample_type = cprof_sample_type_create(profile,
565
0
            (int64_t)input_profile->sample_type->type_strindex,
566
0
            (int64_t)input_profile->sample_type->unit_strindex,
567
0
            0);
568
0
        if (sample_type == NULL) {
569
0
            return CPROF_DECODE_OPENTELEMETRY_INVALID_ARGUMENT_ERROR;
570
0
        }
571
0
    }
572
573
    /* Samples */
574
0
    if (input_profile->samples != NULL) {
575
0
        for (index = 0; index < input_profile->n_samples; index++) {
576
0
            sample = cprof_sample_create(profile);
577
0
            if (sample == NULL) {
578
0
                return CPROF_DECODE_OPENTELEMETRY_ALLOCATION_ERROR;
579
0
            }
580
0
            result = decode_profile_sample_entry(sample,
581
0
                input_profile->samples[index], dictionary);
582
0
            if (result != CPROF_DECODE_OPENTELEMETRY_SUCCESS) {
583
0
                return result;
584
0
            }
585
0
        }
586
0
    }
587
588
0
    profile->time_nanos = (int64_t)input_profile->time_unix_nano;
589
0
    profile->duration_nanos = (int64_t)input_profile->duration_nano;
590
0
    profile->drop_frames = 0;
591
0
    profile->keep_frames = 0;
592
0
    profile->period = input_profile->period;
593
594
0
    if (input_profile->period_type != NULL) {
595
0
        profile->period_type.type = (int64_t)input_profile->period_type->type_strindex;
596
0
        profile->period_type.unit = (int64_t)input_profile->period_type->unit_strindex;
597
0
        profile->period_type.aggregation_temporality = 0;
598
0
    }
599
600
0
    profile->default_sample_type = 0;
601
602
0
    return CPROF_DECODE_OPENTELEMETRY_SUCCESS;
603
0
}
604
605
static int decode_profile_into_scope(struct cprof_scope_profiles *scope_profiles,
606
    Opentelemetry__Proto__Profiles__V1development__Profile *input_profile,
607
    Opentelemetry__Proto__Profiles__V1development__ProfilesDictionary *dictionary)
608
0
{
609
0
    struct cprof_profile *profile;
610
0
    int                   result;
611
612
0
    profile = cprof_profile_create();
613
0
    if (profile == NULL) {
614
0
        return CPROF_DECODE_OPENTELEMETRY_ALLOCATION_ERROR;
615
0
    }
616
617
    /* Profile-level fields (no ProfileContainer in new proto) */
618
0
    if (input_profile->profile_id.data != NULL && input_profile->profile_id.len >= 16) {
619
0
        memcpy(profile->profile_id, input_profile->profile_id.data, 16);
620
0
    }
621
0
    else {
622
0
        memset(profile->profile_id, 0, sizeof(profile->profile_id));
623
0
    }
624
625
0
    profile->start_time_unix_nano = (int64_t)input_profile->time_unix_nano;
626
0
    profile->end_time_unix_nano = (int64_t)input_profile->time_unix_nano +
627
0
        (int64_t)input_profile->duration_nano;
628
629
0
    profile->dropped_attributes_count = input_profile->dropped_attributes_count;
630
631
0
    if (input_profile->original_payload_format != NULL && input_profile->original_payload_format[0] != '\0') {
632
0
        profile->original_payload_format = cfl_sds_create(input_profile->original_payload_format);
633
0
        if (profile->original_payload_format == NULL) {
634
0
            cprof_profile_destroy(profile);
635
0
            return CPROF_DECODE_OPENTELEMETRY_ALLOCATION_ERROR;
636
0
        }
637
0
    }
638
639
0
    if (input_profile->original_payload.data != NULL && input_profile->original_payload.len > 0) {
640
0
        profile->original_payload = cfl_sds_create_len(
641
0
            (const char *)input_profile->original_payload.data,
642
0
            input_profile->original_payload.len);
643
0
        if (profile->original_payload == NULL) {
644
0
            cprof_profile_destroy(profile);
645
0
            return CPROF_DECODE_OPENTELEMETRY_ALLOCATION_ERROR;
646
0
        }
647
0
    }
648
649
0
    result = decode_profile_entry(profile, input_profile, dictionary);
650
0
    if (result != CPROF_DECODE_OPENTELEMETRY_SUCCESS) {
651
0
        cprof_profile_destroy(profile);
652
0
        return result;
653
0
    }
654
655
0
    cfl_list_add(&profile->_head, &scope_profiles->profiles);
656
0
    return CPROF_DECODE_OPENTELEMETRY_SUCCESS;
657
0
}
658
659
static int decode_scope_profiles_entry(struct cprof_resource_profiles *resource_profiles,
660
    Opentelemetry__Proto__Profiles__V1development__ScopeProfiles *input_scope_profiles,
661
    Opentelemetry__Proto__Profiles__V1development__ProfilesDictionary *dictionary)
662
0
{
663
0
    struct cprof_scope_profiles *profiles;
664
0
    int                          result;
665
0
    size_t                       index;
666
667
0
    profiles = cprof_scope_profiles_create(
668
0
        resource_profiles,
669
0
        input_scope_profiles->schema_url != NULL ? input_scope_profiles->schema_url : "");
670
671
0
    if (profiles == NULL) {
672
0
        return CPROF_DECODE_OPENTELEMETRY_ALLOCATION_ERROR;
673
0
    }
674
675
0
    if (input_scope_profiles->scope != NULL) {
676
0
        result = decode_instrumentation_scope(&profiles->scope,
677
0
                                              input_scope_profiles->scope,
678
0
                                              dictionary);
679
0
    }
680
0
    else {
681
0
        profiles->scope = cprof_instrumentation_scope_create(NULL, NULL, NULL, 0);
682
0
        result = profiles->scope != NULL ?
683
0
                 CPROF_DECODE_OPENTELEMETRY_SUCCESS :
684
0
                 CPROF_DECODE_OPENTELEMETRY_ALLOCATION_ERROR;
685
0
    }
686
687
0
    if (result != CPROF_DECODE_OPENTELEMETRY_SUCCESS) {
688
0
        cfl_list_del(&profiles->_head);
689
0
        cprof_scope_profiles_destroy(profiles);
690
0
        return result;
691
0
    }
692
693
0
    if (input_scope_profiles->profiles != NULL && input_scope_profiles->n_profiles > 0) {
694
0
        for (index = 0; index < input_scope_profiles->n_profiles; index++) {
695
0
            result = decode_profile_into_scope(profiles,
696
0
                input_scope_profiles->profiles[index], dictionary);
697
0
            if (result != CPROF_DECODE_OPENTELEMETRY_SUCCESS) {
698
0
                return result;
699
0
            }
700
0
        }
701
0
    }
702
703
    /* cprof_scope_profiles_create already added profiles to resource_profiles */
704
0
    return CPROF_DECODE_OPENTELEMETRY_SUCCESS;
705
0
}
706
707
static int decode_resource_profiles_entry(struct cprof *context,
708
    Opentelemetry__Proto__Profiles__V1development__ResourceProfiles *resource_profile,
709
    Opentelemetry__Proto__Profiles__V1development__ProfilesDictionary *dictionary)
710
0
{
711
0
    struct cprof_resource_profiles *profile;
712
0
    int                             result;
713
0
    size_t                          index;
714
715
0
    profile = cprof_resource_profiles_create(
716
0
        resource_profile->schema_url != NULL ? resource_profile->schema_url : "");
717
718
0
    if (profile == NULL) {
719
0
        return CPROF_DECODE_OPENTELEMETRY_ALLOCATION_ERROR;
720
0
    }
721
722
0
    result = decode_resource(&profile->resource, resource_profile->resource, dictionary);
723
724
0
    if (result != CPROF_DECODE_OPENTELEMETRY_SUCCESS) {
725
0
        cprof_resource_profiles_destroy(profile);
726
0
        return result;
727
0
    }
728
729
0
    result = CPROF_DECODE_OPENTELEMETRY_SUCCESS;
730
731
0
    if (resource_profile->scope_profiles != NULL && resource_profile->n_scope_profiles > 0) {
732
0
        for (index = 0;
733
0
             result == CPROF_DECODE_OPENTELEMETRY_SUCCESS &&
734
0
             index < resource_profile->n_scope_profiles;
735
0
             index++) {
736
0
            result = decode_scope_profiles_entry(profile,
737
0
                resource_profile->scope_profiles[index], dictionary);
738
0
        }
739
0
    }
740
741
0
    if (result != CPROF_DECODE_OPENTELEMETRY_SUCCESS) {
742
0
        cprof_resource_profiles_destroy(profile);
743
0
        return result;
744
0
    }
745
746
0
    result = cprof_resource_profiles_add(context, profile);
747
748
0
    if (result != 0) {
749
0
        cprof_resource_profiles_destroy(profile);
750
751
0
        return CPROF_DECODE_OPENTELEMETRY_ALLOCATION_ERROR;
752
0
    }
753
754
0
    return CPROF_DECODE_OPENTELEMETRY_SUCCESS;
755
0
}
756
757
static int decode_service_request(struct cprof *context,
758
    Opentelemetry__Proto__Collector__Profiles__V1development__ExportProfilesServiceRequest *service_request)
759
0
{
760
0
    int                                                                                     result;
761
0
    size_t                                                                                  index;
762
0
    Opentelemetry__Proto__Profiles__V1development__ProfilesDictionary                      *dictionary;
763
764
0
    dictionary = service_request->dictionary;
765
0
    result = CPROF_DECODE_OPENTELEMETRY_SUCCESS;
766
767
0
    if (service_request->resource_profiles != NULL && service_request->n_resource_profiles > 0) {
768
0
        for (index = 0;
769
0
             result == CPROF_DECODE_OPENTELEMETRY_SUCCESS &&
770
0
             index < service_request->n_resource_profiles;
771
0
             index++) {
772
0
            result = decode_resource_profiles_entry(context,
773
0
                service_request->resource_profiles[index], dictionary);
774
0
        }
775
0
    }
776
777
0
    return result;
778
0
}
779
780
781
int cprof_decode_opentelemetry_create(struct cprof **result_context,
782
                                      unsigned char *in_buf, size_t in_size,
783
                                      size_t *offset)
784
0
{
785
0
    Opentelemetry__Proto__Collector__Profiles__V1development__ExportProfilesServiceRequest *service_request;
786
0
    struct cprof                                                                           *context;
787
0
    size_t                                                                                  remaining;
788
0
    int                                                                                     result;
789
790
0
    result = CPROF_DECODE_OPENTELEMETRY_INVALID_ARGUMENT_ERROR;
791
0
    context = NULL;
792
793
0
    if (offset == NULL ||
794
0
        result_context == NULL ||
795
0
        in_buf == NULL ||
796
0
        *offset > in_size) {
797
0
        return CPROF_DECODE_OPENTELEMETRY_INVALID_ARGUMENT_ERROR;
798
0
    }
799
800
0
    *result_context = NULL;
801
802
0
    remaining = in_size - *offset;
803
804
0
    service_request = opentelemetry__proto__collector__profiles__v1development__export_profiles_service_request__unpack(
805
0
                        NULL,
806
0
                        remaining,
807
0
                        &in_buf[*offset]);
808
809
0
    if (service_request != NULL) {
810
0
        context = cprof_create();
811
812
0
        if (context != NULL) {
813
0
            result = decode_service_request(context, service_request);
814
0
        }
815
0
        else {
816
0
            result = CPROF_DECODE_OPENTELEMETRY_ALLOCATION_ERROR;
817
0
        }
818
819
0
        opentelemetry__proto__collector__profiles__v1development__export_profiles_service_request__free_unpacked(service_request, NULL);
820
0
    }
821
822
0
    if (result == CPROF_DECODE_OPENTELEMETRY_SUCCESS) {
823
0
        *result_context = context;
824
825
0
        if (offset != NULL) {
826
0
            *offset = in_size;
827
0
        }
828
0
    }
829
0
    else if (context != NULL) {
830
0
        cprof_destroy(context);
831
0
    }
832
833
0
    return result;
834
0
}
835
836
void cprof_decode_opentelemetry_destroy(struct cprof *context)
837
0
{
838
0
    if (context != NULL) {
839
0
        cprof_destroy(context);
840
0
    }
841
0
}