diff options
author | David Benjamin <davidben@chromium.org> | 2014-11-08 20:51:36 +0300 |
---|---|---|
committer | Adam Langley <agl@google.com> | 2014-11-11 02:09:59 +0300 |
commit | 0d82482e47c38afc146618809e5631037fc5da75 (patch) | |
tree | f0c8beb843f43bb8b91a7c4df363a3db1536e9de /crypto/err/err.c | |
parent | f2f3cfedb798a45a0605cc8c0a4e157f0119bb04 (diff) |
Fix ownership of error data in ERR_peek_*.
The error queue should only take ownership of the data if ERR_get_* is called,
not ERR_peek_*. Add a test for ERR_peek_error_line_data.
Change-Id: I976fc90fb54437dff723418ef3afd94f1c967922
Reviewed-on: https://boringssl-review.googlesource.com/2237
Reviewed-by: Adam Langley <agl@google.com>
Diffstat (limited to 'crypto/err/err.c')
-rw-r--r-- | crypto/err/err.c | 20 |
1 files changed, 14 insertions, 6 deletions
diff --git a/crypto/err/err.c b/crypto/err/err.c index 6b3d9782..6390b9a4 100644 --- a/crypto/err/err.c +++ b/crypto/err/err.c @@ -181,6 +181,7 @@ static uint32_t get_error_values(int inc, int top, const char **file, int *line, } if (top) { + assert(!inc); /* last error */ i = state->top; } else { @@ -211,14 +212,21 @@ static uint32_t get_error_values(int inc, int top, const char **file, int *line, if (flags != NULL) { *flags = error->flags & ERR_FLAG_PUBLIC_MASK; } - if (error->flags & ERR_FLAG_MALLOCED) { - if (state->to_free) { - OPENSSL_free(state->to_free); + /* If this error is being removed, take ownership of data from + * the error. The semantics are such that the caller doesn't + * take ownership either. Instead the error system takes + * ownership and retains it until the next call that affects the + * error queue. */ + if (inc) { + if (error->flags & ERR_FLAG_MALLOCED) { + if (state->to_free) { + OPENSSL_free(state->to_free); + } + state->to_free = error->data; } - state->to_free = error->data; + error->data = NULL; + error->flags = 0; } - error->data = NULL; - error->flags = 0; } } |