在OpenSSL中错误堆栈和错误队列是一样的吗?

时间:2016-09-15 10:44:08

标签: openssl

在openSSL文档中,我一直在阅读错误队列和错误堆栈。 两个描述都指的是相同的机制吗?或者它们是不同的机制?

1 个答案:

答案 0 :(得分:2)

  

我一直在阅读错误队列和错误堆栈。两个描述都指的是相同的机制吗?或者它们是不同的机制?

据我所知,他们是一样的,给予或接受。它们大多可以互换使用。

错误队列是合乎逻辑的,通常会对其进行抽象讨论。该库至少有两个不同的错误队列。第一个是libcrypto中的一个,您使用ERR_get_error获取错误。第二个是libssl中的一个,您使用SSL_get_error获取错误。

错误堆栈实际上是错误队列的一个实现。这是libcrypto在代码中的样子。它在crypto/err/err.h中声明,并在crypto/err/err.c中实现:

unsigned long ERR_get_error(void)
{
    return (get_error_values(1, 0, NULL, NULL, NULL, NULL));
}

static unsigned long get_error_values(int inc, int top, const char **file,
                                      int *line, const char **data,
                                      int *flags)
{
    int i = 0;
    ERR_STATE *es;
    unsigned long ret;

    es = ERR_get_state();

    if (inc && top) {
        if (file)
            *file = "";
        if (line)
            *line = 0;
        if (data)
            *data = "";
        if (flags)
            *flags = 0;

        return ERR_R_INTERNAL_ERROR;
    }

    if (es->bottom == es->top)
        return 0;
    if (top)
        i = es->top;            /* last error */
    else
        i = (es->bottom + 1) % ERR_NUM_ERRORS; /* first error */

    ret = es->err_buffer[i];
    if (inc) {
        es->bottom = i;
        es->err_buffer[i] = 0;
    }

    if ((file != NULL) && (line != NULL)) {
        if (es->err_file[i] == NULL) {
            *file = "NA";
            if (line != NULL)
                *line = 0;
        } else {
            *file = es->err_file[i];
            if (line != NULL)
                *line = es->err_line[i];
        }
    }

    if (data == NULL) {
        if (inc) {
            err_clear_data(es, i);
        }
    } else {
        if (es->err_data[i] == NULL) {
            *data = "";
            if (flags != NULL)
                *flags = 0;
        } else {
            *data = es->err_data[i];
            if (flags != NULL)
                *flags = es->err_data_flags[i];
        }
    }
    return ret;
}

ERR_STATE *ERR_get_state(void)
{
    static ERR_STATE fallback;
    ERR_STATE *ret, tmp, *tmpp = NULL;
    int i;
    CRYPTO_THREADID tid;

    err_fns_check();
    CRYPTO_THREADID_current(&tid);
    CRYPTO_THREADID_cpy(&tmp.tid, &tid);
    ret = ERRFN(thread_get_item) (&tmp);

    /* ret == the error state, if NULL, make a new one */
    if (ret == NULL) {
        ret = (ERR_STATE *)OPENSSL_malloc(sizeof(ERR_STATE));
        if (ret == NULL)
            return (&fallback);
        CRYPTO_THREADID_cpy(&ret->tid, &tid);
        ret->top = 0;
        ret->bottom = 0;
        for (i = 0; i < ERR_NUM_ERRORS; i++) {
            ret->err_data[i] = NULL;
            ret->err_data_flags[i] = 0;
        }
        tmpp = ERRFN(thread_set_item) (ret);
        /* To check if insertion failed, do a get. */
        if (ERRFN(thread_get_item) (ret) != ret) {
            ERR_STATE_free(ret); /* could not insert it */
            return (&fallback);
        }
        /*
         * If a race occured in this function and we came second, tmpp is the
         * first one that we just replaced.
         */
        if (tmpp)
            ERR_STATE_free(tmpp);
    }
    return ret;
}

这里是声明错误状态列表的地方:

$ grep -IR ERR_STATE * | grep DECLARE
crypto/err/err.c:DECLARE_LHASH_OF(ERR_STATE);