Moving in e2sim originally from it/test/simulators
[sim/e2-interface.git] / e2sim / ASN1c / INTEGER.c
1 /*****************************************************************************
2 #                                                                            *
3 # Copyright 2019 AT&T Intellectual Property                                  *
4 #                                                                            *
5 # Licensed under the Apache License, Version 2.0 (the "License");            *
6 # you may not use this file except in compliance with the License.           *
7 # You may obtain a copy of the License at                                    *
8 #                                                                            *
9 #      http://www.apache.org/licenses/LICENSE-2.0                            *
10 #                                                                            *
11 # Unless required by applicable law or agreed to in writing, software        *
12 # distributed under the License is distributed on an "AS IS" BASIS,          *
13 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.   *
14 # See the License for the specific language governing permissions and        *
15 # limitations under the License.                                             *
16 #                                                                            *
17 ******************************************************************************/
18
19 /*-
20  * Copyright (c) 2003-2014 Lev Walkin <vlm@lionet.info>.
21  * All rights reserved.
22  * Redistribution and modifications are permitted subject to BSD license.
23  */
24 #include <asn_internal.h>
25 #include <INTEGER.h>
26 #include <asn_codecs_prim.h>    /* Encoder and decoder of a primitive type */
27 #include <errno.h>
28
29 /*
30  * INTEGER basic type description.
31  */
32 static const ber_tlv_tag_t asn_DEF_INTEGER_tags[] = {
33         (ASN_TAG_CLASS_UNIVERSAL | (2 << 2))
34 };
35 asn_TYPE_operation_t asn_OP_INTEGER = {
36         INTEGER_free,
37         INTEGER_print,
38         INTEGER_compare,
39         ber_decode_primitive,
40         INTEGER_encode_der,
41         INTEGER_decode_xer,
42         INTEGER_encode_xer,
43 #ifdef  ASN_DISABLE_OER_SUPPORT
44         0,
45         0,
46 #else
47         INTEGER_decode_oer,     /* OER decoder */
48         INTEGER_encode_oer,     /* Canonical OER encoder */
49 #endif  /* ASN_DISABLE_OER_SUPPORT */
50 #ifdef  ASN_DISABLE_PER_SUPPORT
51         0,
52         0,
53         0,
54         0,
55 #else
56         INTEGER_decode_uper,    /* Unaligned PER decoder */
57         INTEGER_encode_uper,    /* Unaligned PER encoder */
58         INTEGER_decode_aper,    /* Aligned PER decoder */
59         INTEGER_encode_aper,    /* Aligned PER encoder */
60 #endif  /* ASN_DISABLE_PER_SUPPORT */
61         INTEGER_random_fill,
62         0       /* Use generic outmost tag fetcher */
63 };
64 asn_TYPE_descriptor_t asn_DEF_INTEGER = {
65         "INTEGER",
66         "INTEGER",
67         &asn_OP_INTEGER,
68         asn_DEF_INTEGER_tags,
69         sizeof(asn_DEF_INTEGER_tags) / sizeof(asn_DEF_INTEGER_tags[0]),
70         asn_DEF_INTEGER_tags,   /* Same as above */
71         sizeof(asn_DEF_INTEGER_tags) / sizeof(asn_DEF_INTEGER_tags[0]),
72         { 0, 0, asn_generic_no_constraint },
73         0, 0,   /* No members */
74         0       /* No specifics */
75 };
76
77 /*
78  * Encode INTEGER type using DER.
79  */
80 asn_enc_rval_t
81 INTEGER_encode_der(const asn_TYPE_descriptor_t *td, const void *sptr,
82                    int tag_mode, ber_tlv_tag_t tag, asn_app_consume_bytes_f *cb,
83                    void *app_key) {
84     const INTEGER_t *st = (const INTEGER_t *)sptr;
85     asn_enc_rval_t rval;
86     INTEGER_t effective_integer;
87
88         ASN_DEBUG("%s %s as INTEGER (tm=%d)",
89                 cb?"Encoding":"Estimating", td->name, tag_mode);
90
91         /*
92          * Canonicalize integer in the buffer.
93          * (Remove too long sign extension, remove some first 0x00 bytes)
94          */
95         if(st->buf) {
96                 uint8_t *buf = st->buf;
97                 uint8_t *end1 = buf + st->size - 1;
98                 int shift;
99
100                 /* Compute the number of superfluous leading bytes */
101                 for(; buf < end1; buf++) {
102                         /*
103                          * If the contents octets of an integer value encoding
104                          * consist of more than one octet, then the bits of the
105                          * first octet and bit 8 of the second octet:
106                          * a) shall not all be ones; and
107                          * b) shall not all be zero.
108                          */
109                         switch(*buf) {
110                         case 0x00: if((buf[1] & 0x80) == 0)
111                                         continue;
112                                 break;
113                         case 0xff: if((buf[1] & 0x80))
114                                         continue;
115                                 break;
116                         }
117                         break;
118                 }
119
120                 /* Remove leading superfluous bytes from the integer */
121                 shift = buf - st->buf;
122                 if(shift) {
123             union {
124                 const uint8_t *c_buf;
125                 uint8_t *nc_buf;
126             } unconst;
127             unconst.c_buf = st->buf;
128             effective_integer.buf = unconst.nc_buf + shift;
129             effective_integer.size = st->size - shift;
130
131             st = &effective_integer;
132         }
133     }
134
135     rval = der_encode_primitive(td, st, tag_mode, tag, cb, app_key);
136     if(rval.structure_ptr == &effective_integer) {
137         rval.structure_ptr = sptr;
138     }
139     return rval;
140 }
141
142 static const asn_INTEGER_enum_map_t *INTEGER_map_enum2value(
143     const asn_INTEGER_specifics_t *specs, const char *lstart,
144     const char *lstop);
145
146 /*
147  * INTEGER specific human-readable output.
148  */
149 static ssize_t
150 INTEGER__dump(const asn_TYPE_descriptor_t *td, const INTEGER_t *st, asn_app_consume_bytes_f *cb, void *app_key, int plainOrXER) {
151     const asn_INTEGER_specifics_t *specs =
152         (const asn_INTEGER_specifics_t *)td->specifics;
153         char scratch[32];
154         uint8_t *buf = st->buf;
155         uint8_t *buf_end = st->buf + st->size;
156         intmax_t value;
157         ssize_t wrote = 0;
158         char *p;
159         int ret;
160
161         if(specs && specs->field_unsigned)
162                 ret = asn_INTEGER2umax(st, (uintmax_t *)&value);
163         else
164                 ret = asn_INTEGER2imax(st, &value);
165
166         /* Simple case: the integer size is small */
167         if(ret == 0) {
168                 const asn_INTEGER_enum_map_t *el;
169                 el = (value >= 0 || !specs || !specs->field_unsigned)
170                         ? INTEGER_map_value2enum(specs, value) : 0;
171                 if(el) {
172                         if(plainOrXER == 0)
173                                 return asn__format_to_callback(cb, app_key,
174                                         "%" ASN_PRIdMAX " (%s)", value, el->enum_name);
175                         else
176                                 return asn__format_to_callback(cb, app_key,
177                                         "<%s/>", el->enum_name);
178                 } else if(plainOrXER && specs && specs->strict_enumeration) {
179                         ASN_DEBUG("ASN.1 forbids dealing with "
180                                 "unknown value of ENUMERATED type");
181                         errno = EPERM;
182                         return -1;
183                 } else {
184             return asn__format_to_callback(cb, app_key,
185                                            (specs && specs->field_unsigned)
186                                                ? "%" ASN_PRIuMAX
187                                                : "%" ASN_PRIdMAX,
188                                            value);
189         }
190         } else if(plainOrXER && specs && specs->strict_enumeration) {
191                 /*
192                  * Here and earlier, we cannot encode the ENUMERATED values
193                  * if there is no corresponding identifier.
194                  */
195                 ASN_DEBUG("ASN.1 forbids dealing with "
196                         "unknown value of ENUMERATED type");
197                 errno = EPERM;
198                 return -1;
199         }
200
201         /* Output in the long xx:yy:zz... format */
202         /* TODO: replace with generic algorithm (Knuth TAOCP Vol 2, 4.3.1) */
203         for(p = scratch; buf < buf_end; buf++) {
204                 const char * const h2c = "0123456789ABCDEF";
205                 if((p - scratch) >= (ssize_t)(sizeof(scratch) - 4)) {
206                         /* Flush buffer */
207                         if(cb(scratch, p - scratch, app_key) < 0)
208                                 return -1;
209                         wrote += p - scratch;
210                         p = scratch;
211                 }
212                 *p++ = h2c[*buf >> 4];
213                 *p++ = h2c[*buf & 0x0F];
214                 *p++ = 0x3a;    /* ":" */
215         }
216         if(p != scratch)
217                 p--;    /* Remove the last ":" */
218
219         wrote += p - scratch;
220         return (cb(scratch, p - scratch, app_key) < 0) ? -1 : wrote;
221 }
222
223 /*
224  * INTEGER specific human-readable output.
225  */
226 int
227 INTEGER_print(const asn_TYPE_descriptor_t *td, const void *sptr, int ilevel,
228               asn_app_consume_bytes_f *cb, void *app_key) {
229     const INTEGER_t *st = (const INTEGER_t *)sptr;
230         ssize_t ret;
231
232         (void)ilevel;
233
234         if(!st || !st->buf)
235                 ret = cb("<absent>", 8, app_key);
236         else
237                 ret = INTEGER__dump(td, st, cb, app_key, 0);
238
239         return (ret < 0) ? -1 : 0;
240 }
241
242 struct e2v_key {
243         const char *start;
244         const char *stop;
245         const asn_INTEGER_enum_map_t *vemap;
246         const unsigned int *evmap;
247 };
248 static int
249 INTEGER__compar_enum2value(const void *kp, const void *am) {
250         const struct e2v_key *key = (const struct e2v_key *)kp;
251         const asn_INTEGER_enum_map_t *el = (const asn_INTEGER_enum_map_t *)am;
252         const char *ptr, *end, *name;
253
254         /* Remap the element (sort by different criterion) */
255         el = key->vemap + key->evmap[el - key->vemap];
256
257         /* Compare strings */
258         for(ptr = key->start, end = key->stop, name = el->enum_name;
259                         ptr < end; ptr++, name++) {
260                 if(*ptr != *name || !*name)
261                         return *(const unsigned char *)ptr
262                                 - *(const unsigned char *)name;
263         }
264         return name[0] ? -1 : 0;
265 }
266
267 static const asn_INTEGER_enum_map_t *
268 INTEGER_map_enum2value(const asn_INTEGER_specifics_t *specs, const char *lstart,
269                        const char *lstop) {
270     const asn_INTEGER_enum_map_t *el_found;
271         int count = specs ? specs->map_count : 0;
272         struct e2v_key key;
273         const char *lp;
274
275         if(!count) return NULL;
276
277         /* Guaranteed: assert(lstart < lstop); */
278         /* Figure out the tag name */
279         for(lstart++, lp = lstart; lp < lstop; lp++) {
280                 switch(*lp) {
281                 case 9: case 10: case 11: case 12: case 13: case 32: /* WSP */
282                 case 0x2f: /* '/' */ case 0x3e: /* '>' */
283                         break;
284                 default:
285                         continue;
286                 }
287                 break;
288         }
289         if(lp == lstop) return NULL;    /* No tag found */
290         lstop = lp;
291
292         key.start = lstart;
293         key.stop = lstop;
294         key.vemap = specs->value2enum;
295         key.evmap = specs->enum2value;
296         el_found = (asn_INTEGER_enum_map_t *)bsearch(&key,
297                 specs->value2enum, count, sizeof(specs->value2enum[0]),
298                 INTEGER__compar_enum2value);
299         if(el_found) {
300                 /* Remap enum2value into value2enum */
301                 el_found = key.vemap + key.evmap[el_found - key.vemap];
302         }
303         return el_found;
304 }
305
306 static int
307 INTEGER__compar_value2enum(const void *kp, const void *am) {
308         long a = *(const long *)kp;
309         const asn_INTEGER_enum_map_t *el = (const asn_INTEGER_enum_map_t *)am;
310         long b = el->nat_value;
311         if(a < b) return -1;
312         else if(a == b) return 0;
313         else return 1;
314 }
315
316 const asn_INTEGER_enum_map_t *
317 INTEGER_map_value2enum(const asn_INTEGER_specifics_t *specs, long value) {
318         int count = specs ? specs->map_count : 0;
319         if(!count) return 0;
320         return (asn_INTEGER_enum_map_t *)bsearch(&value, specs->value2enum,
321                 count, sizeof(specs->value2enum[0]),
322                 INTEGER__compar_value2enum);
323 }
324
325 static int
326 INTEGER_st_prealloc(INTEGER_t *st, int min_size) {
327         void *p = MALLOC(min_size + 1);
328         if(p) {
329                 void *b = st->buf;
330                 st->size = 0;
331                 st->buf = p;
332                 FREEMEM(b);
333                 return 0;
334         } else {
335                 return -1;
336         }
337 }
338
339 /*
340  * Decode the chunk of XML text encoding INTEGER.
341  */
342 static enum xer_pbd_rval
343 INTEGER__xer_body_decode(const asn_TYPE_descriptor_t *td, void *sptr,
344                          const void *chunk_buf, size_t chunk_size) {
345     const asn_INTEGER_specifics_t *specs =
346         (const asn_INTEGER_specifics_t *)td->specifics;
347     INTEGER_t *st = (INTEGER_t *)sptr;
348         intmax_t dec_value;
349         intmax_t hex_value = 0;
350         const char *lp;
351         const char *lstart = (const char *)chunk_buf;
352         const char *lstop = lstart + chunk_size;
353         enum {
354                 ST_LEADSPACE,
355                 ST_SKIPSPHEX,
356                 ST_WAITDIGITS,
357                 ST_DIGITS,
358                 ST_DIGITS_TRAILSPACE,
359                 ST_HEXDIGIT1,
360                 ST_HEXDIGIT2,
361                 ST_HEXDIGITS_TRAILSPACE,
362                 ST_HEXCOLON,
363                 ST_END_ENUM,
364                 ST_UNEXPECTED
365         } state = ST_LEADSPACE;
366         const char *dec_value_start = 0; /* INVARIANT: always !0 in ST_DIGITS */
367         const char *dec_value_end = 0;
368
369         if(chunk_size)
370                 ASN_DEBUG("INTEGER body %ld 0x%2x..0x%2x",
371                         (long)chunk_size, *lstart, lstop[-1]);
372
373         if(INTEGER_st_prealloc(st, (chunk_size/3) + 1))
374                 return XPBD_SYSTEM_FAILURE;
375
376         /*
377          * We may have received a tag here. It will be processed inline.
378          * Use strtoul()-like code and serialize the result.
379          */
380         for(lp = lstart; lp < lstop; lp++) {
381                 int lv = *lp;
382                 switch(lv) {
383                 case 0x09: case 0x0a: case 0x0d: case 0x20:
384                         switch(state) {
385                         case ST_LEADSPACE:
386                         case ST_DIGITS_TRAILSPACE:
387                         case ST_HEXDIGITS_TRAILSPACE:
388                         case ST_SKIPSPHEX:
389                                 continue;
390                         case ST_DIGITS:
391                                 dec_value_end = lp;
392                                 state = ST_DIGITS_TRAILSPACE;
393                                 continue;
394                         case ST_HEXCOLON:
395                                 state = ST_HEXDIGITS_TRAILSPACE;
396                                 continue;
397                         default:
398                                 break;
399                         }
400                         break;
401                 case 0x2d:      /* '-' */
402                         if(state == ST_LEADSPACE) {
403                                 dec_value = 0;
404                                 dec_value_start = lp;
405                                 state = ST_WAITDIGITS;
406                                 continue;
407                         }
408                         break;
409                 case 0x2b:      /* '+' */
410                         if(state == ST_LEADSPACE) {
411                                 dec_value = 0;
412                                 dec_value_start = lp;
413                                 state = ST_WAITDIGITS;
414                                 continue;
415                         }
416                         break;
417                 case 0x30: case 0x31: case 0x32: case 0x33: case 0x34:
418                 case 0x35: case 0x36: case 0x37: case 0x38: case 0x39:
419                         switch(state) {
420                         case ST_DIGITS: continue;
421                         case ST_SKIPSPHEX:      /* Fall through */
422                         case ST_HEXDIGIT1:
423                                 hex_value = (lv - 0x30) << 4;
424                                 state = ST_HEXDIGIT2;
425                                 continue;
426                         case ST_HEXDIGIT2:
427                                 hex_value += (lv - 0x30);
428                                 state = ST_HEXCOLON;
429                                 st->buf[st->size++] = (uint8_t)hex_value;
430                                 continue;
431                         case ST_HEXCOLON:
432                                 return XPBD_BROKEN_ENCODING;
433                         case ST_LEADSPACE:
434                                 dec_value = 0;
435                                 dec_value_start = lp;
436                                 /* FALL THROUGH */
437                         case ST_WAITDIGITS:
438                                 state = ST_DIGITS;
439                                 continue;
440                         default:
441                                 break;
442                         }
443                         break;
444                 case 0x3c:      /* '<', start of XML encoded enumeration */
445                         if(state == ST_LEADSPACE) {
446                                 const asn_INTEGER_enum_map_t *el;
447                                 el = INTEGER_map_enum2value(
448                                         (const asn_INTEGER_specifics_t *)
449                                         td->specifics, lstart, lstop);
450                                 if(el) {
451                                         ASN_DEBUG("Found \"%s\" => %ld",
452                                                 el->enum_name, el->nat_value);
453                                         dec_value = el->nat_value;
454                                         state = ST_END_ENUM;
455                                         lp = lstop - 1;
456                                         continue;
457                                 }
458                                 ASN_DEBUG("Unknown identifier for INTEGER");
459                         }
460                         return XPBD_BROKEN_ENCODING;
461                 case 0x3a:      /* ':' */
462                         if(state == ST_HEXCOLON) {
463                                 /* This colon is expected */
464                                 state = ST_HEXDIGIT1;
465                                 continue;
466                         } else if(state == ST_DIGITS) {
467                                 /* The colon here means that we have
468                                  * decoded the first two hexadecimal
469                                  * places as a decimal value.
470                                  * Switch decoding mode. */
471                                 ASN_DEBUG("INTEGER re-evaluate as hex form");
472                                 state = ST_SKIPSPHEX;
473                                 dec_value_start = 0;
474                                 lp = lstart - 1;
475                                 continue;
476                         } else {
477                                 ASN_DEBUG("state %d at %ld", state, (long)(lp - lstart));
478                                 break;
479                         }
480                 /* [A-Fa-f] */
481                 case 0x41:case 0x42:case 0x43:case 0x44:case 0x45:case 0x46:
482                 case 0x61:case 0x62:case 0x63:case 0x64:case 0x65:case 0x66:
483                         switch(state) {
484                         case ST_SKIPSPHEX:
485                         case ST_LEADSPACE: /* Fall through */
486                         case ST_HEXDIGIT1:
487                                 hex_value = lv - ((lv < 0x61) ? 0x41 : 0x61);
488                                 hex_value += 10;
489                                 hex_value <<= 4;
490                                 state = ST_HEXDIGIT2;
491                                 continue;
492                         case ST_HEXDIGIT2:
493                                 hex_value += lv - ((lv < 0x61) ? 0x41 : 0x61);
494                                 hex_value += 10;
495                                 st->buf[st->size++] = (uint8_t)hex_value;
496                                 state = ST_HEXCOLON;
497                                 continue;
498                         case ST_DIGITS:
499                                 ASN_DEBUG("INTEGER re-evaluate as hex form");
500                                 state = ST_SKIPSPHEX;
501                                 dec_value_start = 0;
502                                 lp = lstart - 1;
503                                 continue;
504                         default:
505                                 break;
506                         }
507                         break;
508                 }
509
510                 /* Found extra non-numeric stuff */
511                 ASN_DEBUG("INTEGER :: Found non-numeric 0x%2x at %ld",
512                         lv, (long)(lp - lstart));
513                 state = ST_UNEXPECTED;
514                 break;
515         }
516
517         switch(state) {
518         case ST_END_ENUM:
519                 /* Got a complete and valid enumeration encoded as a tag. */
520                 break;
521         case ST_DIGITS:
522                 dec_value_end = lstop;
523                 /* FALL THROUGH */
524         case ST_DIGITS_TRAILSPACE:
525                 /* The last symbol encountered was a digit. */
526         switch(asn_strtoimax_lim(dec_value_start, &dec_value_end, &dec_value)) {
527         case ASN_STRTOX_OK:
528             if(specs && specs->field_unsigned && (uintmax_t) dec_value <= ULONG_MAX) {
529                 break;
530             } else if(dec_value >= LONG_MIN && dec_value <= LONG_MAX) {
531                 break;
532             } else {
533                 /*
534                  * We model INTEGER on long for XER,
535                  * to avoid rewriting all the tests at once.
536                  */
537                 ASN_DEBUG("INTEGER exceeds long range");
538             }
539             /* Fall through */
540         case ASN_STRTOX_ERROR_RANGE:
541             ASN_DEBUG("INTEGER decode %s hit range limit", td->name);
542             return XPBD_DECODER_LIMIT;
543                 case ASN_STRTOX_ERROR_INVAL:
544                 case ASN_STRTOX_EXPECT_MORE:
545                 case ASN_STRTOX_EXTRA_DATA:
546                         return XPBD_BROKEN_ENCODING;
547                 }
548                 break;
549         case ST_HEXCOLON:
550         case ST_HEXDIGITS_TRAILSPACE:
551                 st->buf[st->size] = 0;  /* Just in case termination */
552                 return XPBD_BODY_CONSUMED;
553         case ST_HEXDIGIT1:
554         case ST_HEXDIGIT2:
555         case ST_SKIPSPHEX:
556                 return XPBD_BROKEN_ENCODING;
557         case ST_LEADSPACE:
558                 /* Content not found */
559                 return XPBD_NOT_BODY_IGNORE;
560         case ST_WAITDIGITS:
561         case ST_UNEXPECTED:
562                 ASN_DEBUG("INTEGER: No useful digits (state %d)", state);
563                 return XPBD_BROKEN_ENCODING;    /* No digits */
564         }
565
566         /*
567          * Convert the result of parsing of enumeration or a straight
568          * decimal value into a BER representation.
569          */
570         if(asn_imax2INTEGER(st, dec_value)) {
571                 ASN_DEBUG("INTEGER decode %s conversion failed", td->name);
572                 return XPBD_SYSTEM_FAILURE;
573         }
574
575         return XPBD_BODY_CONSUMED;
576 }
577
578 asn_dec_rval_t
579 INTEGER_decode_xer(const asn_codec_ctx_t *opt_codec_ctx,
580                    const asn_TYPE_descriptor_t *td, void **sptr,
581                    const char *opt_mname, const void *buf_ptr, size_t size) {
582     return xer_decode_primitive(opt_codec_ctx, td,
583                 sptr, sizeof(INTEGER_t), opt_mname,
584                 buf_ptr, size, INTEGER__xer_body_decode);
585 }
586
587 asn_enc_rval_t
588 INTEGER_encode_xer(const asn_TYPE_descriptor_t *td, const void *sptr,
589                    int ilevel, enum xer_encoder_flags_e flags,
590                    asn_app_consume_bytes_f *cb, void *app_key) {
591     const INTEGER_t *st = (const INTEGER_t *)sptr;
592         asn_enc_rval_t er = {0,0,0};
593
594         (void)ilevel;
595         (void)flags;
596         
597         if(!st || !st->buf)
598                 ASN__ENCODE_FAILED;
599
600         er.encoded = INTEGER__dump(td, st, cb, app_key, 1);
601         if(er.encoded < 0) ASN__ENCODE_FAILED;
602
603         ASN__ENCODED_OK(er);
604 }
605
606 #ifndef ASN_DISABLE_PER_SUPPORT
607
608 asn_dec_rval_t
609 INTEGER_decode_uper(const asn_codec_ctx_t *opt_codec_ctx,
610                     const asn_TYPE_descriptor_t *td,
611                     const asn_per_constraints_t *constraints, void **sptr,
612                     asn_per_data_t *pd) {
613     const asn_INTEGER_specifics_t *specs =
614         (const asn_INTEGER_specifics_t *)td->specifics;
615     asn_dec_rval_t rval = { RC_OK, 0 };
616         INTEGER_t *st = (INTEGER_t *)*sptr;
617         const asn_per_constraint_t *ct;
618         int repeat;
619
620         (void)opt_codec_ctx;
621
622         if(!st) {
623                 st = (INTEGER_t *)(*sptr = CALLOC(1, sizeof(*st)));
624                 if(!st) ASN__DECODE_FAILED;
625         }
626
627         if(!constraints) constraints = td->encoding_constraints.per_constraints;
628         ct = constraints ? &constraints->value : 0;
629
630         if(ct && ct->flags & APC_EXTENSIBLE) {
631                 int inext = per_get_few_bits(pd, 1);
632                 if(inext < 0) ASN__DECODE_STARVED;
633                 if(inext) ct = 0;
634         }
635
636         FREEMEM(st->buf);
637         st->buf = 0;
638         st->size = 0;
639         if(ct) {
640                 if(ct->flags & APC_SEMI_CONSTRAINED) {
641                         st->buf = (uint8_t *)CALLOC(1, 2);
642                         if(!st->buf) ASN__DECODE_FAILED;
643                         st->size = 1;
644                 } else if(ct->flags & APC_CONSTRAINED && ct->range_bits >= 0) {
645                         size_t size = (ct->range_bits + 7) >> 3;
646                         st->buf = (uint8_t *)MALLOC(1 + size + 1);
647                         if(!st->buf) ASN__DECODE_FAILED;
648                         st->size = size;
649                 }
650         }
651
652         /* X.691-2008/11, #13.2.2, constrained whole number */
653         if(ct && ct->flags != APC_UNCONSTRAINED) {
654                 /* #11.5.6 */
655                 ASN_DEBUG("Integer with range %d bits", ct->range_bits);
656                 if(ct->range_bits >= 0) {
657                         if((size_t)ct->range_bits > 8 * sizeof(unsigned long))
658                                 ASN__DECODE_FAILED;
659
660                         if(specs && specs->field_unsigned) {
661                                 unsigned long uvalue = 0;
662                                 if(uper_get_constrained_whole_number(pd,
663                                         &uvalue, ct->range_bits))
664                                         ASN__DECODE_STARVED;
665                                 ASN_DEBUG("Got value %lu + low %ld",
666                                         uvalue, ct->lower_bound);
667                                 uvalue += ct->lower_bound;
668                                 if(asn_ulong2INTEGER(st, uvalue))
669                                         ASN__DECODE_FAILED;
670                         } else {
671                                 unsigned long uvalue = 0;
672                                 long svalue;
673                                 if(uper_get_constrained_whole_number(pd,
674                                         &uvalue, ct->range_bits))
675                                         ASN__DECODE_STARVED;
676                                 ASN_DEBUG("Got value %lu + low %ld",
677                                         uvalue, ct->lower_bound);
678                 if(per_long_range_unrebase(uvalue, ct->lower_bound,
679                                            ct->upper_bound, &svalue)
680                    || asn_long2INTEGER(st, svalue)) {
681                     ASN__DECODE_FAILED;
682                 }
683                         }
684                         return rval;
685                 }
686         } else {
687                 ASN_DEBUG("Decoding unconstrained integer %s", td->name);
688         }
689
690         /* X.691, #12.2.3, #12.2.4 */
691         do {
692                 ssize_t len = 0;
693                 void *p = NULL;
694                 int ret = 0;
695
696                 /* Get the PER length */
697                 len = uper_get_length(pd, -1, 0, &repeat);
698                 if(len < 0) ASN__DECODE_STARVED;
699
700                 p = REALLOC(st->buf, st->size + len + 1);
701                 if(!p) ASN__DECODE_FAILED;
702                 st->buf = (uint8_t *)p;
703
704                 ret = per_get_many_bits(pd, &st->buf[st->size], 0, 8 * len);
705                 if(ret < 0) ASN__DECODE_STARVED;
706                 st->size += len;
707         } while(repeat);
708         st->buf[st->size] = 0;  /* JIC */
709
710         /* #12.2.3 */
711         if(ct && ct->lower_bound) {
712                 /*
713                  * TODO: replace by in-place arithmetics.
714                  */
715                 long value = 0;
716                 if(asn_INTEGER2long(st, &value))
717                         ASN__DECODE_FAILED;
718                 if(asn_imax2INTEGER(st, value + ct->lower_bound))
719                         ASN__DECODE_FAILED;
720         }
721
722         return rval;
723 }
724
725 asn_enc_rval_t
726 INTEGER_encode_uper(const asn_TYPE_descriptor_t *td,
727                     const asn_per_constraints_t *constraints, const void *sptr,
728                     asn_per_outp_t *po) {
729         const asn_INTEGER_specifics_t *specs =
730                 (const asn_INTEGER_specifics_t *)td->specifics;
731         asn_enc_rval_t er = {0,0,0};
732         const INTEGER_t *st = (const INTEGER_t *)sptr;
733         const uint8_t *buf;
734         const uint8_t *end;
735         const asn_per_constraint_t *ct;
736         long value = 0;
737
738         if(!st || st->size == 0) ASN__ENCODE_FAILED;
739
740         if(!constraints) constraints = td->encoding_constraints.per_constraints;
741         ct = constraints ? &constraints->value : 0;
742
743         er.encoded = 0;
744
745         if(ct) {
746                 int inext = 0;
747                 if(specs && specs->field_unsigned) {
748                         unsigned long uval;
749                         if(asn_INTEGER2ulong(st, &uval))
750                                 ASN__ENCODE_FAILED;
751                         /* Check proper range */
752                         if(ct->flags & APC_SEMI_CONSTRAINED) {
753                                 if(uval < (unsigned long)ct->lower_bound)
754                                         inext = 1;
755                         } else if(ct->range_bits >= 0) {
756                                 if(uval < (unsigned long)ct->lower_bound
757                                 || uval > (unsigned long)ct->upper_bound)
758                                         inext = 1;
759                         }
760                         ASN_DEBUG("Value %lu (%02x/%" ASN_PRI_SIZE ") lb %lu ub %lu %s",
761                                 uval, st->buf[0], st->size,
762                                 ct->lower_bound, ct->upper_bound,
763                                 inext ? "ext" : "fix");
764                         value = uval;
765                 } else {
766                         if(asn_INTEGER2long(st, &value))
767                                 ASN__ENCODE_FAILED;
768                         /* Check proper range */
769                         if(ct->flags & APC_SEMI_CONSTRAINED) {
770                                 if(value < ct->lower_bound)
771                                         inext = 1;
772                         } else if(ct->range_bits >= 0) {
773                                 if(value < ct->lower_bound
774                                 || value > ct->upper_bound)
775                                         inext = 1;
776                         }
777                         ASN_DEBUG("Value %ld (%02x/%" ASN_PRI_SIZE ") lb %ld ub %ld %s",
778                                 value, st->buf[0], st->size,
779                                 ct->lower_bound, ct->upper_bound,
780                                 inext ? "ext" : "fix");
781                 }
782                 if(ct->flags & APC_EXTENSIBLE) {
783                         if(per_put_few_bits(po, inext, 1))
784                                 ASN__ENCODE_FAILED;
785                         if(inext) ct = 0;
786                 } else if(inext) {
787                         ASN__ENCODE_FAILED;
788                 }
789         }
790
791
792         /* X.691-11/2008, #13.2.2, test if constrained whole number */
793         if(ct && ct->range_bits >= 0) {
794         unsigned long v;
795                 /* #11.5.6 -> #11.3 */
796                 ASN_DEBUG("Encoding integer %ld (%lu) with range %d bits",
797                         value, value - ct->lower_bound, ct->range_bits);
798         if(specs && specs->field_unsigned) {
799                 if (  ((unsigned long)ct->lower_bound > (unsigned long)(ct->upper_bound)
800                    || ((unsigned long)value < (unsigned long)ct->lower_bound))
801                    || ((unsigned long)value > (unsigned long)ct->upper_bound)
802                 ) {
803                         ASN_DEBUG("Value %lu to-be-encoded is outside the bounds [%lu, %lu]!",
804                                 value, ct->lower_bound, ct->upper_bound);
805                         ASN__ENCODE_FAILED;
806                 }
807                 v = (unsigned long)value - (unsigned long)ct->lower_bound;
808         } else {
809                 if(per_long_range_rebase(value, ct->lower_bound, ct->upper_bound, &v)) {
810                         ASN__ENCODE_FAILED;
811                 }
812         }
813         if(uper_put_constrained_whole_number_u(po, v, ct->range_bits))
814                 ASN__ENCODE_FAILED;
815         ASN__ENCODED_OK(er);
816         }
817
818         if(ct && ct->lower_bound) {
819                 ASN_DEBUG("Adjust lower bound to %ld", ct->lower_bound);
820                 /* TODO: adjust lower bound */
821                 ASN__ENCODE_FAILED;
822         }
823
824         for(buf = st->buf, end = st->buf + st->size; buf < end;) {
825         int need_eom = 0;
826         ssize_t mayEncode = uper_put_length(po, end - buf, &need_eom);
827         if(mayEncode < 0)
828                         ASN__ENCODE_FAILED;
829                 if(per_put_many_bits(po, buf, 8 * mayEncode))
830                         ASN__ENCODE_FAILED;
831                 buf += mayEncode;
832         if(need_eom && uper_put_length(po, 0, 0)) ASN__ENCODE_FAILED;
833     }
834
835         ASN__ENCODED_OK(er);
836 }
837
838 asn_dec_rval_t
839 INTEGER_decode_aper(const asn_codec_ctx_t *opt_codec_ctx,
840                     const asn_TYPE_descriptor_t *td,
841                     const asn_per_constraints_t *constraints, void **sptr, asn_per_data_t *pd) {
842         const asn_INTEGER_specifics_t *specs = (const asn_INTEGER_specifics_t *)td->specifics;
843         asn_dec_rval_t rval = { RC_OK, 0 };
844         INTEGER_t *st = (INTEGER_t *)*sptr;
845         const asn_per_constraint_t *ct;
846         int repeat;
847
848         (void)opt_codec_ctx;
849
850         if(!st) {
851                 st = (INTEGER_t *)(*sptr = CALLOC(1, sizeof(*st)));
852                 if(!st) ASN__DECODE_FAILED;
853         }
854
855         if(!constraints) constraints = td->encoding_constraints.per_constraints;
856         ct = constraints ? &constraints->value : 0;
857
858         if(ct && ct->flags & APC_EXTENSIBLE) {
859                 int inext = per_get_few_bits(pd, 1);
860                 if(inext < 0) ASN__DECODE_STARVED;
861                 if(inext) ct = 0;
862         }
863
864         FREEMEM(st->buf);
865         st->buf = 0;
866         st->size = 0;
867         if(ct) {
868                 if(ct->flags & APC_SEMI_CONSTRAINED) {
869                         st->buf = (uint8_t *)CALLOC(1, 2);
870                         if(!st->buf) ASN__DECODE_FAILED;
871                         st->size = 1;
872                 } else if(ct->flags & APC_CONSTRAINED && ct->range_bits >= 0) {
873                         size_t size = (ct->range_bits + 7) >> 3;
874                         st->buf = (uint8_t *)MALLOC(1 + size + 1);
875                         if(!st->buf) ASN__DECODE_FAILED;
876                         st->size = size;
877                 }
878         }
879
880         /* X.691, #12.2.2 */
881         if(ct && ct->flags != APC_UNCONSTRAINED) {
882                 /* #10.5.6 */
883                 ASN_DEBUG("Integer with range %d bits", ct->range_bits);
884                 if(ct->range_bits >= 0) {
885                         if (ct->range_bits > 16) {
886                                 int max_range_bytes = (ct->range_bits >> 3) +
887                                                       (((ct->range_bits % 8) > 0) ? 1 : 0);
888                                 int length = 0, i;
889                                 long value = 0;
890
891                                 for (i = 1; ; i++) {
892                                         int upper = 1 << i;
893                                         if (upper >= max_range_bytes)
894                                                 break;
895                                 }
896                                 ASN_DEBUG("Can encode %d (%d bytes) in %d bits", ct->range_bits,
897                                           max_range_bytes, i);
898
899                                 if ((length = per_get_few_bits(pd, i)) < 0)
900                                         ASN__DECODE_FAILED;
901
902                                 /* X.691 #12.2.6 length determinant + lb (1) */
903                                 length += 1;
904                                 ASN_DEBUG("Got length %d", length);
905                                 if (aper_get_align(pd) != 0)
906                                         ASN__DECODE_FAILED;
907                                 while (length--) {
908                                         int buf = per_get_few_bits(pd, 8);
909                                         if (buf < 0)
910                                                 ASN__DECODE_FAILED;
911                                         value += (((long)buf) << (8 * length));
912                                 }
913
914                                 value += ct->lower_bound;
915                                 if((specs && specs->field_unsigned)
916                                         ? asn_uint642INTEGER(st, (unsigned long)value)
917                                         : asn_int642INTEGER(st, value))
918                                         ASN__DECODE_FAILED;
919                                 ASN_DEBUG("Got value %ld + low %ld",
920                                           value, ct->lower_bound);
921                         } else {
922                                 long value = 0;
923                                 if (ct->range_bits < 8) {
924                                         value = per_get_few_bits(pd, ct->range_bits);
925                                         if(value < 0) ASN__DECODE_STARVED;
926                                 } else if (ct->range_bits == 8) {
927                                         if (aper_get_align(pd) < 0)
928                                                 ASN__DECODE_FAILED;
929                                         value = per_get_few_bits(pd, ct->range_bits);
930                                         if(value < 0) ASN__DECODE_STARVED;
931                                 } else {
932                                         /* Align */
933                                         if (aper_get_align(pd) < 0)
934                                                 ASN__DECODE_FAILED;
935                                         value = per_get_few_bits(pd, 16);
936                                         if(value < 0) ASN__DECODE_STARVED;
937                                 }
938                                 value += ct->lower_bound;
939                                 if((specs && specs->field_unsigned)
940                                         ? asn_ulong2INTEGER(st, value)
941                                         : asn_long2INTEGER(st, value))
942                                         ASN__DECODE_FAILED;
943                                 ASN_DEBUG("Got value %ld + low %ld",
944                                           value, ct->lower_bound);
945                         }
946                         return rval;
947                 } else {
948                         ASN__DECODE_FAILED;
949                 }
950         } else {
951                 ASN_DEBUG("Decoding unconstrained integer %s", td->name);
952         }
953
954         /* X.691, #12.2.3, #12.2.4 */
955         do {
956                 ssize_t len;
957                 void *p;
958                 int ret;
959
960                 /* Get the PER length */
961                 len = aper_get_length(pd, -1, -1, &repeat);
962                 if(len < 0) ASN__DECODE_STARVED;
963
964                 p = REALLOC(st->buf, st->size + len + 1);
965                 if(!p) ASN__DECODE_FAILED;
966                 st->buf = (uint8_t *)p;
967
968                 ret = per_get_many_bits(pd, &st->buf[st->size], 0, 8 * len);
969                 if(ret < 0) ASN__DECODE_STARVED;
970                 st->size += len;
971         } while(repeat);
972         st->buf[st->size] = 0;  /* JIC */
973
974         /* #12.2.3 */
975         if(ct && ct->lower_bound) {
976                 /*
977                  * TODO: replace by in-place arithmetics.
978                  */
979                 long value;
980                 if(asn_INTEGER2long(st, &value))
981                         ASN__DECODE_FAILED;
982                 if(asn_long2INTEGER(st, value + ct->lower_bound))
983                         ASN__DECODE_FAILED;
984         }
985
986         return rval;
987 }
988
989 asn_enc_rval_t
990 INTEGER_encode_aper(const asn_TYPE_descriptor_t *td,
991                     const asn_per_constraints_t *constraints,
992                     const void *sptr, asn_per_outp_t *po) {
993         const asn_INTEGER_specifics_t *specs = (const asn_INTEGER_specifics_t *)td->specifics;
994         asn_enc_rval_t er = {0,0,0};
995         const INTEGER_t *st = (const INTEGER_t *)sptr;
996         const uint8_t *buf;
997         const uint8_t *end;
998         const asn_per_constraint_t *ct;
999         long value = 0;
1000
1001         if(!st || st->size == 0) ASN__ENCODE_FAILED;
1002
1003         if(!constraints) constraints = td->encoding_constraints.per_constraints;
1004         ct = constraints ? &constraints->value : 0;
1005
1006         er.encoded = 0;
1007
1008         if(ct) {
1009                 int inext = 0;
1010                 if(specs && specs->field_unsigned) {
1011                         unsigned long uval;
1012                         if(asn_INTEGER2ulong(st, &uval))
1013                                 ASN__ENCODE_FAILED;
1014                         /* Check proper range */
1015                         if(ct->flags & APC_SEMI_CONSTRAINED) {
1016                                 if(uval < (unsigned long)ct->lower_bound)
1017                                         inext = 1;
1018                         } else if(ct->range_bits >= 0) {
1019                                 if(uval < (unsigned long)ct->lower_bound
1020                                         || uval > (unsigned long)ct->upper_bound)
1021                                         inext = 1;
1022                         }
1023                         ASN_DEBUG("Value %lu (%02x/%lu) lb %ld ub %ld %s",
1024                                   uval, st->buf[0], st->size,
1025                                   ct->lower_bound, ct->upper_bound,
1026                                   inext ? "ext" : "fix");
1027                         value = uval;
1028                 } else {
1029                         if(asn_INTEGER2long(st, &value)) ASN__ENCODE_FAILED;
1030                         /* Check proper range */
1031                         if(ct->flags & APC_SEMI_CONSTRAINED) {
1032                                 if(value < ct->lower_bound)
1033                                         inext = 1;
1034                         } else if(ct->range_bits >= 0) {
1035                                 if(value < ct->lower_bound
1036                                         || value > ct->upper_bound)
1037                                         inext = 1;
1038                         }
1039                         ASN_DEBUG("Value %lu (%02x/%lu) lb %ld ub %ld %s",
1040                                   value, st->buf[0], st->size,
1041                                   ct->lower_bound, ct->upper_bound,
1042                                   inext ? "ext" : "fix");
1043                 }
1044                 if(ct->flags & APC_EXTENSIBLE) {
1045                         if(per_put_few_bits(po, inext, 1))
1046                                 ASN__ENCODE_FAILED;
1047                         if(inext) ct = 0;
1048                 } else if(inext) {
1049                         ASN__ENCODE_FAILED;
1050                 }
1051         }
1052
1053         /* X.691, #12.2.2 */
1054         if(ct && ct->range_bits >= 0) {
1055                 unsigned long v;
1056
1057                 /* #10.5.6 */
1058                 ASN_DEBUG("Encoding integer %ld (%lu) with range %d bits",
1059                           value, value - ct->lower_bound, ct->range_bits);
1060
1061                 v = value - ct->lower_bound;
1062
1063                 /* #12 <= 8 -> alignment ? */
1064                 if (ct->range_bits < 8) {
1065                         if(per_put_few_bits(po, 0x00 | v, ct->range_bits))
1066                                 ASN__ENCODE_FAILED;
1067                 } else if (ct->range_bits == 8) {
1068                         if(aper_put_align(po) < 0)
1069                                 ASN__ENCODE_FAILED;
1070                         if(per_put_few_bits(po, 0x00 | v, ct->range_bits))
1071                                 ASN__ENCODE_FAILED;
1072                 } else if (ct->range_bits <= 16) {
1073                         /* Consume the bytes to align on octet */
1074                         if(aper_put_align(po) < 0)
1075                                 ASN__ENCODE_FAILED;
1076                         if(per_put_few_bits(po, 0x0000 | v,
1077                                             16))
1078                                 ASN__ENCODE_FAILED;
1079                 } else {
1080                         /* TODO: extend to >64 bits */
1081                         int64_t v64 = v;
1082                         int i, j;
1083                         int max_range_bytes = (ct->range_bits >> 3) +
1084                                               (((ct->range_bits % 8) > 0) ? 1 : 0);
1085
1086                         for (i = 1; ; i++) {
1087                                 int upper = 1 << i;
1088                                 if (upper >= max_range_bytes)
1089                                         break;
1090                         }
1091
1092                         for (j = sizeof(int64_t) -1; j != 0; j--) {
1093                                 int64_t val;
1094                                 val = v64 >> (j * 8);
1095                                 if (val != 0)
1096                                         break;
1097                         }
1098
1099                         /* Putting length in the minimum number of bits ex: 5 = 3bits */
1100                         if (per_put_few_bits(po, j, i))
1101                                 ASN__ENCODE_FAILED;
1102
1103                         /* Consume the bits to align on octet */
1104                         if (aper_put_align(po) < 0)
1105                                 ASN__ENCODE_FAILED;
1106                         /* Put the value */
1107                         for (i = 0; i <= j; i++) {
1108                                 if(per_put_few_bits(po, (v64 >> (8 * (j - i))) & 0xff, 8))
1109                                         ASN__ENCODE_FAILED;
1110                         }
1111                 }
1112                 ASN__ENCODED_OK(er);
1113         }
1114
1115         if(ct && ct->lower_bound) {
1116                 ASN_DEBUG("Adjust lower bound to %ld", ct->lower_bound);
1117                 /* TODO: adjust lower bound */
1118                 ASN__ENCODE_FAILED;
1119         }
1120
1121         for(buf = st->buf, end = st->buf + st->size; buf < end;) {
1122                 ssize_t mayEncode = aper_put_length(po, -1, end - buf);
1123                 if(mayEncode < 0)
1124                         ASN__ENCODE_FAILED;
1125                 if(per_put_many_bits(po, buf, 8 * mayEncode))
1126                         ASN__ENCODE_FAILED;
1127                 buf += mayEncode;
1128         }
1129
1130         ASN__ENCODED_OK(er);
1131 }
1132
1133 #endif  /* ASN_DISABLE_PER_SUPPORT */
1134
1135 static intmax_t
1136 asn__integer_convert(const uint8_t *b, const uint8_t *end) {
1137     uintmax_t value;
1138
1139     /* Perform the sign initialization */
1140     /* Actually value = -(*b >> 7); gains nothing, yet unreadable! */
1141     if((*b >> 7)) {
1142         value = (uintmax_t)(-1);
1143     } else {
1144         value = 0;
1145     }
1146
1147     /* Conversion engine */
1148     for(; b < end; b++) {
1149         value = (value << 8) | *b;
1150     }
1151
1152     return value;
1153 }
1154
1155 int
1156 asn_INTEGER2imax(const INTEGER_t *iptr, intmax_t *lptr) {
1157         uint8_t *b, *end;
1158         size_t size;
1159
1160         /* Sanity checking */
1161         if(!iptr || !iptr->buf || !lptr) {
1162                 errno = EINVAL;
1163                 return -1;
1164         }
1165
1166         /* Cache the begin/end of the buffer */
1167         b = iptr->buf;  /* Start of the INTEGER buffer */
1168         size = iptr->size;
1169         end = b + size; /* Where to stop */
1170
1171         if(size > sizeof(intmax_t)) {
1172                 uint8_t *end1 = end - 1;
1173                 /*
1174                  * Slightly more advanced processing,
1175                  * able to process INTEGERs with >sizeof(intmax_t) bytes
1176                  * when the actual value is small, e.g. for intmax_t == int32_t
1177                  * (0x0000000000abcdef INTEGER would yield a fine 0x00abcdef int32_t)
1178                  */
1179                 /* Skip out the insignificant leading bytes */
1180                 for(; b < end1; b++) {
1181                         switch(*b) {
1182                                 case 0x00: if((b[1] & 0x80) == 0) continue; break;
1183                                 case 0xff: if((b[1] & 0x80) != 0) continue; break;
1184                         }
1185                         break;
1186                 }
1187
1188                 size = end - b;
1189                 if(size > sizeof(intmax_t)) {
1190                         /* Still cannot fit the sizeof(intmax_t) */
1191                         errno = ERANGE;
1192                         return -1;
1193                 }
1194         }
1195
1196         /* Shortcut processing of a corner case */
1197         if(end == b) {
1198                 *lptr = 0;
1199                 return 0;
1200         }
1201
1202         *lptr = asn__integer_convert(b, end);
1203         return 0;
1204 }
1205
1206 /* FIXME: negative INTEGER values are silently interpreted as large unsigned ones. */
1207 int
1208 asn_INTEGER2umax(const INTEGER_t *iptr, uintmax_t *lptr) {
1209         uint8_t *b, *end;
1210         uintmax_t value;
1211         size_t size;
1212
1213         if(!iptr || !iptr->buf || !lptr) {
1214                 errno = EINVAL;
1215                 return -1;
1216         }
1217
1218         b = iptr->buf;
1219         size = iptr->size;
1220         end = b + size;
1221
1222         /* If all extra leading bytes are zeroes, ignore them */
1223         for(; size > sizeof(value); b++, size--) {
1224                 if(*b) {
1225                         /* Value won't fit into uintmax_t */
1226                         errno = ERANGE;
1227                         return -1;
1228                 }
1229         }
1230
1231         /* Conversion engine */
1232         for(value = 0; b < end; b++)
1233                 value = (value << 8) | *b;
1234
1235         *lptr = value;
1236         return 0;
1237 }
1238
1239 int
1240 asn_umax2INTEGER(INTEGER_t *st, uintmax_t value) {
1241     uint8_t *buf;
1242     uint8_t *end;
1243     uint8_t *b;
1244     int shr;
1245
1246     if(value <= ((~(uintmax_t)0) >> 1)) {
1247         return asn_imax2INTEGER(st, value);
1248     }
1249
1250     buf = (uint8_t *)MALLOC(1 + sizeof(value));
1251     if(!buf) return -1;
1252
1253     end = buf + (sizeof(value) + 1);
1254     buf[0] = 0; /* INTEGERs are signed. 0-byte indicates positive. */
1255     for(b = buf + 1, shr = (sizeof(value) - 1) * 8; b < end; shr -= 8, b++)
1256         *b = (uint8_t)(value >> shr);
1257
1258     if(st->buf) FREEMEM(st->buf);
1259     st->buf = buf;
1260     st->size = 1 + sizeof(value);
1261
1262         return 0;
1263 }
1264
1265 int
1266 asn_imax2INTEGER(INTEGER_t *st, intmax_t value) {
1267         uint8_t *buf, *bp;
1268         uint8_t *p;
1269         uint8_t *pstart;
1270         uint8_t *pend1;
1271         int littleEndian = 1;   /* Run-time detection */
1272         int add;
1273
1274         if(!st) {
1275                 errno = EINVAL;
1276                 return -1;
1277         }
1278
1279         buf = (uint8_t *)(long *)MALLOC(sizeof(value));
1280         if(!buf) return -1;
1281
1282         if(*(char *)&littleEndian) {
1283                 pstart = (uint8_t *)&value + sizeof(value) - 1;
1284                 pend1 = (uint8_t *)&value;
1285                 add = -1;
1286         } else {
1287                 pstart = (uint8_t *)&value;
1288                 pend1 = pstart + sizeof(value) - 1;
1289                 add = 1;
1290         }
1291
1292         /*
1293          * If the contents octet consists of more than one octet,
1294          * then bits of the first octet and bit 8 of the second octet:
1295          * a) shall not all be ones; and
1296          * b) shall not all be zero.
1297          */
1298         for(p = pstart; p != pend1; p += add) {
1299                 switch(*p) {
1300                 case 0x00: if((*(p+add) & 0x80) == 0)
1301                                 continue;
1302                         break;
1303                 case 0xff: if((*(p+add) & 0x80))
1304                                 continue;
1305                         break;
1306                 }
1307                 break;
1308         }
1309         /* Copy the integer body */
1310         for(bp = buf, pend1 += add; p != pend1; p += add)
1311                 *bp++ = *p;
1312
1313         if(st->buf) FREEMEM(st->buf);
1314         st->buf = buf;
1315         st->size = bp - buf;
1316
1317         return 0;
1318 }
1319
1320 int
1321 asn_INTEGER2long(const INTEGER_t *iptr, long *l) {
1322     intmax_t v;
1323     if(asn_INTEGER2imax(iptr, &v) == 0) {
1324         if(v < LONG_MIN || v > LONG_MAX) {
1325             errno = ERANGE;
1326             return -1;
1327         }
1328         *l = v;
1329         return 0;
1330     } else {
1331         return -1;
1332     }
1333 }
1334
1335 int
1336 asn_INTEGER2ulong(const INTEGER_t *iptr, unsigned long *l) {
1337     uintmax_t v;
1338     if(asn_INTEGER2umax(iptr, &v) == 0) {
1339         if(v > ULONG_MAX) {
1340             errno = ERANGE;
1341             return -1;
1342         }
1343         *l = v;
1344         return 0;
1345     } else {
1346         return -1;
1347     }
1348 }
1349
1350 int
1351 asn_long2INTEGER(INTEGER_t *st, long value) {
1352     return asn_imax2INTEGER(st, value);
1353 }
1354
1355 int
1356 asn_ulong2INTEGER(INTEGER_t *st, unsigned long value) {
1357     return asn_imax2INTEGER(st, value);
1358 }
1359
1360
1361 int
1362 asn_uint642INTEGER(INTEGER_t *st, uint64_t value) {
1363         uint8_t *buf;
1364         uint8_t *end;
1365         uint8_t *b;
1366         int shr;
1367
1368         if(value <= INT64_MAX)
1369                 return asn_int642INTEGER(st, value);
1370
1371         buf = (uint8_t *)MALLOC(1 + sizeof(value));
1372         if(!buf) return -1;
1373
1374         end = buf + (sizeof(value) + 1);
1375         buf[0] = 0;
1376         for(b = buf + 1, shr = (sizeof(value)-1)*8; b < end; shr -= 8, b++)
1377                 *b = (uint8_t)(value >> shr);
1378
1379         if(st->buf) FREEMEM(st->buf);
1380         st->buf = buf;
1381         st->size = 1 + sizeof(value);
1382
1383         return 0;
1384 }
1385
1386 int
1387 asn_int642INTEGER(INTEGER_t *st, int64_t value) {
1388         uint8_t *buf, *bp;
1389         uint8_t *p;
1390         uint8_t *pstart;
1391         uint8_t *pend1;
1392         int littleEndian = 1;   /* Run-time detection */
1393         int add;
1394
1395         if(!st) {
1396                 errno = EINVAL;
1397                 return -1;
1398         }
1399
1400         buf = (uint8_t *)MALLOC(sizeof(value));
1401         if(!buf) return -1;
1402
1403         if(*(char *)&littleEndian) {
1404                 pstart = (uint8_t *)&value + sizeof(value) - 1;
1405                 pend1 = (uint8_t *)&value;
1406                 add = -1;
1407         } else {
1408                 pstart = (uint8_t *)&value;
1409                 pend1 = pstart + sizeof(value) - 1;
1410                 add = 1;
1411         }
1412
1413         /*
1414          * If the contents octet consists of more than one octet,
1415          * then bits of the first octet and bit 8 of the second octet:
1416          * a) shall not all be ones; and
1417          * b) shall not all be zero.
1418          */
1419         for(p = pstart; p != pend1; p += add) {
1420                 switch(*p) {
1421                 case 0x00: if((*(p+add) & 0x80) == 0)
1422                                 continue;
1423                         break;
1424                 case 0xff: if((*(p+add) & 0x80))
1425                                 continue;
1426                         break;
1427                 }
1428                 break;
1429         }
1430         /* Copy the integer body */
1431         for(pstart = p, bp = buf, pend1 += add; p != pend1; p += add)
1432                 *bp++ = *p;
1433
1434         if(st->buf) FREEMEM(st->buf);
1435         st->buf = buf;
1436         st->size = bp - buf;
1437
1438         return 0;
1439 }
1440
1441 /*
1442  * Parse the number in the given string until the given *end position,
1443  * returning the position after the last parsed character back using the
1444  * same (*end) pointer.
1445  * WARNING: This behavior is different from the standard strtol/strtoimax(3).
1446  */
1447 enum asn_strtox_result_e
1448 asn_strtoimax_lim(const char *str, const char **end, intmax_t *intp) {
1449         int sign = 1;
1450         intmax_t value;
1451
1452 #define ASN1_INTMAX_MAX ((~(uintmax_t)0) >> 1)
1453     const intmax_t upper_boundary = ASN1_INTMAX_MAX / 10;
1454         intmax_t last_digit_max = ASN1_INTMAX_MAX % 10;
1455 #undef  ASN1_INTMAX_MAX
1456
1457         if(str >= *end) return ASN_STRTOX_ERROR_INVAL;
1458
1459         switch(*str) {
1460         case '-':
1461                 last_digit_max++;
1462                 sign = -1;
1463                 /* FALL THROUGH */
1464         case '+':
1465                 str++;
1466                 if(str >= *end) {
1467                         *end = str;
1468                         return ASN_STRTOX_EXPECT_MORE;
1469                 }
1470         }
1471
1472         for(value = 0; str < (*end); str++) {
1473                 switch(*str) {
1474                 case 0x30: case 0x31: case 0x32: case 0x33: case 0x34:
1475                 case 0x35: case 0x36: case 0x37: case 0x38: case 0x39: {
1476                         int d = *str - '0';
1477                         if(value < upper_boundary) {
1478                                 value = value * 10 + d;
1479                         } else if(value == upper_boundary) {
1480                                 if(d <= last_digit_max) {
1481                                         if(sign > 0) {
1482                                                 value = value * 10 + d;
1483                                         } else {
1484                                                 sign = 1;
1485                                                 value = -value * 10 - d;
1486                                         }
1487                                 } else {
1488                                         *end = str;
1489                                         return ASN_STRTOX_ERROR_RANGE;
1490                                 }
1491                         } else {
1492                                 *end = str;
1493                                 return ASN_STRTOX_ERROR_RANGE;
1494                         }
1495                     }
1496                     continue;
1497                 default:
1498                     *end = str;
1499                     *intp = sign * value;
1500                     return ASN_STRTOX_EXTRA_DATA;
1501                 }
1502         }
1503
1504         *end = str;
1505         *intp = sign * value;
1506         return ASN_STRTOX_OK;
1507 }
1508
1509 /*
1510  * Parse the number in the given string until the given *end position,
1511  * returning the position after the last parsed character back using the
1512  * same (*end) pointer.
1513  * WARNING: This behavior is different from the standard strtoul/strtoumax(3).
1514  */
1515 enum asn_strtox_result_e
1516 asn_strtoumax_lim(const char *str, const char **end, uintmax_t *uintp) {
1517         uintmax_t value;
1518
1519 #define ASN1_UINTMAX_MAX ((~(uintmax_t)0))
1520     const uintmax_t upper_boundary = ASN1_UINTMAX_MAX / 10;
1521     uintmax_t last_digit_max = ASN1_UINTMAX_MAX % 10;
1522 #undef ASN1_UINTMAX_MAX
1523
1524     if(str >= *end) return ASN_STRTOX_ERROR_INVAL;
1525
1526         switch(*str) {
1527         case '-':
1528         return ASN_STRTOX_ERROR_INVAL;
1529         case '+':
1530                 str++;
1531                 if(str >= *end) {
1532                         *end = str;
1533                         return ASN_STRTOX_EXPECT_MORE;
1534                 }
1535         }
1536
1537         for(value = 0; str < (*end); str++) {
1538                 switch(*str) {
1539                 case 0x30: case 0x31: case 0x32: case 0x33: case 0x34:
1540                 case 0x35: case 0x36: case 0x37: case 0x38: case 0x39: {
1541                         unsigned int d = *str - '0';
1542                         if(value < upper_boundary) {
1543                                 value = value * 10 + d;
1544                         } else if(value == upper_boundary) {
1545                                 if(d <= last_digit_max) {
1546                     value = value * 10 + d;
1547                 } else {
1548                                         *end = str;
1549                                         return ASN_STRTOX_ERROR_RANGE;
1550                                 }
1551                         } else {
1552                                 *end = str;
1553                                 return ASN_STRTOX_ERROR_RANGE;
1554                         }
1555                     }
1556                     continue;
1557                 default:
1558                     *end = str;
1559                     *uintp = value;
1560                     return ASN_STRTOX_EXTRA_DATA;
1561                 }
1562         }
1563
1564         *end = str;
1565         *uintp = value;
1566         return ASN_STRTOX_OK;
1567 }
1568
1569 enum asn_strtox_result_e
1570 asn_strtol_lim(const char *str, const char **end, long *lp) {
1571     intmax_t value;
1572     switch(asn_strtoimax_lim(str, end, &value)) {
1573     case ASN_STRTOX_ERROR_RANGE:
1574         return ASN_STRTOX_ERROR_RANGE;
1575     case ASN_STRTOX_ERROR_INVAL:
1576         return ASN_STRTOX_ERROR_INVAL;
1577     case ASN_STRTOX_EXPECT_MORE:
1578         return ASN_STRTOX_EXPECT_MORE;
1579     case ASN_STRTOX_OK:
1580         if(value >= LONG_MIN && value <= LONG_MAX) {
1581             *lp = value;
1582             return ASN_STRTOX_OK;
1583         } else {
1584             return ASN_STRTOX_ERROR_RANGE;
1585         }
1586     case ASN_STRTOX_EXTRA_DATA:
1587         if(value >= LONG_MIN && value <= LONG_MAX) {
1588             *lp = value;
1589             return ASN_STRTOX_EXTRA_DATA;
1590         } else {
1591             return ASN_STRTOX_ERROR_RANGE;
1592         }
1593     }
1594
1595     assert(!"Unreachable");
1596     return ASN_STRTOX_ERROR_INVAL;
1597 }
1598
1599 enum asn_strtox_result_e
1600 asn_strtoul_lim(const char *str, const char **end, unsigned long *ulp) {
1601     uintmax_t value;
1602     switch(asn_strtoumax_lim(str, end, &value)) {
1603     case ASN_STRTOX_ERROR_RANGE:
1604         return ASN_STRTOX_ERROR_RANGE;
1605     case ASN_STRTOX_ERROR_INVAL:
1606         return ASN_STRTOX_ERROR_INVAL;
1607     case ASN_STRTOX_EXPECT_MORE:
1608         return ASN_STRTOX_EXPECT_MORE;
1609     case ASN_STRTOX_OK:
1610         if(value <= ULONG_MAX) {
1611             *ulp = value;
1612             return ASN_STRTOX_OK;
1613         } else {
1614             return ASN_STRTOX_ERROR_RANGE;
1615         }
1616     case ASN_STRTOX_EXTRA_DATA:
1617         if(value <= ULONG_MAX) {
1618             *ulp = value;
1619             return ASN_STRTOX_EXTRA_DATA;
1620         } else {
1621             return ASN_STRTOX_ERROR_RANGE;
1622         }
1623     }
1624
1625     assert(!"Unreachable");
1626     return ASN_STRTOX_ERROR_INVAL;
1627 }
1628
1629 int
1630 INTEGER_compare(const asn_TYPE_descriptor_t *td, const void *aptr,
1631                      const void *bptr) {
1632     const INTEGER_t *a = aptr;
1633     const INTEGER_t *b = bptr;
1634
1635     (void)td;
1636
1637     if(a && b) {
1638         if(a->size && b->size) {
1639             int sign_a = (a->buf[0] & 0x80) ? -1 : 1;
1640             int sign_b = (b->buf[0] & 0x80) ? -1 : 1;
1641
1642             if(sign_a < sign_b) return -1;
1643             if(sign_a > sign_b) return 1;
1644
1645             /* The shortest integer wins, unless comparing negatives */
1646             if(a->size < b->size) {
1647                 return -1 * sign_a;
1648             } else if(a->size > b->size) {
1649                 return 1 * sign_b;
1650             }
1651
1652             return sign_a * memcmp(a->buf, b->buf, a->size);
1653         } else if(a->size) {
1654             int sign = (a->buf[0] & 0x80) ? -1 : 1;
1655             return (1) * sign;
1656         } else if(b->size) {
1657             int sign = (a->buf[0] & 0x80) ? -1 : 1;
1658             return (-1) * sign;
1659         } else {
1660             return 0;
1661         }
1662     } else if(!a && !b) {
1663         return 0;
1664     } else if(!a) {
1665         return -1;
1666     } else {
1667         return 1;
1668     }
1669
1670 }
1671
1672 asn_random_fill_result_t
1673 INTEGER_random_fill(const asn_TYPE_descriptor_t *td, void **sptr,
1674                     const asn_encoding_constraints_t *constraints,
1675                     size_t max_length) {
1676     const asn_INTEGER_specifics_t *specs =
1677         (const asn_INTEGER_specifics_t *)td->specifics;
1678     asn_random_fill_result_t result_ok = {ARFILL_OK, 1};
1679     asn_random_fill_result_t result_failed = {ARFILL_FAILED, 0};
1680     asn_random_fill_result_t result_skipped = {ARFILL_SKIPPED, 0};
1681     INTEGER_t *st = *sptr;
1682     const asn_INTEGER_enum_map_t *emap;
1683     size_t emap_len;
1684     intmax_t value;
1685     int find_inside_map;
1686
1687     if(max_length == 0) return result_skipped;
1688
1689     if(st == NULL) {
1690         st = (INTEGER_t *)CALLOC(1, sizeof(*st));
1691         if(st == NULL) {
1692             return result_failed;
1693         }
1694     }
1695
1696     if(specs) {
1697         emap = specs->value2enum;
1698         emap_len = specs->map_count;
1699         if(specs->strict_enumeration) {
1700             find_inside_map = emap_len > 0;
1701         } else {
1702             find_inside_map = emap_len ? asn_random_between(0, 1) : 0;
1703         }
1704     } else {
1705         emap = 0;
1706         emap_len = 0;
1707         find_inside_map = 0;
1708     }
1709
1710     if(find_inside_map) {
1711         assert(emap_len > 0);
1712         value = emap[asn_random_between(0, emap_len - 1)].nat_value;
1713     } else {
1714         const asn_per_constraints_t *ct;
1715
1716         static const long variants[] = {
1717             -65536, -65535, -65534, -32769, -32768, -32767, -16385, -16384,
1718             -16383, -257,   -256,   -255,   -254,   -129,   -128,   -127,
1719             -126,   -1,     0,      1,      126,    127,    128,    129,
1720             254,    255,    256,    257,    16383,  16384,  16385,  32767,
1721             32768,  32769,  65534,  65535,  65536,  65537};
1722         if(specs && specs->field_unsigned) {
1723             assert(variants[18] == 0);
1724             value = variants[asn_random_between(
1725                 18, sizeof(variants) / sizeof(variants[0]) - 1)];
1726         } else {
1727             value = variants[asn_random_between(
1728                 0, sizeof(variants) / sizeof(variants[0]) - 1)];
1729         }
1730
1731         if(!constraints) constraints = &td->encoding_constraints;
1732         ct = constraints ? constraints->per_constraints : 0;
1733         if(ct && (ct->value.flags & APC_CONSTRAINED)) {
1734             if(value < ct->value.lower_bound || value > ct->value.upper_bound) {
1735                 value = asn_random_between(ct->value.lower_bound,
1736                                            ct->value.upper_bound);
1737             }
1738         }
1739     }
1740
1741     if(asn_imax2INTEGER(st, value)) {
1742         if(st == *sptr) {
1743             ASN_STRUCT_RESET(*td, st);
1744         } else {
1745             ASN_STRUCT_FREE(*td, st);
1746         }
1747         return result_failed;
1748     } else {
1749         *sptr = st;
1750         result_ok.length = st->size;
1751         return result_ok;
1752     }
1753 }