ERR: Add new building blocks for reporting errors
The new building block are ERR_new(), ERR_set_debug(), ERR_set_error(), ERR_vset_error(), which allocate a new error record and set the diverse data in them. They are designed in such a way that it's reasonably easy to create macros that use all of them but then rely completely on the function signature of ERR_set_error() or ERR_vset_error(). Reviewed-by: Paul Dale <paul.dale@oracle.com> (Merged from https://github.com/openssl/openssl/pull/9452)
This commit is contained in:
parent
8a4dc425cc
commit
7c0e20dc6f
5 changed files with 205 additions and 1 deletions
|
@ -1,3 +1,3 @@
|
||||||
LIBS=../../libcrypto
|
LIBS=../../libcrypto
|
||||||
SOURCE[../../libcrypto]=\
|
SOURCE[../../libcrypto]=\
|
||||||
err.c err_all.c err_prn.c
|
err_blocks.c err.c err_all.c err_prn.c
|
||||||
|
|
113
crypto/err/err_blocks.c
Normal file
113
crypto/err/err_blocks.c
Normal file
|
@ -0,0 +1,113 @@
|
||||||
|
/*
|
||||||
|
* Copyright 2019 The OpenSSL Project Authors. All Rights Reserved.
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License 2.0 (the "License"). You may not use
|
||||||
|
* this file except in compliance with the License. You can obtain a copy
|
||||||
|
* in the file LICENSE in the source distribution or at
|
||||||
|
* https://www.openssl.org/source/license.html
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <string.h>
|
||||||
|
#include <openssl/err.h>
|
||||||
|
#include "err_locl.h"
|
||||||
|
|
||||||
|
void ERR_new(void)
|
||||||
|
{
|
||||||
|
ERR_STATE *es;
|
||||||
|
|
||||||
|
es = ERR_get_state();
|
||||||
|
if (es == NULL)
|
||||||
|
return;
|
||||||
|
|
||||||
|
/* Allocate a slot */
|
||||||
|
err_get_slot(es);
|
||||||
|
err_clear(es, es->top, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
void ERR_set_debug(const char *file, int line, const char *func)
|
||||||
|
{
|
||||||
|
ERR_STATE *es;
|
||||||
|
|
||||||
|
es = ERR_get_state();
|
||||||
|
if (es == NULL)
|
||||||
|
return;
|
||||||
|
|
||||||
|
err_set_debug(es, es->top, file, line, func);
|
||||||
|
}
|
||||||
|
|
||||||
|
void ERR_set_error(int lib, int reason, const char *fmt, ...)
|
||||||
|
{
|
||||||
|
va_list args;
|
||||||
|
|
||||||
|
va_start(args, fmt);
|
||||||
|
ERR_vset_error(lib, reason, fmt, args);
|
||||||
|
va_end(args);
|
||||||
|
}
|
||||||
|
|
||||||
|
void ERR_vset_error(int lib, int reason, const char *fmt, va_list args)
|
||||||
|
{
|
||||||
|
ERR_STATE *es;
|
||||||
|
char *buf = NULL;
|
||||||
|
size_t buf_size = 0;
|
||||||
|
unsigned long flags = 0;
|
||||||
|
size_t i;
|
||||||
|
|
||||||
|
es = ERR_get_state();
|
||||||
|
if (es == NULL)
|
||||||
|
return;
|
||||||
|
i = es->top;
|
||||||
|
|
||||||
|
if (fmt != NULL) {
|
||||||
|
int printed_len = 0;
|
||||||
|
char *rbuf = NULL;
|
||||||
|
|
||||||
|
buf = es->err_data[i];
|
||||||
|
buf_size = es->err_data_size[i];
|
||||||
|
|
||||||
|
/*
|
||||||
|
* To protect the string we just grabbed from tampering by other
|
||||||
|
* functions we may call, or to protect them from freeing a pointer
|
||||||
|
* that may no longer be valid at that point, we clear away the
|
||||||
|
* data pointer and the flags. We will set them again at the end
|
||||||
|
* of this function.
|
||||||
|
*/
|
||||||
|
es->err_data[i] = NULL;
|
||||||
|
es->err_data_flags[i] = 0;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Try to maximize the space available. If that fails, we use what
|
||||||
|
* we have.
|
||||||
|
*/
|
||||||
|
if (buf_size < ERR_MAX_DATA_SIZE
|
||||||
|
&& (rbuf = OPENSSL_realloc(buf, ERR_MAX_DATA_SIZE)) != NULL) {
|
||||||
|
buf = rbuf;
|
||||||
|
buf_size = ERR_MAX_DATA_SIZE;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (buf != NULL) {
|
||||||
|
printed_len = BIO_vsnprintf(buf, ERR_MAX_DATA_SIZE, fmt, args);
|
||||||
|
}
|
||||||
|
if (printed_len < 0)
|
||||||
|
printed_len = 0;
|
||||||
|
buf[printed_len] = '\0';
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Try to reduce the size, but only if we maximized above. If that
|
||||||
|
* fails, we keep what we have.
|
||||||
|
* (According to documentation, realloc leaves the old buffer untouched
|
||||||
|
* if it fails)
|
||||||
|
*/
|
||||||
|
if ((rbuf = OPENSSL_realloc(buf, printed_len + 1)) != NULL) {
|
||||||
|
buf = rbuf;
|
||||||
|
buf_size = printed_len + 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (buf != NULL)
|
||||||
|
flags = ERR_TXT_MALLOCED | ERR_TXT_STRING;
|
||||||
|
}
|
||||||
|
|
||||||
|
err_clear_data(es, es->top, 0);
|
||||||
|
err_set_error(es, es->top, lib, reason);
|
||||||
|
if (fmt != NULL)
|
||||||
|
err_set_data(es, es->top, buf, buf_size, flags);
|
||||||
|
}
|
78
doc/man3/ERR_new.pod
Normal file
78
doc/man3/ERR_new.pod
Normal file
|
@ -0,0 +1,78 @@
|
||||||
|
=pod
|
||||||
|
|
||||||
|
=head1 NAME
|
||||||
|
|
||||||
|
ERR_new, ERR_set_debug, ERR_set_error, ERR_vset_error
|
||||||
|
- Error recording building blocks
|
||||||
|
|
||||||
|
=head1 SYNOPSIS
|
||||||
|
|
||||||
|
#include <openssl/err.h>
|
||||||
|
|
||||||
|
void ERR_new(void);
|
||||||
|
void ERR_set_debug(const char *file, int line, const char *func);
|
||||||
|
void ERR_set_error(int lib, int reason, const char *fmt, ...);
|
||||||
|
void ERR_vset_error(int lib, int reason, const char *fmt, va_list args);
|
||||||
|
|
||||||
|
=head1 DESCRIPTION
|
||||||
|
|
||||||
|
The functions described here are generally not used directly, but
|
||||||
|
rather through macros such as L<ERR_raise(3)>.
|
||||||
|
They can still be useful for anyone that wants to make their own
|
||||||
|
macros.
|
||||||
|
|
||||||
|
ERR_new() allocates a new slot in the thread's error queue.
|
||||||
|
|
||||||
|
ERR_set_debug() sets the debug information related to the current
|
||||||
|
error in the thread's error queue.
|
||||||
|
The values that can be given are the file name I<file>, line in the
|
||||||
|
file I<line> and the name of the function I<func> where the error
|
||||||
|
occured.
|
||||||
|
The names must be constant, this function will only save away the
|
||||||
|
pointers, not copy the strings.
|
||||||
|
|
||||||
|
ERR_set_error() sets the error information, which are the library
|
||||||
|
number I<lib> and the reason code I<reason>, and additional data as a
|
||||||
|
format string I<fmt> and an arbitrary number of arguments.
|
||||||
|
The additional data is processed with L<BIO_snprintf(3)> to form the
|
||||||
|
additional data string, which is allocated and store in the error
|
||||||
|
record.
|
||||||
|
|
||||||
|
ERR_vset_error() works like ERR_set_error(), but takes a B<va_list>
|
||||||
|
argument instead of a variable number of arguments.
|
||||||
|
|
||||||
|
=head1 RETURN VALUES
|
||||||
|
|
||||||
|
ERR_new, ERR_set_debug, ERR_set_error and ERR_vset_error
|
||||||
|
do not return any values.
|
||||||
|
|
||||||
|
=head1 NOTES
|
||||||
|
|
||||||
|
The library number is unique to each unit that records errors.
|
||||||
|
OpenSSL has a number of pre-allocated ones for its own uses, but
|
||||||
|
others may allocate their own library number dynamically with
|
||||||
|
L<ERR_get_next_error_library(3)>.
|
||||||
|
|
||||||
|
Reason codes are unique within each library, and may have an
|
||||||
|
associated set of strings as a short description of the reason.
|
||||||
|
For dynamically allocated library numbers, reason strings are recorded
|
||||||
|
with L<ERR_load_strings(3)>.
|
||||||
|
|
||||||
|
Provider authors are supplied with core versions of these functions,
|
||||||
|
see L<provider-base(7)>.
|
||||||
|
|
||||||
|
=head1 SEE ALSO
|
||||||
|
|
||||||
|
L<ERR_raise(3)>, L<ERR_get_next_error_library(3)>,
|
||||||
|
L<ERR_load_strings(3)>, L<BIO_snprintf(3)>, L<provider-base(7)>
|
||||||
|
|
||||||
|
=head1 COPYRIGHT
|
||||||
|
|
||||||
|
Copyright 2000-2019 The OpenSSL Project Authors. All Rights Reserved.
|
||||||
|
|
||||||
|
Licensed under the Apache License 2.0 (the "License"). You may not use
|
||||||
|
this file except in compliance with the License. You can obtain a copy
|
||||||
|
in the file LICENSE in the source distribution or at
|
||||||
|
L<https://www.openssl.org/source/license.html>.
|
||||||
|
|
||||||
|
=cut
|
|
@ -236,6 +236,15 @@ typedef struct ERR_string_data_st {
|
||||||
|
|
||||||
DEFINE_LHASH_OF(ERR_STRING_DATA);
|
DEFINE_LHASH_OF(ERR_STRING_DATA);
|
||||||
|
|
||||||
|
/* 12 lines and some on an 80 column terminal */
|
||||||
|
#define ERR_MAX_DATA_SIZE 1024
|
||||||
|
|
||||||
|
/* Building blocks */
|
||||||
|
void ERR_new(void);
|
||||||
|
void ERR_set_debug(const char *file, int line, const char *func);
|
||||||
|
void ERR_set_error(int lib, int reason, const char *fmt, ...);
|
||||||
|
void ERR_vset_error(int lib, int reason, const char *fmt, va_list args);
|
||||||
|
|
||||||
void ERR_put_error(int lib, int func, int reason, const char *file, int line);
|
void ERR_put_error(int lib, int func, int reason, const char *file, int line);
|
||||||
void ERR_put_func_error(int lib, const char *func, int reason,
|
void ERR_put_func_error(int lib, const char *func, int reason,
|
||||||
const char *file, int line);
|
const char *file, int line);
|
||||||
|
|
|
@ -4700,3 +4700,7 @@ EVP_CIPHER_do_all_ex 4805 3_0_0 EXIST::FUNCTION:
|
||||||
EVP_MD_do_all_ex 4806 3_0_0 EXIST::FUNCTION:
|
EVP_MD_do_all_ex 4806 3_0_0 EXIST::FUNCTION:
|
||||||
EVP_KEYEXCH_provider 4807 3_0_0 EXIST::FUNCTION:
|
EVP_KEYEXCH_provider 4807 3_0_0 EXIST::FUNCTION:
|
||||||
OSSL_PROVIDER_available 4808 3_0_0 EXIST::FUNCTION:
|
OSSL_PROVIDER_available 4808 3_0_0 EXIST::FUNCTION:
|
||||||
|
ERR_new 4809 3_0_0 EXIST::FUNCTION:
|
||||||
|
ERR_set_debug 4810 3_0_0 EXIST::FUNCTION:
|
||||||
|
ERR_set_error 4811 3_0_0 EXIST::FUNCTION:
|
||||||
|
ERR_vset_error 4812 3_0_0 EXIST::FUNCTION:
|
||||||
|
|
Loading…
Reference in a new issue