Coverage Report

Created: 2026-09-28 06:22

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/open5gs/lib/asn1c/common/OCTET_STRING.c
Line
Count
Source
1
/*-
2
 * Copyright (c) 2003-2017 Lev Walkin <vlm@lionet.info>.
3
 * All rights reserved.
4
 * Redistribution and modifications are permitted subject to BSD license.
5
 */
6
#include <asn_internal.h>
7
#include <OCTET_STRING.h>
8
#include <errno.h>
9
10
/*
11
 * OCTET STRING basic type description.
12
 */
13
static const ber_tlv_tag_t asn_DEF_OCTET_STRING_tags[] = {
14
    (ASN_TAG_CLASS_UNIVERSAL | (4 << 2))
15
};
16
asn_OCTET_STRING_specifics_t asn_SPC_OCTET_STRING_specs = {
17
    sizeof(OCTET_STRING_t),
18
    offsetof(OCTET_STRING_t, _asn_ctx),
19
    ASN_OSUBV_STR
20
};
21
asn_TYPE_operation_t asn_OP_OCTET_STRING = {
22
    .kind = ASN_KIND_PRIMITIVE,
23
    OCTET_STRING_free,
24
#if !defined(ASN_DISABLE_PRINT_SUPPORT)
25
    OCTET_STRING_print,  /* OCTET STRING generally means a non-ascii sequence */
26
#else
27
    0,
28
#endif  /* !defined(ASN_DISABLE_PRINT_SUPPORT) */
29
    OCTET_STRING_compare,
30
    OCTET_STRING_copy,
31
#if !defined(ASN_DISABLE_BER_SUPPORT)
32
    OCTET_STRING_decode_ber,
33
    OCTET_STRING_encode_der,
34
#else
35
    0,
36
    0,
37
#endif  /* !defined(ASN_DISABLE_BER_SUPPORT) */
38
#if !defined(ASN_DISABLE_XER_SUPPORT)
39
    OCTET_STRING_decode_xer_auto,    /* Auto-detect hex or Base64 format for decoding */
40
    OCTET_STRING_encode_xer_base64,  /* Per X.693, Base64 is the default encoding for OCTET STRING */
41
#else
42
    0,
43
    0,
44
#endif  /* !defined(ASN_DISABLE_XER_SUPPORT) */
45
#if !defined(ASN_DISABLE_JER_SUPPORT)
46
    OCTET_STRING_decode_jer_hex,
47
    OCTET_STRING_encode_jer,
48
#else
49
    0,
50
    0,
51
#endif  /* !defined(ASN_DISABLE_JER_SUPPORT) */
52
#if !defined(ASN_DISABLE_OER_SUPPORT)
53
    OCTET_STRING_decode_oer,
54
    OCTET_STRING_encode_oer,
55
#else
56
    0,
57
    0,
58
#endif  /* !defined(ASN_DISABLE_OER_SUPPORT) */
59
#if !defined(ASN_DISABLE_UPER_SUPPORT)
60
    OCTET_STRING_decode_uper,  /* Unaligned PER decoder */
61
    OCTET_STRING_encode_uper,  /* Unaligned PER encoder */
62
#else
63
    0,
64
    0,
65
#endif  /* !defined(ASN_DISABLE_UPER_SUPPORT) */
66
#if !defined(ASN_DISABLE_APER_SUPPORT)
67
    OCTET_STRING_decode_aper,  /* Aligned PER decoder */
68
    OCTET_STRING_encode_aper,  /* Aligned PER encoder */
69
#else
70
    0,
71
    0,
72
#endif  /* !defined(ASN_DISABLE_APER_SUPPORT) */
73
#if !defined(ASN_DISABLE_RFILL_SUPPORT)
74
    OCTET_STRING_random_fill,
75
#else
76
    0,
77
#endif  /* !defined(ASN_DISABLE_RFILL_SUPPORT) */
78
    0  /* Use generic outmost tag fetcher */,
79
#if !defined(ASN_DISABLE_CBOR_SUPPORT)
80
    OCTET_STRING_decode_cbor,
81
    OCTET_STRING_encode_cbor,
82
#else
83
    0,
84
    0,
85
#endif  /* !defined(ASN_DISABLE_CBOR_SUPPORT) */
86
};
87
asn_TYPE_descriptor_t asn_DEF_OCTET_STRING = {
88
    "OCTET STRING",  /* Canonical name */
89
    "OCTET_STRING",  /* XML tag name */
90
    &asn_OP_OCTET_STRING,
91
    asn_DEF_OCTET_STRING_tags,
92
    sizeof(asn_DEF_OCTET_STRING_tags)
93
        / sizeof(asn_DEF_OCTET_STRING_tags[0]),
94
    asn_DEF_OCTET_STRING_tags,  /* Same as above */
95
    sizeof(asn_DEF_OCTET_STRING_tags)
96
        / sizeof(asn_DEF_OCTET_STRING_tags[0]),
97
    {
98
#if !defined(ASN_DISABLE_OER_SUPPORT)
99
        0,
100
#endif  /* !defined(ASN_DISABLE_OER_SUPPORT) */
101
#if !defined(ASN_DISABLE_UPER_SUPPORT) || !defined(ASN_DISABLE_APER_SUPPORT)
102
        0,
103
#endif  /* !defined(ASN_DISABLE_UPER_SUPPORT) || !defined(ASN_DISABLE_APER_SUPPORT) */
104
#if !defined(ASN_DISABLE_JER_SUPPORT)
105
        0,
106
#endif  /* !defined(ASN_DISABLE_JER_SUPPORT) */
107
        asn_generic_no_constraint
108
    },
109
    0, 0,  /* No members */
110
    &asn_SPC_OCTET_STRING_specs
111
};
112
113
void
114
OCTET_STRING_free(const asn_TYPE_descriptor_t *td, void *sptr,
115
18.2k
                  enum asn_struct_free_method method) {
116
18.2k
  OCTET_STRING_t *st = (OCTET_STRING_t *)sptr;
117
118
18.2k
  if(!td || !st)
119
0
    return;
120
121
18.2k
  ASN_DEBUG("Freeing %s as OCTET STRING", td->name);
122
123
18.2k
  if(st->buf) {
124
17.9k
    FREEMEM(st->buf);
125
17.9k
    st->buf = 0;
126
17.9k
  }
127
128
#if !defined(ASN_DISABLE_BER_SUPPORT)
129
    const asn_OCTET_STRING_specifics_t *specs;
130
    asn_struct_ctx_t *ctx;
131
132
    specs = td->specifics
133
            ? (const asn_OCTET_STRING_specifics_t *)td->specifics
134
            : &asn_SPC_OCTET_STRING_specs;
135
    ctx = (asn_struct_ctx_t *)((char *)st + specs->ctx_offset);
136
137
    /*
138
     * Remove decode-time stack.
139
     */
140
    struct _stack *stck;
141
    stck = (struct _stack *)ctx->ptr;
142
    if(stck) {
143
        while(stck->tail) {
144
            struct _stack_el *sel = stck->tail;
145
            stck->tail = sel->prev;
146
            FREEMEM(sel);
147
        }
148
        FREEMEM(stck);
149
    }
150
#endif  /* !defined(ASN_DISABLE_BER_SUPPORT) */
151
152
18.2k
    switch(method) {
153
7.18k
    case ASFM_FREE_EVERYTHING:
154
7.18k
        FREEMEM(sptr);
155
7.18k
        break;
156
11.0k
    case ASFM_FREE_UNDERLYING:
157
11.0k
        break;
158
61
    case ASFM_FREE_UNDERLYING_AND_RESET:
159
61
        memset(sptr, 0,
160
61
               td->specifics
161
61
                   ? ((const asn_OCTET_STRING_specifics_t *)(td->specifics))
162
61
                         ->struct_size
163
61
                   : sizeof(OCTET_STRING_t));
164
61
        break;
165
18.2k
    }
166
18.2k
}
167
168
/*
169
 * Conversion routines.
170
 */
171
int
172
0
OCTET_STRING_fromBuf(OCTET_STRING_t *st, const char *str, int len) {
173
0
  void *buf;
174
175
0
  if(st == 0 || (str == 0 && len)) {
176
0
    errno = EINVAL;
177
0
    return -1;
178
0
  }
179
180
  /*
181
   * Clear the OCTET STRING.
182
   */
183
0
  if(str == NULL) {
184
0
    FREEMEM(st->buf);
185
0
    st->buf = 0;
186
0
    st->size = 0;
187
0
    return 0;
188
0
  }
189
190
  /* Determine the original string size, if not explicitly given */
191
0
  if(len < 0)
192
0
    len = strlen(str);
193
194
  /* Allocate and fill the memory */
195
0
  buf = MALLOC(len + 1);
196
0
  if(buf == NULL)
197
0
    return -1;
198
199
0
  memcpy(buf, str, len);
200
0
  ((uint8_t *)buf)[len] = '\0'; /* Couldn't use memcpy(len+1)! */
201
0
  FREEMEM(st->buf);
202
0
  st->buf = (uint8_t *)buf;
203
0
  st->size = len;
204
205
0
  return 0;
206
0
}
207
208
OCTET_STRING_t *
209
OCTET_STRING_new_fromBuf(const asn_TYPE_descriptor_t *td, const char *str,
210
0
                         int len) {
211
0
    const asn_OCTET_STRING_specifics_t *specs =
212
0
        td->specifics ? (const asn_OCTET_STRING_specifics_t *)td->specifics
213
0
                      : &asn_SPC_OCTET_STRING_specs;
214
0
    OCTET_STRING_t *st;
215
216
    /* 
217
     * Sanity check: struct_size should be at least as large as OCTET_STRING_t.
218
     * If it's smaller, accessing OCTET_STRING_t fields could cause memory corruption.
219
     */
220
0
    if(specs->struct_size < sizeof(OCTET_STRING_t)) {
221
0
        ASN_DEBUG("Type descriptor %s has struct_size %u which is smaller than OCTET_STRING_t (%zu)",
222
0
                  td->name ? td->name : "unknown", specs->struct_size, sizeof(OCTET_STRING_t));
223
0
        return NULL;
224
0
    }
225
226
0
  st = (OCTET_STRING_t *)CALLOC(1, specs->struct_size);
227
0
  if(st && str && OCTET_STRING_fromBuf(st, str, len)) {
228
0
    FREEMEM(st);
229
0
    st = NULL;
230
0
  }
231
232
0
  return st;
233
0
}
234
235
/*
236
 * Lexicographically compare the common prefix of both strings,
237
 * and if it is the same return -1 for the smallest string.
238
 */
239
int
240
OCTET_STRING_compare(const asn_TYPE_descriptor_t *td, const void *aptr,
241
0
                     const void *bptr) {
242
0
    const asn_OCTET_STRING_specifics_t *specs = td->specifics;
243
0
    const OCTET_STRING_t *a = aptr;
244
0
    const OCTET_STRING_t *b = bptr;
245
246
0
    (void)specs;
247
0
    assert(!specs || specs->subvariant != ASN_OSUBV_BIT);
248
249
0
    if(a && b) {
250
0
        size_t common_prefix_size = a->size <= b->size ? a->size : b->size;
251
0
        int ret = memcmp(a->buf, b->buf, common_prefix_size);
252
0
        if(ret == 0) {
253
            /* Figure out which string with equal prefixes is longer. */
254
0
            if(a->size < b->size) {
255
0
                return -1;
256
0
            } else if(a->size > b->size) {
257
0
                return 1;
258
0
            } else {
259
0
                return 0;
260
0
            }
261
0
        } else {
262
0
            return ret < 0 ? -1 : 1;
263
0
        }
264
0
    } else if(!a && !b) {
265
0
        return 0;
266
0
    } else if(!a) {
267
0
        return -1;
268
0
    } else {
269
0
        return 1;
270
0
    }
271
272
0
}
273
274
int
275
OCTET_STRING_copy(const asn_TYPE_descriptor_t *td, void **aptr,
276
0
                     const void *bptr) {
277
0
    const asn_OCTET_STRING_specifics_t *specs =
278
0
        td->specifics ? (const asn_OCTET_STRING_specifics_t *)td->specifics
279
0
                      : &asn_SPC_OCTET_STRING_specs;
280
0
    OCTET_STRING_t *a = *aptr;
281
0
    const OCTET_STRING_t *b = bptr;
282
283
0
    if(!b) {
284
0
        if(a) {
285
0
            FREEMEM(a->buf);
286
0
            a->buf = 0;
287
0
            a->size = 0;
288
0
            FREEMEM(a);
289
0
        }
290
0
        *aptr = 0;
291
0
        return 0;
292
0
    }
293
294
0
    if(!a) {
295
0
        a = *aptr = (OCTET_STRING_t *)CALLOC(1, specs->struct_size);
296
0
        if(!a) return -1;
297
0
    }
298
299
0
    void *buf = MALLOC(b->size + 1);
300
0
    if(!buf) return -1;
301
0
    memcpy(buf, b->buf, b->size);
302
0
    ((uint8_t *)buf)[b->size] = '\0';
303
304
0
    FREEMEM(a->buf);
305
0
    a->buf = (uint8_t *)buf;
306
0
    a->size = b->size;
307
308
0
    return 0;
309
0
}
310
311
#if !defined(ASN_DISABLE_UPER_SUPPORT) || !defined(ASN_DISABLE_APER_SUPPORT)
312
int
313
OCTET_STRING_per_get_characters(asn_per_data_t *po, uint8_t *buf,
314
                                size_t units, unsigned int bpc, unsigned int unit_bits,
315
12.3k
                                long lb, long ub, const asn_per_constraints_t *pc) {
316
12.3k
    uint8_t *end = buf + units * bpc;
317
318
12.3k
    ASN_DEBUG("Expanding %d characters into (%ld..%ld):%d",
319
12.3k
              (int)units, lb, ub, unit_bits);
320
321
    /* X.691: 27.5.4 */
322
12.3k
    if((unsigned long)ub <= ((unsigned long)2 << (unit_bits - 1))) {
323
        /* Decode without translation */
324
12.3k
        lb = 0;
325
12.3k
    } else if(pc && pc->code2value) {
326
0
        if(unit_bits > 16)
327
0
            return 1;  /* FATAL: can't have constrained
328
                        * UniversalString with more than
329
                        * 16 million code points */
330
0
        for(; buf < end; buf += bpc) {
331
0
            int value;
332
0
            int code = per_get_few_bits(po, unit_bits);
333
0
            if(code < 0) return -1;  /* WMORE */
334
0
            value = pc->code2value(code);
335
0
            if(value < 0) {
336
0
                ASN_DEBUG("Code %d (0x%02x) is"
337
0
                          " not in map (%ld..%ld)",
338
0
                          code, code, lb, ub);
339
0
                return 1;  /* FATAL */
340
0
            }
341
0
            switch(bpc) {
342
0
            case 1: *buf = value; break;
343
0
            case 2: buf[0] = value >> 8; buf[1] = value; break;
344
0
            case 4: buf[0] = value >> 24; buf[1] = value >> 16;
345
0
                buf[2] = value >> 8; buf[3] = value; break;
346
0
            }
347
0
        }
348
0
        return 0;
349
0
    }
350
351
    /* Shortcut the no-op copying to the aligned structure */
352
12.3k
    if(lb == 0 && (unit_bits == 8 * bpc)) {
353
12.3k
        return per_get_many_bits(po, buf, 0, unit_bits * units);
354
12.3k
    }
355
356
0
    for(; buf < end; buf += bpc) {
357
0
        int32_t code = per_get_few_bits(po, unit_bits);
358
0
        int32_t ch = code + lb;
359
0
        if(code < 0) return -1;  /* WMORE */
360
0
        if(ch > ub) {
361
0
            ASN_DEBUG("Code %d is out of range (%ld..%ld)",
362
0
                      ch, lb, ub);
363
0
            return 1;  /* FATAL */
364
0
        }
365
0
        switch(bpc) {
366
0
        case 1: *buf = ch; break;
367
0
        case 2: buf[0] = ch >> 8; buf[1] = ch; break;
368
0
        case 4: buf[0] = ch >> 24; buf[1] = ch >> 16;
369
0
            buf[2] = ch >> 8; buf[3] = ch; break;
370
0
        }
371
0
    }
372
373
0
    return 0;
374
0
}
375
376
int
377
OCTET_STRING_per_put_characters(asn_per_outp_t *po, const uint8_t *buf,
378
                                size_t units, unsigned int bpc, unsigned int unit_bits,
379
0
                                long lb, long ub, const asn_per_constraints_t *pc) {
380
0
    const uint8_t *end = buf + units * bpc;
381
382
0
    ASN_DEBUG("Squeezing %d characters into (%ld..%ld):%d (%d bpc)",
383
0
              (int)units, lb, ub, unit_bits, bpc);
384
385
    /* X.691: 27.5.4 */
386
0
    if((unsigned long)ub <= ((unsigned long)2 << (unit_bits - 1))) {
387
        /* Encode as is */
388
0
        lb = 0;
389
0
    } else if(pc && pc->value2code) {
390
0
        for(; buf < end; buf += bpc) {
391
0
            int code;
392
0
            uint32_t value;
393
0
            switch(bpc) {
394
0
            case 1: value = *(const uint8_t *)buf; break;
395
0
            case 2: value = (buf[0] << 8) | buf[1]; break;
396
0
            case 4: value = (buf[0] << 24) | (buf[1] << 16)
397
0
                | (buf[2] << 8) | buf[3]; break;
398
0
            default: return -1;
399
0
            }
400
0
            code = pc->value2code(value);
401
0
            if(code < 0) {
402
0
                ASN_DEBUG("Character %d (0x%02x) is"
403
0
                          " not in map (%ld..%ld)",
404
0
                          *buf, *buf, lb, ub);
405
0
                return -1;
406
0
            }
407
0
            if(per_put_few_bits(po, code, unit_bits))
408
0
    return -1;
409
0
        }
410
0
    }
411
412
    /* Shortcut the no-op copying to the aligned structure */
413
0
    if(lb == 0 && (unit_bits == 8 * bpc)) {
414
0
        return per_put_many_bits(po, buf, unit_bits * units);
415
0
    }
416
417
0
    for(ub -= lb; buf < end; buf += bpc) {
418
0
        int ch;
419
0
        uint32_t value;
420
0
        switch(bpc) {
421
0
        case 1:
422
0
            value = *(const uint8_t *)buf;
423
0
            break;
424
0
        case 2:
425
0
            value = (buf[0] << 8) | buf[1];
426
0
            break;
427
0
        case 4:
428
0
            value = (buf[0] << 24) | (buf[1] << 16) | (buf[2] << 8) | buf[3];
429
0
            break;
430
0
        default:
431
0
            return -1;
432
0
        }
433
0
        ch = value - lb;
434
0
        if(ch < 0 || ch > ub) {
435
0
            ASN_DEBUG("Character %d (0x%02x) is out of range (%ld..%ld)", *buf,
436
0
                      value, lb, ub + lb);
437
0
            return -1;
438
0
        }
439
0
        if(per_put_few_bits(po, ch, unit_bits)) return -1;
440
0
    }
441
442
0
    return 0;
443
0
}
444
#endif  /* !defined(ASN_DISABLE_UPER_SUPPORT) || !defined(ASN_DISABLE_APER_SUPPORT) */