1e1051a39Sopenharmony_ci/* 2e1051a39Sopenharmony_ci * Copyright 2019-2021 The OpenSSL Project Authors. All Rights Reserved. 3e1051a39Sopenharmony_ci * 4e1051a39Sopenharmony_ci * Licensed under the Apache License 2.0 (the "License"). You may not use 5e1051a39Sopenharmony_ci * this file except in compliance with the License. You can obtain a copy 6e1051a39Sopenharmony_ci * in the file LICENSE in the source distribution or at 7e1051a39Sopenharmony_ci * https://www.openssl.org/source/license.html 8e1051a39Sopenharmony_ci */ 9e1051a39Sopenharmony_ci 10e1051a39Sopenharmony_ci#define OSSL_FORCE_ERR_STATE 11e1051a39Sopenharmony_ci 12e1051a39Sopenharmony_ci#include <string.h> 13e1051a39Sopenharmony_ci#include <openssl/err.h> 14e1051a39Sopenharmony_ci#include "err_local.h" 15e1051a39Sopenharmony_ci 16e1051a39Sopenharmony_civoid ERR_new(void) 17e1051a39Sopenharmony_ci{ 18e1051a39Sopenharmony_ci ERR_STATE *es; 19e1051a39Sopenharmony_ci 20e1051a39Sopenharmony_ci es = ossl_err_get_state_int(); 21e1051a39Sopenharmony_ci if (es == NULL) 22e1051a39Sopenharmony_ci return; 23e1051a39Sopenharmony_ci 24e1051a39Sopenharmony_ci /* Allocate a slot */ 25e1051a39Sopenharmony_ci err_get_slot(es); 26e1051a39Sopenharmony_ci err_clear(es, es->top, 0); 27e1051a39Sopenharmony_ci} 28e1051a39Sopenharmony_ci 29e1051a39Sopenharmony_civoid ERR_set_debug(const char *file, int line, const char *func) 30e1051a39Sopenharmony_ci{ 31e1051a39Sopenharmony_ci ERR_STATE *es; 32e1051a39Sopenharmony_ci 33e1051a39Sopenharmony_ci es = ossl_err_get_state_int(); 34e1051a39Sopenharmony_ci if (es == NULL) 35e1051a39Sopenharmony_ci return; 36e1051a39Sopenharmony_ci 37e1051a39Sopenharmony_ci err_set_debug(es, es->top, file, line, func); 38e1051a39Sopenharmony_ci} 39e1051a39Sopenharmony_ci 40e1051a39Sopenharmony_civoid ERR_set_error(int lib, int reason, const char *fmt, ...) 41e1051a39Sopenharmony_ci{ 42e1051a39Sopenharmony_ci va_list args; 43e1051a39Sopenharmony_ci 44e1051a39Sopenharmony_ci va_start(args, fmt); 45e1051a39Sopenharmony_ci ERR_vset_error(lib, reason, fmt, args); 46e1051a39Sopenharmony_ci va_end(args); 47e1051a39Sopenharmony_ci} 48e1051a39Sopenharmony_ci 49e1051a39Sopenharmony_civoid ERR_vset_error(int lib, int reason, const char *fmt, va_list args) 50e1051a39Sopenharmony_ci{ 51e1051a39Sopenharmony_ci ERR_STATE *es; 52e1051a39Sopenharmony_ci char *buf = NULL; 53e1051a39Sopenharmony_ci size_t buf_size = 0; 54e1051a39Sopenharmony_ci unsigned long flags = 0; 55e1051a39Sopenharmony_ci size_t i; 56e1051a39Sopenharmony_ci 57e1051a39Sopenharmony_ci es = ossl_err_get_state_int(); 58e1051a39Sopenharmony_ci if (es == NULL) 59e1051a39Sopenharmony_ci return; 60e1051a39Sopenharmony_ci i = es->top; 61e1051a39Sopenharmony_ci 62e1051a39Sopenharmony_ci if (fmt != NULL) { 63e1051a39Sopenharmony_ci int printed_len = 0; 64e1051a39Sopenharmony_ci char *rbuf = NULL; 65e1051a39Sopenharmony_ci 66e1051a39Sopenharmony_ci buf = es->err_data[i]; 67e1051a39Sopenharmony_ci buf_size = es->err_data_size[i]; 68e1051a39Sopenharmony_ci 69e1051a39Sopenharmony_ci /* 70e1051a39Sopenharmony_ci * To protect the string we just grabbed from tampering by other 71e1051a39Sopenharmony_ci * functions we may call, or to protect them from freeing a pointer 72e1051a39Sopenharmony_ci * that may no longer be valid at that point, we clear away the 73e1051a39Sopenharmony_ci * data pointer and the flags. We will set them again at the end 74e1051a39Sopenharmony_ci * of this function. 75e1051a39Sopenharmony_ci */ 76e1051a39Sopenharmony_ci es->err_data[i] = NULL; 77e1051a39Sopenharmony_ci es->err_data_flags[i] = 0; 78e1051a39Sopenharmony_ci 79e1051a39Sopenharmony_ci /* 80e1051a39Sopenharmony_ci * Try to maximize the space available. If that fails, we use what 81e1051a39Sopenharmony_ci * we have. 82e1051a39Sopenharmony_ci */ 83e1051a39Sopenharmony_ci if (buf_size < ERR_MAX_DATA_SIZE 84e1051a39Sopenharmony_ci && (rbuf = OPENSSL_realloc(buf, ERR_MAX_DATA_SIZE)) != NULL) { 85e1051a39Sopenharmony_ci buf = rbuf; 86e1051a39Sopenharmony_ci buf_size = ERR_MAX_DATA_SIZE; 87e1051a39Sopenharmony_ci } 88e1051a39Sopenharmony_ci 89e1051a39Sopenharmony_ci if (buf != NULL) { 90e1051a39Sopenharmony_ci printed_len = BIO_vsnprintf(buf, buf_size, fmt, args); 91e1051a39Sopenharmony_ci } 92e1051a39Sopenharmony_ci if (printed_len < 0) 93e1051a39Sopenharmony_ci printed_len = 0; 94e1051a39Sopenharmony_ci if (buf != NULL) 95e1051a39Sopenharmony_ci buf[printed_len] = '\0'; 96e1051a39Sopenharmony_ci 97e1051a39Sopenharmony_ci /* 98e1051a39Sopenharmony_ci * Try to reduce the size, but only if we maximized above. If that 99e1051a39Sopenharmony_ci * fails, we keep what we have. 100e1051a39Sopenharmony_ci * (According to documentation, realloc leaves the old buffer untouched 101e1051a39Sopenharmony_ci * if it fails) 102e1051a39Sopenharmony_ci */ 103e1051a39Sopenharmony_ci if ((rbuf = OPENSSL_realloc(buf, printed_len + 1)) != NULL) { 104e1051a39Sopenharmony_ci buf = rbuf; 105e1051a39Sopenharmony_ci buf_size = printed_len + 1; 106e1051a39Sopenharmony_ci buf[printed_len] = '\0'; 107e1051a39Sopenharmony_ci } 108e1051a39Sopenharmony_ci 109e1051a39Sopenharmony_ci if (buf != NULL) 110e1051a39Sopenharmony_ci flags = ERR_TXT_MALLOCED | ERR_TXT_STRING; 111e1051a39Sopenharmony_ci } 112e1051a39Sopenharmony_ci 113e1051a39Sopenharmony_ci err_clear_data(es, es->top, 0); 114e1051a39Sopenharmony_ci err_set_error(es, es->top, lib, reason); 115e1051a39Sopenharmony_ci if (fmt != NULL) 116e1051a39Sopenharmony_ci err_set_data(es, es->top, buf, buf_size, flags); 117e1051a39Sopenharmony_ci} 118