err.c 29.3 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"},
156
{ERR_PACK(ERR_LIB_HMAC,0,0)		,"HMAC routines"},
D
Dr. Stephen Henson 已提交
157
{ERR_PACK(ERR_LIB_CMS,0,0)		,"CMS routines"},
158 159 160 161 162 163 164 165 166 167 168 169 170
{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"},
171
#ifdef OPENSSL_SYS_WINDOWS
172 173
	{ERR_PACK(0,SYS_F_WSASTARTUP,0),	"WSAstartup"},
#endif
174
	{ERR_PACK(0,SYS_F_OPENDIR,0),		"opendir"},
B
Ben Laurie 已提交
175
	{ERR_PACK(0,SYS_F_FREAD,0),		"fread"},
176 177 178 179 180 181 182 183 184 185 186 187 188
	{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 已提交
189
{ERR_R_DSA_LIB				,"DSA lib"},
190 191 192
{ERR_R_X509_LIB				,"X509 lib"},
{ERR_R_ASN1_LIB				,"ASN1 lib"},
{ERR_R_CONF_LIB				,"CONF lib"},
B
Bodo Möller 已提交
193 194
{ERR_R_CRYPTO_LIB			,"CRYPTO lib"},
{ERR_R_EC_LIB				,"EC lib"},
195 196 197
{ERR_R_SSL_LIB				,"SSL lib"},
{ERR_R_BIO_LIB				,"BIO lib"},
{ERR_R_PKCS7_LIB			,"PKCS7 lib"},
B
Bodo Möller 已提交
198
{ERR_R_X509V3_LIB			,"X509V3 lib"},
199
{ERR_R_PKCS12_LIB			,"PKCS12 lib"},
B
Bodo Möller 已提交
200 201 202 203
{ERR_R_RAND_LIB				,"RAND lib"},
{ERR_R_DSO_LIB				,"DSO lib"},
{ERR_R_ENGINE_LIB			,"ENGINE lib"},
{ERR_R_OCSP_LIB				,"OCSP lib"},
204
{ERR_R_TS_LIB				,"TS lib"},
B
Bodo Möller 已提交
205

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

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

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


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

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

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

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

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

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

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

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

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

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

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

	return ret;
365
	}
366

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

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

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

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

392 393
	return p;
	}
394

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

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

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

409 410
	return p;
	}
411

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

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

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

426 427
	return p;
	}
428

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

	return ret;
555 556 557
	}


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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

703 704
/********************************************************/

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

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

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

	es=ERR_get_state();

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


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

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

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

B
Bodo Möller 已提交
767

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

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

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

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

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

B
Bodo Möller 已提交
789

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

	es=ERR_get_state();

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

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

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

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

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

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

918
	return ret;
919 920
	}

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

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

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

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

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

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

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

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

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

982
void ERR_remove_thread_state(CRYPTO_THREADID *tid)
983
	{
984
	ERR_STATE tmp;
985

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

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

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

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

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

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

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

	es=ERR_get_state();

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

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

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

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

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

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

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