int ASN1_get_object(const unsigned char **pp, long *plength, int *ptag,
                    int *pclass, long omax)
{
    int i, ret;
    long l;
    const unsigned char *p = *pp;
    int tag, xclass, inf;
    long max = omax;
    if (!max)
        goto err;
    ret = (*p & V_ASN1_CONSTRUCTED);
    xclass = (*p & V_ASN1_PRIVATE);
    i = *p & V_ASN1_PRIMITIVE_TAG;
    if (i == V_ASN1_PRIMITIVE_TAG) {
        p++;
        if (--max == 0)
            goto err;
        l = 0;
        while (*p & 0x80) {
            l <<= 7L;
            l |= *(p++) & 0x7f;
            if (--max == 0)
                goto err;
            if (l > (INT_MAX >> 7L))
                goto err;
        }
        l <<= 7L;
        l |= *(p++) & 0x7f;
        tag = (int)l;
        if (--max == 0)
            goto err;
    } else {
        tag = i;
        p++;
        if (--max == 0)
            goto err;
    }
    *ptag = tag;
    *pclass = xclass;
    if (!asn1_get_length(&p, &inf, plength, max))
        goto err;
    if (inf && !(ret & V_ASN1_CONSTRUCTED))
        goto err;
    if (*plength > (omax - (p - *pp))) {
        ASN1err(ASN1_F_ASN1_GET_OBJECT, ASN1_R_TOO_LONG);
        ret |= 0x80;
    }
    *pp = p;
    return ret | inf;
 err:
    ASN1err(ASN1_F_ASN1_GET_OBJECT, ASN1_R_HEADER_TOO_LONG);
    return 0x80;
}
['int asn1parse_main(int argc, char **argv)\n{\n    ASN1_TYPE *at = NULL;\n    BIO *in = NULL, *b64 = NULL, *derout = NULL;\n    BUF_MEM *buf = NULL;\n    STACK_OF(OPENSSL_STRING) *osk = NULL;\n    char *genstr = NULL, *genconf = NULL;\n    char *infile = NULL, *oidfile = NULL, *derfile = NULL;\n    unsigned char *str = NULL;\n    char *name = NULL, *header = NULL, *prog;\n    const unsigned char *ctmpbuf;\n    int indent = 0, noout = 0, dump = 0, strictpem = 0, informat = FORMAT_PEM;\n    int offset = 0, ret = 1, i, j;\n    long num, tmplen;\n    unsigned char *tmpbuf;\n    unsigned int length = 0;\n    OPTION_CHOICE o;\n    const ASN1_ITEM *it = NULL;\n    prog = opt_init(argc, argv, asn1parse_options);\n    if ((osk = sk_OPENSSL_STRING_new_null()) == NULL) {\n        BIO_printf(bio_err, "%s: Memory allocation failure\\n", prog);\n        goto end;\n    }\n    while ((o = opt_next()) != OPT_EOF) {\n        switch (o) {\n        case OPT_EOF:\n        case OPT_ERR:\n opthelp:\n            BIO_printf(bio_err, "%s: Use -help for summary.\\n", prog);\n            goto end;\n        case OPT_HELP:\n            opt_help(asn1parse_options);\n            ret = 0;\n            goto end;\n        case OPT_INFORM:\n            if (!opt_format(opt_arg(), OPT_FMT_PEMDER, &informat))\n                goto opthelp;\n            break;\n        case OPT_IN:\n            infile = opt_arg();\n            break;\n        case OPT_OUT:\n            derfile = opt_arg();\n            break;\n        case OPT_INDENT:\n            indent = 1;\n            break;\n        case OPT_NOOUT:\n            noout = 1;\n            break;\n        case OPT_OID:\n            oidfile = opt_arg();\n            break;\n        case OPT_OFFSET:\n            offset = strtol(opt_arg(), NULL, 0);\n            break;\n        case OPT_LENGTH:\n            length = strtol(opt_arg(), NULL, 0);\n            break;\n        case OPT_DUMP:\n            dump = -1;\n            break;\n        case OPT_DLIMIT:\n            dump = strtol(opt_arg(), NULL, 0);\n            break;\n        case OPT_STRPARSE:\n            sk_OPENSSL_STRING_push(osk, opt_arg());\n            break;\n        case OPT_GENSTR:\n            genstr = opt_arg();\n            break;\n        case OPT_GENCONF:\n            genconf = opt_arg();\n            break;\n        case OPT_STRICTPEM:\n            strictpem = 1;\n            informat = FORMAT_PEM;\n            break;\n        case OPT_ITEM:\n            it = ASN1_ITEM_lookup(opt_arg());\n            if (it == NULL) {\n                size_t tmp;\n                BIO_printf(bio_err, "Unknown item name %s\\n", opt_arg());\n                BIO_puts(bio_err, "Supported types:\\n");\n                for (tmp = 0;; tmp++) {\n                    it = ASN1_ITEM_get(tmp);\n                    if (it == NULL)\n                        break;\n                    BIO_printf(bio_err, "    %s\\n", it->sname);\n                }\n                goto end;\n            }\n            break;\n        }\n    }\n    argc = opt_num_rest();\n    if (argc != 0)\n        goto opthelp;\n    if (oidfile != NULL) {\n        in = bio_open_default(oidfile, \'r\', FORMAT_TEXT);\n        if (in == NULL)\n            goto end;\n        OBJ_create_objects(in);\n        BIO_free(in);\n    }\n    if ((in = bio_open_default(infile, \'r\', informat)) == NULL)\n        goto end;\n    if (derfile && (derout = bio_open_default(derfile, \'w\', FORMAT_ASN1)) == NULL)\n        goto end;\n    if ((buf = BUF_MEM_new()) == NULL)\n        goto end;\n    if (strictpem) {\n        if (PEM_read_bio(in, &name, &header, &str, &num) != 1) {\n            BIO_printf(bio_err, "Error reading PEM file\\n");\n            ERR_print_errors(bio_err);\n            goto end;\n        }\n        buf->data = (char *)str;\n        buf->length = buf->max = num;\n    } else {\n        if (!BUF_MEM_grow(buf, BUFSIZ * 8))\n            goto end;\n        if (genstr || genconf) {\n            num = do_generate(genstr, genconf, buf);\n            if (num < 0) {\n                ERR_print_errors(bio_err);\n                goto end;\n            }\n        } else {\n            if (informat == FORMAT_PEM) {\n                BIO *tmp;\n                if ((b64 = BIO_new(BIO_f_base64())) == NULL)\n                    goto end;\n                BIO_push(b64, in);\n                tmp = in;\n                in = b64;\n                b64 = tmp;\n            }\n            num = 0;\n            for (;;) {\n                if (!BUF_MEM_grow(buf, num + BUFSIZ))\n                    goto end;\n                i = BIO_read(in, &(buf->data[num]), BUFSIZ);\n                if (i <= 0)\n                    break;\n                num += i;\n            }\n        }\n        str = (unsigned char *)buf->data;\n    }\n    if (sk_OPENSSL_STRING_num(osk)) {\n        tmpbuf = str;\n        tmplen = num;\n        for (i = 0; i < sk_OPENSSL_STRING_num(osk); i++) {\n            ASN1_TYPE *atmp;\n            int typ;\n            j = strtol(sk_OPENSSL_STRING_value(osk, i), NULL, 0);\n            if (j <= 0 || j >= tmplen) {\n                BIO_printf(bio_err, "\'%s\' is out of range\\n",\n                           sk_OPENSSL_STRING_value(osk, i));\n                continue;\n            }\n            tmpbuf += j;\n            tmplen -= j;\n            atmp = at;\n            ctmpbuf = tmpbuf;\n            at = d2i_ASN1_TYPE(NULL, &ctmpbuf, tmplen);\n            ASN1_TYPE_free(atmp);\n            if (!at) {\n                BIO_printf(bio_err, "Error parsing structure\\n");\n                ERR_print_errors(bio_err);\n                goto end;\n            }\n            typ = ASN1_TYPE_get(at);\n            if ((typ == V_ASN1_OBJECT)\n                || (typ == V_ASN1_BOOLEAN)\n                || (typ == V_ASN1_NULL)) {\n                BIO_printf(bio_err, "Can\'t parse %s type\\n", ASN1_tag2str(typ));\n                ERR_print_errors(bio_err);\n                goto end;\n            }\n            tmpbuf = at->value.asn1_string->data;\n            tmplen = at->value.asn1_string->length;\n        }\n        str = tmpbuf;\n        num = tmplen;\n    }\n    if (offset < 0 || offset >= num) {\n        BIO_printf(bio_err, "Error: offset out of range\\n");\n        goto end;\n    }\n    num -= offset;\n    if (length == 0 || length > (unsigned int)num)\n        length = (unsigned int)num;\n    if (derout != NULL) {\n        if (BIO_write(derout, str + offset, length) != (int)length) {\n            BIO_printf(bio_err, "Error writing output\\n");\n            ERR_print_errors(bio_err);\n            goto end;\n        }\n    }\n    if (!noout) {\n        const unsigned char *p = str + offset;\n        if (it != NULL) {\n            ASN1_VALUE *value = ASN1_item_d2i(NULL, &p, length, it);\n            if (value == NULL) {\n                BIO_printf(bio_err, "Error parsing item %s\\n", it->sname);\n                ERR_print_errors(bio_err);\n                goto end;\n            }\n            ASN1_item_print(bio_out, value, 0, it, NULL);\n            ASN1_item_free(value, it);\n        } else {\n            if (!ASN1_parse_dump(bio_out, p, length, indent, dump)) {\n                ERR_print_errors(bio_err);\n                goto end;\n            }\n        }\n    }\n    ret = 0;\n end:\n    BIO_free(derout);\n    BIO_free(in);\n    BIO_free(b64);\n    if (ret != 0)\n        ERR_print_errors(bio_err);\n    BUF_MEM_free(buf);\n    OPENSSL_free(name);\n    OPENSSL_free(header);\n    ASN1_TYPE_free(at);\n    sk_OPENSSL_STRING_free(osk);\n    return ret;\n}', 'IMPLEMENT_ASN1_FUNCTIONS_fname(ASN1_TYPE, ASN1_ANY, ASN1_TYPE)', 'ASN1_VALUE *ASN1_item_d2i(ASN1_VALUE **pval,\n                          const unsigned char **in, long len,\n                          const ASN1_ITEM *it)\n{\n    ASN1_TLC c;\n    ASN1_VALUE *ptmpval = NULL;\n    if (!pval)\n        pval = &ptmpval;\n    asn1_tlc_clear_nc(&c);\n    if (ASN1_item_ex_d2i(pval, in, len, it, -1, 0, 0, &c) > 0)\n        return *pval;\n    return NULL;\n}', 'int ASN1_item_ex_d2i(ASN1_VALUE **pval, const unsigned char **in, long len,\n                     const ASN1_ITEM *it,\n                     int tag, int aclass, char opt, ASN1_TLC *ctx)\n{\n    int rv;\n    rv = asn1_item_embed_d2i(pval, in, len, it, tag, aclass, opt, ctx, 0);\n    if (rv <= 0)\n        ASN1_item_ex_free(pval, it);\n    return rv;\n}', 'static int asn1_item_embed_d2i(ASN1_VALUE **pval, const unsigned char **in,\n                               long len, const ASN1_ITEM *it,\n                               int tag, int aclass, char opt, ASN1_TLC *ctx,\n                               int depth)\n{\n    const ASN1_TEMPLATE *tt, *errtt = NULL;\n    const ASN1_EXTERN_FUNCS *ef;\n    const ASN1_AUX *aux = it->funcs;\n    ASN1_aux_cb *asn1_cb;\n    const unsigned char *p = NULL, *q;\n    unsigned char oclass;\n    char seq_eoc, seq_nolen, cst, isopt;\n    long tmplen;\n    int i;\n    int otag;\n    int ret = 0;\n    ASN1_VALUE **pchptr;\n    if (!pval)\n        return 0;\n    if (aux && aux->asn1_cb)\n        asn1_cb = aux->asn1_cb;\n    else\n        asn1_cb = 0;\n    if (++depth > ASN1_MAX_CONSTRUCTED_NEST) {\n        ASN1err(ASN1_F_ASN1_ITEM_EMBED_D2I, ASN1_R_NESTED_TOO_DEEP);\n        goto err;\n    }\n    switch (it->itype) {\n    case ASN1_ITYPE_PRIMITIVE:\n        if (it->templates) {\n            if ((tag != -1) || opt) {\n                ASN1err(ASN1_F_ASN1_ITEM_EMBED_D2I,\n                        ASN1_R_ILLEGAL_OPTIONS_ON_ITEM_TEMPLATE);\n                goto err;\n            }\n            return asn1_template_ex_d2i(pval, in, len,\n                                        it->templates, opt, ctx, depth);\n        }\n        return asn1_d2i_ex_primitive(pval, in, len, it,\n                                     tag, aclass, opt, ctx);\n    case ASN1_ITYPE_MSTRING:\n        p = *in;\n        ret = asn1_check_tlen(NULL, &otag, &oclass, NULL, NULL,\n                              &p, len, -1, 0, 1, ctx);\n        if (!ret) {\n            ASN1err(ASN1_F_ASN1_ITEM_EMBED_D2I, ERR_R_NESTED_ASN1_ERROR);\n            goto err;\n        }\n        if (oclass != V_ASN1_UNIVERSAL) {\n            if (opt)\n                return -1;\n            ASN1err(ASN1_F_ASN1_ITEM_EMBED_D2I, ASN1_R_MSTRING_NOT_UNIVERSAL);\n            goto err;\n        }\n        if (!(ASN1_tag2bit(otag) & it->utype)) {\n            if (opt)\n                return -1;\n            ASN1err(ASN1_F_ASN1_ITEM_EMBED_D2I, ASN1_R_MSTRING_WRONG_TAG);\n            goto err;\n        }\n        return asn1_d2i_ex_primitive(pval, in, len, it, otag, 0, 0, ctx);\n    case ASN1_ITYPE_EXTERN:\n        ef = it->funcs;\n        return ef->asn1_ex_d2i(pval, in, len, it, tag, aclass, opt, ctx);\n    case ASN1_ITYPE_CHOICE:\n        if (asn1_cb && !asn1_cb(ASN1_OP_D2I_PRE, pval, it, NULL))\n            goto auxerr;\n        if (*pval) {\n            i = asn1_get_choice_selector(pval, it);\n            if ((i >= 0) && (i < it->tcount)) {\n                tt = it->templates + i;\n                pchptr = asn1_get_field_ptr(pval, tt);\n                asn1_template_free(pchptr, tt);\n                asn1_set_choice_selector(pval, -1, it);\n            }\n        } else if (!ASN1_item_ex_new(pval, it)) {\n            ASN1err(ASN1_F_ASN1_ITEM_EMBED_D2I, ERR_R_NESTED_ASN1_ERROR);\n            goto err;\n        }\n        p = *in;\n        for (i = 0, tt = it->templates; i < it->tcount; i++, tt++) {\n            pchptr = asn1_get_field_ptr(pval, tt);\n            ret = asn1_template_ex_d2i(pchptr, &p, len, tt, 1, ctx, depth);\n            if (ret == -1)\n                continue;\n            if (ret > 0)\n                break;\n            asn1_template_free(pchptr, tt);\n            errtt = tt;\n            ASN1err(ASN1_F_ASN1_ITEM_EMBED_D2I, ERR_R_NESTED_ASN1_ERROR);\n            goto err;\n        }\n        if (i == it->tcount) {\n            if (opt) {\n                ASN1_item_ex_free(pval, it);\n                return -1;\n            }\n            ASN1err(ASN1_F_ASN1_ITEM_EMBED_D2I, ASN1_R_NO_MATCHING_CHOICE_TYPE);\n            goto err;\n        }\n        asn1_set_choice_selector(pval, i, it);\n        if (asn1_cb && !asn1_cb(ASN1_OP_D2I_POST, pval, it, NULL))\n            goto auxerr;\n        *in = p;\n        return 1;\n    case ASN1_ITYPE_NDEF_SEQUENCE:\n    case ASN1_ITYPE_SEQUENCE:\n        p = *in;\n        tmplen = len;\n        if (tag == -1) {\n            tag = V_ASN1_SEQUENCE;\n            aclass = V_ASN1_UNIVERSAL;\n        }\n        ret = asn1_check_tlen(&len, NULL, NULL, &seq_eoc, &cst,\n                              &p, len, tag, aclass, opt, ctx);\n        if (!ret) {\n            ASN1err(ASN1_F_ASN1_ITEM_EMBED_D2I, ERR_R_NESTED_ASN1_ERROR);\n            goto err;\n        } else if (ret == -1)\n            return -1;\n        if (aux && (aux->flags & ASN1_AFLG_BROKEN)) {\n            len = tmplen - (p - *in);\n            seq_nolen = 1;\n        }\n        else\n            seq_nolen = seq_eoc;\n        if (!cst) {\n            ASN1err(ASN1_F_ASN1_ITEM_EMBED_D2I, ASN1_R_SEQUENCE_NOT_CONSTRUCTED);\n            goto err;\n        }\n        if (!*pval && !ASN1_item_ex_new(pval, it)) {\n            ASN1err(ASN1_F_ASN1_ITEM_EMBED_D2I, ERR_R_NESTED_ASN1_ERROR);\n            goto err;\n        }\n        if (asn1_cb && !asn1_cb(ASN1_OP_D2I_PRE, pval, it, NULL))\n            goto auxerr;\n        for (i = 0, tt = it->templates; i < it->tcount; i++, tt++) {\n            if (tt->flags & ASN1_TFLG_ADB_MASK) {\n                const ASN1_TEMPLATE *seqtt;\n                ASN1_VALUE **pseqval;\n                seqtt = asn1_do_adb(*pval, tt, 0);\n                if (seqtt == NULL)\n                    continue;\n                pseqval = asn1_get_field_ptr(pval, seqtt);\n                asn1_template_free(pseqval, seqtt);\n            }\n        }\n        for (i = 0, tt = it->templates; i < it->tcount; i++, tt++) {\n            const ASN1_TEMPLATE *seqtt;\n            ASN1_VALUE **pseqval;\n            seqtt = asn1_do_adb(*pval, tt, 1);\n            if (seqtt == NULL)\n                goto err;\n            pseqval = asn1_get_field_ptr(pval, seqtt);\n            if (!len)\n                break;\n            q = p;\n            if (asn1_check_eoc(&p, len)) {\n                if (!seq_eoc) {\n                    ASN1err(ASN1_F_ASN1_ITEM_EMBED_D2I, ASN1_R_UNEXPECTED_EOC);\n                    goto err;\n                }\n                len -= p - q;\n                seq_eoc = 0;\n                q = p;\n                break;\n            }\n            if (i == (it->tcount - 1))\n                isopt = 0;\n            else\n                isopt = (char)(seqtt->flags & ASN1_TFLG_OPTIONAL);\n            ret = asn1_template_ex_d2i(pseqval, &p, len, seqtt, isopt, ctx,\n                                       depth);\n            if (!ret) {\n                errtt = seqtt;\n                goto err;\n            } else if (ret == -1) {\n                asn1_template_free(pseqval, seqtt);\n                continue;\n            }\n            len -= p - q;\n        }\n        if (seq_eoc && !asn1_check_eoc(&p, len)) {\n            ASN1err(ASN1_F_ASN1_ITEM_EMBED_D2I, ASN1_R_MISSING_EOC);\n            goto err;\n        }\n        if (!seq_nolen && len) {\n            ASN1err(ASN1_F_ASN1_ITEM_EMBED_D2I, ASN1_R_SEQUENCE_LENGTH_MISMATCH);\n            goto err;\n        }\n        for (; i < it->tcount; tt++, i++) {\n            const ASN1_TEMPLATE *seqtt;\n            seqtt = asn1_do_adb(*pval, tt, 1);\n            if (seqtt == NULL)\n                goto err;\n            if (seqtt->flags & ASN1_TFLG_OPTIONAL) {\n                ASN1_VALUE **pseqval;\n                pseqval = asn1_get_field_ptr(pval, seqtt);\n                asn1_template_free(pseqval, seqtt);\n            } else {\n                errtt = seqtt;\n                ASN1err(ASN1_F_ASN1_ITEM_EMBED_D2I, ASN1_R_FIELD_MISSING);\n                goto err;\n            }\n        }\n        if (!asn1_enc_save(pval, *in, p - *in, it))\n            goto auxerr;\n        if (asn1_cb && !asn1_cb(ASN1_OP_D2I_POST, pval, it, NULL))\n            goto auxerr;\n        *in = p;\n        return 1;\n    default:\n        return 0;\n    }\n auxerr:\n    ASN1err(ASN1_F_ASN1_ITEM_EMBED_D2I, ASN1_R_AUX_ERROR);\n err:\n    if (errtt)\n        ERR_add_error_data(4, "Field=", errtt->field_name,\n                           ", Type=", it->sname);\n    else\n        ERR_add_error_data(2, "Type=", it->sname);\n    return 0;\n}', 'static int asn1_check_tlen(long *olen, int *otag, unsigned char *oclass,\n                           char *inf, char *cst,\n                           const unsigned char **in, long len,\n                           int exptag, int expclass, char opt, ASN1_TLC *ctx)\n{\n    int i;\n    int ptag, pclass;\n    long plen;\n    const unsigned char *p, *q;\n    p = *in;\n    q = p;\n    if (ctx && ctx->valid) {\n        i = ctx->ret;\n        plen = ctx->plen;\n        pclass = ctx->pclass;\n        ptag = ctx->ptag;\n        p += ctx->hdrlen;\n    } else {\n        i = ASN1_get_object(&p, &plen, &ptag, &pclass, len);\n        if (ctx) {\n            ctx->ret = i;\n            ctx->plen = plen;\n            ctx->pclass = pclass;\n            ctx->ptag = ptag;\n            ctx->hdrlen = p - q;\n            ctx->valid = 1;\n            if (!(i & 0x81) && ((plen + ctx->hdrlen) > len)) {\n                ASN1err(ASN1_F_ASN1_CHECK_TLEN, ASN1_R_TOO_LONG);\n                asn1_tlc_clear(ctx);\n                return 0;\n            }\n        }\n    }\n    if (i & 0x80) {\n        ASN1err(ASN1_F_ASN1_CHECK_TLEN, ASN1_R_BAD_OBJECT_HEADER);\n        asn1_tlc_clear(ctx);\n        return 0;\n    }\n    if (exptag >= 0) {\n        if ((exptag != ptag) || (expclass != pclass)) {\n            if (opt)\n                return -1;\n            asn1_tlc_clear(ctx);\n            ASN1err(ASN1_F_ASN1_CHECK_TLEN, ASN1_R_WRONG_TAG);\n            return 0;\n        }\n        asn1_tlc_clear(ctx);\n    }\n    if (i & 1)\n        plen = len - (p - q);\n    if (inf)\n        *inf = i & 1;\n    if (cst)\n        *cst = i & V_ASN1_CONSTRUCTED;\n    if (olen)\n        *olen = plen;\n    if (oclass)\n        *oclass = pclass;\n    if (otag)\n        *otag = ptag;\n    *in = p;\n    return 1;\n}', 'int ASN1_get_object(const unsigned char **pp, long *plength, int *ptag,\n                    int *pclass, long omax)\n{\n    int i, ret;\n    long l;\n    const unsigned char *p = *pp;\n    int tag, xclass, inf;\n    long max = omax;\n    if (!max)\n        goto err;\n    ret = (*p & V_ASN1_CONSTRUCTED);\n    xclass = (*p & V_ASN1_PRIVATE);\n    i = *p & V_ASN1_PRIMITIVE_TAG;\n    if (i == V_ASN1_PRIMITIVE_TAG) {\n        p++;\n        if (--max == 0)\n            goto err;\n        l = 0;\n        while (*p & 0x80) {\n            l <<= 7L;\n            l |= *(p++) & 0x7f;\n            if (--max == 0)\n                goto err;\n            if (l > (INT_MAX >> 7L))\n                goto err;\n        }\n        l <<= 7L;\n        l |= *(p++) & 0x7f;\n        tag = (int)l;\n        if (--max == 0)\n            goto err;\n    } else {\n        tag = i;\n        p++;\n        if (--max == 0)\n            goto err;\n    }\n    *ptag = tag;\n    *pclass = xclass;\n    if (!asn1_get_length(&p, &inf, plength, max))\n        goto err;\n    if (inf && !(ret & V_ASN1_CONSTRUCTED))\n        goto err;\n    if (*plength > (omax - (p - *pp))) {\n        ASN1err(ASN1_F_ASN1_GET_OBJECT, ASN1_R_TOO_LONG);\n        ret |= 0x80;\n    }\n    *pp = p;\n    return ret | inf;\n err:\n    ASN1err(ASN1_F_ASN1_GET_OBJECT, ASN1_R_HEADER_TOO_LONG);\n    return 0x80;\n}']