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>
This commit is contained in:
David Benjamin 2014-11-08 12:51:36 -05:00 committed by Adam Langley
parent f2f3cfedb7
commit 0d82482e47
2 changed files with 28 additions and 9 deletions

View File

@ -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;
}
}

View File

@ -42,9 +42,9 @@ static int test_overflow(void) {
}
static int test_put_error(void) {
uint32_t packed_error;
int line, flags;
const char *file, *data;
uint32_t peeked_packed_error, packed_error;
int peeked_line, line, peeked_flags, flags;
const char *peeked_file, *file, *peeked_data, *data;
if (ERR_get_error() != 0) {
fprintf(stderr, "ERR_get_error returned value before an error was added.\n");
@ -54,7 +54,18 @@ static int test_put_error(void) {
ERR_put_error(1, 2, 3, "test", 4);
ERR_add_error_data(1, "testing");
peeked_packed_error = ERR_peek_error_line_data(&peeked_file, &peeked_line,
&peeked_data, &peeked_flags);
packed_error = ERR_get_error_line_data(&file, &line, &data, &flags);
if (peeked_packed_error != packed_error ||
peeked_file != file ||
peeked_data != data ||
peeked_flags != flags) {
fprintf(stderr, "Bad peeked error data returned.\n");
return 0;
}
if (strcmp(file, "test") != 0 ||
line != 4 ||
(flags & ERR_FLAG_STRING) == 0 ||