err.c 29.6 KB
Newer Older
1
/* crypto/err/err.c */
2
/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57
 * All rights reserved.
 *
 * This package is an SSL implementation written
 * by Eric Young (eay@cryptsoft.com).
 * The implementation was written so as to conform with Netscapes SSL.
 * 
 * This library is free for commercial and non-commercial use as long as
 * the following conditions are aheared to.  The following conditions
 * apply to all code found in this distribution, be it the RC4, RSA,
 * lhash, DES, etc., code; not just the SSL code.  The SSL documentation
 * included with this distribution is covered by the same copyright terms
 * except that the holder is Tim Hudson (tjh@cryptsoft.com).
 * 
 * Copyright remains Eric Young's, and as such any Copyright notices in
 * the code are not to be removed.
 * If this package is used in a product, Eric Young should be given attribution
 * as the author of the parts of the library used.
 * This can be in the form of a textual message at program startup or
 * in documentation (online or textual) provided with the package.
 * 
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 * 1. Redistributions of source code must retain the copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 * 3. All advertising materials mentioning features or use of this software
 *    must display the following acknowledgement:
 *    "This product includes cryptographic software written by
 *     Eric Young (eay@cryptsoft.com)"
 *    The word 'cryptographic' can be left out if the rouines from the library
 *    being used are not cryptographic related :-).
 * 4. If you include any Windows specific code (or a derivative thereof) from 
 *    the apps directory (application code) you must include an acknowledgement:
 *    "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
 * 
 * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
 * SUCH DAMAGE.
 * 
 * The licence and distribution terms for any publically available version or
 * derivative of this code cannot be changed.  i.e. this code cannot simply be
 * copied and put under another distribution licence
 * [including the GNU Public Licence.]
 */
58
/* ====================================================================
59
 * Copyright (c) 1998-2006 The OpenSSL Project.  All rights reserved.
60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer. 
 *
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in
 *    the documentation and/or other materials provided with the
 *    distribution.
 *
 * 3. All advertising materials mentioning features or use of this
 *    software must display the following acknowledgment:
 *    "This product includes software developed by the OpenSSL Project
 *    for use in the OpenSSL Toolkit. (http://www.openssl.org/)"
 *
 * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
 *    endorse or promote products derived from this software without
 *    prior written permission. For written permission, please contact
 *    openssl-core@openssl.org.
 *
 * 5. Products derived from this software may not be called "OpenSSL"
 *    nor may "OpenSSL" appear in their names without prior written
 *    permission of the OpenSSL Project.
 *
 * 6. Redistributions of any form whatsoever must retain the following
 *    acknowledgment:
 *    "This product includes software developed by the OpenSSL Project
 *    for use in the OpenSSL Toolkit (http://www.openssl.org/)"
 *
 * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
 * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE OpenSSL PROJECT OR
 * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
 * OF THE POSSIBILITY OF SUCH DAMAGE.
 * ====================================================================
 *
 * This product includes cryptographic software written by Eric Young
 * (eay@cryptsoft.com).  This product includes software written by Tim
 * Hudson (tjh@cryptsoft.com).
 *
 */
111

112 113
#define OPENSSL_NO_FIPS_ERR

114
#include <stdio.h>
U
Ulf Möller 已提交
115
#include <stdarg.h>
116
#include <string.h>
117
#include "cryptlib.h"
118 119 120
#include <openssl/lhash.h>
#include <openssl/crypto.h>
#include <openssl/buffer.h>
B
Bodo Möller 已提交
121
#include <openssl/bio.h>
122
#include <openssl/err.h>
123

B
Ben Laurie 已提交
124 125 126
DECLARE_LHASH_OF(ERR_STRING_DATA);
DECLARE_LHASH_OF(ERR_STATE);

127 128
static void err_load_strings(int lib, ERR_STRING_DATA *str);

129
static void ERR_STATE_free(ERR_STATE *s);
130
#ifndef OPENSSL_NO_ERR
131 132 133 134 135 136 137 138 139 140 141
static ERR_STRING_DATA ERR_str_libraries[]=
	{
{ERR_PACK(ERR_LIB_NONE,0,0)		,"unknown library"},
{ERR_PACK(ERR_LIB_SYS,0,0)		,"system library"},
{ERR_PACK(ERR_LIB_BN,0,0)		,"bignum routines"},
{ERR_PACK(ERR_LIB_RSA,0,0)		,"rsa routines"},
{ERR_PACK(ERR_LIB_DH,0,0)		,"Diffie-Hellman routines"},
{ERR_PACK(ERR_LIB_EVP,0,0)		,"digital envelope routines"},
{ERR_PACK(ERR_LIB_BUF,0,0)		,"memory buffer routines"},
{ERR_PACK(ERR_LIB_OBJ,0,0)		,"object identifier routines"},
{ERR_PACK(ERR_LIB_PEM,0,0)		,"PEM routines"},
B
Bodo Möller 已提交
142
{ERR_PACK(ERR_LIB_DSA,0,0)		,"dsa routines"},
143
{ERR_PACK(ERR_LIB_X509,0,0)		,"x509 certificate routines"},
B
Bodo Möller 已提交
144
{ERR_PACK(ERR_LIB_ASN1,0,0)		,"asn1 encoding routines"},
U
Ulf Möller 已提交
145
{ERR_PACK(ERR_LIB_CONF,0,0)		,"configuration file routines"},
B
Bodo Möller 已提交
146 147
{ERR_PACK(ERR_LIB_CRYPTO,0,0)		,"common libcrypto routines"},
{ERR_PACK(ERR_LIB_EC,0,0)		,"elliptic curve routines"},
148 149
{ERR_PACK(ERR_LIB_ECDSA,0,0)		,"ECDSA routines"},
{ERR_PACK(ERR_LIB_ECDH,0,0)		,"ECDH routines"},
150 151 152
{ERR_PACK(ERR_LIB_SSL,0,0)		,"SSL routines"},
{ERR_PACK(ERR_LIB_BIO,0,0)		,"BIO routines"},
{ERR_PACK(ERR_LIB_PKCS7,0,0)		,"PKCS7 routines"},
153
{ERR_PACK(ERR_LIB_X509V3,0,0)		,"X509 V3 routines"},
154
{ERR_PACK(ERR_LIB_PKCS12,0,0)		,"PKCS12 routines"},
155
{ERR_PACK(ERR_LIB_RAND,0,0)		,"random number generator"},
156
{ERR_PACK(ERR_LIB_DSO,0,0)		,"DSO support routines"},
157
{ERR_PACK(ERR_LIB_TS,0,0)		,"time stamp routines"},
158
{ERR_PACK(ERR_LIB_ENGINE,0,0)		,"engine routines"},
159
{ERR_PACK(ERR_LIB_OCSP,0,0)		,"OCSP routines"},
D
Dr. Stephen Henson 已提交
160
{ERR_PACK(ERR_LIB_FIPS,0,0)		,"FIPS routines"},
D
Dr. Stephen Henson 已提交
161
{ERR_PACK(ERR_LIB_CMS,0,0)		,"CMS routines"},
D
Dr. Stephen Henson 已提交
162
{ERR_PACK(ERR_LIB_HMAC,0,0)		,"HMAC routines"},
163 164 165 166 167 168 169 170 171 172 173 174 175
{0,NULL},
	};

static ERR_STRING_DATA ERR_str_functs[]=
	{
	{ERR_PACK(0,SYS_F_FOPEN,0),     	"fopen"},
	{ERR_PACK(0,SYS_F_CONNECT,0),		"connect"},
	{ERR_PACK(0,SYS_F_GETSERVBYNAME,0),	"getservbyname"},
	{ERR_PACK(0,SYS_F_SOCKET,0),		"socket"}, 
	{ERR_PACK(0,SYS_F_IOCTLSOCKET,0),	"ioctlsocket"},
	{ERR_PACK(0,SYS_F_BIND,0),		"bind"},
	{ERR_PACK(0,SYS_F_LISTEN,0),		"listen"},
	{ERR_PACK(0,SYS_F_ACCEPT,0),		"accept"},
176
#ifdef OPENSSL_SYS_WINDOWS
177 178
	{ERR_PACK(0,SYS_F_WSASTARTUP,0),	"WSAstartup"},
#endif
179
	{ERR_PACK(0,SYS_F_OPENDIR,0),		"opendir"},
B
Ben Laurie 已提交
180
	{ERR_PACK(0,SYS_F_FREAD,0),		"fread"},
181 182 183 184 185 186 187 188 189 190 191 192 193
	{0,NULL},
	};

static ERR_STRING_DATA ERR_str_reasons[]=
	{
{ERR_R_SYS_LIB				,"system lib"},
{ERR_R_BN_LIB				,"BN lib"},
{ERR_R_RSA_LIB				,"RSA lib"},
{ERR_R_DH_LIB				,"DH lib"},
{ERR_R_EVP_LIB				,"EVP lib"},
{ERR_R_BUF_LIB				,"BUF lib"},
{ERR_R_OBJ_LIB				,"OBJ lib"},
{ERR_R_PEM_LIB				,"PEM lib"},
B
Bodo Möller 已提交
194
{ERR_R_DSA_LIB				,"DSA lib"},
195 196 197
{ERR_R_X509_LIB				,"X509 lib"},
{ERR_R_ASN1_LIB				,"ASN1 lib"},
{ERR_R_CONF_LIB				,"CONF lib"},
B
Bodo Möller 已提交
198 199
{ERR_R_CRYPTO_LIB			,"CRYPTO lib"},
{ERR_R_EC_LIB				,"EC lib"},
200 201 202
{ERR_R_SSL_LIB				,"SSL lib"},
{ERR_R_BIO_LIB				,"BIO lib"},
{ERR_R_PKCS7_LIB			,"PKCS7 lib"},
B
Bodo Möller 已提交
203
{ERR_R_X509V3_LIB			,"X509V3 lib"},
204
{ERR_R_PKCS12_LIB			,"PKCS12 lib"},
B
Bodo Möller 已提交
205 206 207 208
{ERR_R_RAND_LIB				,"RAND lib"},
{ERR_R_DSO_LIB				,"DSO lib"},
{ERR_R_ENGINE_LIB			,"ENGINE lib"},
{ERR_R_OCSP_LIB				,"OCSP lib"},
209
{ERR_R_TS_LIB				,"TS lib"},
210
{ERR_R_ECDSA_LIB			,"ECDSA lib"},
B
Bodo Möller 已提交
211

212 213 214 215 216 217
{ERR_R_NESTED_ASN1_ERROR		,"nested asn1 error"},
{ERR_R_BAD_ASN1_OBJECT_HEADER		,"bad asn1 object header"},
{ERR_R_BAD_GET_ASN1_OBJECT_CALL		,"bad get asn1 object call"},
{ERR_R_EXPECTING_AN_ASN1_SEQUENCE	,"expecting an asn1 sequence"},
{ERR_R_ASN1_LENGTH_MISMATCH		,"asn1 length mismatch"},
{ERR_R_MISSING_ASN1_EOS			,"missing asn1 eos"},
B
Bodo Möller 已提交
218 219 220 221 222 223

{ERR_R_FATAL                            ,"fatal"},
{ERR_R_MALLOC_FAILURE			,"malloc failure"},
{ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED	,"called a function you should not call"},
{ERR_R_PASSED_NULL_PARAMETER		,"passed a null parameter"},
{ERR_R_INTERNAL_ERROR			,"internal error"},
B
Bodo Möller 已提交
224
{ERR_R_DISABLED				,"called a function that was disabled at compile-time"},
225

226 227
{0,NULL},
	};
228
#endif
229 230


231 232 233 234
/* Define the predeclared (but externally opaque) "ERR_FNS" type */
struct st_ERR_FNS
	{
	/* Works on the "error_hash" string table */
B
Ben Laurie 已提交
235
	LHASH_OF(ERR_STRING_DATA) *(*cb_err_get)(int create);
236 237 238
	void (*cb_err_del)(void);
	ERR_STRING_DATA *(*cb_err_get_item)(const ERR_STRING_DATA *);
	ERR_STRING_DATA *(*cb_err_set_item)(ERR_STRING_DATA *);
239
	ERR_STRING_DATA *(*cb_err_del_item)(ERR_STRING_DATA *);
240
	/* Works on the "thread_hash" error-state table */
B
Ben Laurie 已提交
241 242
	LHASH_OF(ERR_STATE) *(*cb_thread_get)(int create);
	void (*cb_thread_release)(LHASH_OF(ERR_STATE) **hash);
243 244 245 246 247 248 249 250
	ERR_STATE *(*cb_thread_get_item)(const ERR_STATE *);
	ERR_STATE *(*cb_thread_set_item)(ERR_STATE *);
	void (*cb_thread_del_item)(const ERR_STATE *);
	/* Returns the next available error "library" numbers */
	int (*cb_get_next_lib)(void);
	};

/* Predeclarations of the "err_defaults" functions */
B
Ben Laurie 已提交
251
static LHASH_OF(ERR_STRING_DATA) *int_err_get(int create);
252 253 254
static void int_err_del(void);
static ERR_STRING_DATA *int_err_get_item(const ERR_STRING_DATA *);
static ERR_STRING_DATA *int_err_set_item(ERR_STRING_DATA *);
255
static ERR_STRING_DATA *int_err_del_item(ERR_STRING_DATA *);
B
Ben Laurie 已提交
256 257
static LHASH_OF(ERR_STATE) *int_thread_get(int create);
static void int_thread_release(LHASH_OF(ERR_STATE) **hash);
258 259 260 261 262 263 264 265 266 267 268
static ERR_STATE *int_thread_get_item(const ERR_STATE *);
static ERR_STATE *int_thread_set_item(ERR_STATE *);
static void int_thread_del_item(const ERR_STATE *);
static int int_err_get_next_lib(void);
/* The static ERR_FNS table using these defaults functions */
static const ERR_FNS err_defaults =
	{
	int_err_get,
	int_err_del,
	int_err_get_item,
	int_err_set_item,
269
	int_err_del_item,
270
	int_thread_get,
271
	int_thread_release,
272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288
	int_thread_get_item,
	int_thread_set_item,
	int_thread_del_item,
	int_err_get_next_lib
	};

/* The replacable table of ERR_FNS functions we use at run-time */
static const ERR_FNS *err_fns = NULL;

/* Eg. rather than using "err_get()", use "ERRFN(err_get)()". */
#define ERRFN(a) err_fns->cb_##a

/* The internal state used by "err_defaults" - as such, the setting, reading,
 * creating, and deleting of this data should only be permitted via the
 * "err_defaults" functions. This way, a linked module can completely defer all
 * ERR state operation (together with requisite locking) to the implementations
 * and state in the loading application. */
B
Ben Laurie 已提交
289 290
static LHASH_OF(ERR_STRING_DATA) *int_error_hash = NULL;
static LHASH_OF(ERR_STATE) *int_thread_hash = NULL;
291
static int int_thread_hash_references = 0;
292
static int int_err_library_number= ERR_LIB_USER;
293 294 295 296 297

/* Internal function that checks whether "err_fns" is set and if not, sets it to
 * the defaults. */
static void err_fns_check(void)
	{
298 299
	if (err_fns) return;
	
300
	CRYPTO_w_lock(CRYPTO_LOCK_ERR);
301
	if (!err_fns)
302 303 304 305 306 307 308 309 310 311 312 313 314 315
		err_fns = &err_defaults;
	CRYPTO_w_unlock(CRYPTO_LOCK_ERR);
	}

/* API functions to get or set the underlying ERR functions. */

const ERR_FNS *ERR_get_implementation(void)
	{
	err_fns_check();
	return err_fns;
	}

int ERR_set_implementation(const ERR_FNS *fns)
	{
316 317
	int ret = 0;

318 319 320
	CRYPTO_w_lock(CRYPTO_LOCK_ERR);
	/* It's too late if 'err_fns' is non-NULL. BTW: not much point setting
	 * an error is there?! */
321
	if (!err_fns)
322 323
		{
		err_fns = fns;
324
		ret = 1;
325 326
		}
	CRYPTO_w_unlock(CRYPTO_LOCK_ERR);
327
	return ret;
328 329 330 331 332
	}

/* These are the callbacks provided to "lh_new()" when creating the LHASH tables
 * internal to the "err_defaults" implementation. */

B
Bodo Möller 已提交
333
static unsigned long get_error_values(int inc,int top,const char **file,int *line,
334 335 336 337
				      const char **data,int *flags);

/* The internal functions used in the "err_defaults" implementation */

B
Ben Laurie 已提交
338
static unsigned long err_string_data_hash(const ERR_STRING_DATA *a)
339
	{
B
Ben Laurie 已提交
340 341 342 343 344 345
	unsigned long ret,l;

	l=a->error;
	ret=l^ERR_GET_LIB(l)^ERR_GET_FUNC(l);
	return(ret^ret%19*13);
	}
346
static IMPLEMENT_LHASH_HASH_FN(err_string_data, ERR_STRING_DATA)
B
Ben Laurie 已提交
347 348 349 350 351 352

static int err_string_data_cmp(const ERR_STRING_DATA *a,
			       const ERR_STRING_DATA *b)
	{
	return (int)(a->error - b->error);
	}
353
static IMPLEMENT_LHASH_COMP_FN(err_string_data, ERR_STRING_DATA)
B
Ben Laurie 已提交
354 355 356 357

static LHASH_OF(ERR_STRING_DATA) *int_err_get(int create)
	{
	LHASH_OF(ERR_STRING_DATA) *ret = NULL;
358

359
	CRYPTO_w_lock(CRYPTO_LOCK_ERR);
B
Bodo Möller 已提交
360 361 362
	if (!int_error_hash && create)
		{
		CRYPTO_push_info("int_err_get (err.c)");
B
Ben Laurie 已提交
363
		int_error_hash = lh_ERR_STRING_DATA_new();
B
Bodo Möller 已提交
364 365
		CRYPTO_pop_info();
		}
366 367
	if (int_error_hash)
		ret = int_error_hash;
368
	CRYPTO_w_unlock(CRYPTO_LOCK_ERR);
369 370

	return ret;
371
	}
372

373 374 375
static void int_err_del(void)
	{
	CRYPTO_w_lock(CRYPTO_LOCK_ERR);
376
	if (int_error_hash)
377
		{
B
Ben Laurie 已提交
378
		lh_ERR_STRING_DATA_free(int_error_hash);
379 380 381 382
		int_error_hash = NULL;
		}
	CRYPTO_w_unlock(CRYPTO_LOCK_ERR);
	}
383

384 385 386
static ERR_STRING_DATA *int_err_get_item(const ERR_STRING_DATA *d)
	{
	ERR_STRING_DATA *p;
B
Ben Laurie 已提交
387
	LHASH_OF(ERR_STRING_DATA) *hash;
388

389
	err_fns_check();
B
Bodo Möller 已提交
390
	hash = ERRFN(err_get)(0);
391
	if (!hash)
392
		return NULL;
393

394
	CRYPTO_r_lock(CRYPTO_LOCK_ERR);
B
Ben Laurie 已提交
395
	p = lh_ERR_STRING_DATA_retrieve(hash, d);
396
	CRYPTO_r_unlock(CRYPTO_LOCK_ERR);
397

398 399
	return p;
	}
400

401 402 403
static ERR_STRING_DATA *int_err_set_item(ERR_STRING_DATA *d)
	{
	ERR_STRING_DATA *p;
B
Ben Laurie 已提交
404
	LHASH_OF(ERR_STRING_DATA) *hash;
405

406
	err_fns_check();
B
Bodo Möller 已提交
407
	hash = ERRFN(err_get)(1);
408
	if (!hash)
409
		return NULL;
410

411
	CRYPTO_w_lock(CRYPTO_LOCK_ERR);
B
Ben Laurie 已提交
412
	p = lh_ERR_STRING_DATA_insert(hash, d);
413
	CRYPTO_w_unlock(CRYPTO_LOCK_ERR);
414

415 416
	return p;
	}
417

418 419 420
static ERR_STRING_DATA *int_err_del_item(ERR_STRING_DATA *d)
	{
	ERR_STRING_DATA *p;
B
Ben Laurie 已提交
421
	LHASH_OF(ERR_STRING_DATA) *hash;
422

423
	err_fns_check();
B
Bodo Möller 已提交
424
	hash = ERRFN(err_get)(0);
425
	if (!hash)
426
		return NULL;
427

428
	CRYPTO_w_lock(CRYPTO_LOCK_ERR);
B
Ben Laurie 已提交
429
	p = lh_ERR_STRING_DATA_delete(hash, d);
430
	CRYPTO_w_unlock(CRYPTO_LOCK_ERR);
431

432 433
	return p;
	}
434

B
Ben Laurie 已提交
435 436
static unsigned long err_state_hash(const ERR_STATE *a)
	{
437
	return CRYPTO_THREADID_hash(&a->tid) * 13;
B
Ben Laurie 已提交
438
	}
439
static IMPLEMENT_LHASH_HASH_FN(err_state, ERR_STATE)
B
Ben Laurie 已提交
440 441 442

static int err_state_cmp(const ERR_STATE *a, const ERR_STATE *b)
	{
443
	return CRYPTO_THREADID_cmp(&a->tid, &b->tid);
B
Ben Laurie 已提交
444
	}
445
static IMPLEMENT_LHASH_COMP_FN(err_state, ERR_STATE)
B
Ben Laurie 已提交
446 447

static LHASH_OF(ERR_STATE) *int_thread_get(int create)
448
	{
B
Ben Laurie 已提交
449
	LHASH_OF(ERR_STATE) *ret = NULL;
450

451
	CRYPTO_w_lock(CRYPTO_LOCK_ERR);
B
Bodo Möller 已提交
452 453 454
	if (!int_thread_hash && create)
		{
		CRYPTO_push_info("int_thread_get (err.c)");
B
Ben Laurie 已提交
455
		int_thread_hash = lh_ERR_STATE_new();
B
Bodo Möller 已提交
456 457
		CRYPTO_pop_info();
		}
458
	if (int_thread_hash)
459 460
		{
		int_thread_hash_references++;
461
		ret = int_thread_hash;
462
		}
463
	CRYPTO_w_unlock(CRYPTO_LOCK_ERR);
464
	return ret;
465
	}
466

B
Ben Laurie 已提交
467
static void int_thread_release(LHASH_OF(ERR_STATE) **hash)
468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489
	{
	int i;

	if (hash == NULL || *hash == NULL)
		return;

	i = CRYPTO_add(&int_thread_hash_references, -1, CRYPTO_LOCK_ERR);

#ifdef REF_PRINT
	fprintf(stderr,"%4d:%s\n",int_thread_hash_references,"ERR");
#endif
	if (i > 0) return;
#ifdef REF_CHECK
	if (i < 0)
		{
		fprintf(stderr,"int_thread_release, bad reference count\n");
		abort(); /* ok */
		}
#endif
	*hash = NULL;
	}

490 491 492
static ERR_STATE *int_thread_get_item(const ERR_STATE *d)
	{
	ERR_STATE *p;
B
Ben Laurie 已提交
493
	LHASH_OF(ERR_STATE) *hash;
494

495
	err_fns_check();
B
Bodo Möller 已提交
496
	hash = ERRFN(thread_get)(0);
497
	if (!hash)
498
		return NULL;
499

500
	CRYPTO_r_lock(CRYPTO_LOCK_ERR);
B
Ben Laurie 已提交
501
	p = lh_ERR_STATE_retrieve(hash, d);
502
	CRYPTO_r_unlock(CRYPTO_LOCK_ERR);
503

504
	ERRFN(thread_release)(&hash);
505 506
	return p;
	}
507

508 509 510
static ERR_STATE *int_thread_set_item(ERR_STATE *d)
	{
	ERR_STATE *p;
B
Ben Laurie 已提交
511
	LHASH_OF(ERR_STATE) *hash;
512

513
	err_fns_check();
B
Bodo Möller 已提交
514
	hash = ERRFN(thread_get)(1);
515
	if (!hash)
516
		return NULL;
517

518
	CRYPTO_w_lock(CRYPTO_LOCK_ERR);
B
Ben Laurie 已提交
519
	p = lh_ERR_STATE_insert(hash, d);
520
	CRYPTO_w_unlock(CRYPTO_LOCK_ERR);
521

522
	ERRFN(thread_release)(&hash);
523 524
	return p;
	}
525

526 527 528
static void int_thread_del_item(const ERR_STATE *d)
	{
	ERR_STATE *p;
B
Ben Laurie 已提交
529
	LHASH_OF(ERR_STATE) *hash;
530

531
	err_fns_check();
B
Bodo Möller 已提交
532
	hash = ERRFN(thread_get)(0);
533
	if (!hash)
534
		return;
535

536
	CRYPTO_w_lock(CRYPTO_LOCK_ERR);
B
Ben Laurie 已提交
537
	p = lh_ERR_STATE_delete(hash, d);
538
	/* make sure we don't leak memory */
539
	if (int_thread_hash_references == 1
B
Ben Laurie 已提交
540
	    && int_thread_hash && lh_ERR_STATE_num_items(int_thread_hash) == 0)
541
		{
B
Ben Laurie 已提交
542
		lh_ERR_STATE_free(int_thread_hash);
543 544 545
		int_thread_hash = NULL;
		}
	CRYPTO_w_unlock(CRYPTO_LOCK_ERR);
546

547
	ERRFN(thread_release)(&hash);
548
	if (p)
549 550
		ERR_STATE_free(p);
	}
551

552 553
static int int_err_get_next_lib(void)
	{
554 555
	int ret;

556
	CRYPTO_w_lock(CRYPTO_LOCK_ERR);
557
	ret = int_err_library_number++;
558
	CRYPTO_w_unlock(CRYPTO_LOCK_ERR);
559 560

	return ret;
561 562 563
	}


564
#ifndef OPENSSL_NO_ERR
565 566 567 568 569 570 571 572 573 574 575 576 577
#define NUM_SYS_STR_REASONS 127
#define LEN_SYS_STR_REASON 32

static ERR_STRING_DATA SYS_str_reasons[NUM_SYS_STR_REASONS + 1];
/* SYS_str_reasons is filled with copies of strerror() results at
 * initialization.
 * 'errno' values up to 127 should cover all usual errors,
 * others will be displayed numerically by ERR_error_string.
 * It is crucial that we have something for each reason code
 * that occurs in ERR_str_reasons, or bogus reason strings
 * will be returned for SYSerr(), which always gets an errno
 * value and never one of those 'standard' reason codes. */

578
static void build_SYS_str_reasons(void)
579
	{
580
	/* OPENSSL_malloc cannot be used here, use static storage instead */
581 582
	static char strerror_tab[NUM_SYS_STR_REASONS][LEN_SYS_STR_REASON];
	int i;
583 584
	static int init = 1;

B
Bodo Möller 已提交
585 586 587 588 589 590 591 592
	CRYPTO_r_lock(CRYPTO_LOCK_ERR);
	if (!init)
		{
		CRYPTO_r_unlock(CRYPTO_LOCK_ERR);
		return;
		}
	
	CRYPTO_r_unlock(CRYPTO_LOCK_ERR);
593
	CRYPTO_w_lock(CRYPTO_LOCK_ERR);
B
Bodo Möller 已提交
594 595 596 597 598
	if (!init)
		{
		CRYPTO_w_unlock(CRYPTO_LOCK_ERR);
		return;
		}
599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622

	for (i = 1; i <= NUM_SYS_STR_REASONS; i++)
		{
		ERR_STRING_DATA *str = &SYS_str_reasons[i - 1];

		str->error = (unsigned long)i;
		if (str->string == NULL)
			{
			char (*dest)[LEN_SYS_STR_REASON] = &(strerror_tab[i - 1]);
			char *src = strerror(i);
			if (src != NULL)
				{
				strncpy(*dest, src, sizeof *dest);
				(*dest)[sizeof *dest - 1] = '\0';
				str->string = *dest;
				}
			}
		if (str->string == NULL)
			str->string = "unknown";
		}

	/* Now we still have SYS_str_reasons[NUM_SYS_STR_REASONS] = {0, NULL},
	 * as required by ERR_load_strings. */

623 624
	init = 0;
	
625
	CRYPTO_w_unlock(CRYPTO_LOCK_ERR);
626
	}
627 628
#endif

629
#define err_clear_data(p,i) \
630
	do { \
631 632 633
	if (((p)->err_data[i] != NULL) && \
		(p)->err_data_flags[i] & ERR_TXT_MALLOCED) \
		{  \
634
		OPENSSL_free((p)->err_data[i]); \
635 636
		(p)->err_data[i]=NULL; \
		} \
637 638 639 640 641
	(p)->err_data_flags[i]=0; \
	} while(0)

#define err_clear(p,i) \
	do { \
642 643
	(p)->err_flags[i]=0; \
	(p)->err_buffer[i]=0; \
644
	err_clear_data(p,i); \
645 646
	(p)->err_file[i]=NULL; \
	(p)->err_line[i]= -1; \
647
	} while(0)
648

U
Ulf Möller 已提交
649
static void ERR_STATE_free(ERR_STATE *s)
650 651 652
	{
	int i;

653
	if (s == NULL)
B
Ben Laurie 已提交
654 655
	    return;

656 657 658 659
	for (i=0; i<ERR_NUM_ERRORS; i++)
		{
		err_clear_data(s,i);
		}
660
	OPENSSL_free(s);
661 662
	}

U
Ulf Möller 已提交
663
void ERR_load_ERR_strings(void)
664
	{
665
	err_fns_check();
666
#ifndef OPENSSL_NO_ERR
667 668 669 670 671
	err_load_strings(0,ERR_str_libraries);
	err_load_strings(0,ERR_str_reasons);
	err_load_strings(ERR_LIB_SYS,ERR_str_functs);
	build_SYS_str_reasons();
	err_load_strings(ERR_LIB_SYS,SYS_str_reasons);
672 673 674
#endif
	}

675
static void err_load_strings(int lib, ERR_STRING_DATA *str)
676 677 678
	{
	while (str->error)
		{
679 680
		if (lib)
			str->error|=ERR_PACK(lib,0,0);
681
		ERRFN(err_set_item)(str);
682 683 684 685
		str++;
		}
	}

686 687
void ERR_load_strings(int lib, ERR_STRING_DATA *str)
	{
B
typo  
Bodo Möller 已提交
688
	ERR_load_ERR_strings();
689 690 691
	err_load_strings(lib, str);
	}

692 693
void ERR_unload_strings(int lib, ERR_STRING_DATA *str)
	{
694
	while (str->error)
695
		{
696 697
		if (lib)
			str->error|=ERR_PACK(lib,0,0);
698 699 700 701 702
		ERRFN(err_del_item)(str);
		str++;
		}
	}

U
Ulf Möller 已提交
703
void ERR_free_strings(void)
704
	{
705 706
	err_fns_check();
	ERRFN(err_del)();
707 708
	}

709 710
/********************************************************/

U
Ulf Möller 已提交
711 712
void ERR_put_error(int lib, int func, int reason, const char *file,
	     int line)
713 714 715
	{
	ERR_STATE *es;

716 717 718 719 720 721 722 723 724 725 726 727 728 729 730 731 732 733 734
#ifdef _OSD_POSIX
	/* In the BS2000-OSD POSIX subsystem, the compiler generates
	 * path names in the form "*POSIX(/etc/passwd)".
	 * This dirty hack strips them to something sensible.
	 * @@@ We shouldn't modify a const string, though.
	 */
	if (strncmp(file,"*POSIX(", sizeof("*POSIX(")-1) == 0) {
		char *end;

		/* Skip the "*POSIX(" prefix */
		file += sizeof("*POSIX(")-1;
		end = &file[strlen(file)-1];
		if (*end == ')')
			*end = '\0';
		/* Optional: use the basename of the path only. */
		if ((end = strrchr(file, '/')) != NULL)
			file = &end[1];
	}
#endif
735 736 737 738 739
	es=ERR_get_state();

	es->top=(es->top+1)%ERR_NUM_ERRORS;
	if (es->top == es->bottom)
		es->bottom=(es->bottom+1)%ERR_NUM_ERRORS;
740
	es->err_flags[es->top]=0;
741 742 743
	es->err_buffer[es->top]=ERR_PACK(lib,func,reason);
	es->err_file[es->top]=file;
	es->err_line[es->top]=line;
744
	err_clear_data(es,es->top);
745 746
	}

U
Ulf Möller 已提交
747
void ERR_clear_error(void)
748
	{
B
Bodo Möller 已提交
749
	int i;
750 751 752 753 754 755
	ERR_STATE *es;

	es=ERR_get_state();

	for (i=0; i<ERR_NUM_ERRORS; i++)
		{
756
		err_clear(es,i);
757 758 759 760 761
		}
	es->top=es->bottom=0;
	}


U
Ulf Möller 已提交
762
unsigned long ERR_get_error(void)
B
Bodo Möller 已提交
763
	{ return(get_error_values(1,0,NULL,NULL,NULL,NULL)); }
764

U
Ulf Möller 已提交
765 766
unsigned long ERR_get_error_line(const char **file,
	     int *line)
B
Bodo Möller 已提交
767
	{ return(get_error_values(1,0,file,line,NULL,NULL)); }
768

U
Ulf Möller 已提交
769 770
unsigned long ERR_get_error_line_data(const char **file, int *line,
	     const char **data, int *flags)
B
Bodo Möller 已提交
771
	{ return(get_error_values(1,0,file,line,data,flags)); }
772

B
Bodo Möller 已提交
773

U
Ulf Möller 已提交
774
unsigned long ERR_peek_error(void)
B
Bodo Möller 已提交
775
	{ return(get_error_values(0,0,NULL,NULL,NULL,NULL)); }
776

B
Bodo Möller 已提交
777 778
unsigned long ERR_peek_error_line(const char **file, int *line)
	{ return(get_error_values(0,0,file,line,NULL,NULL)); }
779

U
Ulf Möller 已提交
780 781
unsigned long ERR_peek_error_line_data(const char **file, int *line,
	     const char **data, int *flags)
B
Bodo Möller 已提交
782 783
	{ return(get_error_values(0,0,file,line,data,flags)); }

B
Bodo Möller 已提交
784 785 786 787 788 789 790

unsigned long ERR_peek_last_error(void)
	{ return(get_error_values(0,1,NULL,NULL,NULL,NULL)); }

unsigned long ERR_peek_last_error_line(const char **file, int *line)
	{ return(get_error_values(0,1,file,line,NULL,NULL)); }

B
Bodo Möller 已提交
791 792 793
unsigned long ERR_peek_last_error_line_data(const char **file, int *line,
	     const char **data, int *flags)
	{ return(get_error_values(0,1,file,line,data,flags)); }
U
Ulf Möller 已提交
794

B
Bodo Möller 已提交
795

B
Bodo Möller 已提交
796
static unsigned long get_error_values(int inc, int top, const char **file, int *line,
U
Ulf Möller 已提交
797
	     const char **data, int *flags)
798 799
	{	
	int i=0;
800
	ERR_STATE *es;
801
	unsigned long ret;
802 803 804

	es=ERR_get_state();

B
Bodo Möller 已提交
805 806 807 808 809 810 811 812 813 814
	if (inc && top)
		{
		if (file) *file = "";
		if (line) *line = 0;
		if (data) *data = "";
		if (flags) *flags = 0;
			
		return ERR_R_INTERNAL_ERROR;
		}

815
	if (es->bottom == es->top) return 0;
B
Bodo Möller 已提交
816
	if (top)
817
		i=es->top;			 /* last error */
B
Bodo Möller 已提交
818 819
	else
		i=(es->bottom+1)%ERR_NUM_ERRORS; /* first error */
820 821 822

	ret=es->err_buffer[i];
	if (inc)
823
		{
824 825
		es->bottom=i;
		es->err_buffer[i]=0;
826
		}
827 828

	if ((file != NULL) && (line != NULL))
829
		{
830 831 832 833 834 835 836 837 838 839
		if (es->err_file[i] == NULL)
			{
			*file="NA";
			if (line != NULL) *line=0;
			}
		else
			{
			*file=es->err_file[i];
			if (line != NULL) *line=es->err_line[i];
			}
840 841
		}

B
Bodo Möller 已提交
842 843
	if (data == NULL)
		{
B
Bodo Möller 已提交
844
		if (inc)
B
Bodo Möller 已提交
845
			{
B
Bodo Möller 已提交
846
			err_clear_data(es, i);
B
Bodo Möller 已提交
847 848 849
			}
		}
	else
850 851 852 853 854 855 856 857 858 859 860 861
		{
		if (es->err_data[i] == NULL)
			{
			*data="";
			if (flags != NULL) *flags=0;
			}
		else
			{
			*data=es->err_data[i];
			if (flags != NULL) *flags=es->err_data_flags[i];
			}
		}
862
	return ret;
863 864
	}

B
Bodo Möller 已提交
865
void ERR_error_string_n(unsigned long e, char *buf, size_t len)
866
	{
B
Bodo Möller 已提交
867
	char lsbuf[64], fsbuf[64], rsbuf[64];
B
Ben Laurie 已提交
868
	const char *ls,*fs,*rs;
869 870 871 872 873 874 875 876 877 878
	unsigned long l,f,r;

	l=ERR_GET_LIB(e);
	f=ERR_GET_FUNC(e);
	r=ERR_GET_REASON(e);

	ls=ERR_lib_error_string(e);
	fs=ERR_func_error_string(e);
	rs=ERR_reason_error_string(e);

B
Bodo Möller 已提交
879 880
	if (ls == NULL) 
		BIO_snprintf(lsbuf, sizeof(lsbuf), "lib(%lu)", l);
881
	if (fs == NULL)
B
Bodo Möller 已提交
882
		BIO_snprintf(fsbuf, sizeof(fsbuf), "func(%lu)", f);
883
	if (rs == NULL)
B
Bodo Möller 已提交
884 885 886 887 888 889 890 891 892 893 894 895 896 897 898 899 900 901 902 903 904 905 906 907 908 909 910 911 912 913 914 915 916 917 918 919 920 921
		BIO_snprintf(rsbuf, sizeof(rsbuf), "reason(%lu)", r);

	BIO_snprintf(buf, len,"error:%08lX:%s:%s:%s", e, ls?ls:lsbuf, 
		fs?fs:fsbuf, rs?rs:rsbuf);
	if (strlen(buf) == len-1)
		{
		/* output may be truncated; make sure we always have 5 
		 * colon-separated fields, i.e. 4 colons ... */
#define NUM_COLONS 4
		if (len > NUM_COLONS) /* ... if possible */
			{
			int i;
			char *s = buf;
			
			for (i = 0; i < NUM_COLONS; i++)
				{
				char *colon = strchr(s, ':');
				if (colon == NULL || colon > &buf[len-1] - NUM_COLONS + i)
					{
					/* set colon no. i at last possible position
					 * (buf[len-1] is the terminating 0)*/
					colon = &buf[len-1] - NUM_COLONS + i;
					*colon = ':';
					}
				s = colon + 1;
				}
			}
		}
	}

/* BAD for multi-threading: uses a local buffer if ret == NULL */
/* ERR_error_string_n should be used instead for ret != NULL
 * as ERR_error_string cannot know how large the buffer is */
char *ERR_error_string(unsigned long e, char *ret)
	{
	static char buf[256];

	if (ret == NULL) ret=buf;
922
	ERR_error_string_n(e, ret, 256);
923

924
	return ret;
925 926
	}

B
Ben Laurie 已提交
927
LHASH_OF(ERR_STRING_DATA) *ERR_get_string_table(void)
928
	{
929
	err_fns_check();
B
Bodo Möller 已提交
930
	return ERRFN(err_get)(0);
931 932
	}

B
Ben Laurie 已提交
933
LHASH_OF(ERR_STATE) *ERR_get_err_state_table(void)
934
	{
935
	err_fns_check();
B
Bodo Möller 已提交
936
	return ERRFN(thread_get)(0);
937 938
	}

B
Ben Laurie 已提交
939
void ERR_release_err_state_table(LHASH_OF(ERR_STATE) **hash)
940 941 942 943 944
	{
	err_fns_check();
	ERRFN(thread_release)(hash);
	}

U
Ulf Möller 已提交
945
const char *ERR_lib_error_string(unsigned long e)
946
	{
947
	ERR_STRING_DATA d,*p;
948 949
	unsigned long l;

950
	err_fns_check();
951
	l=ERR_GET_LIB(e);
952 953
	d.error=ERR_PACK(l,0,0);
	p=ERRFN(err_get_item)(&d);
954 955 956
	return((p == NULL)?NULL:p->string);
	}

U
Ulf Möller 已提交
957
const char *ERR_func_error_string(unsigned long e)
958
	{
959
	ERR_STRING_DATA d,*p;
960 961
	unsigned long l,f;

962
	err_fns_check();
963 964
	l=ERR_GET_LIB(e);
	f=ERR_GET_FUNC(e);
965 966
	d.error=ERR_PACK(l,f,0);
	p=ERRFN(err_get_item)(&d);
967 968 969
	return((p == NULL)?NULL:p->string);
	}

U
Ulf Möller 已提交
970
const char *ERR_reason_error_string(unsigned long e)
971 972 973 974
	{
	ERR_STRING_DATA d,*p=NULL;
	unsigned long l,r;

975
	err_fns_check();
976 977
	l=ERR_GET_LIB(e);
	r=ERR_GET_REASON(e);
978 979
	d.error=ERR_PACK(l,0,r);
	p=ERRFN(err_get_item)(&d);
980
	if (!p)
981
		{
982 983
		d.error=ERR_PACK(0,0,r);
		p=ERRFN(err_get_item)(&d);
984 985 986 987
		}
	return((p == NULL)?NULL:p->string);
	}

988
void ERR_remove_thread_state(const CRYPTO_THREADID *id)
989
	{
990
	ERR_STATE tmp;
991

992 993
	if (id)
		CRYPTO_THREADID_cpy(&tmp.tid, id);
994
	else
995 996
		CRYPTO_THREADID_current(&tmp.tid);
	err_fns_check();
997 998 999
	/* thread_del_item automatically destroys the LHASH if the number of
	 * items reaches zero. */
	ERRFN(thread_del_item)(&tmp);
1000 1001
	}

1002 1003 1004 1005 1006 1007 1008
#ifndef OPENSSL_NO_DEPRECATED
void ERR_remove_state(unsigned long pid)
	{
	ERR_remove_thread_state(NULL);
	}
#endif

U
Ulf Möller 已提交
1009
ERR_STATE *ERR_get_state(void)
1010 1011
	{
	static ERR_STATE fallback;
1012
	ERR_STATE *ret,tmp,*tmpp=NULL;
1013
	int i;
1014
	CRYPTO_THREADID tid;
1015

1016
	err_fns_check();
1017 1018
	CRYPTO_THREADID_current(&tid);
	CRYPTO_THREADID_cpy(&tmp.tid, &tid);
1019
	ret=ERRFN(thread_get_item)(&tmp);
1020 1021 1022 1023

	/* ret == the error state, if NULL, make a new one */
	if (ret == NULL)
		{
1024
		ret=(ERR_STATE *)OPENSSL_malloc(sizeof(ERR_STATE));
1025
		if (ret == NULL) return(&fallback);
1026
		CRYPTO_THREADID_cpy(&ret->tid, &tid);
1027 1028
		ret->top=0;
		ret->bottom=0;
1029 1030 1031 1032 1033
		for (i=0; i<ERR_NUM_ERRORS; i++)
			{
			ret->err_data[i]=NULL;
			ret->err_data_flags[i]=0;
			}
1034 1035
		tmpp = ERRFN(thread_set_item)(ret);
		/* To check if insertion failed, do a get. */
1036
		if (ERRFN(thread_get_item)(ret) != ret)
1037 1038 1039 1040
			{
			ERR_STATE_free(ret); /* could not insert it */
			return(&fallback);
			}
1041
		/* If a race occurred in this function and we came second, tmpp
1042
		 * is the first one that we just replaced. */
1043
		if (tmpp)
1044
			ERR_STATE_free(tmpp);
1045
		}
1046
	return ret;
1047 1048
	}

U
Ulf Möller 已提交
1049
int ERR_get_next_error_library(void)
1050
	{
1051 1052
	err_fns_check();
	return ERRFN(get_next_lib)();
1053 1054
	}

U
Ulf Möller 已提交
1055
void ERR_set_error_data(char *data, int flags)
1056 1057 1058 1059 1060 1061 1062 1063 1064 1065
	{
	ERR_STATE *es;
	int i;

	es=ERR_get_state();

	i=es->top;
	if (i == 0)
		i=ERR_NUM_ERRORS-1;

B
Bodo Möller 已提交
1066
	err_clear_data(es,i);
1067
	es->err_data[i]=data;
B
Bodo Möller 已提交
1068
	es->err_data_flags[i]=flags;
1069 1070
	}

U
Ulf Möller 已提交
1071
void ERR_add_error_data(int num, ...)
1072
	{
U
Ulf Möller 已提交
1073
	va_list args;
1074 1075 1076 1077 1078 1079 1080
	va_start(args, num);
	ERR_add_error_vdata(num, args);
	va_end(args);
	}

void ERR_add_error_vdata(int num, va_list args)
	{
1081 1082 1083
	int i,n,s;
	char *str,*p,*a;

B
Bodo Möller 已提交
1084
	s=80;
1085
	str=OPENSSL_malloc(s+1);
1086 1087 1088 1089 1090 1091
	if (str == NULL) return;
	str[0]='\0';

	n=0;
	for (i=0; i<num; i++)
		{
U
Ulf Möller 已提交
1092
		a=va_arg(args, char*);
1093 1094
		/* ignore NULLs, thanks to Bob Beck <beck@obtuse.com> */
		if (a != NULL)
1095
			{
1096 1097
			n+=strlen(a);
			if (n > s)
1098
				{
1099
				s=n+20;
1100
				p=OPENSSL_realloc(str,s+1);
1101 1102
				if (p == NULL)
					{
1103
					OPENSSL_free(str);
1104
					return;
1105 1106 1107
					}
				else
					str=p;
1108
				}
N
Nils Larsch 已提交
1109
			BUF_strlcat(str,a,(size_t)s+1);
1110 1111 1112 1113
			}
		}
	ERR_set_error_data(str,ERR_TXT_MALLOCED|ERR_TXT_STRING);
	}
1114 1115 1116 1117 1118 1119 1120 1121 1122 1123 1124 1125 1126 1127 1128 1129 1130 1131 1132 1133 1134 1135 1136

int ERR_set_mark(void)
	{
	ERR_STATE *es;

	es=ERR_get_state();

	if (es->bottom == es->top) return 0;
	es->err_flags[es->top]|=ERR_FLAG_MARK;
	return 1;
	}

int ERR_pop_to_mark(void)
	{
	ERR_STATE *es;

	es=ERR_get_state();

	while(es->bottom != es->top
		&& (es->err_flags[es->top] & ERR_FLAG_MARK) == 0)
		{
		err_clear(es,es->top);
		es->top-=1;
N
Nils Larsch 已提交
1137
		if (es->top == -1) es->top=ERR_NUM_ERRORS-1;
1138 1139 1140 1141 1142 1143
		}
		
	if (es->bottom == es->top) return 0;
	es->err_flags[es->top]&=~ERR_FLAG_MARK;
	return 1;
	}