err.c 29.4 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

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

B
Ben Laurie 已提交
122 123 124
DECLARE_LHASH_OF(ERR_STRING_DATA);
DECLARE_LHASH_OF(ERR_STATE);

125 126
static void err_load_strings(int lib, ERR_STRING_DATA *str);

127
static void ERR_STATE_free(ERR_STATE *s);
128
#ifndef OPENSSL_NO_ERR
129 130 131 132 133 134 135 136 137 138 139
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 已提交
140
{ERR_PACK(ERR_LIB_DSA,0,0)		,"dsa routines"},
141
{ERR_PACK(ERR_LIB_X509,0,0)		,"x509 certificate routines"},
B
Bodo Möller 已提交
142
{ERR_PACK(ERR_LIB_ASN1,0,0)		,"asn1 encoding routines"},
U
Ulf Möller 已提交
143
{ERR_PACK(ERR_LIB_CONF,0,0)		,"configuration file routines"},
B
Bodo Möller 已提交
144 145
{ERR_PACK(ERR_LIB_CRYPTO,0,0)		,"common libcrypto routines"},
{ERR_PACK(ERR_LIB_EC,0,0)		,"elliptic curve routines"},
146 147 148
{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"},
149
{ERR_PACK(ERR_LIB_X509V3,0,0)		,"X509 V3 routines"},
150
{ERR_PACK(ERR_LIB_PKCS12,0,0)		,"PKCS12 routines"},
151
{ERR_PACK(ERR_LIB_RAND,0,0)		,"random number generator"},
152
{ERR_PACK(ERR_LIB_DSO,0,0)		,"DSO support routines"},
153
{ERR_PACK(ERR_LIB_TS,0,0)		,"time stamp routines"},
154
{ERR_PACK(ERR_LIB_ENGINE,0,0)		,"engine routines"},
155
{ERR_PACK(ERR_LIB_OCSP,0,0)		,"OCSP routines"},
D
Dr. Stephen Henson 已提交
156
{ERR_PACK(ERR_LIB_FIPS,0,0)		,"FIPS routines"},
D
Dr. Stephen Henson 已提交
157
{ERR_PACK(ERR_LIB_CMS,0,0)		,"CMS routines"},
D
Dr. Stephen Henson 已提交
158
{ERR_PACK(ERR_LIB_HMAC,0,0)		,"HMAC routines"},
159 160 161 162 163 164 165 166 167 168 169 170 171
{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"},
172
#ifdef OPENSSL_SYS_WINDOWS
173 174
	{ERR_PACK(0,SYS_F_WSASTARTUP,0),	"WSAstartup"},
#endif
175
	{ERR_PACK(0,SYS_F_OPENDIR,0),		"opendir"},
B
Ben Laurie 已提交
176
	{ERR_PACK(0,SYS_F_FREAD,0),		"fread"},
177 178 179 180 181 182 183 184 185 186 187 188 189
	{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 已提交
190
{ERR_R_DSA_LIB				,"DSA lib"},
191 192 193
{ERR_R_X509_LIB				,"X509 lib"},
{ERR_R_ASN1_LIB				,"ASN1 lib"},
{ERR_R_CONF_LIB				,"CONF lib"},
B
Bodo Möller 已提交
194 195
{ERR_R_CRYPTO_LIB			,"CRYPTO lib"},
{ERR_R_EC_LIB				,"EC lib"},
196 197 198
{ERR_R_SSL_LIB				,"SSL lib"},
{ERR_R_BIO_LIB				,"BIO lib"},
{ERR_R_PKCS7_LIB			,"PKCS7 lib"},
B
Bodo Möller 已提交
199
{ERR_R_X509V3_LIB			,"X509V3 lib"},
200
{ERR_R_PKCS12_LIB			,"PKCS12 lib"},
B
Bodo Möller 已提交
201 202 203 204
{ERR_R_RAND_LIB				,"RAND lib"},
{ERR_R_DSO_LIB				,"DSO lib"},
{ERR_R_ENGINE_LIB			,"ENGINE lib"},
{ERR_R_OCSP_LIB				,"OCSP lib"},
205
{ERR_R_TS_LIB				,"TS lib"},
B
Bodo Möller 已提交
206

207 208 209 210 211 212
{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 已提交
213 214 215 216 217 218

{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 已提交
219
{ERR_R_DISABLED				,"called a function that was disabled at compile-time"},
220

221 222
{0,NULL},
	};
223
#endif
224 225


226 227 228 229
/* Define the predeclared (but externally opaque) "ERR_FNS" type */
struct st_ERR_FNS
	{
	/* Works on the "error_hash" string table */
B
Ben Laurie 已提交
230
	LHASH_OF(ERR_STRING_DATA) *(*cb_err_get)(int create);
231 232 233
	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 *);
234
	ERR_STRING_DATA *(*cb_err_del_item)(ERR_STRING_DATA *);
235
	/* Works on the "thread_hash" error-state table */
B
Ben Laurie 已提交
236 237
	LHASH_OF(ERR_STATE) *(*cb_thread_get)(int create);
	void (*cb_thread_release)(LHASH_OF(ERR_STATE) **hash);
238 239 240 241 242 243 244 245
	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 已提交
246
static LHASH_OF(ERR_STRING_DATA) *int_err_get(int create);
247 248 249
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 *);
250
static ERR_STRING_DATA *int_err_del_item(ERR_STRING_DATA *);
B
Ben Laurie 已提交
251 252
static LHASH_OF(ERR_STATE) *int_thread_get(int create);
static void int_thread_release(LHASH_OF(ERR_STATE) **hash);
253 254 255 256 257 258 259 260 261 262 263
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,
264
	int_err_del_item,
265
	int_thread_get,
266
	int_thread_release,
267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283
	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 已提交
284 285
static LHASH_OF(ERR_STRING_DATA) *int_error_hash = NULL;
static LHASH_OF(ERR_STATE) *int_thread_hash = NULL;
286
static int int_thread_hash_references = 0;
287
static int int_err_library_number= ERR_LIB_USER;
288 289 290 291 292

/* Internal function that checks whether "err_fns" is set and if not, sets it to
 * the defaults. */
static void err_fns_check(void)
	{
293 294
	if (err_fns) return;
	
295
	CRYPTO_w_lock(CRYPTO_LOCK_ERR);
296
	if (!err_fns)
297 298 299 300 301 302 303 304 305 306 307 308 309 310
		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)
	{
311 312
	int ret = 0;

313 314 315
	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?! */
316
	if (!err_fns)
317 318
		{
		err_fns = fns;
319
		ret = 1;
320 321
		}
	CRYPTO_w_unlock(CRYPTO_LOCK_ERR);
322
	return ret;
323 324 325 326 327
	}

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

B
Bodo Möller 已提交
328
static unsigned long get_error_values(int inc,int top,const char **file,int *line,
329 330 331 332
				      const char **data,int *flags);

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

B
Ben Laurie 已提交
333
static unsigned long err_string_data_hash(const ERR_STRING_DATA *a)
334
	{
B
Ben Laurie 已提交
335 336 337 338 339 340
	unsigned long ret,l;

	l=a->error;
	ret=l^ERR_GET_LIB(l)^ERR_GET_FUNC(l);
	return(ret^ret%19*13);
	}
341
static IMPLEMENT_LHASH_HASH_FN(err_string_data, ERR_STRING_DATA)
B
Ben Laurie 已提交
342 343 344 345 346 347

static int err_string_data_cmp(const ERR_STRING_DATA *a,
			       const ERR_STRING_DATA *b)
	{
	return (int)(a->error - b->error);
	}
348
static IMPLEMENT_LHASH_COMP_FN(err_string_data, ERR_STRING_DATA)
B
Ben Laurie 已提交
349 350 351 352

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

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

	return ret;
366
	}
367

368 369 370
static void int_err_del(void)
	{
	CRYPTO_w_lock(CRYPTO_LOCK_ERR);
371
	if (int_error_hash)
372
		{
B
Ben Laurie 已提交
373
		lh_ERR_STRING_DATA_free(int_error_hash);
374 375 376 377
		int_error_hash = NULL;
		}
	CRYPTO_w_unlock(CRYPTO_LOCK_ERR);
	}
378

379 380 381
static ERR_STRING_DATA *int_err_get_item(const ERR_STRING_DATA *d)
	{
	ERR_STRING_DATA *p;
B
Ben Laurie 已提交
382
	LHASH_OF(ERR_STRING_DATA) *hash;
383

384
	err_fns_check();
B
Bodo Möller 已提交
385
	hash = ERRFN(err_get)(0);
386
	if (!hash)
387
		return NULL;
388

389
	CRYPTO_r_lock(CRYPTO_LOCK_ERR);
B
Ben Laurie 已提交
390
	p = lh_ERR_STRING_DATA_retrieve(hash, d);
391
	CRYPTO_r_unlock(CRYPTO_LOCK_ERR);
392

393 394
	return p;
	}
395

396 397 398
static ERR_STRING_DATA *int_err_set_item(ERR_STRING_DATA *d)
	{
	ERR_STRING_DATA *p;
B
Ben Laurie 已提交
399
	LHASH_OF(ERR_STRING_DATA) *hash;
400

401
	err_fns_check();
B
Bodo Möller 已提交
402
	hash = ERRFN(err_get)(1);
403
	if (!hash)
404
		return NULL;
405

406
	CRYPTO_w_lock(CRYPTO_LOCK_ERR);
B
Ben Laurie 已提交
407
	p = lh_ERR_STRING_DATA_insert(hash, d);
408
	CRYPTO_w_unlock(CRYPTO_LOCK_ERR);
409

410 411
	return p;
	}
412

413 414 415
static ERR_STRING_DATA *int_err_del_item(ERR_STRING_DATA *d)
	{
	ERR_STRING_DATA *p;
B
Ben Laurie 已提交
416
	LHASH_OF(ERR_STRING_DATA) *hash;
417

418
	err_fns_check();
B
Bodo Möller 已提交
419
	hash = ERRFN(err_get)(0);
420
	if (!hash)
421
		return NULL;
422

423
	CRYPTO_w_lock(CRYPTO_LOCK_ERR);
B
Ben Laurie 已提交
424
	p = lh_ERR_STRING_DATA_delete(hash, d);
425
	CRYPTO_w_unlock(CRYPTO_LOCK_ERR);
426

427 428
	return p;
	}
429

B
Ben Laurie 已提交
430 431
static unsigned long err_state_hash(const ERR_STATE *a)
	{
432
	return CRYPTO_THREADID_hash(&a->tid) * 13;
B
Ben Laurie 已提交
433
	}
434
static IMPLEMENT_LHASH_HASH_FN(err_state, ERR_STATE)
B
Ben Laurie 已提交
435 436 437

static int err_state_cmp(const ERR_STATE *a, const ERR_STATE *b)
	{
438
	return CRYPTO_THREADID_cmp(&a->tid, &b->tid);
B
Ben Laurie 已提交
439
	}
440
static IMPLEMENT_LHASH_COMP_FN(err_state, ERR_STATE)
B
Ben Laurie 已提交
441 442

static LHASH_OF(ERR_STATE) *int_thread_get(int create)
443
	{
B
Ben Laurie 已提交
444
	LHASH_OF(ERR_STATE) *ret = NULL;
445

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

B
Ben Laurie 已提交
462
static void int_thread_release(LHASH_OF(ERR_STATE) **hash)
463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484
	{
	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;
	}

485 486 487
static ERR_STATE *int_thread_get_item(const ERR_STATE *d)
	{
	ERR_STATE *p;
B
Ben Laurie 已提交
488
	LHASH_OF(ERR_STATE) *hash;
489

490
	err_fns_check();
B
Bodo Möller 已提交
491
	hash = ERRFN(thread_get)(0);
492
	if (!hash)
493
		return NULL;
494

495
	CRYPTO_r_lock(CRYPTO_LOCK_ERR);
B
Ben Laurie 已提交
496
	p = lh_ERR_STATE_retrieve(hash, d);
497
	CRYPTO_r_unlock(CRYPTO_LOCK_ERR);
498

499
	ERRFN(thread_release)(&hash);
500 501
	return p;
	}
502

503 504 505
static ERR_STATE *int_thread_set_item(ERR_STATE *d)
	{
	ERR_STATE *p;
B
Ben Laurie 已提交
506
	LHASH_OF(ERR_STATE) *hash;
507

508
	err_fns_check();
B
Bodo Möller 已提交
509
	hash = ERRFN(thread_get)(1);
510
	if (!hash)
511
		return NULL;
512

513
	CRYPTO_w_lock(CRYPTO_LOCK_ERR);
B
Ben Laurie 已提交
514
	p = lh_ERR_STATE_insert(hash, d);
515
	CRYPTO_w_unlock(CRYPTO_LOCK_ERR);
516

517
	ERRFN(thread_release)(&hash);
518 519
	return p;
	}
520

521 522 523
static void int_thread_del_item(const ERR_STATE *d)
	{
	ERR_STATE *p;
B
Ben Laurie 已提交
524
	LHASH_OF(ERR_STATE) *hash;
525

526
	err_fns_check();
B
Bodo Möller 已提交
527
	hash = ERRFN(thread_get)(0);
528
	if (!hash)
529
		return;
530

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

542
	ERRFN(thread_release)(&hash);
543
	if (p)
544 545
		ERR_STATE_free(p);
	}
546

547 548
static int int_err_get_next_lib(void)
	{
549 550
	int ret;

551
	CRYPTO_w_lock(CRYPTO_LOCK_ERR);
552
	ret = int_err_library_number++;
553
	CRYPTO_w_unlock(CRYPTO_LOCK_ERR);
554 555

	return ret;
556 557 558
	}


559
#ifndef OPENSSL_NO_ERR
560 561 562 563 564 565 566 567 568 569 570 571 572
#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. */

573
static void build_SYS_str_reasons(void)
574
	{
575
	/* OPENSSL_malloc cannot be used here, use static storage instead */
576 577
	static char strerror_tab[NUM_SYS_STR_REASONS][LEN_SYS_STR_REASON];
	int i;
578 579
	static int init = 1;

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

	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. */

618 619
	init = 0;
	
620
	CRYPTO_w_unlock(CRYPTO_LOCK_ERR);
621
	}
622 623
#endif

624
#define err_clear_data(p,i) \
625
	do { \
626 627 628
	if (((p)->err_data[i] != NULL) && \
		(p)->err_data_flags[i] & ERR_TXT_MALLOCED) \
		{  \
629
		OPENSSL_free((p)->err_data[i]); \
630 631
		(p)->err_data[i]=NULL; \
		} \
632 633 634 635 636
	(p)->err_data_flags[i]=0; \
	} while(0)

#define err_clear(p,i) \
	do { \
637 638
	(p)->err_flags[i]=0; \
	(p)->err_buffer[i]=0; \
639
	err_clear_data(p,i); \
640 641
	(p)->err_file[i]=NULL; \
	(p)->err_line[i]= -1; \
642
	} while(0)
643

U
Ulf Möller 已提交
644
static void ERR_STATE_free(ERR_STATE *s)
645 646 647
	{
	int i;

648
	if (s == NULL)
B
Ben Laurie 已提交
649 650
	    return;

651 652 653 654
	for (i=0; i<ERR_NUM_ERRORS; i++)
		{
		err_clear_data(s,i);
		}
655
	OPENSSL_free(s);
656 657
	}

U
Ulf Möller 已提交
658
void ERR_load_ERR_strings(void)
659
	{
660
	err_fns_check();
661
#ifndef OPENSSL_NO_ERR
662 663 664 665 666
	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);
667 668 669
#endif
	}

670
static void err_load_strings(int lib, ERR_STRING_DATA *str)
671 672 673
	{
	while (str->error)
		{
674 675
		if (lib)
			str->error|=ERR_PACK(lib,0,0);
676
		ERRFN(err_set_item)(str);
677 678 679 680
		str++;
		}
	}

681 682
void ERR_load_strings(int lib, ERR_STRING_DATA *str)
	{
B
typo  
Bodo Möller 已提交
683
	ERR_load_ERR_strings();
684 685 686
	err_load_strings(lib, str);
	}

687 688
void ERR_unload_strings(int lib, ERR_STRING_DATA *str)
	{
689
	while (str->error)
690
		{
691 692
		if (lib)
			str->error|=ERR_PACK(lib,0,0);
693 694 695 696 697
		ERRFN(err_del_item)(str);
		str++;
		}
	}

U
Ulf Möller 已提交
698
void ERR_free_strings(void)
699
	{
700 701
	err_fns_check();
	ERRFN(err_del)();
702 703
	}

704 705
/********************************************************/

U
Ulf Möller 已提交
706 707
void ERR_put_error(int lib, int func, int reason, const char *file,
	     int line)
708 709 710
	{
	ERR_STATE *es;

711 712 713 714 715 716 717 718 719 720 721 722 723 724 725 726 727 728 729
#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
730 731 732 733 734
	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;
735
	es->err_flags[es->top]=0;
736 737 738
	es->err_buffer[es->top]=ERR_PACK(lib,func,reason);
	es->err_file[es->top]=file;
	es->err_line[es->top]=line;
739
	err_clear_data(es,es->top);
740 741
	}

U
Ulf Möller 已提交
742
void ERR_clear_error(void)
743
	{
B
Bodo Möller 已提交
744
	int i;
745 746 747 748 749 750
	ERR_STATE *es;

	es=ERR_get_state();

	for (i=0; i<ERR_NUM_ERRORS; i++)
		{
751
		err_clear(es,i);
752 753 754 755 756
		}
	es->top=es->bottom=0;
	}


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

U
Ulf Möller 已提交
760 761
unsigned long ERR_get_error_line(const char **file,
	     int *line)
B
Bodo Möller 已提交
762
	{ return(get_error_values(1,0,file,line,NULL,NULL)); }
763

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

B
Bodo Möller 已提交
768

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

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

U
Ulf Möller 已提交
775 776
unsigned long ERR_peek_error_line_data(const char **file, int *line,
	     const char **data, int *flags)
B
Bodo Möller 已提交
777 778
	{ return(get_error_values(0,0,file,line,data,flags)); }

B
Bodo Möller 已提交
779 780 781 782 783 784 785

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 已提交
786 787 788
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 已提交
789

B
Bodo Möller 已提交
790

B
Bodo Möller 已提交
791
static unsigned long get_error_values(int inc, int top, const char **file, int *line,
U
Ulf Möller 已提交
792
	     const char **data, int *flags)
793 794
	{	
	int i=0;
795
	ERR_STATE *es;
796
	unsigned long ret;
797 798 799

	es=ERR_get_state();

B
Bodo Möller 已提交
800 801 802 803 804 805 806 807 808 809
	if (inc && top)
		{
		if (file) *file = "";
		if (line) *line = 0;
		if (data) *data = "";
		if (flags) *flags = 0;
			
		return ERR_R_INTERNAL_ERROR;
		}

810
	if (es->bottom == es->top) return 0;
B
Bodo Möller 已提交
811
	if (top)
812
		i=es->top;			 /* last error */
B
Bodo Möller 已提交
813 814
	else
		i=(es->bottom+1)%ERR_NUM_ERRORS; /* first error */
815 816 817

	ret=es->err_buffer[i];
	if (inc)
818
		{
819 820
		es->bottom=i;
		es->err_buffer[i]=0;
821
		}
822 823

	if ((file != NULL) && (line != NULL))
824
		{
825 826 827 828 829 830 831 832 833 834
		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];
			}
835 836
		}

B
Bodo Möller 已提交
837 838
	if (data == NULL)
		{
B
Bodo Möller 已提交
839
		if (inc)
B
Bodo Möller 已提交
840
			{
B
Bodo Möller 已提交
841
			err_clear_data(es, i);
B
Bodo Möller 已提交
842 843 844
			}
		}
	else
845 846 847 848 849 850 851 852 853 854 855 856
		{
		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];
			}
		}
857
	return ret;
858 859
	}

B
Bodo Möller 已提交
860
void ERR_error_string_n(unsigned long e, char *buf, size_t len)
861
	{
B
Bodo Möller 已提交
862
	char lsbuf[64], fsbuf[64], rsbuf[64];
B
Ben Laurie 已提交
863
	const char *ls,*fs,*rs;
864 865 866 867 868 869 870 871 872 873
	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 已提交
874 875
	if (ls == NULL) 
		BIO_snprintf(lsbuf, sizeof(lsbuf), "lib(%lu)", l);
876
	if (fs == NULL)
B
Bodo Möller 已提交
877
		BIO_snprintf(fsbuf, sizeof(fsbuf), "func(%lu)", f);
878
	if (rs == NULL)
B
Bodo Möller 已提交
879 880 881 882 883 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
		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;
917
	ERR_error_string_n(e, ret, 256);
918

919
	return ret;
920 921
	}

B
Ben Laurie 已提交
922
LHASH_OF(ERR_STRING_DATA) *ERR_get_string_table(void)
923
	{
924
	err_fns_check();
B
Bodo Möller 已提交
925
	return ERRFN(err_get)(0);
926 927
	}

B
Ben Laurie 已提交
928
LHASH_OF(ERR_STATE) *ERR_get_err_state_table(void)
929
	{
930
	err_fns_check();
B
Bodo Möller 已提交
931
	return ERRFN(thread_get)(0);
932 933
	}

B
Ben Laurie 已提交
934
void ERR_release_err_state_table(LHASH_OF(ERR_STATE) **hash)
935 936 937 938 939
	{
	err_fns_check();
	ERRFN(thread_release)(hash);
	}

U
Ulf Möller 已提交
940
const char *ERR_lib_error_string(unsigned long e)
941
	{
942
	ERR_STRING_DATA d,*p;
943 944
	unsigned long l;

945
	err_fns_check();
946
	l=ERR_GET_LIB(e);
947 948
	d.error=ERR_PACK(l,0,0);
	p=ERRFN(err_get_item)(&d);
949 950 951
	return((p == NULL)?NULL:p->string);
	}

U
Ulf Möller 已提交
952
const char *ERR_func_error_string(unsigned long e)
953
	{
954
	ERR_STRING_DATA d,*p;
955 956
	unsigned long l,f;

957
	err_fns_check();
958 959
	l=ERR_GET_LIB(e);
	f=ERR_GET_FUNC(e);
960 961
	d.error=ERR_PACK(l,f,0);
	p=ERRFN(err_get_item)(&d);
962 963 964
	return((p == NULL)?NULL:p->string);
	}

U
Ulf Möller 已提交
965
const char *ERR_reason_error_string(unsigned long e)
966 967 968 969
	{
	ERR_STRING_DATA d,*p=NULL;
	unsigned long l,r;

970
	err_fns_check();
971 972
	l=ERR_GET_LIB(e);
	r=ERR_GET_REASON(e);
973 974
	d.error=ERR_PACK(l,0,r);
	p=ERRFN(err_get_item)(&d);
975
	if (!p)
976
		{
977 978
		d.error=ERR_PACK(0,0,r);
		p=ERRFN(err_get_item)(&d);
979 980 981 982
		}
	return((p == NULL)?NULL:p->string);
	}

983
void ERR_remove_thread_state(const CRYPTO_THREADID *id)
984
	{
985
	ERR_STATE tmp;
986

987 988
	if (id)
		CRYPTO_THREADID_cpy(&tmp.tid, id);
989
	else
990 991
		CRYPTO_THREADID_current(&tmp.tid);
	err_fns_check();
992 993 994
	/* thread_del_item automatically destroys the LHASH if the number of
	 * items reaches zero. */
	ERRFN(thread_del_item)(&tmp);
995 996
	}

997 998 999 1000 1001 1002 1003
#ifndef OPENSSL_NO_DEPRECATED
void ERR_remove_state(unsigned long pid)
	{
	ERR_remove_thread_state(NULL);
	}
#endif

U
Ulf Möller 已提交
1004
ERR_STATE *ERR_get_state(void)
1005 1006
	{
	static ERR_STATE fallback;
1007
	ERR_STATE *ret,tmp,*tmpp=NULL;
1008
	int i;
1009
	CRYPTO_THREADID tid;
1010

1011
	err_fns_check();
1012 1013
	CRYPTO_THREADID_current(&tid);
	CRYPTO_THREADID_cpy(&tmp.tid, &tid);
1014
	ret=ERRFN(thread_get_item)(&tmp);
1015 1016 1017 1018

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

U
Ulf Möller 已提交
1044
int ERR_get_next_error_library(void)
1045
	{
1046 1047
	err_fns_check();
	return ERRFN(get_next_lib)();
1048 1049
	}

U
Ulf Möller 已提交
1050
void ERR_set_error_data(char *data, int flags)
1051 1052 1053 1054 1055 1056 1057 1058 1059 1060
	{
	ERR_STATE *es;
	int i;

	es=ERR_get_state();

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

B
Bodo Möller 已提交
1061
	err_clear_data(es,i);
1062
	es->err_data[i]=data;
B
Bodo Möller 已提交
1063
	es->err_data_flags[i]=flags;
1064 1065
	}

U
Ulf Möller 已提交
1066
void ERR_add_error_data(int num, ...)
1067
	{
U
Ulf Möller 已提交
1068
	va_list args;
1069 1070 1071
	int i,n,s;
	char *str,*p,*a;

B
Bodo Möller 已提交
1072
	s=80;
1073
	str=OPENSSL_malloc(s+1);
1074 1075 1076
	if (str == NULL) return;
	str[0]='\0';

U
Ulf Möller 已提交
1077
	va_start(args, num);
1078 1079 1080
	n=0;
	for (i=0; i<num; i++)
		{
U
Ulf Möller 已提交
1081
		a=va_arg(args, char*);
1082 1083
		/* ignore NULLs, thanks to Bob Beck <beck@obtuse.com> */
		if (a != NULL)
1084
			{
1085 1086
			n+=strlen(a);
			if (n > s)
1087
				{
1088
				s=n+20;
1089
				p=OPENSSL_realloc(str,s+1);
1090 1091
				if (p == NULL)
					{
1092
					OPENSSL_free(str);
1093
					goto err;
1094 1095 1096
					}
				else
					str=p;
1097
				}
N
Nils Larsch 已提交
1098
			BUF_strlcat(str,a,(size_t)s+1);
1099 1100 1101 1102
			}
		}
	ERR_set_error_data(str,ERR_TXT_MALLOCED|ERR_TXT_STRING);

1103
err:
U
Ulf Möller 已提交
1104
	va_end(args);
1105
	}
1106 1107 1108 1109 1110 1111 1112 1113 1114 1115 1116 1117 1118 1119 1120 1121 1122 1123 1124 1125 1126 1127 1128

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 已提交
1129
		if (es->top == -1) es->top=ERR_NUM_ERRORS-1;
1130 1131 1132 1133 1134 1135
		}
		
	if (es->bottom == es->top) return 0;
	es->err_flags[es->top]&=~ERR_FLAG_MARK;
	return 1;
	}