"Fossies" - the Fresh Open Source Software Archive

Member "mod_auth_gssapi-1.6.3/src/asn1c/INTEGER.c" (15 Mar 2017, 25240 Bytes) of package /linux/www/apache_httpd_modules/mod_auth_gssapi-1.6.3.tar.gz:


As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) C and C++ source code syntax highlighting (style: standard) with prefixed line numbers and code folding option. Alternatively you can here view or download the uninterpreted source code file. For more information about "INTEGER.c" see the Fossies "Dox" file reference documentation.

    1 /*-
    2  * Copyright (c) 2003-2014 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 <asn_codecs_prim.h>    /* Encoder and decoder of a primitive type */
    9 #include <errno.h>
   10 
   11 /*
   12  * INTEGER basic type description.
   13  */
   14 static ber_tlv_tag_t asn_DEF_INTEGER_tags[] = {
   15     (ASN_TAG_CLASS_UNIVERSAL | (2 << 2))
   16 };
   17 asn_TYPE_descriptor_t asn_DEF_INTEGER = {
   18     "INTEGER",
   19     "INTEGER",
   20     ASN__PRIMITIVE_TYPE_free,
   21     INTEGER_print,
   22     asn_generic_no_constraint,
   23     ber_decode_primitive,
   24     INTEGER_encode_der,
   25     INTEGER_decode_xer,
   26     INTEGER_encode_xer,
   27 #ifdef  ASN_DISABLE_PER_SUPPORT
   28     0,
   29     0,
   30 #else
   31     INTEGER_decode_uper,    /* Unaligned PER decoder */
   32     INTEGER_encode_uper,    /* Unaligned PER encoder */
   33 #endif  /* ASN_DISABLE_PER_SUPPORT */
   34     0, /* Use generic outmost tag fetcher */
   35     asn_DEF_INTEGER_tags,
   36     sizeof(asn_DEF_INTEGER_tags) / sizeof(asn_DEF_INTEGER_tags[0]),
   37     asn_DEF_INTEGER_tags,   /* Same as above */
   38     sizeof(asn_DEF_INTEGER_tags) / sizeof(asn_DEF_INTEGER_tags[0]),
   39     0,  /* No PER visible constraints */
   40     0, 0,   /* No members */
   41     0   /* No specifics */
   42 };
   43 
   44 /*
   45  * Encode INTEGER type using DER.
   46  */
   47 asn_enc_rval_t
   48 INTEGER_encode_der(asn_TYPE_descriptor_t *td, void *sptr,
   49     int tag_mode, ber_tlv_tag_t tag,
   50     asn_app_consume_bytes_f *cb, void *app_key) {
   51     INTEGER_t *st = (INTEGER_t *)sptr;
   52 
   53     ASN_DEBUG("%s %s as INTEGER (tm=%d)",
   54         cb?"Encoding":"Estimating", td->name, tag_mode);
   55 
   56     /*
   57      * Canonicalize integer in the buffer.
   58      * (Remove too long sign extension, remove some first 0x00 bytes)
   59      */
   60     if(st->buf) {
   61         uint8_t *buf = st->buf;
   62         uint8_t *end1 = buf + st->size - 1;
   63         int shift;
   64 
   65         /* Compute the number of superfluous leading bytes */
   66         for(; buf < end1; buf++) {
   67             /*
   68              * If the contents octets of an integer value encoding
   69              * consist of more than one octet, then the bits of the
   70              * first octet and bit 8 of the second octet:
   71              * a) shall not all be ones; and
   72              * b) shall not all be zero.
   73              */
   74             switch(*buf) {
   75             case 0x00: if((buf[1] & 0x80) == 0)
   76                     continue;
   77                 break;
   78             case 0xff: if((buf[1] & 0x80))
   79                     continue;
   80                 break;
   81             }
   82             break;
   83         }
   84 
   85         /* Remove leading superfluous bytes from the integer */
   86         shift = buf - st->buf;
   87         if(shift) {
   88             uint8_t *nb = st->buf;
   89             uint8_t *end;
   90 
   91             st->size -= shift;  /* New size, minus bad bytes */
   92             end = nb + st->size;
   93 
   94             for(; nb < end; nb++, buf++)
   95                 *nb = *buf;
   96         }
   97 
   98     } /* if(1) */
   99 
  100     return der_encode_primitive(td, sptr, tag_mode, tag, cb, app_key);
  101 }
  102 
  103 static const asn_INTEGER_enum_map_t *INTEGER_map_enum2value(asn_INTEGER_specifics_t *specs, const char *lstart, const char *lstop);
  104 
  105 /*
  106  * INTEGER specific human-readable output.
  107  */
  108 static ssize_t
  109 INTEGER__dump(asn_TYPE_descriptor_t *td, const INTEGER_t *st, asn_app_consume_bytes_f *cb, void *app_key, int plainOrXER) {
  110     asn_INTEGER_specifics_t *specs=(asn_INTEGER_specifics_t *)td->specifics;
  111     char scratch[32];   /* Enough for 64-bit integer */
  112     uint8_t *buf = st->buf;
  113     uint8_t *buf_end = st->buf + st->size;
  114     signed long value;
  115     ssize_t wrote = 0;
  116     char *p;
  117     int ret;
  118 
  119     if(specs && specs->field_unsigned)
  120         ret = asn_INTEGER2ulong(st, (unsigned long *)&value);
  121     else
  122         ret = asn_INTEGER2long(st, &value);
  123 
  124     /* Simple case: the integer size is small */
  125     if(ret == 0) {
  126         const asn_INTEGER_enum_map_t *el;
  127         size_t scrsize;
  128         char *scr;
  129 
  130         el = (value >= 0 || !specs || !specs->field_unsigned)
  131             ? INTEGER_map_value2enum(specs, value) : 0;
  132         if(el) {
  133             scrsize = el->enum_len + 32;
  134             scr = (char *)alloca(scrsize);
  135             if(plainOrXER == 0)
  136                 ret = snprintf(scr, scrsize,
  137                     "%ld (%s)", value, el->enum_name);
  138             else
  139                 ret = snprintf(scr, scrsize,
  140                     "<%s/>", el->enum_name);
  141         } else if(plainOrXER && specs && specs->strict_enumeration) {
  142             ASN_DEBUG("ASN.1 forbids dealing with "
  143                 "unknown value of ENUMERATED type");
  144             errno = EPERM;
  145             return -1;
  146         } else {
  147             scrsize = sizeof(scratch);
  148             scr = scratch;
  149             ret = snprintf(scr, scrsize,
  150                 (specs && specs->field_unsigned)
  151                 ?"%lu":"%ld", value);
  152         }
  153         assert(ret > 0 && (size_t)ret < scrsize);
  154         return (cb(scr, ret, app_key) < 0) ? -1 : ret;
  155     } else if(plainOrXER && specs && specs->strict_enumeration) {
  156         /*
  157          * Here and earlier, we cannot encode the ENUMERATED values
  158          * if there is no corresponding identifier.
  159          */
  160         ASN_DEBUG("ASN.1 forbids dealing with "
  161             "unknown value of ENUMERATED type");
  162         errno = EPERM;
  163         return -1;
  164     }
  165 
  166     /* Output in the long xx:yy:zz... format */
  167     /* TODO: replace with generic algorithm (Knuth TAOCP Vol 2, 4.3.1) */
  168     for(p = scratch; buf < buf_end; buf++) {
  169         static const char *h2c = "0123456789ABCDEF";
  170         if((p - scratch) >= (ssize_t)(sizeof(scratch) - 4)) {
  171             /* Flush buffer */
  172             if(cb(scratch, p - scratch, app_key) < 0)
  173                 return -1;
  174             wrote += p - scratch;
  175             p = scratch;
  176         }
  177         *p++ = h2c[*buf >> 4];
  178         *p++ = h2c[*buf & 0x0F];
  179         *p++ = 0x3a;    /* ":" */
  180     }
  181     if(p != scratch)
  182         p--;    /* Remove the last ":" */
  183 
  184     wrote += p - scratch;
  185     return (cb(scratch, p - scratch, app_key) < 0) ? -1 : wrote;
  186 }
  187 
  188 /*
  189  * INTEGER specific human-readable output.
  190  */
  191 int
  192 INTEGER_print(asn_TYPE_descriptor_t *td, const void *sptr, int ilevel,
  193     asn_app_consume_bytes_f *cb, void *app_key) {
  194     const INTEGER_t *st = (const INTEGER_t *)sptr;
  195     ssize_t ret;
  196 
  197     (void)td;
  198     (void)ilevel;
  199 
  200     if(!st || !st->buf)
  201         ret = cb("<absent>", 8, app_key);
  202     else
  203         ret = INTEGER__dump(td, st, cb, app_key, 0);
  204 
  205     return (ret < 0) ? -1 : 0;
  206 }
  207 
  208 struct e2v_key {
  209     const char *start;
  210     const char *stop;
  211     asn_INTEGER_enum_map_t *vemap;
  212     unsigned int *evmap;
  213 };
  214 static int
  215 INTEGER__compar_enum2value(const void *kp, const void *am) {
  216     const struct e2v_key *key = (const struct e2v_key *)kp;
  217     const asn_INTEGER_enum_map_t *el = (const asn_INTEGER_enum_map_t *)am;
  218     const char *ptr, *end, *name;
  219 
  220     /* Remap the element (sort by different criterion) */
  221     el = key->vemap + key->evmap[el - key->vemap];
  222 
  223     /* Compare strings */
  224     for(ptr = key->start, end = key->stop, name = el->enum_name;
  225             ptr < end; ptr++, name++) {
  226         if(*ptr != *name)
  227             return *(const unsigned char *)ptr
  228                 - *(const unsigned char *)name;
  229     }
  230     return name[0] ? -1 : 0;
  231 }
  232 
  233 static const asn_INTEGER_enum_map_t *
  234 INTEGER_map_enum2value(asn_INTEGER_specifics_t *specs, const char *lstart, const char *lstop) {
  235     asn_INTEGER_enum_map_t *el_found;
  236     int count = specs ? specs->map_count : 0;
  237     struct e2v_key key;
  238     const char *lp;
  239 
  240     if(!count) return NULL;
  241 
  242     /* Guaranteed: assert(lstart < lstop); */
  243     /* Figure out the tag name */
  244     for(lstart++, lp = lstart; lp < lstop; lp++) {
  245         switch(*lp) {
  246         case 9: case 10: case 11: case 12: case 13: case 32: /* WSP */
  247         case 0x2f: /* '/' */ case 0x3e: /* '>' */
  248             break;
  249         default:
  250             continue;
  251         }
  252         break;
  253     }
  254     if(lp == lstop) return NULL;    /* No tag found */
  255     lstop = lp;
  256 
  257     key.start = lstart;
  258     key.stop = lstop;
  259     key.vemap = specs->value2enum;
  260     key.evmap = specs->enum2value;
  261     el_found = (asn_INTEGER_enum_map_t *)bsearch(&key,
  262         specs->value2enum, count, sizeof(specs->value2enum[0]),
  263         INTEGER__compar_enum2value);
  264     if(el_found) {
  265         /* Remap enum2value into value2enum */
  266         el_found = key.vemap + key.evmap[el_found - key.vemap];
  267     }
  268     return el_found;
  269 }
  270 
  271 static int
  272 INTEGER__compar_value2enum(const void *kp, const void *am) {
  273     long a = *(const long *)kp;
  274     const asn_INTEGER_enum_map_t *el = (const asn_INTEGER_enum_map_t *)am;
  275     long b = el->nat_value;
  276     if(a < b) return -1;
  277     else if(a == b) return 0;
  278     else return 1;
  279 }
  280 
  281 const asn_INTEGER_enum_map_t *
  282 INTEGER_map_value2enum(asn_INTEGER_specifics_t *specs, long value) {
  283     int count = specs ? specs->map_count : 0;
  284     if(!count) return 0;
  285     return (asn_INTEGER_enum_map_t *)bsearch(&value, specs->value2enum,
  286         count, sizeof(specs->value2enum[0]),
  287         INTEGER__compar_value2enum);
  288 }
  289 
  290 static int
  291 INTEGER_st_prealloc(INTEGER_t *st, int min_size) {
  292     void *p = MALLOC(min_size + 1);
  293     if(p) {
  294         void *b = st->buf;
  295         st->size = 0;
  296         st->buf = p;
  297         FREEMEM(b);
  298         return 0;
  299     } else {
  300         return -1;
  301     }
  302 }
  303 
  304 /*
  305  * Decode the chunk of XML text encoding INTEGER.
  306  */
  307 static enum xer_pbd_rval
  308 INTEGER__xer_body_decode(asn_TYPE_descriptor_t *td, void *sptr, const void *chunk_buf, size_t chunk_size) {
  309     INTEGER_t *st = (INTEGER_t *)sptr;
  310     long dec_value;
  311     long hex_value = 0;
  312     const char *lp;
  313     const char *lstart = (const char *)chunk_buf;
  314     const char *lstop = lstart + chunk_size;
  315     enum {
  316         ST_LEADSPACE,
  317         ST_SKIPSPHEX,
  318         ST_WAITDIGITS,
  319         ST_DIGITS,
  320         ST_DIGITS_TRAILSPACE,
  321         ST_HEXDIGIT1,
  322         ST_HEXDIGIT2,
  323         ST_HEXDIGITS_TRAILSPACE,
  324         ST_HEXCOLON,
  325         ST_END_ENUM,
  326         ST_UNEXPECTED
  327     } state = ST_LEADSPACE;
  328     const char *dec_value_start = 0; /* INVARIANT: always !0 in ST_DIGITS */
  329     const char *dec_value_end = 0;
  330 
  331     if(chunk_size)
  332         ASN_DEBUG("INTEGER body %ld 0x%2x..0x%2x",
  333             (long)chunk_size, *lstart, lstop[-1]);
  334 
  335     if(INTEGER_st_prealloc(st, (chunk_size/3) + 1))
  336         return XPBD_SYSTEM_FAILURE;
  337 
  338     /*
  339      * We may have received a tag here. It will be processed inline.
  340      * Use strtoul()-like code and serialize the result.
  341      */
  342     for(lp = lstart; lp < lstop; lp++) {
  343         int lv = *lp;
  344         switch(lv) {
  345         case 0x09: case 0x0a: case 0x0d: case 0x20:
  346             switch(state) {
  347             case ST_LEADSPACE:
  348             case ST_DIGITS_TRAILSPACE:
  349             case ST_HEXDIGITS_TRAILSPACE:
  350             case ST_SKIPSPHEX:
  351                 continue;
  352             case ST_DIGITS:
  353                 dec_value_end = lp;
  354                 state = ST_DIGITS_TRAILSPACE;
  355                 continue;
  356             case ST_HEXCOLON:
  357                 state = ST_HEXDIGITS_TRAILSPACE;
  358                 continue;
  359             default:
  360                 break;
  361             }
  362             break;
  363         case 0x2d:  /* '-' */
  364             if(state == ST_LEADSPACE) {
  365                 dec_value = 0;
  366                 dec_value_start = lp;
  367                 state = ST_WAITDIGITS;
  368                 continue;
  369             }
  370             break;
  371         case 0x2b:  /* '+' */
  372             if(state == ST_LEADSPACE) {
  373                 dec_value = 0;
  374                 dec_value_start = lp;
  375                 state = ST_WAITDIGITS;
  376                 continue;
  377             }
  378             break;
  379         case 0x30: case 0x31: case 0x32: case 0x33: case 0x34:
  380         case 0x35: case 0x36: case 0x37: case 0x38: case 0x39:
  381             switch(state) {
  382             case ST_DIGITS: continue;
  383             case ST_SKIPSPHEX:  /* Fall through */
  384             case ST_HEXDIGIT1:
  385                 hex_value = (lv - 0x30) << 4;
  386                 state = ST_HEXDIGIT2;
  387                 continue;
  388             case ST_HEXDIGIT2:
  389                 hex_value += (lv - 0x30);
  390                 state = ST_HEXCOLON;
  391                 st->buf[st->size++] = (uint8_t)hex_value;
  392                 continue;
  393             case ST_HEXCOLON:
  394                 return XPBD_BROKEN_ENCODING;
  395             case ST_LEADSPACE:
  396                 dec_value = 0;
  397                 dec_value_start = lp;
  398                 /* FALL THROUGH */
  399             case ST_WAITDIGITS:
  400                 state = ST_DIGITS;
  401                 continue;
  402             default:
  403                 break;
  404             }
  405             break;
  406         case 0x3c:  /* '<', start of XML encoded enumeration */
  407             if(state == ST_LEADSPACE) {
  408                 const asn_INTEGER_enum_map_t *el;
  409                 el = INTEGER_map_enum2value(
  410                     (asn_INTEGER_specifics_t *)
  411                     td->specifics, lstart, lstop);
  412                 if(el) {
  413                     ASN_DEBUG("Found \"%s\" => %ld",
  414                         el->enum_name, el->nat_value);
  415                     dec_value = el->nat_value;
  416                     state = ST_END_ENUM;
  417                     lp = lstop - 1;
  418                     continue;
  419                 }
  420                 ASN_DEBUG("Unknown identifier for INTEGER");
  421             }
  422             return XPBD_BROKEN_ENCODING;
  423         case 0x3a:  /* ':' */
  424             if(state == ST_HEXCOLON) {
  425                 /* This colon is expected */
  426                 state = ST_HEXDIGIT1;
  427                 continue;
  428             } else if(state == ST_DIGITS) {
  429                 /* The colon here means that we have
  430                  * decoded the first two hexadecimal
  431                  * places as a decimal value.
  432                  * Switch decoding mode. */
  433                 ASN_DEBUG("INTEGER re-evaluate as hex form");
  434                 state = ST_SKIPSPHEX;
  435                 dec_value_start = 0;
  436                 lp = lstart - 1;
  437                 continue;
  438             } else {
  439                 ASN_DEBUG("state %d at %ld", state, (long)(lp - lstart));
  440                 break;
  441             }
  442         /* [A-Fa-f] */
  443         case 0x41:case 0x42:case 0x43:case 0x44:case 0x45:case 0x46:
  444         case 0x61:case 0x62:case 0x63:case 0x64:case 0x65:case 0x66:
  445             switch(state) {
  446             case ST_SKIPSPHEX:
  447             case ST_LEADSPACE: /* Fall through */
  448             case ST_HEXDIGIT1:
  449                 hex_value = lv - ((lv < 0x61) ? 0x41 : 0x61);
  450                 hex_value += 10;
  451                 hex_value <<= 4;
  452                 state = ST_HEXDIGIT2;
  453                 continue;
  454             case ST_HEXDIGIT2:
  455                 hex_value += lv - ((lv < 0x61) ? 0x41 : 0x61);
  456                 hex_value += 10;
  457                 st->buf[st->size++] = (uint8_t)hex_value;
  458                 state = ST_HEXCOLON;
  459                 continue;
  460             case ST_DIGITS:
  461                 ASN_DEBUG("INTEGER re-evaluate as hex form");
  462                 state = ST_SKIPSPHEX;
  463                 dec_value_start = 0;
  464                 lp = lstart - 1;
  465                 continue;
  466             default:
  467                 break;
  468             }
  469             break;
  470         }
  471 
  472         /* Found extra non-numeric stuff */
  473         ASN_DEBUG("INTEGER :: Found non-numeric 0x%2x at %ld",
  474             lv, (long)(lp - lstart));
  475         state = ST_UNEXPECTED;
  476         break;
  477     }
  478 
  479     switch(state) {
  480     case ST_END_ENUM:
  481         /* Got a complete and valid enumeration encoded as a tag. */
  482         break;
  483     case ST_DIGITS:
  484         dec_value_end = lstop;
  485         /* FALL THROUGH */
  486     case ST_DIGITS_TRAILSPACE:
  487         /* The last symbol encountered was a digit. */
  488         switch(asn_strtol_lim(dec_value_start, &dec_value_end, &dec_value)) {
  489         case ASN_STRTOL_OK:
  490             break;
  491         case ASN_STRTOL_ERROR_RANGE:
  492             return XPBD_DECODER_LIMIT;
  493         case ASN_STRTOL_ERROR_INVAL:
  494         case ASN_STRTOL_EXPECT_MORE:
  495         case ASN_STRTOL_EXTRA_DATA:
  496             return XPBD_BROKEN_ENCODING;
  497         }
  498         break;
  499     case ST_HEXCOLON:
  500     case ST_HEXDIGITS_TRAILSPACE:
  501         st->buf[st->size] = 0;  /* Just in case termination */
  502         return XPBD_BODY_CONSUMED;
  503     case ST_HEXDIGIT1:
  504     case ST_HEXDIGIT2:
  505     case ST_SKIPSPHEX:
  506         return XPBD_BROKEN_ENCODING;
  507     case ST_LEADSPACE:
  508         /* Content not found */
  509         return XPBD_NOT_BODY_IGNORE;
  510     case ST_WAITDIGITS:
  511     case ST_UNEXPECTED:
  512         ASN_DEBUG("INTEGER: No useful digits (state %d)", state);
  513         return XPBD_BROKEN_ENCODING;    /* No digits */
  514     }
  515 
  516     /*
  517      * Convert the result of parsing of enumeration or a straight
  518      * decimal value into a BER representation.
  519      */
  520     if(asn_long2INTEGER(st, dec_value))
  521         return XPBD_SYSTEM_FAILURE;
  522 
  523     return XPBD_BODY_CONSUMED;
  524 }
  525 
  526 asn_dec_rval_t
  527 INTEGER_decode_xer(asn_codec_ctx_t *opt_codec_ctx,
  528     asn_TYPE_descriptor_t *td, void **sptr, const char *opt_mname,
  529         const void *buf_ptr, size_t size) {
  530 
  531     return xer_decode_primitive(opt_codec_ctx, td,
  532         sptr, sizeof(INTEGER_t), opt_mname,
  533         buf_ptr, size, INTEGER__xer_body_decode);
  534 }
  535 
  536 asn_enc_rval_t
  537 INTEGER_encode_xer(asn_TYPE_descriptor_t *td, void *sptr,
  538     int ilevel, enum xer_encoder_flags_e flags,
  539         asn_app_consume_bytes_f *cb, void *app_key) {
  540     const INTEGER_t *st = (const INTEGER_t *)sptr;
  541     asn_enc_rval_t er;
  542 
  543     (void)ilevel;
  544     (void)flags;
  545     
  546     if(!st || !st->buf)
  547         _ASN_ENCODE_FAILED;
  548 
  549     er.encoded = INTEGER__dump(td, st, cb, app_key, 1);
  550     if(er.encoded < 0) _ASN_ENCODE_FAILED;
  551 
  552     _ASN_ENCODED_OK(er);
  553 }
  554 
  555 #ifndef ASN_DISABLE_PER_SUPPORT
  556 
  557 asn_dec_rval_t
  558 INTEGER_decode_uper(asn_codec_ctx_t *opt_codec_ctx, asn_TYPE_descriptor_t *td,
  559     asn_per_constraints_t *constraints, void **sptr, asn_per_data_t *pd) {
  560     asn_INTEGER_specifics_t *specs=(asn_INTEGER_specifics_t *)td->specifics;
  561     asn_dec_rval_t rval = { RC_OK, 0 };
  562     INTEGER_t *st = (INTEGER_t *)*sptr;
  563     asn_per_constraint_t *ct;
  564     int repeat;
  565 
  566     (void)opt_codec_ctx;
  567 
  568     if(!st) {
  569         st = (INTEGER_t *)(*sptr = CALLOC(1, sizeof(*st)));
  570         if(!st) _ASN_DECODE_FAILED;
  571     }
  572 
  573     if(!constraints) constraints = td->per_constraints;
  574     ct = constraints ? &constraints->value : 0;
  575 
  576     if(ct && ct->flags & APC_EXTENSIBLE) {
  577         int inext = per_get_few_bits(pd, 1);
  578         if(inext < 0) _ASN_DECODE_STARVED;
  579         if(inext) ct = 0;
  580     }
  581 
  582     FREEMEM(st->buf);
  583     st->buf = 0;
  584     st->size = 0;
  585     if(ct) {
  586         if(ct->flags & APC_SEMI_CONSTRAINED) {
  587             st->buf = (uint8_t *)CALLOC(1, 2);
  588             if(!st->buf) _ASN_DECODE_FAILED;
  589             st->size = 1;
  590         } else if(ct->flags & APC_CONSTRAINED && ct->range_bits >= 0) {
  591             size_t size = (ct->range_bits + 7) >> 3;
  592             st->buf = (uint8_t *)MALLOC(1 + size + 1);
  593             if(!st->buf) _ASN_DECODE_FAILED;
  594             st->size = size;
  595         }
  596     }
  597 
  598     /* X.691-2008/11, #13.2.2, constrained whole number */
  599     if(ct && ct->flags != APC_UNCONSTRAINED) {
  600         /* #11.5.6 */
  601         ASN_DEBUG("Integer with range %d bits", ct->range_bits);
  602         if(ct->range_bits >= 0) {
  603             if((size_t)ct->range_bits > 8 * sizeof(unsigned long))
  604                 _ASN_DECODE_FAILED;
  605 
  606             if(specs && specs->field_unsigned) {
  607                 unsigned long uvalue;
  608                 if(uper_get_constrained_whole_number(pd,
  609                     &uvalue, ct->range_bits))
  610                     _ASN_DECODE_STARVED;
  611                 ASN_DEBUG("Got value %lu + low %ld",
  612                     uvalue, ct->lower_bound);
  613                 uvalue += ct->lower_bound;
  614                 if(asn_ulong2INTEGER(st, uvalue))
  615                     _ASN_DECODE_FAILED;
  616             } else {
  617                 unsigned long svalue;
  618                 if(uper_get_constrained_whole_number(pd,
  619                     &svalue, ct->range_bits))
  620                     _ASN_DECODE_STARVED;
  621                 ASN_DEBUG("Got value %ld + low %ld",
  622                     svalue, ct->lower_bound);
  623                 svalue += ct->lower_bound;
  624                 if(asn_long2INTEGER(st, svalue))
  625                     _ASN_DECODE_FAILED;
  626             }
  627             return rval;
  628         }
  629     } else {
  630         ASN_DEBUG("Decoding unconstrained integer %s", td->name);
  631     }
  632 
  633     /* X.691, #12.2.3, #12.2.4 */
  634     do {
  635         ssize_t len;
  636         void *p;
  637         int ret;
  638 
  639         /* Get the PER length */
  640         len = uper_get_length(pd, -1, &repeat);
  641         if(len < 0) _ASN_DECODE_STARVED;
  642 
  643         p = REALLOC(st->buf, st->size + len + 1);
  644         if(!p) _ASN_DECODE_FAILED;
  645         st->buf = (uint8_t *)p;
  646 
  647         ret = per_get_many_bits(pd, &st->buf[st->size], 0, 8 * len);
  648         if(ret < 0) _ASN_DECODE_STARVED;
  649         st->size += len;
  650     } while(repeat);
  651     st->buf[st->size] = 0;  /* JIC */
  652 
  653     /* #12.2.3 */
  654     if(ct && ct->lower_bound) {
  655         /*
  656          * TODO: replace by in-place arithmetics.
  657          */
  658         long value;
  659         if(asn_INTEGER2long(st, &value))
  660             _ASN_DECODE_FAILED;
  661         if(asn_long2INTEGER(st, value + ct->lower_bound))
  662             _ASN_DECODE_FAILED;
  663     }
  664 
  665     return rval;
  666 }
  667 
  668 asn_enc_rval_t
  669 INTEGER_encode_uper(asn_TYPE_descriptor_t *td,
  670     asn_per_constraints_t *constraints, void *sptr, asn_per_outp_t *po) {
  671     asn_INTEGER_specifics_t *specs=(asn_INTEGER_specifics_t *)td->specifics;
  672     asn_enc_rval_t er;
  673     INTEGER_t *st = (INTEGER_t *)sptr;
  674     const uint8_t *buf;
  675     const uint8_t *end;
  676     asn_per_constraint_t *ct;
  677     long value = 0;
  678 
  679     if(!st || st->size == 0) _ASN_ENCODE_FAILED;
  680 
  681     if(!constraints) constraints = td->per_constraints;
  682     ct = constraints ? &constraints->value : 0;
  683 
  684     er.encoded = 0;
  685 
  686     if(ct) {
  687         int inext = 0;
  688         if(specs && specs->field_unsigned) {
  689             unsigned long uval;
  690             if(asn_INTEGER2ulong(st, &uval))
  691                 _ASN_ENCODE_FAILED;
  692             /* Check proper range */
  693             if(ct->flags & APC_SEMI_CONSTRAINED) {
  694                 if(uval < (unsigned long)ct->lower_bound)
  695                     inext = 1;
  696             } else if(ct->range_bits >= 0) {
  697                 if(uval < (unsigned long)ct->lower_bound
  698                 || uval > (unsigned long)ct->upper_bound)
  699                     inext = 1;
  700             }
  701             ASN_DEBUG("Value %lu (%02x/%d) lb %lu ub %lu %s",
  702                 uval, st->buf[0], st->size,
  703                 ct->lower_bound, ct->upper_bound,
  704                 inext ? "ext" : "fix");
  705             value = uval;
  706         } else {
  707             if(asn_INTEGER2long(st, &value))
  708                 _ASN_ENCODE_FAILED;
  709             /* Check proper range */
  710             if(ct->flags & APC_SEMI_CONSTRAINED) {
  711                 if(value < ct->lower_bound)
  712                     inext = 1;
  713             } else if(ct->range_bits >= 0) {
  714                 if(value < ct->lower_bound
  715                 || value > ct->upper_bound)
  716                     inext = 1;
  717             }
  718             ASN_DEBUG("Value %ld (%02x/%d) lb %ld ub %ld %s",
  719                 value, st->buf[0], st->size,
  720                 ct->lower_bound, ct->upper_bound,
  721                 inext ? "ext" : "fix");
  722         }
  723         if(ct->flags & APC_EXTENSIBLE) {
  724             if(per_put_few_bits(po, inext, 1))
  725                 _ASN_ENCODE_FAILED;
  726             if(inext) ct = 0;
  727         } else if(inext) {
  728             _ASN_ENCODE_FAILED;
  729         }
  730     }
  731 
  732 
  733     /* X.691-11/2008, #13.2.2, test if constrained whole number */
  734     if(ct && ct->range_bits >= 0) {
  735         /* #11.5.6 -> #11.3 */
  736         ASN_DEBUG("Encoding integer %ld (%lu) with range %d bits",
  737             value, value - ct->lower_bound, ct->range_bits);
  738         unsigned long v = value - ct->lower_bound;
  739         if(uper_put_constrained_whole_number_u(po, v, ct->range_bits))
  740             _ASN_ENCODE_FAILED;
  741         _ASN_ENCODED_OK(er);
  742     }
  743 
  744     if(ct && ct->lower_bound) {
  745         ASN_DEBUG("Adjust lower bound to %ld", ct->lower_bound);
  746         /* TODO: adjust lower bound */
  747         _ASN_ENCODE_FAILED;
  748     }
  749 
  750     for(buf = st->buf, end = st->buf + st->size; buf < end;) {
  751         ssize_t mayEncode = uper_put_length(po, end - buf);
  752         if(mayEncode < 0)
  753             _ASN_ENCODE_FAILED;
  754         if(per_put_many_bits(po, buf, 8 * mayEncode))
  755             _ASN_ENCODE_FAILED;
  756         buf += mayEncode;
  757     }
  758 
  759     _ASN_ENCODED_OK(er);
  760 }
  761 
  762 #endif  /* ASN_DISABLE_PER_SUPPORT */
  763 
  764 int
  765 asn_INTEGER2long(const INTEGER_t *iptr, long *lptr) {
  766     uint8_t *b, *end;
  767     size_t size;
  768     long l;
  769 
  770     /* Sanity checking */
  771     if(!iptr || !iptr->buf || !lptr) {
  772         errno = EINVAL;
  773         return -1;
  774     }
  775 
  776     /* Cache the begin/end of the buffer */
  777     b = iptr->buf;  /* Start of the INTEGER buffer */
  778     size = iptr->size;
  779     end = b + size; /* Where to stop */
  780 
  781     if(size > sizeof(long)) {
  782         uint8_t *end1 = end - 1;
  783         /*
  784          * Slightly more advanced processing,
  785          * able to >sizeof(long) bytes,
  786          * when the actual value is small
  787          * (0x0000000000abcdef would yield a fine 0x00abcdef)
  788          */
  789         /* Skip out the insignificant leading bytes */
  790         for(; b < end1; b++) {
  791             switch(*b) {
  792             case 0x00: if((b[1] & 0x80) == 0) continue; break;
  793             case 0xff: if((b[1] & 0x80) != 0) continue; break;
  794             }
  795             break;
  796         }
  797 
  798         size = end - b;
  799         if(size > sizeof(long)) {
  800             /* Still cannot fit the long */
  801             errno = ERANGE;
  802             return -1;
  803         }
  804     }
  805 
  806     /* Shortcut processing of a corner case */
  807     if(end == b) {
  808         *lptr = 0;
  809         return 0;
  810     }
  811 
  812     /* Perform the sign initialization */
  813     /* Actually l = -(*b >> 7); gains nothing, yet unreadable! */
  814     if((*b >> 7)) l = -1; else l = 0;
  815 
  816     /* Conversion engine */
  817     for(; b < end; b++)
  818         l = (l << 8) | *b;
  819 
  820     *lptr = l;
  821     return 0;
  822 }
  823 
  824 int
  825 asn_INTEGER2ulong(const INTEGER_t *iptr, unsigned long *lptr) {
  826     uint8_t *b, *end;
  827     unsigned long l;
  828     size_t size;
  829 
  830     if(!iptr || !iptr->buf || !lptr) {
  831         errno = EINVAL;
  832         return -1;
  833     }
  834 
  835     b = iptr->buf;
  836     size = iptr->size;
  837     end = b + size;
  838 
  839     /* If all extra leading bytes are zeroes, ignore them */
  840     for(; size > sizeof(unsigned long); b++, size--) {
  841         if(*b) {
  842             /* Value won't fit unsigned long */
  843             errno = ERANGE;
  844             return -1;
  845         }
  846     }
  847 
  848     /* Conversion engine */
  849     for(l = 0; b < end; b++)
  850         l = (l << 8) | *b;
  851 
  852     *lptr = l;
  853     return 0;
  854 }
  855 
  856 int
  857 asn_ulong2INTEGER(INTEGER_t *st, unsigned long value) {
  858     uint8_t *buf;
  859     uint8_t *end;
  860     uint8_t *b;
  861     int shr;
  862 
  863     if(value <= LONG_MAX)
  864         return asn_long2INTEGER(st, value);
  865 
  866     buf = (uint8_t *)MALLOC(1 + sizeof(value));
  867     if(!buf) return -1;
  868 
  869     end = buf + (sizeof(value) + 1);
  870     buf[0] = 0;
  871     for(b = buf + 1, shr = (sizeof(long)-1)*8; b < end; shr -= 8, b++)
  872         *b = (uint8_t)(value >> shr);
  873 
  874     if(st->buf) FREEMEM(st->buf);
  875     st->buf = buf;
  876     st->size = 1 + sizeof(value);
  877 
  878     return 0;
  879 }
  880 
  881 int
  882 asn_long2INTEGER(INTEGER_t *st, long value) {
  883     uint8_t *buf, *bp;
  884     uint8_t *p;
  885     uint8_t *pstart;
  886     uint8_t *pend1;
  887     int littleEndian = 1;   /* Run-time detection */
  888     int add;
  889 
  890     if(!st) {
  891         errno = EINVAL;
  892         return -1;
  893     }
  894 
  895     buf = (uint8_t *)MALLOC(sizeof(value));
  896     if(!buf) return -1;
  897 
  898     if(*(char *)&littleEndian) {
  899         pstart = (uint8_t *)&value + sizeof(value) - 1;
  900         pend1 = (uint8_t *)&value;
  901         add = -1;
  902     } else {
  903         pstart = (uint8_t *)&value;
  904         pend1 = pstart + sizeof(value) - 1;
  905         add = 1;
  906     }
  907 
  908     /*
  909      * If the contents octet consists of more than one octet,
  910      * then bits of the first octet and bit 8 of the second octet:
  911      * a) shall not all be ones; and
  912      * b) shall not all be zero.
  913      */
  914     for(p = pstart; p != pend1; p += add) {
  915         switch(*p) {
  916         case 0x00: if((*(p+add) & 0x80) == 0)
  917                 continue;
  918             break;
  919         case 0xff: if((*(p+add) & 0x80))
  920                 continue;
  921             break;
  922         }
  923         break;
  924     }
  925     /* Copy the integer body */
  926     for(pstart = p, bp = buf, pend1 += add; p != pend1; p += add)
  927         *bp++ = *p;
  928 
  929     if(st->buf) FREEMEM(st->buf);
  930     st->buf = buf;
  931     st->size = bp - buf;
  932 
  933     return 0;
  934 }
  935 
  936 /*
  937  * This function is going to be DEPRECATED soon.
  938  */
  939 enum asn_strtol_result_e
  940 asn_strtol(const char *str, const char *end, long *lp) {
  941     const char *endp = end;
  942 
  943     switch(asn_strtol_lim(str, &endp, lp)) {
  944     case ASN_STRTOL_ERROR_RANGE:
  945         return ASN_STRTOL_ERROR_RANGE;
  946     case ASN_STRTOL_ERROR_INVAL:
  947         return ASN_STRTOL_ERROR_INVAL;
  948     case ASN_STRTOL_EXPECT_MORE:
  949         return ASN_STRTOL_ERROR_INVAL;  /* Retain old behavior */
  950     case ASN_STRTOL_OK:
  951         return ASN_STRTOL_OK;
  952     case ASN_STRTOL_EXTRA_DATA:
  953         return ASN_STRTOL_ERROR_INVAL;  /* Retain old behavior */
  954     }
  955 
  956     return ASN_STRTOL_ERROR_INVAL;  /* Retain old behavior */
  957 }
  958 
  959 /*
  960  * Parse the number in the given string until the given *end position,
  961  * returning the position after the last parsed character back using the
  962  * same (*end) pointer.
  963  * WARNING: This behavior is different from the standard strtol(3).
  964  */
  965 enum asn_strtol_result_e
  966 asn_strtol_lim(const char *str, const char **end, long *lp) {
  967     int sign = 1;
  968     long l;
  969 
  970     const long upper_boundary = LONG_MAX / 10;
  971     long last_digit_max = LONG_MAX % 10;
  972 
  973     if(str >= *end) return ASN_STRTOL_ERROR_INVAL;
  974 
  975     switch(*str) {
  976     case '-':
  977         last_digit_max++;
  978         sign = -1;
  979     case '+':
  980         str++;
  981         if(str >= *end) {
  982             *end = str;
  983             return ASN_STRTOL_EXPECT_MORE;
  984         }
  985     }
  986 
  987     for(l = 0; str < (*end); str++) {
  988         switch(*str) {
  989         case 0x30: case 0x31: case 0x32: case 0x33: case 0x34:
  990         case 0x35: case 0x36: case 0x37: case 0x38: case 0x39: {
  991             int d = *str - '0';
  992             if(l < upper_boundary) {
  993                 l = l * 10 + d;
  994             } else if(l == upper_boundary) {
  995                 if(d <= last_digit_max) {
  996                     if(sign > 0) {
  997                         l = l * 10 + d;
  998                     } else {
  999                         sign = 1;
 1000                         l = -l * 10 - d;
 1001                     }
 1002                 } else {
 1003                     *end = str;
 1004                     return ASN_STRTOL_ERROR_RANGE;
 1005                 }
 1006             } else {
 1007                 *end = str;
 1008                 return ASN_STRTOL_ERROR_RANGE;
 1009             }
 1010             }
 1011             continue;
 1012         default:
 1013             *end = str;
 1014             *lp = sign * l;
 1015             return ASN_STRTOL_EXTRA_DATA;
 1016         }
 1017     }
 1018 
 1019     *end = str;
 1020     *lp = sign * l;
 1021     return ASN_STRTOL_OK;
 1022 }
 1023