int asn1_time_to_tm(struct tm *tm, const ASN1_TIME *d)
{
    static const int min[9] = { 0, 0, 1, 1, 0, 0, 0, 0, 0 };
    static const int max[9] = { 99, 99, 12, 31, 23, 59, 59, 12, 59 };
    static const int mdays[12] = { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };
    char *a;
    int n, i, i2, l, o, min_l = 11, strict = 0, end = 6, btz = 5, md;
    struct tm tmp;
#if defined(CHARSET_EBCDIC)
    const char upper_z = 0x5A, num_zero = 0x30, period = 0x2E, minus = 0x2D, plus = 0x2B;
#else
    const char upper_z = 'Z', num_zero = '0', period = '.', minus = '-', plus = '+';
#endif
    if (d->type == V_ASN1_UTCTIME) {
        if (d->flags & ASN1_STRING_FLAG_X509_TIME) {
            min_l = 13;
            strict = 1;
        }
    } else if (d->type == V_ASN1_GENERALIZEDTIME) {
        end = 7;
        btz = 6;
        if (d->flags & ASN1_STRING_FLAG_X509_TIME) {
            min_l = 15;
            strict = 1;
        } else {
            min_l = 13;
        }
    } else {
        return 0;
    }
    l = d->length;
    a = (char *)d->data;
    o = 0;
    memset(&tmp, 0, sizeof(tmp));
    if (l < min_l)
        goto err;
    for (i = 0; i < end; i++) {
        if (!strict && (i == btz) && ((a[o] == upper_z) || (a[o] == plus) || (a[o] == minus))) {
            i++;
            break;
        }
        if (!ascii_isdigit(a[o]))
            goto err;
        n = a[o] - num_zero;
        if (++o == l)
            goto err;
        if (!ascii_isdigit(a[o]))
            goto err;
        n = (n * 10) + a[o] - num_zero;
        if (++o == l)
            goto err;
        i2 = (d->type == V_ASN1_UTCTIME) ? i + 1 : i;
        if ((n < min[i2]) || (n > max[i2]))
            goto err;
        switch (i2) {
        case 0:
            tmp.tm_year = n * 100 - 1900;
            break;
        case 1:
            if (d->type == V_ASN1_UTCTIME)
                tmp.tm_year = n < 50 ? n + 100 : n;
            else
                tmp.tm_year += n;
            break;
        case 2:
            tmp.tm_mon = n - 1;
            break;
        case 3:
            if (tmp.tm_mon == 1) {
                md = mdays[1] + leap_year(tmp.tm_year + 1900);
            } else {
                md = mdays[tmp.tm_mon];
            }
            if (n > md)
                goto err;
            tmp.tm_mday = n;
            determine_days(&tmp);
            break;
        case 4:
            tmp.tm_hour = n;
            break;
        case 5:
            tmp.tm_min = n;
            break;
        case 6:
            tmp.tm_sec = n;
            break;
        }
    }
    if (d->type == V_ASN1_GENERALIZEDTIME && a[o] == period) {
        if (strict)
            goto err;
        if (++o == l)
            goto err;
        i = o;
        while ((o < l) && ascii_isdigit(a[o]))
            o++;
        if (i == o)
            goto err;
        if (o == l)
            goto err;
    }
    if (a[o] == upper_z) {
        o++;
    } else if (!strict && ((a[o] == plus) || (a[o] == minus))) {
        int offsign = a[o] == minus ? 1 : -1;
        int offset = 0;
        o++;
        if (o + 4 != l)
            goto err;
        for (i = end; i < end + 2; i++) {
            if (!ascii_isdigit(a[o]))
                goto err;
            n = a[o] - num_zero;
            o++;
            if (!ascii_isdigit(a[o]))
                goto err;
            n = (n * 10) + a[o] - num_zero;
            i2 = (d->type == V_ASN1_UTCTIME) ? i + 1 : i;
            if ((n < min[i2]) || (n > max[i2]))
                goto err;
            if (tm != NULL) {
                if (i == end)
                    offset = n * 3600;
                else if (i == end + 1)
                    offset += n * 60;
            }
            o++;
        }
        if (offset && !OPENSSL_gmtime_adj(&tmp, 0, offset * offsign))
            goto err;
    } else {
        goto err;
    }
    if (o == l) {
        if (tm != NULL)
            *tm = tmp;
        return 1;
    }
 err:
    return 0;
}
["int asn1_time_to_tm(struct tm *tm, const ASN1_TIME *d)\n{\n    static const int min[9] = { 0, 0, 1, 1, 0, 0, 0, 0, 0 };\n    static const int max[9] = { 99, 99, 12, 31, 23, 59, 59, 12, 59 };\n    static const int mdays[12] = { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };\n    char *a;\n    int n, i, i2, l, o, min_l = 11, strict = 0, end = 6, btz = 5, md;\n    struct tm tmp;\n#if defined(CHARSET_EBCDIC)\n    const char upper_z = 0x5A, num_zero = 0x30, period = 0x2E, minus = 0x2D, plus = 0x2B;\n#else\n    const char upper_z = 'Z', num_zero = '0', period = '.', minus = '-', plus = '+';\n#endif\n    if (d->type == V_ASN1_UTCTIME) {\n        if (d->flags & ASN1_STRING_FLAG_X509_TIME) {\n            min_l = 13;\n            strict = 1;\n        }\n    } else if (d->type == V_ASN1_GENERALIZEDTIME) {\n        end = 7;\n        btz = 6;\n        if (d->flags & ASN1_STRING_FLAG_X509_TIME) {\n            min_l = 15;\n            strict = 1;\n        } else {\n            min_l = 13;\n        }\n    } else {\n        return 0;\n    }\n    l = d->length;\n    a = (char *)d->data;\n    o = 0;\n    memset(&tmp, 0, sizeof(tmp));\n    if (l < min_l)\n        goto err;\n    for (i = 0; i < end; i++) {\n        if (!strict && (i == btz) && ((a[o] == upper_z) || (a[o] == plus) || (a[o] == minus))) {\n            i++;\n            break;\n        }\n        if (!ascii_isdigit(a[o]))\n            goto err;\n        n = a[o] - num_zero;\n        if (++o == l)\n            goto err;\n        if (!ascii_isdigit(a[o]))\n            goto err;\n        n = (n * 10) + a[o] - num_zero;\n        if (++o == l)\n            goto err;\n        i2 = (d->type == V_ASN1_UTCTIME) ? i + 1 : i;\n        if ((n < min[i2]) || (n > max[i2]))\n            goto err;\n        switch (i2) {\n        case 0:\n            tmp.tm_year = n * 100 - 1900;\n            break;\n        case 1:\n            if (d->type == V_ASN1_UTCTIME)\n                tmp.tm_year = n < 50 ? n + 100 : n;\n            else\n                tmp.tm_year += n;\n            break;\n        case 2:\n            tmp.tm_mon = n - 1;\n            break;\n        case 3:\n            if (tmp.tm_mon == 1) {\n                md = mdays[1] + leap_year(tmp.tm_year + 1900);\n            } else {\n                md = mdays[tmp.tm_mon];\n            }\n            if (n > md)\n                goto err;\n            tmp.tm_mday = n;\n            determine_days(&tmp);\n            break;\n        case 4:\n            tmp.tm_hour = n;\n            break;\n        case 5:\n            tmp.tm_min = n;\n            break;\n        case 6:\n            tmp.tm_sec = n;\n            break;\n        }\n    }\n    if (d->type == V_ASN1_GENERALIZEDTIME && a[o] == period) {\n        if (strict)\n            goto err;\n        if (++o == l)\n            goto err;\n        i = o;\n        while ((o < l) && ascii_isdigit(a[o]))\n            o++;\n        if (i == o)\n            goto err;\n        if (o == l)\n            goto err;\n    }\n    if (a[o] == upper_z) {\n        o++;\n    } else if (!strict && ((a[o] == plus) || (a[o] == minus))) {\n        int offsign = a[o] == minus ? 1 : -1;\n        int offset = 0;\n        o++;\n        if (o + 4 != l)\n            goto err;\n        for (i = end; i < end + 2; i++) {\n            if (!ascii_isdigit(a[o]))\n                goto err;\n            n = a[o] - num_zero;\n            o++;\n            if (!ascii_isdigit(a[o]))\n                goto err;\n            n = (n * 10) + a[o] - num_zero;\n            i2 = (d->type == V_ASN1_UTCTIME) ? i + 1 : i;\n            if ((n < min[i2]) || (n > max[i2]))\n                goto err;\n            if (tm != NULL) {\n                if (i == end)\n                    offset = n * 3600;\n                else if (i == end + 1)\n                    offset += n * 60;\n            }\n            o++;\n        }\n        if (offset && !OPENSSL_gmtime_adj(&tmp, 0, offset * offsign))\n            goto err;\n    } else {\n        goto err;\n    }\n    if (o == l) {\n        if (tm != NULL)\n            *tm = tmp;\n        return 1;\n    }\n err:\n    return 0;\n}"]