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>kris/onging/CECPQ3_patch15
@@ -181,6 +181,7 @@ static uint32_t get_error_values(int inc, int top, const char **file, int *line, | |||||
} | } | ||||
if (top) { | if (top) { | ||||
assert(!inc); | |||||
/* last error */ | /* last error */ | ||||
i = state->top; | i = state->top; | ||||
} else { | } else { | ||||
@@ -211,14 +212,21 @@ static uint32_t get_error_values(int inc, int top, const char **file, int *line, | |||||
if (flags != NULL) { | if (flags != NULL) { | ||||
*flags = error->flags & ERR_FLAG_PUBLIC_MASK; | *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; | |||||
} | } | ||||
} | } | ||||
@@ -42,9 +42,9 @@ static int test_overflow(void) { | |||||
} | } | ||||
static int test_put_error(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) { | if (ERR_get_error() != 0) { | ||||
fprintf(stderr, "ERR_get_error returned value before an error was added.\n"); | 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_put_error(1, 2, 3, "test", 4); | ||||
ERR_add_error_data(1, "testing"); | 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); | 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 || | if (strcmp(file, "test") != 0 || | ||||
line != 4 || | line != 4 || | ||||
(flags & ERR_FLAG_STRING) == 0 || | (flags & ERR_FLAG_STRING) == 0 || | ||||