Coverage Report

Created: 2026-08-14 06:04

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/open5gs/lib/asn1c/common/INTEGER.c
Line
Count
Source
1
/*
2
 * Copyright (c) 2003-2019 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
#include <errno.h>
9
#include <inttypes.h>
10
/*
11
 * INTEGER basic type description.
12
 */
13
static const ber_tlv_tag_t asn_DEF_INTEGER_tags[] = {
14
    (ASN_TAG_CLASS_UNIVERSAL | (2 << 2))
15
};
16
asn_TYPE_operation_t asn_OP_INTEGER = {
17
    .kind = ASN_KIND_PRIMITIVE,
18
    INTEGER_free,
19
#if !defined(ASN_DISABLE_PRINT_SUPPORT)
20
    INTEGER_print,
21
#else
22
    0,
23
#endif  /* !defined(ASN_DISABLE_PRINT_SUPPORT) */
24
    INTEGER_compare,
25
    INTEGER_copy,
26
#if !defined(ASN_DISABLE_BER_SUPPORT)
27
    ber_decode_primitive,
28
    INTEGER_encode_der,
29
#else
30
    0,
31
    0,
32
#endif  /* !defined(ASN_DISABLE_BER_SUPPORT) */
33
#if !defined(ASN_DISABLE_XER_SUPPORT)
34
    INTEGER_decode_xer,
35
    INTEGER_encode_xer,
36
#else
37
    0,
38
    0,
39
#endif  /* !defined(ASN_DISABLE_XER_SUPPORT) */
40
#if !defined(ASN_DISABLE_JER_SUPPORT)
41
    INTEGER_decode_jer,
42
    INTEGER_encode_jer,
43
#else
44
    0,
45
    0,
46
#endif  /* !defined(ASN_DISABLE_JER_SUPPORT) */
47
#if !defined(ASN_DISABLE_OER_SUPPORT)
48
    INTEGER_decode_oer,  /* OER decoder */
49
    INTEGER_encode_oer,  /* Canonical OER encoder */
50
#else
51
    0,
52
    0,
53
#endif  /* !defined(ASN_DISABLE_OER_SUPPORT) */
54
#if !defined(ASN_DISABLE_UPER_SUPPORT)
55
    INTEGER_decode_uper,  /* Unaligned PER decoder */
56
    INTEGER_encode_uper,  /* Unaligned PER encoder */
57
#else
58
    0,
59
    0,
60
#endif  /* !defined(ASN_DISABLE_UPER_SUPPORT) */
61
#if !defined(ASN_DISABLE_APER_SUPPORT)
62
    INTEGER_decode_aper,  /* Aligned PER decoder */
63
    INTEGER_encode_aper,  /* Aligned PER encoder */
64
#else
65
    0,
66
    0,
67
#endif  /* !defined(ASN_DISABLE_APER_SUPPORT) */
68
#if !defined(ASN_DISABLE_RFILL_SUPPORT)
69
    INTEGER_random_fill,
70
#else
71
    0,
72
#endif  /* !defined(ASN_DISABLE_RFILL_SUPPORT) */
73
0,  /* Use generic outmost tag fetcher */
74
#if !defined(ASN_DISABLE_CBOR_SUPPORT)
75
    INTEGER_decode_cbor,
76
    INTEGER_encode_cbor,
77
#else
78
    0,
79
    0,
80
#endif  /* !defined(ASN_DISABLE_CBOR_SUPPORT) */
81
};
82
asn_TYPE_descriptor_t asn_DEF_INTEGER = {
83
    "INTEGER",
84
    "INTEGER",
85
    &asn_OP_INTEGER,
86
    asn_DEF_INTEGER_tags,
87
    sizeof(asn_DEF_INTEGER_tags) / sizeof(asn_DEF_INTEGER_tags[0]),
88
    asn_DEF_INTEGER_tags, /* Same as above */
89
    sizeof(asn_DEF_INTEGER_tags) / sizeof(asn_DEF_INTEGER_tags[0]),
90
    {
91
#if !defined(ASN_DISABLE_OER_SUPPORT)
92
        0,
93
#endif  /* !defined(ASN_DISABLE_OER_SUPPORT) */
94
#if !defined(ASN_DISABLE_UPER_SUPPORT) || !defined(ASN_DISABLE_APER_SUPPORT)
95
        0,
96
#endif  /* !defined(ASN_DISABLE_UPER_SUPPORT) || !defined(ASN_DISABLE_APER_SUPPORT) */
97
#if !defined(ASN_DISABLE_JER_SUPPORT)
98
        0,
99
#endif  /* !defined(ASN_DISABLE_JER_SUPPORT) */
100
        asn_generic_no_constraint
101
    },
102
    0, 0,  /* No members */
103
    0  /* No specifics */
104
};
105
106
/*
107
 * INTEGER specific human-readable output.
108
 */
109
ssize_t
110
0
INTEGER__dump(const asn_TYPE_descriptor_t *td, const INTEGER_t *st, asn_app_consume_bytes_f *cb, void *app_key, int plainOrXEROrJER) {
111
0
    const asn_INTEGER_specifics_t *specs =
112
0
        (const asn_INTEGER_specifics_t *)td->specifics;
113
0
  char scratch[32];
114
0
  uint8_t *buf = st->buf;
115
0
  uint8_t *buf_end = st->buf + st->size;
116
0
  intmax_t value = 0;
117
0
  ssize_t wrote = 0;
118
0
  char *p = NULL;
119
0
  int ret = -1;
120
121
0
  if(specs && specs->field_unsigned)
122
0
    ret = asn_INTEGER2umax(st, (uintmax_t *)&value);
123
0
  else
124
0
    ret = asn_INTEGER2imax(st, &value);
125
126
  /* Simple case: the integer size is small */
127
0
  if(ret == 0) {
128
0
    const asn_INTEGER_enum_map_t *el;
129
0
    el = (value >= 0 || !specs || !specs->field_unsigned)
130
0
      ? INTEGER_map_value2enum(specs, value) : 0;
131
0
    if(el) {
132
0
      if(plainOrXEROrJER == 0)
133
0
        return asn__format_to_callback(cb, app_key,
134
0
          "%" ASN_PRIdMAX " (%s)", value, el->enum_name);
135
0
      else if (plainOrXEROrJER == 1)
136
0
        return asn__format_to_callback(cb, app_key,
137
0
          "<%s/>", el->enum_name);
138
0
      else if (plainOrXEROrJER == 2)
139
0
        return asn__format_to_callback(cb, app_key,
140
0
          "\"%s\"", el->enum_name);
141
0
    } else if(plainOrXEROrJER && specs && specs->strict_enumeration) {
142
0
      ASN_DEBUG("ASN.1 forbids dealing with "
143
0
        "unknown value of ENUMERATED type");
144
0
      errno = EPERM;
145
0
      return -1;
146
0
    } else {
147
0
            return asn__format_to_callback(cb, app_key,
148
0
                                           (specs && specs->field_unsigned)
149
0
                                               ? "%" ASN_PRIuMAX
150
0
                                               : "%" ASN_PRIdMAX,
151
0
                                           value);
152
0
        }
153
0
  } else if(plainOrXEROrJER && specs && specs->strict_enumeration) {
154
    /*
155
     * Here and earlier, we cannot encode the ENUMERATED values
156
     * if there is no corresponding identifier.
157
     */
158
0
    ASN_DEBUG("ASN.1 forbids dealing with "
159
0
      "unknown value of ENUMERATED type");
160
0
    errno = EPERM;
161
0
    return -1;
162
0
  }
163
164
  /* Output in the long xx:yy:zz... format */
165
  /* TODO: replace with generic algorithm (Knuth TAOCP Vol 2, 4.3.1) */
166
  
167
  /* For JER (JSON), large integers should be quoted as strings */
168
0
  if(plainOrXEROrJER == 2) {
169
0
    if(cb("\"", 1, app_key) < 0) return -1;
170
0
    wrote += 1;
171
0
  }
172
  
173
0
  for(p = scratch; buf < buf_end; buf++) {
174
0
    const char * const h2c = "0123456789ABCDEF";
175
0
    if((p - scratch) >= (ssize_t)(sizeof(scratch) - 4)) {
176
      /* Flush buffer */
177
0
      if(cb(scratch, p - scratch, app_key) < 0)
178
0
        return -1;
179
0
      wrote += p - scratch;
180
0
      p = scratch;
181
0
    }
182
0
    *p++ = h2c[*buf >> 4];
183
0
    *p++ = h2c[*buf & 0x0F];
184
0
    *p++ = 0x3a;  /* ":" */
185
0
  }
186
0
  if(p != scratch)
187
0
    p--; /* Remove the last ":" */
188
189
0
  wrote += p - scratch;
190
0
  if((cb(scratch, p - scratch, app_key) < 0)) return -1;
191
  
192
  /* Close quote for JER (JSON) */
193
0
  if(plainOrXEROrJER == 2) {
194
0
    if(cb("\"", 1, app_key) < 0) return -1;
195
0
    wrote += 1;
196
0
  }
197
  
198
0
  return wrote;
199
0
}
200
201
static int
202
0
INTEGER__compar_value2enum(const void *kp, const void *am) {
203
0
  long a = *(const long *)kp;
204
0
  const asn_INTEGER_enum_map_t *el = (const asn_INTEGER_enum_map_t *)am;
205
0
  long b = el->nat_value;
206
0
  if(a < b) return -1;
207
0
  else if(a == b) return 0;
208
0
  else return 1;
209
0
}
210
211
const asn_INTEGER_enum_map_t *
212
0
INTEGER_map_value2enum(const asn_INTEGER_specifics_t *specs, long value) {
213
0
  int count = specs ? specs->map_count : 0;
214
0
  if(!count) return 0;
215
0
  return (asn_INTEGER_enum_map_t *)bsearch(&value, specs->value2enum,
216
0
    count, sizeof(specs->value2enum[0]),
217
0
    INTEGER__compar_value2enum);
218
0
}
219
220
static intmax_t
221
156k
asn__integer_convert(const uint8_t *b, const uint8_t *end) {
222
156k
    uintmax_t value;
223
224
    /* Perform the sign initialization */
225
    /* Actually value = -(*b >> 7); gains nothing, yet unreadable! */
226
156k
    if((*b >> 7)) {
227
321
        value = (uintmax_t)(-1);
228
155k
    } else {
229
155k
        value = 0;
230
155k
    }
231
232
    /* Conversion engine */
233
369k
    for(; b < end; b++) {
234
213k
        value = (value << 8) | *b;
235
213k
    }
236
237
156k
    return value;
238
156k
}
239
240
int
241
156k
asn_INTEGER2imax(const INTEGER_t *iptr, intmax_t *lptr) {
242
156k
  uint8_t *b, *end;
243
156k
  size_t size = 0;
244
245
  /* Sanity checking */
246
156k
  if(!iptr || !iptr->buf || !lptr) {
247
0
    errno = EINVAL;
248
0
    return -1;
249
0
  }
250
251
  /* Cache the begin/end of the buffer */
252
156k
  b = iptr->buf;  /* Start of the INTEGER buffer */
253
156k
  size = iptr->size;
254
156k
  end = b + size; /* Where to stop */
255
256
156k
  if(size > sizeof(intmax_t)) {
257
320
    uint8_t *end1 = end - 1;
258
    /*
259
     * Slightly more advanced processing,
260
     * able to process INTEGERs with >sizeof(intmax_t) bytes
261
     * when the actual value is small, e.g. for intmax_t == int32_t
262
     * (0x0000000000abcdef INTEGER would yield a fine 0x00abcdef int32_t)
263
     */
264
    /* Skip out the insignificant leading bytes */
265
2.12k
    for(; b < end1; b++) {
266
2.07k
      switch(*b) {
267
1.05k
        case 0x00: if((b[1] & 0x80) == 0) continue; break;
268
925
        case 0xff: if((b[1] & 0x80) != 0) continue; break;
269
2.07k
      }
270
275
      break;
271
2.07k
    }
272
273
320
    size = end - b;
274
320
    if(size > sizeof(intmax_t)) {
275
      /* Still cannot fit the sizeof(intmax_t) */
276
35
      errno = ERANGE;
277
35
      return -1;
278
35
    }
279
320
  }
280
281
  /* Shortcut processing of a corner case */
282
156k
  if(end == b) {
283
357
    *lptr = 0;
284
357
    return 0;
285
357
  }
286
287
156k
  *lptr = asn__integer_convert(b, end);
288
156k
  return 0;
289
156k
}
290
291
/* FIXME: negative INTEGER values are silently interpreted as large unsigned ones. */
292
int
293
5.37k
asn_INTEGER2umax(const INTEGER_t *iptr, uintmax_t *lptr) {
294
5.37k
  uint8_t *b, *end;
295
5.37k
  uintmax_t value;
296
5.37k
  size_t size;
297
298
5.37k
  if(!iptr || !iptr->buf || !lptr) {
299
0
    errno = EINVAL;
300
0
    return -1;
301
0
  }
302
303
5.37k
  b = iptr->buf;
304
5.37k
  size = iptr->size;
305
5.37k
  end = b + size;
306
307
  /* If all extra leading bytes are zeroes, ignore them */
308
5.37k
  for(; size > sizeof(value); b++, size--) {
309
0
    if(*b) {
310
      /* Value won't fit into uintmax_t */
311
0
      errno = ERANGE;
312
0
      return -1;
313
0
    }
314
0
  }
315
316
  /* Conversion engine */
317
11.7k
  for(value = 0; b < end; b++)
318
6.41k
    value = (value << 8) | *b;
319
320
5.37k
  *lptr = value;
321
5.37k
  return 0;
322
5.37k
}
323
324
int
325
5.37k
asn_umax2INTEGER(INTEGER_t *st, uintmax_t value) {
326
5.37k
    uint8_t *buf;
327
5.37k
    uint8_t *end;
328
5.37k
    uint8_t *b;
329
5.37k
    int shr;
330
331
5.37k
    if(value <= ((~(uintmax_t)0) >> 1)) {
332
5.37k
        return asn_imax2INTEGER(st, value);
333
5.37k
    }
334
335
0
    buf = (uint8_t *)MALLOC(1 + sizeof(value));
336
0
    if(!buf) return -1;
337
338
0
    end = buf + (sizeof(value) + 1);
339
0
    buf[0] = 0; /* INTEGERs are signed. 0-byte indicates positive. */
340
0
    for(b = buf + 1, shr = (sizeof(value) - 1) * 8; b < end; shr -= 8, b++)
341
0
        *b = (uint8_t)(value >> shr);
342
343
0
    if(st->buf) FREEMEM(st->buf);
344
0
    st->buf = buf;
345
0
    st->size = 1 + sizeof(value);
346
347
0
  return 0;
348
0
}
349
350
int
351
166k
asn_imax2INTEGER(INTEGER_t *st, intmax_t value) {
352
166k
  uint8_t *buf, *bp;
353
166k
  volatile uint8_t *p;
354
166k
  volatile uint8_t *pstart;
355
166k
  volatile uint8_t *pend1;
356
166k
  int littleEndian = 1; /* Run-time detection */
357
166k
  volatile int add;
358
359
166k
  if(!st) {
360
0
    errno = EINVAL;
361
0
    return -1;
362
0
  }
363
364
166k
  buf = (uint8_t *)(long *)MALLOC(sizeof(value));
365
166k
  if(!buf) return -1;
366
367
166k
  if(*(char *)&littleEndian) {
368
166k
    pstart = (uint8_t *)&value + sizeof(value) - 1;
369
166k
    pend1 = (uint8_t *)&value;
370
166k
    add = -1;
371
166k
  } else {
372
0
    pstart = (uint8_t *)&value;
373
0
    pend1 = pstart + sizeof(value) - 1;
374
0
    add = 1;
375
0
  }
376
377
  /*
378
   * If the contents octet consists of more than one octet,
379
   * then bits of the first octet and bit 8 of the second octet:
380
   * a) shall not all be ones; and
381
   * b) shall not all be zero.
382
   */
383
1.27M
  for(p = pstart; p != pend1; p += add) {
384
1.15M
    switch(*p) {
385
1.12M
    case 0x00: if((*(p+add) & 0x80) == 0)
386
1.10M
        continue;
387
17.9k
      break;
388
17.9k
    case 0xff: if((*(p+add) & 0x80))
389
272
        continue;
390
28
      break;
391
1.15M
    }
392
46.9k
    break;
393
1.15M
  }
394
  /* Copy the integer body */
395
390k
  for(bp = buf, pend1 += add; p != pend1; p += add)
396
223k
    *bp++ = *p;
397
398
166k
  if(st->buf) FREEMEM(st->buf);
399
166k
  st->buf = buf;
400
166k
  st->size = bp - buf;
401
402
166k
  return 0;
403
166k
}
404
405
int
406
156k
asn_INTEGER2long(const INTEGER_t *iptr, long *l) {
407
156k
    intmax_t v;
408
156k
    if(asn_INTEGER2imax(iptr, &v) == 0) {
409
156k
        if(v < LONG_MIN || v > LONG_MAX) {
410
0
            errno = ERANGE;
411
0
            return -1;
412
0
        }
413
156k
        *l = v;
414
156k
        return 0;
415
156k
    } else {
416
35
        return -1;
417
35
    }
418
156k
}
419
420
int
421
5.37k
asn_INTEGER2ulong(const INTEGER_t *iptr, unsigned long *l) {
422
5.37k
    uintmax_t v;
423
5.37k
    if(asn_INTEGER2umax(iptr, &v) == 0) {
424
5.37k
        if(v > ULONG_MAX) {
425
0
            errno = ERANGE;
426
0
            return -1;
427
0
        }
428
5.37k
        *l = v;
429
5.37k
        return 0;
430
5.37k
    } else {
431
0
        return -1;
432
0
    }
433
5.37k
}
434
435
int
436
0
asn_long2INTEGER(INTEGER_t *st, long value) {
437
0
    return asn_imax2INTEGER(st, value);
438
0
}
439
440
int
441
0
asn_ulong2INTEGER(INTEGER_t *st, unsigned long value) {
442
0
    return asn_imax2INTEGER(st, value);
443
0
}
444
445
0
int asn_INTEGER2int64(const INTEGER_t *st, int64_t *value) {
446
0
    intmax_t v;
447
0
    if(asn_INTEGER2imax(st, &v) == 0) {
448
0
        if(v < INT64_MIN || v > INT64_MAX) {
449
0
            errno = ERANGE;
450
0
            return -1;
451
0
        }
452
0
        *value = v;
453
0
        return 0;
454
0
    } else {
455
0
        return -1;
456
0
    }
457
0
}
458
459
0
int asn_INTEGER2uint64(const INTEGER_t *st, uint64_t *value) {
460
0
    uintmax_t v;
461
0
    if(asn_INTEGER2umax(st, &v) == 0) {
462
0
        if(v > UINT64_MAX) {
463
0
            errno = ERANGE;
464
0
            return -1;
465
0
        }
466
0
        *value = v;
467
0
        return 0;
468
0
    } else {
469
0
        return -1;
470
0
    }
471
0
}
472
473
int
474
0
asn_uint642INTEGER(INTEGER_t *st, uint64_t value) {
475
0
  uint8_t *buf;
476
0
  uint8_t *end;
477
0
  uint8_t *b;
478
0
  int shr;
479
480
0
  if(value <= INT64_MAX)
481
0
    return asn_int642INTEGER(st, value);
482
483
0
  buf = (uint8_t *)MALLOC(1 + sizeof(value));
484
0
  if(!buf) return -1;
485
486
0
  end = buf + (sizeof(value) + 1);
487
0
  buf[0] = 0;
488
0
  for(b = buf + 1, shr = (sizeof(value)-1)*8; b < end; shr -= 8, b++)
489
0
    *b = (uint8_t)(value >> shr);
490
491
0
  if(st->buf) FREEMEM(st->buf);
492
0
  st->buf = buf;
493
0
  st->size = 1 + sizeof(value);
494
495
0
  return 0;
496
0
}
497
498
int
499
0
asn_int642INTEGER(INTEGER_t *st, int64_t value) {
500
0
  uint8_t *buf, *bp;
501
0
  volatile uint8_t *p;
502
0
  volatile uint8_t *pstart;
503
0
  volatile uint8_t *pend1;
504
0
  int littleEndian = 1; /* Run-time detection */
505
0
  volatile int add;
506
507
0
  if(!st) {
508
0
    errno = EINVAL;
509
0
    return -1;
510
0
  }
511
512
0
  buf = (uint8_t *)MALLOC(sizeof(value));
513
0
  if(!buf) return -1;
514
515
0
  if(*(char *)&littleEndian) {
516
0
    pstart = (uint8_t *)&value + sizeof(value) - 1;
517
0
    pend1 = (uint8_t *)&value;
518
0
    add = -1;
519
0
  } else {
520
0
    pstart = (uint8_t *)&value;
521
0
    pend1 = pstart + sizeof(value) - 1;
522
0
    add = 1;
523
0
  }
524
525
  /*
526
   * If the contents octet consists of more than one octet,
527
   * then bits of the first octet and bit 8 of the second octet:
528
   * a) shall not all be ones; and
529
   * b) shall not all be zero.
530
   */
531
0
  for(p = pstart; p != pend1; p += add) {
532
0
    switch(*p) {
533
0
    case 0x00: if((*(p+add) & 0x80) == 0)
534
0
        continue;
535
0
      break;
536
0
    case 0xff: if((*(p+add) & 0x80))
537
0
        continue;
538
0
      break;
539
0
    }
540
0
    break;
541
0
  }
542
  /* Copy the integer body */
543
0
  for(pstart = p, bp = buf, pend1 += add; p != pend1; p += add)
544
0
    *bp++ = *p;
545
546
0
  if(st->buf) FREEMEM(st->buf);
547
0
  st->buf = buf;
548
0
  st->size = bp - buf;
549
550
0
  return 0;
551
0
}
552
553
/*
554
 * Parse the number in the given string until the given *end position,
555
 * returning the position after the last parsed character back using the
556
 * same (*end) pointer.
557
 * WARNING: This behavior is different from the standard strtol/strtoimax(3).
558
 */
559
enum asn_strtox_result_e
560
0
asn_strtoimax_lim(const char *str, const char **end, intmax_t *intp) {
561
0
    int sign = 1;
562
0
    intmax_t value;
563
564
0
    const intmax_t asn1_intmax_max = ((~(uintmax_t)0) >> 1);
565
0
    const intmax_t upper_boundary = asn1_intmax_max / 10;
566
0
    intmax_t last_digit_max = asn1_intmax_max % 10;
567
568
0
    if(str >= *end) return ASN_STRTOX_ERROR_INVAL;
569
570
0
    switch(*str) {
571
0
    case '-':
572
0
        last_digit_max++;
573
0
        sign = -1;
574
        /* FALL THROUGH */
575
0
    case '+':
576
0
        str++;
577
0
        if(str >= *end) {
578
0
            *end = str;
579
0
            return ASN_STRTOX_EXPECT_MORE;
580
0
        }
581
0
    }
582
583
0
    for(value = 0; str < (*end); str++) {
584
0
        if(*str >= 0x30 && *str <= 0x39) {
585
0
            int d = *str - '0';
586
0
            if(value < upper_boundary) {
587
0
                value = value * 10 + d;
588
0
            } else if(value == upper_boundary) {
589
0
                if(d <= last_digit_max) {
590
0
                    if(sign > 0) {
591
0
                        value = value * 10 + d;
592
0
                    } else {
593
0
                        sign = 1;
594
0
                        value = -value * 10 - d;
595
0
                    }
596
0
                    str += 1;
597
0
                    if(str < *end) {
598
                        // If digits continue, we're guaranteed out of range.
599
0
                        *end = str;
600
0
                        if(*str >= 0x30 && *str <= 0x39) {
601
0
                            return ASN_STRTOX_ERROR_RANGE;
602
0
                        } else {
603
0
                            *intp = sign * value;
604
0
                            return ASN_STRTOX_EXTRA_DATA;
605
0
                        }
606
0
                    }
607
0
                    break;
608
0
                } else {
609
0
                    *end = str;
610
0
                    return ASN_STRTOX_ERROR_RANGE;
611
0
                }
612
0
            } else {
613
0
                *end = str;
614
0
                return ASN_STRTOX_ERROR_RANGE;
615
0
            }
616
0
        } else {
617
0
            *end = str;
618
0
            *intp = sign * value;
619
0
            return ASN_STRTOX_EXTRA_DATA;
620
0
        }
621
0
    }
622
623
0
    *end = str;
624
0
    *intp = sign * value;
625
0
    return ASN_STRTOX_OK;
626
0
}
627
628
/*
629
 * Parse the number in the given string until the given *end position,
630
 * returning the position after the last parsed character back using the
631
 * same (*end) pointer.
632
 * WARNING: This behavior is different from the standard strtoul/strtoumax(3).
633
 */
634
enum asn_strtox_result_e
635
0
asn_strtoumax_lim(const char *str, const char **end, uintmax_t *uintp) {
636
0
    uintmax_t value;
637
638
0
    const uintmax_t asn1_uintmax_max = ((~(uintmax_t)0));
639
0
    const uintmax_t upper_boundary = asn1_uintmax_max / 10;
640
0
    uintmax_t last_digit_max = asn1_uintmax_max % 10;
641
642
0
    if(str >= *end) return ASN_STRTOX_ERROR_INVAL;
643
644
0
    switch(*str) {
645
0
    case '-':
646
0
        return ASN_STRTOX_ERROR_INVAL;
647
0
    case '+':
648
0
        str++;
649
0
        if(str >= *end) {
650
0
            *end = str;
651
0
            return ASN_STRTOX_EXPECT_MORE;
652
0
        }
653
0
    }
654
655
0
    for(value = 0; str < (*end); str++) {
656
0
        if(*str >= 0x30 && *str <= 0x39) {
657
0
            unsigned int d = *str - '0';
658
0
            if(value < upper_boundary) {
659
0
                value = value * 10 + d;
660
0
            } else if(value == upper_boundary) {
661
0
                if(d <= last_digit_max) {
662
0
                    value = value * 10 + d;
663
0
                    str += 1;
664
0
                    if(str < *end) {
665
                        // If digits continue, we're guaranteed out of range.
666
0
                        *end = str;
667
0
                        if(*str >= 0x30 && *str <= 0x39) {
668
0
                            return ASN_STRTOX_ERROR_RANGE;
669
0
                        } else {
670
0
                            *uintp = value;
671
0
                            return ASN_STRTOX_EXTRA_DATA;
672
0
                        }
673
0
                    }
674
0
                    break;
675
0
                } else {
676
0
                    *end = str;
677
0
                    return ASN_STRTOX_ERROR_RANGE;
678
0
                }
679
0
            } else {
680
0
                *end = str;
681
0
                return ASN_STRTOX_ERROR_RANGE;
682
0
            }
683
0
        } else {
684
0
            *end = str;
685
0
            *uintp = value;
686
0
            return ASN_STRTOX_EXTRA_DATA;
687
0
        }
688
0
    }
689
690
0
    *end = str;
691
0
    *uintp = value;
692
0
    return ASN_STRTOX_OK;
693
0
}
694
695
enum asn_strtox_result_e
696
0
asn_strtol_lim(const char *str, const char **end, long *lp) {
697
0
    intmax_t value;
698
0
    switch(asn_strtoimax_lim(str, end, &value)) {
699
0
    case ASN_STRTOX_ERROR_RANGE:
700
0
        return ASN_STRTOX_ERROR_RANGE;
701
0
    case ASN_STRTOX_ERROR_INVAL:
702
0
        return ASN_STRTOX_ERROR_INVAL;
703
0
    case ASN_STRTOX_EXPECT_MORE:
704
0
        return ASN_STRTOX_EXPECT_MORE;
705
0
    case ASN_STRTOX_OK:
706
0
        if(value >= LONG_MIN && value <= LONG_MAX) {
707
0
            *lp = value;
708
0
            return ASN_STRTOX_OK;
709
0
        } else {
710
0
            return ASN_STRTOX_ERROR_RANGE;
711
0
        }
712
0
    case ASN_STRTOX_EXTRA_DATA:
713
0
        if(value >= LONG_MIN && value <= LONG_MAX) {
714
0
            *lp = value;
715
0
            return ASN_STRTOX_EXTRA_DATA;
716
0
        } else {
717
0
            return ASN_STRTOX_ERROR_RANGE;
718
0
        }
719
0
    }
720
721
0
    assert(!"Unreachable");
722
0
    return ASN_STRTOX_ERROR_INVAL;
723
0
}
724
725
enum asn_strtox_result_e
726
0
asn_strtoul_lim(const char *str, const char **end, unsigned long *ulp) {
727
0
    uintmax_t value;
728
0
    switch(asn_strtoumax_lim(str, end, &value)) {
729
0
    case ASN_STRTOX_ERROR_RANGE:
730
0
        return ASN_STRTOX_ERROR_RANGE;
731
0
    case ASN_STRTOX_ERROR_INVAL:
732
0
        return ASN_STRTOX_ERROR_INVAL;
733
0
    case ASN_STRTOX_EXPECT_MORE:
734
0
        return ASN_STRTOX_EXPECT_MORE;
735
0
    case ASN_STRTOX_OK:
736
0
        if(value <= ULONG_MAX) {
737
0
            *ulp = value;
738
0
            return ASN_STRTOX_OK;
739
0
        } else {
740
0
            return ASN_STRTOX_ERROR_RANGE;
741
0
        }
742
0
    case ASN_STRTOX_EXTRA_DATA:
743
0
        if(value <= ULONG_MAX) {
744
0
            *ulp = value;
745
0
            return ASN_STRTOX_EXTRA_DATA;
746
0
        } else {
747
0
            return ASN_STRTOX_ERROR_RANGE;
748
0
        }
749
0
    }
750
751
0
    assert(!"Unreachable");
752
0
    return ASN_STRTOX_ERROR_INVAL;
753
0
}
754
755
int
756
INTEGER_compare(const asn_TYPE_descriptor_t *td, const void *aptr,
757
0
                     const void *bptr) {
758
0
    const INTEGER_t *a = aptr;
759
0
    const INTEGER_t *b = bptr;
760
761
0
    (void)td;
762
763
0
    if(a && b) {
764
0
        if(a->size && b->size) {
765
0
            int sign_a = (a->buf[0] & 0x80) ? -1 : 1;
766
0
            int sign_b = (b->buf[0] & 0x80) ? -1 : 1;
767
768
0
            if(sign_a < sign_b) return -1;
769
0
            if(sign_a > sign_b) return 1;
770
771
            /* The shortest integer wins, unless comparing negatives */
772
0
            if(a->size < b->size) {
773
0
                return -1 * sign_a;
774
0
            } else if(a->size > b->size) {
775
0
                return 1 * sign_b;
776
0
            }
777
778
0
            return sign_a * memcmp(a->buf, b->buf, a->size);
779
0
        } else if(a->size) {
780
0
            int sign = (a->buf[0] & 0x80) ? -1 : 1;
781
0
            return (1) * sign;
782
0
        } else if(b->size) {
783
0
            int sign = (a->buf[0] & 0x80) ? -1 : 1;
784
0
            return (-1) * sign;
785
0
        } else {
786
0
            return 0;
787
0
        }
788
0
    } else if(!a && !b) {
789
0
        return 0;
790
0
    } else if(!a) {
791
0
        return -1;
792
0
    } else {
793
0
        return 1;
794
0
    }
795
796
0
}
797
798
int
799
INTEGER_copy(const asn_TYPE_descriptor_t *td, void **aptr,
800
0
                     const void *bptr) {
801
0
    (void)td;
802
0
    INTEGER_t *a = *aptr;
803
0
    const INTEGER_t *b = bptr;
804
805
0
    if(!b) {
806
0
        if(a) {
807
0
            FREEMEM(a->buf);
808
0
            FREEMEM(a);
809
0
            *aptr = 0;
810
0
        }
811
0
        return 0;
812
0
    }
813
814
0
    if(!a) {
815
0
        a = *aptr = CALLOC(1, sizeof(*a));
816
0
        if(!a) return -1;
817
0
    }
818
819
0
    if(b->size) {
820
0
        uint8_t* buf = MALLOC(b->size);
821
0
        if(!buf) return -1;
822
0
        memcpy(buf, b->buf, b->size);
823
0
        FREEMEM(a->buf);
824
0
        a->buf = buf;
825
0
        a->size = b->size;
826
0
    } else {
827
0
        FREEMEM(a->buf);
828
0
        a->buf = 0;
829
0
        a->size = 0;
830
0
    }
831
832
0
    return 0;
833
0
}