Coverage Report

Created: 2026-07-14 06:05

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/open5gs/lib/asn1c/common/INTEGER_aper.c
Line
Count
Source
1
/*
2
 * Copyright (c) 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 <INTEGER.h>
8
9
/* Return ceil(log2(v)) for positive v. */
10
static unsigned
11
15.1k
aper_log2_ceil_size(size_t v) {
12
15.1k
    unsigned bits = 0;
13
15.1k
    size_t power = 1;
14
15
51.5k
    while(power < v) {
16
36.3k
        power <<= 1;
17
36.3k
        bits++;
18
36.3k
    }
19
20
15.1k
    return bits;
21
15.1k
}
22
23
asn_dec_rval_t
24
INTEGER_decode_aper(const asn_codec_ctx_t *opt_codec_ctx,
25
                    const asn_TYPE_descriptor_t *td,
26
173k
                    const asn_per_constraints_t *constraints, void **sptr, asn_per_data_t *pd) {
27
173k
    const asn_INTEGER_specifics_t *specs = (const asn_INTEGER_specifics_t *)td->specifics;
28
173k
    asn_dec_rval_t rval = { RC_OK, 0 };
29
173k
    INTEGER_t *st = (INTEGER_t *)*sptr;
30
173k
    const asn_per_constraint_t *ct;
31
173k
    asn_per_constraint_t ct_ext_copy;  /* Local copy for extension case */
32
173k
    int repeat;
33
173k
    int inext = 0;  /* Track if value is in extension part (outside constraint range) */
34
35
173k
    (void)opt_codec_ctx;
36
37
173k
    if(!st) {
38
5.43k
        st = (INTEGER_t *)(*sptr = CALLOC(1, sizeof(*st)));
39
5.43k
        if(!st) ASN__DECODE_FAILED;
40
5.43k
    }
41
42
173k
    if(!constraints) constraints = td->encoding_constraints.per_constraints;
43
173k
    ct = constraints ? &constraints->value : 0;
44
45
173k
    if(ct && ct->flags & APC_EXTENSIBLE) {
46
3.94k
        inext = per_get_few_bits(pd, 1);
47
3.94k
        if(inext < 0) ASN__DECODE_STARVED;
48
3.93k
        if(inext) {
49
            /*
50
             * Value encoded in extension root's extension container.
51
             *
52
             * If the original constraint was semi-constrained (only lower_bound
53
             * present), treat the extension value as semi-constrained too:
54
             * preserve lower_bound while allowing unconstrained length (range_bits=-1).
55
             *
56
             * If the original constraint was fully constrained or unconstrained,
57
             * extension values MUST be treated as fully unconstrained here.
58
             */
59
741
            if(ct->flags & APC_SEMI_CONSTRAINED) {
60
0
                ct_ext_copy = *ct;
61
0
                ct_ext_copy.flags = APC_SEMI_CONSTRAINED;
62
0
                ct_ext_copy.range_bits = -1;
63
0
                ct_ext_copy.effective_bits = -1;
64
0
                ct = &ct_ext_copy;
65
741
            } else {
66
                /* keep previous behavior for other cases */
67
741
                ct = 0;
68
741
            }
69
741
        }
70
3.93k
    }
71
72
173k
    FREEMEM(st->buf);
73
173k
    st->buf = 0;
74
173k
    st->size = 0;
75
173k
    if(ct) {
76
172k
        if(ct->flags & APC_SEMI_CONSTRAINED) {
77
0
            st->buf = (uint8_t *)CALLOC(1, 2);
78
0
            if(!st->buf) ASN__DECODE_FAILED;
79
0
            st->size = 1;
80
172k
        } else if(ct->flags & APC_CONSTRAINED && ct->range_bits >= 0) {
81
172k
            size_t size = (ct->range_bits + 7) >> 3;
82
172k
            st->buf = (uint8_t *)MALLOC(1 + size + 1);
83
172k
            if(!st->buf) ASN__DECODE_FAILED;
84
172k
            st->size = size;
85
172k
        }
86
172k
    }
87
88
    /* X.691, #12.2.2 */
89
173k
    if(ct && ct->flags != APC_UNCONSTRAINED) {
90
        /* #10.5.6 */
91
172k
        ASN_DEBUG("Integer with range %d bits", ct->range_bits);
92
172k
        if(ct->range_bits >= 0) {
93
172k
            if (ct->range_bits > 16) {
94
                /* X.691 13.2.6: constrained whole number with range > 65536. */
95
15.1k
                size_t max_range_bytes = ((size_t)ct->range_bits + 7) >> 3;
96
                /* Length determinant is (len - 1) in ceil(log2(max_bytes)) bits. */
97
15.1k
                unsigned length_bits = aper_log2_ceil_size(max_range_bytes);
98
15.1k
                int len_minus_one;
99
15.1k
                size_t len;
100
15.1k
                intmax_t value = 0;
101
102
15.1k
                len_minus_one = per_get_few_bits(pd, length_bits);
103
15.1k
                if(len_minus_one < 0) ASN__DECODE_STARVED;
104
15.0k
                len = (size_t)len_minus_one + 1;
105
15.0k
                if(len > max_range_bytes || len > sizeof(value)) ASN__DECODE_FAILED;
106
15.0k
                ASN_DEBUG("Constrained INTEGER>16 decode: range_bits=%d max_bytes=%" ASN_PRI_SIZE " len_bits=%u len=%" ASN_PRI_SIZE,
107
15.0k
                          ct->range_bits, max_range_bytes, length_bits, len);
108
109
15.0k
                if(aper_get_align(pd) < 0) ASN__DECODE_FAILED;
110
111
31.8k
                while(len > 0) {
112
16.8k
                    int buf = per_get_few_bits(pd, 8);
113
16.8k
                    if(buf < 0) ASN__DECODE_STARVED;
114
16.7k
                    if(value > (INTMAX_MAX >> 8)) ASN__DECODE_FAILED;
115
16.7k
                    value = (value << 8) | buf;
116
16.7k
                    len--;
117
16.7k
                }
118
119
14.9k
                if(ct->upper_bound < ct->lower_bound) {
120
1
                    ASN__DECODE_FAILED;
121
1
                }
122
14.9k
                if(value < 0) {
123
                    /* Offset must not be negative */
124
0
                    ASN__DECODE_FAILED;
125
14.9k
                } else {
126
14.9k
                    intmax_t range = ct->upper_bound - ct->lower_bound;
127
14.9k
                    if(range < 0) ASN__DECODE_FAILED;
128
14.9k
                    if((uintmax_t)value > (uintmax_t)range) {
129
142
                        ASN__DECODE_FAILED;
130
142
                    }
131
14.9k
                }
132
133
                /* Add lower bound; safe after the above checks */
134
14.8k
                value += ct->lower_bound;
135
                
136
                /* Validate the decoded value is within the constraint bounds */
137
14.8k
                if(specs && specs->field_unsigned) {
138
8.37k
                    if((uintmax_t)value > (uintmax_t)ct->upper_bound)
139
0
                        ASN__DECODE_FAILED;
140
8.37k
                    if(asn_umax2INTEGER(st, (uintmax_t)value))
141
0
                        ASN__DECODE_FAILED;
142
8.37k
                } else {
143
6.47k
                    if(value < ct->lower_bound || value > ct->upper_bound)
144
0
                        ASN__DECODE_FAILED;
145
6.47k
                    if(asn_imax2INTEGER(st, value))
146
0
                        ASN__DECODE_FAILED;
147
6.47k
                }
148
                
149
14.8k
                ASN_DEBUG("Got value %"ASN_PRIdMAX" + low %"ASN_PRIdMAX"",
150
14.8k
                          value, (intmax_t)ct->lower_bound);
151
157k
            } else {
152
157k
                intmax_t value = 0;
153
157k
                if (ct->range_bits < 8) {
154
946
                    value = per_get_few_bits(pd, ct->range_bits);
155
946
                    if(value < 0) ASN__DECODE_STARVED;
156
156k
                } else if (ct->range_bits == 8) {
157
11.9k
                    if (aper_get_align(pd) < 0)
158
0
                        ASN__DECODE_FAILED;
159
11.9k
                    value = per_get_few_bits(pd, ct->range_bits);
160
11.9k
                    if(value < 0) ASN__DECODE_STARVED;
161
144k
                } else {
162
                    /* Align */
163
144k
                    if (aper_get_align(pd) < 0)
164
0
                        ASN__DECODE_FAILED;
165
144k
                    value = per_get_few_bits(pd, 16);
166
144k
                    if(value < 0) ASN__DECODE_STARVED;
167
144k
                }
168
156k
                value += ct->lower_bound;
169
                /* Validate the decoded value is within the constraint bounds */
170
156k
                if(specs && specs->field_unsigned) {
171
0
                    if((uintmax_t)value > (uintmax_t)ct->upper_bound)
172
0
                        ASN__DECODE_FAILED;
173
0
                    if(asn_umax2INTEGER(st, (uintmax_t)value))
174
0
                        ASN__DECODE_FAILED;
175
156k
                } else {
176
156k
                    if(value < ct->lower_bound || value > ct->upper_bound)
177
41
                        ASN__DECODE_FAILED;
178
156k
                    if(asn_imax2INTEGER(st, value))
179
0
                        ASN__DECODE_FAILED;
180
156k
                }
181
156k
                ASN_DEBUG("Got value %"ASN_PRIdMAX" + low %"ASN_PRIdMAX"",
182
156k
                          value, (intmax_t)ct->lower_bound);
183
156k
            }
184
171k
            return rval;
185
172k
        }
186
        /* Semi-constrained (range_bits < 0): fall through to unconstrained decoding */
187
172k
    } else {
188
741
        ASN_DEBUG("Decoding unconstrained integer %s", td->name);
189
741
    }
190
191
    /* X.691, #12.2.3, #12.2.4 */
192
741
    do {
193
741
        ssize_t len;
194
741
        void *p;
195
741
        int ret;
196
197
        /* Get the PER length */
198
741
        len = aper_get_length(pd, -1, -1, -1, &repeat);
199
741
        if(len < 0) ASN__DECODE_STARVED;
200
201
715
        p = REALLOC(st->buf, st->size + len + 1);
202
715
        if(!p) ASN__DECODE_FAILED;
203
715
        st->buf = (uint8_t *)p;
204
205
715
        ret = per_get_many_bits(pd, &st->buf[st->size], 0, 8 * len);
206
715
        if(ret < 0) ASN__DECODE_STARVED;
207
688
        st->size += len;
208
688
    } while(repeat);
209
688
    st->buf[st->size] = 0;  /* JIC */
210
211
    /* #12.2.3 */
212
688
    if(ct && ct->lower_bound) {
213
        /*
214
         * TODO: replace by in-place arithmetics.
215
         */
216
0
        long value;
217
0
        if(asn_INTEGER2long(st, &value))
218
0
            ASN__DECODE_FAILED;
219
0
        if(asn_long2INTEGER(st, value + ct->lower_bound))
220
0
            ASN__DECODE_FAILED;
221
0
    }
222
223
688
    return rval;
224
688
}
225
226
asn_enc_rval_t
227
INTEGER_encode_aper(const asn_TYPE_descriptor_t *td,
228
                    const asn_per_constraints_t *constraints,
229
0
                    const void *sptr, asn_per_outp_t *po) {
230
0
    const asn_INTEGER_specifics_t *specs = (const asn_INTEGER_specifics_t *)td->specifics;
231
0
    asn_enc_rval_t er = {0,0,0};
232
0
    const INTEGER_t *st = (const INTEGER_t *)sptr;
233
0
    const uint8_t *buf;
234
0
    const uint8_t *end;
235
0
    const asn_per_constraint_t *ct;
236
0
    asn_per_constraint_t ct_ext_copy;  /* Local copy for extension case */
237
0
    intmax_t value = 0;
238
239
0
    if(!st || st->size == 0) ASN__ENCODE_FAILED;
240
241
0
    if(!constraints) constraints = td->encoding_constraints.per_constraints;
242
0
    ct = constraints ? &constraints->value : 0;
243
244
0
    er.encoded = 0;
245
246
0
    if(ct) {
247
0
        int inext = 0;
248
0
        if(specs && specs->field_unsigned) {
249
0
            uintmax_t uval;
250
0
            if(asn_INTEGER2umax(st, &uval))
251
0
                ASN__ENCODE_FAILED;
252
            /* Check proper range */
253
0
            if(ct->flags & APC_SEMI_CONSTRAINED) {
254
0
                if(uval < (uintmax_t)ct->lower_bound)
255
0
                    inext = 1;
256
0
            } else if(ct->range_bits >= 0) {
257
0
                if(uval < (uintmax_t)ct->lower_bound
258
0
                        || uval > (uintmax_t)ct->upper_bound)
259
0
                    inext = 1;
260
0
            }
261
0
            ASN_DEBUG("Value %"ASN_PRIdMAX" (%02x/%"ASN_PRI_SIZE") lb %"ASN_PRIdMAX" ub %"ASN_PRIdMAX" %s",
262
0
                      uval, st->buf[0], st->size,
263
0
                      (intmax_t)ct->lower_bound,
264
0
                      (intmax_t)ct->upper_bound,
265
0
                      inext ? "ext" : "fix");
266
0
            value = uval;
267
0
        } else {
268
0
            if(asn_INTEGER2imax(st, &value)) ASN__ENCODE_FAILED;
269
            /* Check proper range */
270
0
            if(ct->flags & APC_SEMI_CONSTRAINED) {
271
0
                if(value < ct->lower_bound)
272
0
                    inext = 1;
273
0
            } else if(ct->range_bits >= 0) {
274
0
                if(value < ct->lower_bound
275
0
                        || value > ct->upper_bound)
276
0
                    inext = 1;
277
0
            }
278
0
            ASN_DEBUG("Value %"ASN_PRIdMAX" (%02x/%"ASN_PRI_SIZE") lb %"ASN_PRIdMAX" ub %"ASN_PRIdMAX" %s",
279
0
                      value, st->buf[0], st->size,
280
0
                      (intmax_t)ct->lower_bound,
281
0
                      (intmax_t)ct->upper_bound,
282
0
                      inext ? "ext" : "fix");
283
0
        }
284
0
        if(ct->flags & APC_EXTENSIBLE) {
285
0
            if(per_put_few_bits(po, inext, 1))
286
0
                ASN__ENCODE_FAILED;
287
0
            if(inext) {
288
0
                if(ct->flags & APC_SEMI_CONSTRAINED) {
289
0
                    ct_ext_copy = *ct;
290
0
                    ct_ext_copy.flags = APC_SEMI_CONSTRAINED;
291
0
                    ct_ext_copy.range_bits = -1;
292
0
                    ct_ext_copy.effective_bits = -1;
293
0
                    ct = &ct_ext_copy;
294
0
                } else {
295
0
                    ct = 0;
296
0
                }
297
0
            }
298
0
        } else if(inext) {
299
0
            ASN__ENCODE_FAILED;
300
0
        }
301
0
    }
302
303
    /* X.691, #12.2.2 */
304
0
    if(ct && ct->range_bits >= 0) {
305
0
        uintmax_t v;
306
307
        /* #10.5.6 */
308
0
        ASN_DEBUG("Encoding integer %"ASN_PRIdMAX" (%"ASN_PRIdMAX") with range %d bits",
309
0
                  value, (intmax_t)(value - ct->lower_bound),
310
0
                  ct->range_bits);
311
312
0
        v = value - ct->lower_bound;
313
314
        /* #12 <= 8 -> alignment ? */
315
0
        int range = ct->upper_bound - ct->lower_bound + 1;
316
0
        if (ct->range_bits < 8 || (ct->range_bits == 8 && range < 256)) {
317
0
            if(per_put_few_bits(po, 0x00 | v, ct->range_bits))
318
0
                ASN__ENCODE_FAILED;
319
0
        } else if (ct->range_bits == 8) {
320
0
            if(aper_put_align(po) < 0)
321
0
                ASN__ENCODE_FAILED;
322
0
            if(per_put_few_bits(po, 0x00 | v, ct->range_bits))
323
0
                ASN__ENCODE_FAILED;
324
0
        } else if (ct->range_bits <= 16) {
325
            /* Consume the bytes to align on octet */
326
0
            if(aper_put_align(po) < 0)
327
0
                ASN__ENCODE_FAILED;
328
0
            if(per_put_few_bits(po, 0x0000 | v, 16))
329
0
                ASN__ENCODE_FAILED;
330
0
        } else {
331
            /* X.691 13.2.6: constrained whole number with range > 65536. */
332
0
            size_t max_range_bytes = ((size_t)ct->range_bits + 7) >> 3;
333
            /* Determinant width for (num_bytes - 1). */
334
0
            unsigned length_bits = aper_log2_ceil_size(max_range_bytes);
335
0
            size_t num_bytes = 0;
336
0
            uint8_t buf[sizeof(v)];
337
0
            uintmax_t tmp = v;
338
339
0
            do {
340
0
                num_bytes++;
341
0
                tmp >>= 8;
342
0
            } while(tmp);
343
344
0
            if(num_bytes > max_range_bytes || num_bytes > sizeof(buf))
345
0
                ASN__ENCODE_FAILED;
346
0
            ASN_DEBUG("Constrained INTEGER>16 encode: range_bits=%d max_bytes=%" ASN_PRI_SIZE " len_bits=%u len=%" ASN_PRI_SIZE " offset=%" ASN_PRIuMAX,
347
0
                      ct->range_bits, max_range_bytes, length_bits, num_bytes, v);
348
349
0
            if(per_put_few_bits(po, num_bytes - 1, length_bits))
350
0
                ASN__ENCODE_FAILED;
351
352
0
            if(aper_put_align(po) < 0)
353
0
                ASN__ENCODE_FAILED;
354
355
0
            tmp = v;
356
0
            {
357
0
                size_t i;
358
0
                for(i = 0; i < num_bytes; i++) {
359
0
                    buf[num_bytes - i - 1] = (uint8_t)(tmp & 0xff);
360
0
                    tmp >>= 8;
361
0
                }
362
0
            }
363
364
0
            if(per_put_many_bits(po, buf, 8 * num_bytes))
365
0
                ASN__ENCODE_FAILED;
366
0
        }
367
0
        ASN__ENCODED_OK(er);
368
0
    }
369
370
0
    if(ct && ct->lower_bound) {
371
0
        ASN_DEBUG("Adjust lower bound to %"ASN_PRIdMAX"", (intmax_t)ct->lower_bound);
372
        /*
373
         * Encode semi-constrained integer by subtracting lower bound.
374
         * Per X.691, the value is encoded as (value - lower_bound),
375
         * which is always non-negative.
376
         */
377
0
        INTEGER_t adjusted_int;
378
0
        memset(&adjusted_int, 0, sizeof(adjusted_int));
379
380
0
        if(specs && specs->field_unsigned) {
381
0
            uintmax_t uval;
382
0
            if(asn_INTEGER2umax(st, &uval))
383
0
                ASN__ENCODE_FAILED;
384
            /* Check that value is >= lower_bound to avoid underflow */
385
0
            if(uval < (uintmax_t)ct->lower_bound)
386
0
                ASN__ENCODE_FAILED;
387
0
            uval -= (uintmax_t)ct->lower_bound;
388
0
            if(asn_umax2INTEGER(&adjusted_int, uval)) {
389
0
                ASN_STRUCT_RESET(asn_DEF_INTEGER, &adjusted_int);
390
0
                ASN__ENCODE_FAILED;
391
0
            }
392
0
        } else {
393
0
            intmax_t sval;
394
0
            if(asn_INTEGER2imax(st, &sval))
395
0
                ASN__ENCODE_FAILED;
396
            /* Check that value is >= lower_bound */
397
0
            if(sval < ct->lower_bound)
398
0
                ASN__ENCODE_FAILED;
399
0
            sval -= ct->lower_bound;
400
0
            if(asn_imax2INTEGER(&adjusted_int, sval)) {
401
0
                ASN_STRUCT_RESET(asn_DEF_INTEGER, &adjusted_int);
402
0
                ASN__ENCODE_FAILED;
403
0
            }
404
0
        }
405
406
        /* Encode the adjusted value using unconstrained encoding */
407
0
        buf = adjusted_int.buf;
408
0
        end = adjusted_int.buf + adjusted_int.size;
409
0
        while(buf < end) {
410
0
            int need_eom = 0;
411
0
            ssize_t mayEncode = aper_put_length(po, -1, -1, end - buf, &need_eom);
412
0
            if(mayEncode < 0) {
413
0
                ASN_STRUCT_RESET(asn_DEF_INTEGER, &adjusted_int);
414
0
                ASN__ENCODE_FAILED;
415
0
            }
416
0
            if(per_put_many_bits(po, buf, 8 * mayEncode)) {
417
0
                ASN_STRUCT_RESET(asn_DEF_INTEGER, &adjusted_int);
418
0
                ASN__ENCODE_FAILED;
419
0
            }
420
0
            buf += mayEncode;
421
0
            if(need_eom && (aper_put_length(po, -1, -1, 0, NULL) < 0)) {
422
0
                ASN_STRUCT_RESET(asn_DEF_INTEGER, &adjusted_int);
423
0
                ASN__ENCODE_FAILED;
424
0
            }
425
0
        }
426
427
0
        ASN_STRUCT_RESET(asn_DEF_INTEGER, &adjusted_int);
428
0
        ASN__ENCODED_OK(er);
429
0
    }
430
431
0
    for(buf = st->buf, end = st->buf + st->size; buf < end;) {
432
0
        int need_eom = 0;
433
0
        ssize_t mayEncode = aper_put_length(po, -1, -1, end - buf, &need_eom);
434
0
        if(mayEncode < 0)
435
0
            ASN__ENCODE_FAILED;
436
0
        if(per_put_many_bits(po, buf, 8 * mayEncode))
437
0
            ASN__ENCODE_FAILED;
438
0
        buf += mayEncode;
439
0
        if(need_eom && (aper_put_length(po, -1, -1, 0, NULL) < 0))
440
0
            ASN__ENCODE_FAILED;
441
0
    }
442
443
0
    ASN__ENCODED_OK(er);
444
0
}