Use a placeholder for unknown errors in ERR_*_error_string.

Change-Id: I3a16fa731cfa7c92e5fec19f78ae48650921f626
Reviewed-on: https://boringssl-review.googlesource.com/c/boringssl/+/47104
Reviewed-by: Adam Langley <agl@google.com>
grpc-202302
David Benjamin 4 years ago committed by Adam Langley
parent 16c76acc78
commit eec7f32470
  1. 167
      crypto/err/err.c
  2. 10
      crypto/err/err_test.cc
  3. 5
      include/openssl/err.h

@ -368,84 +368,6 @@ void ERR_clear_system_error(void) {
errno = 0;
}
char *ERR_error_string(uint32_t packed_error, char *ret) {
static char buf[ERR_ERROR_STRING_BUF_LEN];
if (ret == NULL) {
// TODO(fork): remove this.
ret = buf;
}
#if !defined(NDEBUG)
// This is aimed to help catch callers who don't provide
// |ERR_ERROR_STRING_BUF_LEN| bytes of space.
OPENSSL_memset(ret, 0, ERR_ERROR_STRING_BUF_LEN);
#endif
return ERR_error_string_n(packed_error, ret, ERR_ERROR_STRING_BUF_LEN);
}
char *ERR_error_string_n(uint32_t packed_error, char *buf, size_t len) {
char lib_buf[64], reason_buf[64];
const char *lib_str, *reason_str;
unsigned lib, reason;
if (len == 0) {
return NULL;
}
lib = ERR_GET_LIB(packed_error);
reason = ERR_GET_REASON(packed_error);
lib_str = ERR_lib_error_string(packed_error);
reason_str = ERR_reason_error_string(packed_error);
if (lib_str == NULL) {
BIO_snprintf(lib_buf, sizeof(lib_buf), "lib(%u)", lib);
lib_str = lib_buf;
}
if (reason_str == NULL) {
BIO_snprintf(reason_buf, sizeof(reason_buf), "reason(%u)", reason);
reason_str = reason_buf;
}
BIO_snprintf(buf, len, "error:%08" PRIx32 ":%s:OPENSSL_internal:%s",
packed_error, lib_str, reason_str);
if (strlen(buf) == len - 1) {
// output may be truncated; make sure we always have 5 colon-separated
// fields, i.e. 4 colons.
static const unsigned num_colons = 4;
unsigned i;
char *s = buf;
if (len <= num_colons) {
// In this situation it's not possible to ensure that the correct number
// of colons are included in the output.
return buf;
}
for (i = 0; i < num_colons; i++) {
char *colon = strchr(s, ':');
char *last_pos = &buf[len - 1] - num_colons + i;
if (colon == NULL || colon > last_pos) {
// set colon |i| at last possible position (buf[len-1] is the
// terminating 0). If we're setting this colon, then all whole of the
// rest of the string must be colons in order to have the correct
// number.
OPENSSL_memset(last_pos, ':', num_colons - i);
break;
}
s = colon + 1;
}
}
return buf;
}
// err_string_cmp is a compare function for searching error values with
// |bsearch| in |err_string_lookup|.
static int err_string_cmp(const void *a, const void *b) {
@ -530,7 +452,7 @@ static const char *const kLibraryNames[ERR_NUM_LIBS] = {
"User defined functions", // ERR_LIB_USER
};
const char *ERR_lib_error_string(uint32_t packed_error) {
static const char *err_lib_error_string(uint32_t packed_error) {
const uint32_t lib = ERR_GET_LIB(packed_error);
if (lib >= ERR_NUM_LIBS) {
@ -539,11 +461,16 @@ const char *ERR_lib_error_string(uint32_t packed_error) {
return kLibraryNames[lib];
}
const char *ERR_lib_error_string(uint32_t packed_error) {
const char *ret = err_lib_error_string(packed_error);
return ret == NULL ? "unknown library" : ret;
}
const char *ERR_func_error_string(uint32_t packed_error) {
return "OPENSSL_internal";
}
const char *ERR_reason_error_string(uint32_t packed_error) {
static const char *err_reason_error_string(uint32_t packed_error) {
const uint32_t lib = ERR_GET_LIB(packed_error);
const uint32_t reason = ERR_GET_REASON(packed_error);
@ -579,6 +506,86 @@ const char *ERR_reason_error_string(uint32_t packed_error) {
kOpenSSLReasonValuesLen, kOpenSSLReasonStringData);
}
const char *ERR_reason_error_string(uint32_t packed_error) {
const char *ret = err_reason_error_string(packed_error);
return ret == NULL ? "unknown error" : ret;
}
char *ERR_error_string(uint32_t packed_error, char *ret) {
static char buf[ERR_ERROR_STRING_BUF_LEN];
if (ret == NULL) {
// TODO(fork): remove this.
ret = buf;
}
#if !defined(NDEBUG)
// This is aimed to help catch callers who don't provide
// |ERR_ERROR_STRING_BUF_LEN| bytes of space.
OPENSSL_memset(ret, 0, ERR_ERROR_STRING_BUF_LEN);
#endif
return ERR_error_string_n(packed_error, ret, ERR_ERROR_STRING_BUF_LEN);
}
char *ERR_error_string_n(uint32_t packed_error, char *buf, size_t len) {
if (len == 0) {
return NULL;
}
unsigned lib = ERR_GET_LIB(packed_error);
unsigned reason = ERR_GET_REASON(packed_error);
const char *lib_str = err_lib_error_string(packed_error);
const char *reason_str = err_reason_error_string(packed_error);
char lib_buf[64], reason_buf[64];
if (lib_str == NULL) {
BIO_snprintf(lib_buf, sizeof(lib_buf), "lib(%u)", lib);
lib_str = lib_buf;
}
if (reason_str == NULL) {
BIO_snprintf(reason_buf, sizeof(reason_buf), "reason(%u)", reason);
reason_str = reason_buf;
}
BIO_snprintf(buf, len, "error:%08" PRIx32 ":%s:OPENSSL_internal:%s",
packed_error, lib_str, reason_str);
if (strlen(buf) == len - 1) {
// output may be truncated; make sure we always have 5 colon-separated
// fields, i.e. 4 colons.
static const unsigned num_colons = 4;
unsigned i;
char *s = buf;
if (len <= num_colons) {
// In this situation it's not possible to ensure that the correct number
// of colons are included in the output.
return buf;
}
for (i = 0; i < num_colons; i++) {
char *colon = strchr(s, ':');
char *last_pos = &buf[len - 1] - num_colons + i;
if (colon == NULL || colon > last_pos) {
// set colon |i| at last possible position (buf[len-1] is the
// terminating 0). If we're setting this colon, then all whole of the
// rest of the string must be colons in order to have the correct
// number.
OPENSSL_memset(last_pos, ':', num_colons - i);
break;
}
s = colon + 1;
}
}
return buf;
}
void ERR_print_errors_cb(ERR_print_errors_callback_t callback, void *ctx) {
char buf[ERR_ERROR_STRING_BUF_LEN];
char buf2[1024];

@ -283,3 +283,13 @@ TEST(ErrTest, String) {
// A buffer length of zero should not touch the buffer.
ERR_error_string_n(err, nullptr, 0);
}
// Error-printing functions should return something with unknown errors.
TEST(ErrTest, UnknownError) {
uint32_t err = ERR_PACK(0xff, 0xfff);
EXPECT_TRUE(ERR_lib_error_string(err));
EXPECT_TRUE(ERR_reason_error_string(err));
char buf[128];
ERR_error_string_n(err, buf, sizeof(buf));
EXPECT_NE(0u, strlen(buf));
}

@ -223,11 +223,12 @@ OPENSSL_EXPORT char *ERR_error_string_n(uint32_t packed_error, char *buf,
size_t len);
// ERR_lib_error_string returns a string representation of the library that
// generated |packed_error|.
// generated |packed_error|, or a placeholder string is the library is
// unrecognized.
OPENSSL_EXPORT const char *ERR_lib_error_string(uint32_t packed_error);
// ERR_reason_error_string returns a string representation of the reason for
// |packed_error|.
// |packed_error|, or a placeholder string if the reason is unrecognized.
OPENSSL_EXPORT const char *ERR_reason_error_string(uint32_t packed_error);
// ERR_print_errors_callback_t is the type of a function used by

Loading…
Cancel
Save