static int get_cert_by_subject(X509_LOOKUP *xl, X509_LOOKUP_TYPE type,
                               X509_NAME *name, X509_OBJECT *ret)
{
    BY_DIR *ctx;
    union {
        X509 st_x509;
        X509_CRL crl;
    } data;
    int ok = 0;
    int i, j, k;
    unsigned long h;
    BUF_MEM *b = NULL;
    X509_OBJECT stmp, *tmp;
    const char *postfix = "";
    if (name == NULL)
        return 0;
    stmp.type = type;
    if (type == X509_LU_X509) {
        data.st_x509.cert_info.subject = name;
        stmp.data.x509 = &data.st_x509;
        postfix = "";
    } else if (type == X509_LU_CRL) {
        data.crl.crl.issuer = name;
        stmp.data.crl = &data.crl;
        postfix = "r";
    } else {
        X509err(X509_F_GET_CERT_BY_SUBJECT, X509_R_WRONG_LOOKUP_TYPE);
        goto finish;
    }
    if ((b = BUF_MEM_new()) == NULL) {
        X509err(X509_F_GET_CERT_BY_SUBJECT, ERR_R_BUF_LIB);
        goto finish;
    }
    ctx = (BY_DIR *)xl->method_data;
    h = X509_NAME_hash(name);
    for (i = 0; i < sk_BY_DIR_ENTRY_num(ctx->dirs); i++) {
        BY_DIR_ENTRY *ent;
        int idx;
        BY_DIR_HASH htmp, *hent;
        ent = sk_BY_DIR_ENTRY_value(ctx->dirs, i);
        j = strlen(ent->dir) + 1 + 8 + 6 + 1 + 1;
        if (!BUF_MEM_grow(b, j)) {
            X509err(X509_F_GET_CERT_BY_SUBJECT, ERR_R_MALLOC_FAILURE);
            goto finish;
        }
        if (type == X509_LU_CRL && ent->hashes) {
            htmp.hash = h;
            CRYPTO_THREAD_read_lock(ctx->lock);
            idx = sk_BY_DIR_HASH_find(ent->hashes, &htmp);
            if (idx >= 0) {
                hent = sk_BY_DIR_HASH_value(ent->hashes, idx);
                k = hent->suffix;
            } else {
                hent = NULL;
                k = 0;
            }
            CRYPTO_THREAD_unlock(ctx->lock);
        } else {
            k = 0;
            hent = NULL;
        }
        for (;;) {
            char c = '/';
#ifdef OPENSSL_SYS_VMS
            c = ent->dir[strlen(ent->dir) - 1];
            if (c != ':' && c != '>' && c != ']') {
                c = ':';
            } else {
                c = '\0';
            }
#endif
            if (c == '\0') {
                BIO_snprintf(b->data, b->max,
                             "%s%08lx.%s%d", ent->dir, h, postfix, k);
            } else {
                BIO_snprintf(b->data, b->max,
                             "%s%c%08lx.%s%d", ent->dir, c, h, postfix, k);
            }
#ifndef OPENSSL_NO_POSIX_IO
# ifdef _WIN32
#  define stat _stat
# endif
            {
                struct stat st;
                if (stat(b->data, &st) < 0)
                    break;
            }
#endif
            if (type == X509_LU_X509) {
                if ((X509_load_cert_file(xl, b->data, ent->dir_type)) == 0)
                    break;
            } else if (type == X509_LU_CRL) {
                if ((X509_load_crl_file(xl, b->data, ent->dir_type)) == 0)
                    break;
            }
            k++;
        }
        CRYPTO_THREAD_write_lock(ctx->lock);
        j = sk_X509_OBJECT_find(xl->store_ctx->objs, &stmp);
        if (j != -1)
            tmp = sk_X509_OBJECT_value(xl->store_ctx->objs, j);
        else
            tmp = NULL;
        CRYPTO_THREAD_unlock(ctx->lock);
        if (type == X509_LU_CRL) {
            CRYPTO_THREAD_write_lock(ctx->lock);
            if (!hent) {
                htmp.hash = h;
                idx = sk_BY_DIR_HASH_find(ent->hashes, &htmp);
                if (idx >= 0)
                    hent = sk_BY_DIR_HASH_value(ent->hashes, idx);
            }
            if (!hent) {
                hent = OPENSSL_malloc(sizeof(*hent));
                if (hent == NULL) {
                    CRYPTO_THREAD_unlock(ctx->lock);
                    X509err(X509_F_GET_CERT_BY_SUBJECT, ERR_R_MALLOC_FAILURE);
                    ok = 0;
                    goto finish;
                }
                hent->hash = h;
                hent->suffix = k;
                if (!sk_BY_DIR_HASH_push(ent->hashes, hent)) {
                    CRYPTO_THREAD_unlock(ctx->lock);
                    OPENSSL_free(hent);
                    ok = 0;
                    goto finish;
                }
            } else if (hent->suffix < k) {
                hent->suffix = k;
            }
            CRYPTO_THREAD_unlock(ctx->lock);
        }
        if (tmp != NULL) {
            ok = 1;
            ret->type = tmp->type;
            memcpy(&ret->data, &tmp->data, sizeof(ret->data));
            ERR_clear_error();
            goto finish;
        }
    }
 finish:
    BUF_MEM_free(b);
    return ok;
}
['static int get_cert_by_subject(X509_LOOKUP *xl, X509_LOOKUP_TYPE type,\n                               X509_NAME *name, X509_OBJECT *ret)\n{\n    BY_DIR *ctx;\n    union {\n        X509 st_x509;\n        X509_CRL crl;\n    } data;\n    int ok = 0;\n    int i, j, k;\n    unsigned long h;\n    BUF_MEM *b = NULL;\n    X509_OBJECT stmp, *tmp;\n    const char *postfix = "";\n    if (name == NULL)\n        return 0;\n    stmp.type = type;\n    if (type == X509_LU_X509) {\n        data.st_x509.cert_info.subject = name;\n        stmp.data.x509 = &data.st_x509;\n        postfix = "";\n    } else if (type == X509_LU_CRL) {\n        data.crl.crl.issuer = name;\n        stmp.data.crl = &data.crl;\n        postfix = "r";\n    } else {\n        X509err(X509_F_GET_CERT_BY_SUBJECT, X509_R_WRONG_LOOKUP_TYPE);\n        goto finish;\n    }\n    if ((b = BUF_MEM_new()) == NULL) {\n        X509err(X509_F_GET_CERT_BY_SUBJECT, ERR_R_BUF_LIB);\n        goto finish;\n    }\n    ctx = (BY_DIR *)xl->method_data;\n    h = X509_NAME_hash(name);\n    for (i = 0; i < sk_BY_DIR_ENTRY_num(ctx->dirs); i++) {\n        BY_DIR_ENTRY *ent;\n        int idx;\n        BY_DIR_HASH htmp, *hent;\n        ent = sk_BY_DIR_ENTRY_value(ctx->dirs, i);\n        j = strlen(ent->dir) + 1 + 8 + 6 + 1 + 1;\n        if (!BUF_MEM_grow(b, j)) {\n            X509err(X509_F_GET_CERT_BY_SUBJECT, ERR_R_MALLOC_FAILURE);\n            goto finish;\n        }\n        if (type == X509_LU_CRL && ent->hashes) {\n            htmp.hash = h;\n            CRYPTO_THREAD_read_lock(ctx->lock);\n            idx = sk_BY_DIR_HASH_find(ent->hashes, &htmp);\n            if (idx >= 0) {\n                hent = sk_BY_DIR_HASH_value(ent->hashes, idx);\n                k = hent->suffix;\n            } else {\n                hent = NULL;\n                k = 0;\n            }\n            CRYPTO_THREAD_unlock(ctx->lock);\n        } else {\n            k = 0;\n            hent = NULL;\n        }\n        for (;;) {\n            char c = \'/\';\n#ifdef OPENSSL_SYS_VMS\n            c = ent->dir[strlen(ent->dir) - 1];\n            if (c != \':\' && c != \'>\' && c != \']\') {\n                c = \':\';\n            } else {\n                c = \'\\0\';\n            }\n#endif\n            if (c == \'\\0\') {\n                BIO_snprintf(b->data, b->max,\n                             "%s%08lx.%s%d", ent->dir, h, postfix, k);\n            } else {\n                BIO_snprintf(b->data, b->max,\n                             "%s%c%08lx.%s%d", ent->dir, c, h, postfix, k);\n            }\n#ifndef OPENSSL_NO_POSIX_IO\n# ifdef _WIN32\n#  define stat _stat\n# endif\n            {\n                struct stat st;\n                if (stat(b->data, &st) < 0)\n                    break;\n            }\n#endif\n            if (type == X509_LU_X509) {\n                if ((X509_load_cert_file(xl, b->data, ent->dir_type)) == 0)\n                    break;\n            } else if (type == X509_LU_CRL) {\n                if ((X509_load_crl_file(xl, b->data, ent->dir_type)) == 0)\n                    break;\n            }\n            k++;\n        }\n        CRYPTO_THREAD_write_lock(ctx->lock);\n        j = sk_X509_OBJECT_find(xl->store_ctx->objs, &stmp);\n        if (j != -1)\n            tmp = sk_X509_OBJECT_value(xl->store_ctx->objs, j);\n        else\n            tmp = NULL;\n        CRYPTO_THREAD_unlock(ctx->lock);\n        if (type == X509_LU_CRL) {\n            CRYPTO_THREAD_write_lock(ctx->lock);\n            if (!hent) {\n                htmp.hash = h;\n                idx = sk_BY_DIR_HASH_find(ent->hashes, &htmp);\n                if (idx >= 0)\n                    hent = sk_BY_DIR_HASH_value(ent->hashes, idx);\n            }\n            if (!hent) {\n                hent = OPENSSL_malloc(sizeof(*hent));\n                if (hent == NULL) {\n                    CRYPTO_THREAD_unlock(ctx->lock);\n                    X509err(X509_F_GET_CERT_BY_SUBJECT, ERR_R_MALLOC_FAILURE);\n                    ok = 0;\n                    goto finish;\n                }\n                hent->hash = h;\n                hent->suffix = k;\n                if (!sk_BY_DIR_HASH_push(ent->hashes, hent)) {\n                    CRYPTO_THREAD_unlock(ctx->lock);\n                    OPENSSL_free(hent);\n                    ok = 0;\n                    goto finish;\n                }\n            } else if (hent->suffix < k) {\n                hent->suffix = k;\n            }\n            CRYPTO_THREAD_unlock(ctx->lock);\n        }\n        if (tmp != NULL) {\n            ok = 1;\n            ret->type = tmp->type;\n            memcpy(&ret->data, &tmp->data, sizeof(ret->data));\n            ERR_clear_error();\n            goto finish;\n        }\n    }\n finish:\n    BUF_MEM_free(b);\n    return ok;\n}', 'void BUF_MEM_free(BUF_MEM *a)\n{\n    if (a->data != NULL) {\n        if (a->flags & BUF_MEM_FLAG_SECURE)\n            OPENSSL_secure_clear_free(a->data, a->max);\n        else\n            OPENSSL_clear_free(a->data, a->max);\n    }\n    OPENSSL_free(a);\n}']