Line data Source code
1 : /* crypto/err/err.c */
2 : /* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
3 : * All rights reserved.
4 : *
5 : * This package is an SSL implementation written
6 : * by Eric Young (eay@cryptsoft.com).
7 : * The implementation was written so as to conform with Netscapes SSL.
8 : *
9 : * This library is free for commercial and non-commercial use as long as
10 : * the following conditions are aheared to. The following conditions
11 : * apply to all code found in this distribution, be it the RC4, RSA,
12 : * lhash, DES, etc., code; not just the SSL code. The SSL documentation
13 : * included with this distribution is covered by the same copyright terms
14 : * except that the holder is Tim Hudson (tjh@cryptsoft.com).
15 : *
16 : * Copyright remains Eric Young's, and as such any Copyright notices in
17 : * the code are not to be removed.
18 : * If this package is used in a product, Eric Young should be given attribution
19 : * as the author of the parts of the library used.
20 : * This can be in the form of a textual message at program startup or
21 : * in documentation (online or textual) provided with the package.
22 : *
23 : * Redistribution and use in source and binary forms, with or without
24 : * modification, are permitted provided that the following conditions
25 : * are met:
26 : * 1. Redistributions of source code must retain the copyright
27 : * notice, this list of conditions and the following disclaimer.
28 : * 2. Redistributions in binary form must reproduce the above copyright
29 : * notice, this list of conditions and the following disclaimer in the
30 : * documentation and/or other materials provided with the distribution.
31 : * 3. All advertising materials mentioning features or use of this software
32 : * must display the following acknowledgement:
33 : * "This product includes cryptographic software written by
34 : * Eric Young (eay@cryptsoft.com)"
35 : * The word 'cryptographic' can be left out if the rouines from the library
36 : * being used are not cryptographic related :-).
37 : * 4. If you include any Windows specific code (or a derivative thereof) from
38 : * the apps directory (application code) you must include an acknowledgement:
39 : * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
40 : *
41 : * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
42 : * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
43 : * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
44 : * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
45 : * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
46 : * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
47 : * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
48 : * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
49 : * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
50 : * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
51 : * SUCH DAMAGE.
52 : *
53 : * The licence and distribution terms for any publically available version or
54 : * derivative of this code cannot be changed. i.e. this code cannot simply be
55 : * copied and put under another distribution licence
56 : * [including the GNU Public Licence.]
57 : */
58 : /* ====================================================================
59 : * Copyright (c) 1998-2006 The OpenSSL Project. All rights reserved.
60 : *
61 : * Redistribution and use in source and binary forms, with or without
62 : * modification, are permitted provided that the following conditions
63 : * are met:
64 : *
65 : * 1. Redistributions of source code must retain the above copyright
66 : * notice, this list of conditions and the following disclaimer.
67 : *
68 : * 2. Redistributions in binary form must reproduce the above copyright
69 : * notice, this list of conditions and the following disclaimer in
70 : * the documentation and/or other materials provided with the
71 : * distribution.
72 : *
73 : * 3. All advertising materials mentioning features or use of this
74 : * software must display the following acknowledgment:
75 : * "This product includes software developed by the OpenSSL Project
76 : * for use in the OpenSSL Toolkit. (http://www.openssl.org/)"
77 : *
78 : * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
79 : * endorse or promote products derived from this software without
80 : * prior written permission. For written permission, please contact
81 : * openssl-core@openssl.org.
82 : *
83 : * 5. Products derived from this software may not be called "OpenSSL"
84 : * nor may "OpenSSL" appear in their names without prior written
85 : * permission of the OpenSSL Project.
86 : *
87 : * 6. Redistributions of any form whatsoever must retain the following
88 : * acknowledgment:
89 : * "This product includes software developed by the OpenSSL Project
90 : * for use in the OpenSSL Toolkit (http://www.openssl.org/)"
91 : *
92 : * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
93 : * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
94 : * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
95 : * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR
96 : * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
97 : * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
98 : * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
99 : * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
100 : * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
101 : * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
102 : * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
103 : * OF THE POSSIBILITY OF SUCH DAMAGE.
104 : * ====================================================================
105 : *
106 : * This product includes cryptographic software written by Eric Young
107 : * (eay@cryptsoft.com). This product includes software written by Tim
108 : * Hudson (tjh@cryptsoft.com).
109 : *
110 : */
111 :
112 : #include <stdio.h>
113 : #include <stdarg.h>
114 : #include <string.h>
115 : #include "cryptlib.h"
116 : #include <openssl/lhash.h>
117 : #include <openssl/crypto.h>
118 : #include <openssl/buffer.h>
119 : #include <openssl/bio.h>
120 : #include <openssl/err.h>
121 :
122 : DECLARE_LHASH_OF(ERR_STRING_DATA);
123 : DECLARE_LHASH_OF(ERR_STATE);
124 :
125 : static void err_load_strings(int lib, ERR_STRING_DATA *str);
126 :
127 : static void ERR_STATE_free(ERR_STATE *s);
128 : #ifndef OPENSSL_NO_ERR
129 : static ERR_STRING_DATA ERR_str_libraries[] = {
130 : {ERR_PACK(ERR_LIB_NONE, 0, 0), "unknown library"},
131 : {ERR_PACK(ERR_LIB_SYS, 0, 0), "system library"},
132 : {ERR_PACK(ERR_LIB_BN, 0, 0), "bignum routines"},
133 : {ERR_PACK(ERR_LIB_RSA, 0, 0), "rsa routines"},
134 : {ERR_PACK(ERR_LIB_DH, 0, 0), "Diffie-Hellman routines"},
135 : {ERR_PACK(ERR_LIB_EVP, 0, 0), "digital envelope routines"},
136 : {ERR_PACK(ERR_LIB_BUF, 0, 0), "memory buffer routines"},
137 : {ERR_PACK(ERR_LIB_OBJ, 0, 0), "object identifier routines"},
138 : {ERR_PACK(ERR_LIB_PEM, 0, 0), "PEM routines"},
139 : {ERR_PACK(ERR_LIB_DSA, 0, 0), "dsa routines"},
140 : {ERR_PACK(ERR_LIB_X509, 0, 0), "x509 certificate routines"},
141 : {ERR_PACK(ERR_LIB_ASN1, 0, 0), "asn1 encoding routines"},
142 : {ERR_PACK(ERR_LIB_CONF, 0, 0), "configuration file routines"},
143 : {ERR_PACK(ERR_LIB_CRYPTO, 0, 0), "common libcrypto routines"},
144 : {ERR_PACK(ERR_LIB_EC, 0, 0), "elliptic curve routines"},
145 : {ERR_PACK(ERR_LIB_SSL, 0, 0), "SSL routines"},
146 : {ERR_PACK(ERR_LIB_BIO, 0, 0), "BIO routines"},
147 : {ERR_PACK(ERR_LIB_PKCS7, 0, 0), "PKCS7 routines"},
148 : {ERR_PACK(ERR_LIB_X509V3, 0, 0), "X509 V3 routines"},
149 : {ERR_PACK(ERR_LIB_PKCS12, 0, 0), "PKCS12 routines"},
150 : {ERR_PACK(ERR_LIB_RAND, 0, 0), "random number generator"},
151 : {ERR_PACK(ERR_LIB_DSO, 0, 0), "DSO support routines"},
152 : {ERR_PACK(ERR_LIB_TS, 0, 0), "time stamp routines"},
153 : {ERR_PACK(ERR_LIB_ENGINE, 0, 0), "engine routines"},
154 : {ERR_PACK(ERR_LIB_OCSP, 0, 0), "OCSP routines"},
155 : {ERR_PACK(ERR_LIB_FIPS, 0, 0), "FIPS routines"},
156 : {ERR_PACK(ERR_LIB_CMS, 0, 0), "CMS routines"},
157 : {ERR_PACK(ERR_LIB_HMAC, 0, 0), "HMAC routines"},
158 : {0, NULL},
159 : };
160 :
161 : static ERR_STRING_DATA ERR_str_functs[] = {
162 : {ERR_PACK(0, SYS_F_FOPEN, 0), "fopen"},
163 : {ERR_PACK(0, SYS_F_CONNECT, 0), "connect"},
164 : {ERR_PACK(0, SYS_F_GETSERVBYNAME, 0), "getservbyname"},
165 : {ERR_PACK(0, SYS_F_SOCKET, 0), "socket"},
166 : {ERR_PACK(0, SYS_F_IOCTLSOCKET, 0), "ioctlsocket"},
167 : {ERR_PACK(0, SYS_F_BIND, 0), "bind"},
168 : {ERR_PACK(0, SYS_F_LISTEN, 0), "listen"},
169 : {ERR_PACK(0, SYS_F_ACCEPT, 0), "accept"},
170 : # ifdef OPENSSL_SYS_WINDOWS
171 : {ERR_PACK(0, SYS_F_WSASTARTUP, 0), "WSAstartup"},
172 : # endif
173 : {ERR_PACK(0, SYS_F_OPENDIR, 0), "opendir"},
174 : {ERR_PACK(0, SYS_F_FREAD, 0), "fread"},
175 : {0, NULL},
176 : };
177 :
178 : static ERR_STRING_DATA ERR_str_reasons[] = {
179 : {ERR_R_SYS_LIB, "system lib"},
180 : {ERR_R_BN_LIB, "BN lib"},
181 : {ERR_R_RSA_LIB, "RSA lib"},
182 : {ERR_R_DH_LIB, "DH lib"},
183 : {ERR_R_EVP_LIB, "EVP lib"},
184 : {ERR_R_BUF_LIB, "BUF lib"},
185 : {ERR_R_OBJ_LIB, "OBJ lib"},
186 : {ERR_R_PEM_LIB, "PEM lib"},
187 : {ERR_R_DSA_LIB, "DSA lib"},
188 : {ERR_R_X509_LIB, "X509 lib"},
189 : {ERR_R_ASN1_LIB, "ASN1 lib"},
190 : {ERR_R_CONF_LIB, "CONF lib"},
191 : {ERR_R_CRYPTO_LIB, "CRYPTO lib"},
192 : {ERR_R_EC_LIB, "EC lib"},
193 : {ERR_R_SSL_LIB, "SSL lib"},
194 : {ERR_R_BIO_LIB, "BIO lib"},
195 : {ERR_R_PKCS7_LIB, "PKCS7 lib"},
196 : {ERR_R_X509V3_LIB, "X509V3 lib"},
197 : {ERR_R_PKCS12_LIB, "PKCS12 lib"},
198 : {ERR_R_RAND_LIB, "RAND lib"},
199 : {ERR_R_DSO_LIB, "DSO lib"},
200 : {ERR_R_ENGINE_LIB, "ENGINE lib"},
201 : {ERR_R_OCSP_LIB, "OCSP lib"},
202 : {ERR_R_TS_LIB, "TS lib"},
203 :
204 : {ERR_R_NESTED_ASN1_ERROR, "nested asn1 error"},
205 : {ERR_R_BAD_ASN1_OBJECT_HEADER, "bad asn1 object header"},
206 : {ERR_R_BAD_GET_ASN1_OBJECT_CALL, "bad get asn1 object call"},
207 : {ERR_R_EXPECTING_AN_ASN1_SEQUENCE, "expecting an asn1 sequence"},
208 : {ERR_R_ASN1_LENGTH_MISMATCH, "asn1 length mismatch"},
209 : {ERR_R_MISSING_ASN1_EOS, "missing asn1 eos"},
210 :
211 : {ERR_R_FATAL, "fatal"},
212 : {ERR_R_MALLOC_FAILURE, "malloc failure"},
213 : {ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED,
214 : "called a function you should not call"},
215 : {ERR_R_PASSED_NULL_PARAMETER, "passed a null parameter"},
216 : {ERR_R_INTERNAL_ERROR, "internal error"},
217 : {ERR_R_DISABLED, "called a function that was disabled at compile-time"},
218 :
219 : {0, NULL},
220 : };
221 : #endif
222 :
223 : /* Define the predeclared (but externally opaque) "ERR_FNS" type */
224 : struct st_ERR_FNS {
225 : /* Works on the "error_hash" string table */
226 : LHASH_OF(ERR_STRING_DATA) *(*cb_err_get) (int create);
227 : void (*cb_err_del) (void);
228 : ERR_STRING_DATA *(*cb_err_get_item) (const ERR_STRING_DATA *);
229 : ERR_STRING_DATA *(*cb_err_set_item) (ERR_STRING_DATA *);
230 : ERR_STRING_DATA *(*cb_err_del_item) (ERR_STRING_DATA *);
231 : /* Works on the "thread_hash" error-state table */
232 : LHASH_OF(ERR_STATE) *(*cb_thread_get) (int create);
233 : void (*cb_thread_release) (LHASH_OF(ERR_STATE) **hash);
234 : ERR_STATE *(*cb_thread_get_item) (const ERR_STATE *);
235 : ERR_STATE *(*cb_thread_set_item) (ERR_STATE *);
236 : void (*cb_thread_del_item) (const ERR_STATE *);
237 : /* Returns the next available error "library" numbers */
238 : int (*cb_get_next_lib) (void);
239 : };
240 :
241 : /* Predeclarations of the "err_defaults" functions */
242 : static LHASH_OF(ERR_STRING_DATA) *int_err_get(int create);
243 : static void int_err_del(void);
244 : static ERR_STRING_DATA *int_err_get_item(const ERR_STRING_DATA *);
245 : static ERR_STRING_DATA *int_err_set_item(ERR_STRING_DATA *);
246 : static ERR_STRING_DATA *int_err_del_item(ERR_STRING_DATA *);
247 : static LHASH_OF(ERR_STATE) *int_thread_get(int create);
248 : static void int_thread_release(LHASH_OF(ERR_STATE) **hash);
249 : static ERR_STATE *int_thread_get_item(const ERR_STATE *);
250 : static ERR_STATE *int_thread_set_item(ERR_STATE *);
251 : static void int_thread_del_item(const ERR_STATE *);
252 : static int int_err_get_next_lib(void);
253 : /* The static ERR_FNS table using these defaults functions */
254 : static const ERR_FNS err_defaults = {
255 : int_err_get,
256 : int_err_del,
257 : int_err_get_item,
258 : int_err_set_item,
259 : int_err_del_item,
260 : int_thread_get,
261 : int_thread_release,
262 : int_thread_get_item,
263 : int_thread_set_item,
264 : int_thread_del_item,
265 : int_err_get_next_lib
266 : };
267 :
268 : /* The replacable table of ERR_FNS functions we use at run-time */
269 : static const ERR_FNS *err_fns = NULL;
270 :
271 : /* Eg. rather than using "err_get()", use "ERRFN(err_get)()". */
272 : #define ERRFN(a) err_fns->cb_##a
273 :
274 : /*
275 : * The internal state used by "err_defaults" - as such, the setting, reading,
276 : * creating, and deleting of this data should only be permitted via the
277 : * "err_defaults" functions. This way, a linked module can completely defer
278 : * all ERR state operation (together with requisite locking) to the
279 : * implementations and state in the loading application.
280 : */
281 : static LHASH_OF(ERR_STRING_DATA) *int_error_hash = NULL;
282 : static LHASH_OF(ERR_STATE) *int_thread_hash = NULL;
283 : static int int_thread_hash_references = 0;
284 : static int int_err_library_number = ERR_LIB_USER;
285 :
286 : /*
287 : * Internal function that checks whether "err_fns" is set and if not, sets it
288 : * to the defaults.
289 : */
290 1741634 : static void err_fns_check(void)
291 : {
292 1741634 : if (err_fns)
293 1741634 : return;
294 :
295 122 : CRYPTO_w_lock(CRYPTO_LOCK_ERR);
296 122 : if (!err_fns)
297 122 : err_fns = &err_defaults;
298 122 : CRYPTO_w_unlock(CRYPTO_LOCK_ERR);
299 : }
300 :
301 : /* API functions to get or set the underlying ERR functions. */
302 :
303 0 : const ERR_FNS *ERR_get_implementation(void)
304 : {
305 0 : err_fns_check();
306 0 : return err_fns;
307 : }
308 :
309 0 : int ERR_set_implementation(const ERR_FNS *fns)
310 : {
311 : int ret = 0;
312 :
313 0 : CRYPTO_w_lock(CRYPTO_LOCK_ERR);
314 : /*
315 : * It's too late if 'err_fns' is non-NULL. BTW: not much point setting an
316 : * error is there?!
317 : */
318 0 : if (!err_fns) {
319 0 : err_fns = fns;
320 : ret = 1;
321 : }
322 0 : CRYPTO_w_unlock(CRYPTO_LOCK_ERR);
323 0 : return ret;
324 : }
325 :
326 : /*
327 : * These are the callbacks provided to "lh_new()" when creating the LHASH
328 : * tables internal to the "err_defaults" implementation.
329 : */
330 :
331 : static unsigned long get_error_values(int inc, int top, const char **file,
332 : int *line, const char **data,
333 : int *flags);
334 :
335 : /* The internal functions used in the "err_defaults" implementation */
336 :
337 : static unsigned long err_string_data_hash(const ERR_STRING_DATA *a)
338 : {
339 : unsigned long ret, l;
340 :
341 : l = a->error;
342 1687708 : ret = l ^ ERR_GET_LIB(l) ^ ERR_GET_FUNC(l);
343 1687708 : return (ret ^ ret % 19 * 13);
344 : }
345 :
346 3375416 : static IMPLEMENT_LHASH_HASH_FN(err_string_data, ERR_STRING_DATA)
347 :
348 : static int err_string_data_cmp(const ERR_STRING_DATA *a,
349 : const ERR_STRING_DATA *b)
350 : {
351 1455267 : return (int)(a->error - b->error);
352 : }
353 :
354 2910534 : static IMPLEMENT_LHASH_COMP_FN(err_string_data, ERR_STRING_DATA)
355 :
356 1687708 : static LHASH_OF(ERR_STRING_DATA) *int_err_get(int create)
357 : {
358 : LHASH_OF(ERR_STRING_DATA) *ret = NULL;
359 :
360 1687708 : CRYPTO_w_lock(CRYPTO_LOCK_ERR);
361 1687708 : if (!int_error_hash && create) {
362 121 : CRYPTO_push_info("int_err_get (err.c)");
363 121 : int_error_hash = lh_ERR_STRING_DATA_new();
364 121 : CRYPTO_pop_info();
365 : }
366 1687708 : if (int_error_hash)
367 : ret = int_error_hash;
368 1687708 : CRYPTO_w_unlock(CRYPTO_LOCK_ERR);
369 :
370 1687708 : return ret;
371 : }
372 :
373 0 : static void int_err_del(void)
374 : {
375 0 : CRYPTO_w_lock(CRYPTO_LOCK_ERR);
376 0 : if (int_error_hash) {
377 0 : lh_ERR_STRING_DATA_free(int_error_hash);
378 0 : int_error_hash = NULL;
379 : }
380 0 : CRYPTO_w_unlock(CRYPTO_LOCK_ERR);
381 0 : }
382 :
383 3388 : static ERR_STRING_DATA *int_err_get_item(const ERR_STRING_DATA *d)
384 : {
385 : ERR_STRING_DATA *p;
386 : LHASH_OF(ERR_STRING_DATA) *hash;
387 :
388 3388 : err_fns_check();
389 3388 : hash = ERRFN(err_get) (0);
390 3388 : if (!hash)
391 : return NULL;
392 :
393 3388 : CRYPTO_r_lock(CRYPTO_LOCK_ERR);
394 3388 : p = lh_ERR_STRING_DATA_retrieve(hash, d);
395 3388 : CRYPTO_r_unlock(CRYPTO_LOCK_ERR);
396 :
397 3388 : return p;
398 : }
399 :
400 1684320 : static ERR_STRING_DATA *int_err_set_item(ERR_STRING_DATA *d)
401 : {
402 : ERR_STRING_DATA *p;
403 : LHASH_OF(ERR_STRING_DATA) *hash;
404 :
405 1684320 : err_fns_check();
406 1684320 : hash = ERRFN(err_get) (1);
407 1684320 : if (!hash)
408 : return NULL;
409 :
410 1684320 : CRYPTO_w_lock(CRYPTO_LOCK_ERR);
411 1684320 : p = lh_ERR_STRING_DATA_insert(hash, d);
412 1684320 : CRYPTO_w_unlock(CRYPTO_LOCK_ERR);
413 :
414 1684320 : return p;
415 : }
416 :
417 0 : static ERR_STRING_DATA *int_err_del_item(ERR_STRING_DATA *d)
418 : {
419 : ERR_STRING_DATA *p;
420 : LHASH_OF(ERR_STRING_DATA) *hash;
421 :
422 0 : err_fns_check();
423 0 : hash = ERRFN(err_get) (0);
424 0 : if (!hash)
425 : return NULL;
426 :
427 0 : CRYPTO_w_lock(CRYPTO_LOCK_ERR);
428 0 : p = lh_ERR_STRING_DATA_delete(hash, d);
429 0 : CRYPTO_w_unlock(CRYPTO_LOCK_ERR);
430 :
431 0 : return p;
432 : }
433 :
434 : static unsigned long err_state_hash(const ERR_STATE *a)
435 : {
436 21881 : return CRYPTO_THREADID_hash(&a->tid) * 13;
437 : }
438 :
439 43762 : static IMPLEMENT_LHASH_HASH_FN(err_state, ERR_STATE)
440 :
441 : static int err_state_cmp(const ERR_STATE *a, const ERR_STATE *b)
442 : {
443 21647 : return CRYPTO_THREADID_cmp(&a->tid, &b->tid);
444 : }
445 :
446 43294 : static IMPLEMENT_LHASH_COMP_FN(err_state, ERR_STATE)
447 :
448 22002 : static LHASH_OF(ERR_STATE) *int_thread_get(int create)
449 : {
450 : LHASH_OF(ERR_STATE) *ret = NULL;
451 :
452 22002 : CRYPTO_w_lock(CRYPTO_LOCK_ERR);
453 22003 : if (!int_thread_hash && create) {
454 122 : CRYPTO_push_info("int_thread_get (err.c)");
455 122 : int_thread_hash = lh_ERR_STATE_new();
456 122 : CRYPTO_pop_info();
457 : }
458 22003 : if (int_thread_hash) {
459 21881 : int_thread_hash_references++;
460 : ret = int_thread_hash;
461 : }
462 22003 : CRYPTO_w_unlock(CRYPTO_LOCK_ERR);
463 22003 : return ret;
464 : }
465 :
466 21881 : static void int_thread_release(LHASH_OF(ERR_STATE) **hash)
467 : {
468 : int i;
469 :
470 21881 : if (hash == NULL || *hash == NULL)
471 : return;
472 :
473 21881 : i = CRYPTO_add(&int_thread_hash_references, -1, CRYPTO_LOCK_ERR);
474 :
475 : #ifdef REF_PRINT
476 : fprintf(stderr, "%4d:%s\n", int_thread_hash_references, "ERR");
477 : #endif
478 21881 : if (i > 0)
479 : return;
480 : #ifdef REF_CHECK
481 : if (i < 0) {
482 : fprintf(stderr, "int_thread_release, bad reference count\n");
483 : abort(); /* ok */
484 : }
485 : #endif
486 21856 : *hash = NULL;
487 : }
488 :
489 21824 : static ERR_STATE *int_thread_get_item(const ERR_STATE *d)
490 : {
491 : ERR_STATE *p;
492 : LHASH_OF(ERR_STATE) *hash;
493 :
494 21824 : err_fns_check();
495 21824 : hash = ERRFN(thread_get) (0);
496 21825 : if (!hash)
497 : return NULL;
498 :
499 21703 : CRYPTO_r_lock(CRYPTO_LOCK_ERR);
500 21703 : p = lh_ERR_STATE_retrieve(hash, d);
501 21703 : CRYPTO_r_unlock(CRYPTO_LOCK_ERR);
502 :
503 21703 : ERRFN(thread_release) (&hash);
504 21703 : return p;
505 : }
506 :
507 178 : static ERR_STATE *int_thread_set_item(ERR_STATE *d)
508 : {
509 : ERR_STATE *p;
510 : LHASH_OF(ERR_STATE) *hash;
511 :
512 178 : err_fns_check();
513 178 : hash = ERRFN(thread_get) (1);
514 178 : if (!hash)
515 : return NULL;
516 :
517 178 : CRYPTO_w_lock(CRYPTO_LOCK_ERR);
518 178 : p = lh_ERR_STATE_insert(hash, d);
519 178 : CRYPTO_w_unlock(CRYPTO_LOCK_ERR);
520 :
521 178 : ERRFN(thread_release) (&hash);
522 178 : return p;
523 : }
524 :
525 0 : static void int_thread_del_item(const ERR_STATE *d)
526 : {
527 : ERR_STATE *p;
528 : LHASH_OF(ERR_STATE) *hash;
529 :
530 0 : err_fns_check();
531 0 : hash = ERRFN(thread_get) (0);
532 0 : if (!hash)
533 0 : return;
534 :
535 0 : CRYPTO_w_lock(CRYPTO_LOCK_ERR);
536 0 : p = lh_ERR_STATE_delete(hash, d);
537 : /* make sure we don't leak memory */
538 0 : if (int_thread_hash_references == 1
539 0 : && int_thread_hash && lh_ERR_STATE_num_items(int_thread_hash) == 0) {
540 0 : lh_ERR_STATE_free(int_thread_hash);
541 0 : int_thread_hash = NULL;
542 : }
543 0 : CRYPTO_w_unlock(CRYPTO_LOCK_ERR);
544 :
545 0 : ERRFN(thread_release) (&hash);
546 0 : if (p)
547 0 : ERR_STATE_free(p);
548 : }
549 :
550 0 : static int int_err_get_next_lib(void)
551 : {
552 : int ret;
553 :
554 0 : CRYPTO_w_lock(CRYPTO_LOCK_ERR);
555 0 : ret = int_err_library_number++;
556 0 : CRYPTO_w_unlock(CRYPTO_LOCK_ERR);
557 :
558 0 : return ret;
559 : }
560 :
561 : #ifndef OPENSSL_NO_ERR
562 : # define NUM_SYS_STR_REASONS 127
563 : # define LEN_SYS_STR_REASON 32
564 :
565 : static ERR_STRING_DATA SYS_str_reasons[NUM_SYS_STR_REASONS + 1];
566 : /*
567 : * SYS_str_reasons is filled with copies of strerror() results at
568 : * initialization. 'errno' values up to 127 should cover all usual errors,
569 : * others will be displayed numerically by ERR_error_string. It is crucial
570 : * that we have something for each reason code that occurs in
571 : * ERR_str_reasons, or bogus reason strings will be returned for SYSerr(),
572 : * which always gets an errno value and never one of those 'standard' reason
573 : * codes.
574 : */
575 :
576 6897 : static void build_SYS_str_reasons(void)
577 : {
578 : /* OPENSSL_malloc cannot be used here, use static storage instead */
579 : static char strerror_tab[NUM_SYS_STR_REASONS][LEN_SYS_STR_REASON];
580 : int i;
581 : static int init = 1;
582 :
583 6897 : CRYPTO_r_lock(CRYPTO_LOCK_ERR);
584 6897 : if (!init) {
585 6776 : CRYPTO_r_unlock(CRYPTO_LOCK_ERR);
586 6776 : return;
587 : }
588 :
589 121 : CRYPTO_r_unlock(CRYPTO_LOCK_ERR);
590 121 : CRYPTO_w_lock(CRYPTO_LOCK_ERR);
591 121 : if (!init) {
592 0 : CRYPTO_w_unlock(CRYPTO_LOCK_ERR);
593 0 : return;
594 : }
595 :
596 15367 : for (i = 1; i <= NUM_SYS_STR_REASONS; i++) {
597 15367 : ERR_STRING_DATA *str = &SYS_str_reasons[i - 1];
598 :
599 15367 : str->error = (unsigned long)i;
600 15367 : if (str->string == NULL) {
601 15367 : char (*dest)[LEN_SYS_STR_REASON] = &(strerror_tab[i - 1]);
602 15367 : char *src = strerror(i);
603 15367 : if (src != NULL) {
604 : strncpy(*dest, src, sizeof *dest);
605 15367 : (*dest)[sizeof *dest - 1] = '\0';
606 15367 : str->string = *dest;
607 : }
608 : }
609 15367 : if (str->string == NULL)
610 0 : str->string = "unknown";
611 : }
612 :
613 : /*
614 : * Now we still have SYS_str_reasons[NUM_SYS_STR_REASONS] = {0, NULL}, as
615 : * required by ERR_load_strings.
616 : */
617 :
618 121 : init = 0;
619 :
620 121 : CRYPTO_w_unlock(CRYPTO_LOCK_ERR);
621 : }
622 : #endif
623 :
624 : #define err_clear_data(p,i) \
625 : do { \
626 : if (((p)->err_data[i] != NULL) && \
627 : (p)->err_data_flags[i] & ERR_TXT_MALLOCED) \
628 : { \
629 : OPENSSL_free((p)->err_data[i]); \
630 : (p)->err_data[i]=NULL; \
631 : } \
632 : (p)->err_data_flags[i]=0; \
633 : } while(0)
634 :
635 : #define err_clear(p,i) \
636 : do { \
637 : (p)->err_flags[i]=0; \
638 : (p)->err_buffer[i]=0; \
639 : err_clear_data(p,i); \
640 : (p)->err_file[i]=NULL; \
641 : (p)->err_line[i]= -1; \
642 : } while(0)
643 :
644 0 : static void ERR_STATE_free(ERR_STATE *s)
645 : {
646 : int i;
647 :
648 0 : if (s == NULL)
649 0 : return;
650 :
651 0 : for (i = 0; i < ERR_NUM_ERRORS; i++) {
652 0 : err_clear_data(s, i);
653 : }
654 0 : OPENSSL_free(s);
655 : }
656 :
657 6897 : void ERR_load_ERR_strings(void)
658 : {
659 6897 : err_fns_check();
660 : #ifndef OPENSSL_NO_ERR
661 6897 : err_load_strings(0, ERR_str_libraries);
662 6897 : err_load_strings(0, ERR_str_reasons);
663 6897 : err_load_strings(ERR_LIB_SYS, ERR_str_functs);
664 6897 : build_SYS_str_reasons();
665 6897 : err_load_strings(ERR_LIB_SYS, SYS_str_reasons);
666 : #endif
667 6897 : }
668 :
669 34364 : static void err_load_strings(int lib, ERR_STRING_DATA *str)
670 : {
671 1753048 : while (str->error) {
672 1684320 : if (lib)
673 944889 : str->error |= ERR_PACK(lib, 0, 0);
674 1684320 : ERRFN(err_set_item) (str);
675 1684320 : str++;
676 : }
677 34364 : }
678 :
679 6776 : void ERR_load_strings(int lib, ERR_STRING_DATA *str)
680 : {
681 6776 : ERR_load_ERR_strings();
682 6776 : err_load_strings(lib, str);
683 6776 : }
684 :
685 0 : void ERR_unload_strings(int lib, ERR_STRING_DATA *str)
686 : {
687 0 : while (str->error) {
688 0 : if (lib)
689 0 : str->error |= ERR_PACK(lib, 0, 0);
690 0 : ERRFN(err_del_item) (str);
691 0 : str++;
692 : }
693 0 : }
694 :
695 0 : void ERR_free_strings(void)
696 : {
697 0 : err_fns_check();
698 0 : ERRFN(err_del) ();
699 0 : }
700 :
701 : /********************************************************/
702 :
703 874 : void ERR_put_error(int lib, int func, int reason, const char *file, int line)
704 : {
705 : ERR_STATE *es;
706 :
707 : #ifdef _OSD_POSIX
708 : /*
709 : * In the BS2000-OSD POSIX subsystem, the compiler generates path names
710 : * in the form "*POSIX(/etc/passwd)". This dirty hack strips them to
711 : * something sensible. @@@ We shouldn't modify a const string, though.
712 : */
713 : if (strncmp(file, "*POSIX(", sizeof("*POSIX(") - 1) == 0) {
714 : char *end;
715 :
716 : /* Skip the "*POSIX(" prefix */
717 : file += sizeof("*POSIX(") - 1;
718 : end = &file[strlen(file) - 1];
719 : if (*end == ')')
720 : *end = '\0';
721 : /* Optional: use the basename of the path only. */
722 : if ((end = strrchr(file, '/')) != NULL)
723 : file = &end[1];
724 : }
725 : #endif
726 874 : es = ERR_get_state();
727 :
728 874 : es->top = (es->top + 1) % ERR_NUM_ERRORS;
729 874 : if (es->top == es->bottom)
730 0 : es->bottom = (es->bottom + 1) % ERR_NUM_ERRORS;
731 874 : es->err_flags[es->top] = 0;
732 874 : es->err_buffer[es->top] = ERR_PACK(lib, func, reason);
733 874 : es->err_file[es->top] = file;
734 874 : es->err_line[es->top] = line;
735 874 : err_clear_data(es, es->top);
736 874 : }
737 :
738 3901 : void ERR_clear_error(void)
739 : {
740 : int i;
741 : ERR_STATE *es;
742 :
743 3901 : es = ERR_get_state();
744 :
745 66317 : for (i = 0; i < ERR_NUM_ERRORS; i++) {
746 62416 : err_clear(es, i);
747 : }
748 3901 : es->top = es->bottom = 0;
749 3901 : }
750 :
751 0 : unsigned long ERR_get_error(void)
752 : {
753 0 : return (get_error_values(1, 0, NULL, NULL, NULL, NULL));
754 : }
755 :
756 0 : unsigned long ERR_get_error_line(const char **file, int *line)
757 : {
758 0 : return (get_error_values(1, 0, file, line, NULL, NULL));
759 : }
760 :
761 0 : unsigned long ERR_get_error_line_data(const char **file, int *line,
762 : const char **data, int *flags)
763 : {
764 0 : return (get_error_values(1, 0, file, line, data, flags));
765 : }
766 :
767 15999 : unsigned long ERR_peek_error(void)
768 : {
769 15999 : return (get_error_values(0, 0, NULL, NULL, NULL, NULL));
770 : }
771 :
772 0 : unsigned long ERR_peek_error_line(const char **file, int *line)
773 : {
774 0 : return (get_error_values(0, 0, file, line, NULL, NULL));
775 : }
776 :
777 0 : unsigned long ERR_peek_error_line_data(const char **file, int *line,
778 : const char **data, int *flags)
779 : {
780 0 : return (get_error_values(0, 0, file, line, data, flags));
781 : }
782 :
783 0 : unsigned long ERR_peek_last_error(void)
784 : {
785 0 : return (get_error_values(0, 1, NULL, NULL, NULL, NULL));
786 : }
787 :
788 0 : unsigned long ERR_peek_last_error_line(const char **file, int *line)
789 : {
790 0 : return (get_error_values(0, 1, file, line, NULL, NULL));
791 : }
792 :
793 0 : unsigned long ERR_peek_last_error_line_data(const char **file, int *line,
794 : const char **data, int *flags)
795 : {
796 0 : return (get_error_values(0, 1, file, line, data, flags));
797 : }
798 :
799 15999 : static unsigned long get_error_values(int inc, int top, const char **file,
800 : int *line, const char **data,
801 : int *flags)
802 : {
803 : int i = 0;
804 : ERR_STATE *es;
805 : unsigned long ret;
806 :
807 15999 : es = ERR_get_state();
808 :
809 16000 : if (inc && top) {
810 0 : if (file)
811 0 : *file = "";
812 0 : if (line)
813 0 : *line = 0;
814 0 : if (data)
815 0 : *data = "";
816 0 : if (flags)
817 0 : *flags = 0;
818 :
819 : return ERR_R_INTERNAL_ERROR;
820 : }
821 :
822 16000 : if (es->bottom == es->top)
823 : return 0;
824 872 : if (top)
825 : i = es->top; /* last error */
826 : else
827 872 : i = (es->bottom + 1) % ERR_NUM_ERRORS; /* first error */
828 :
829 872 : ret = es->err_buffer[i];
830 872 : if (inc) {
831 0 : es->bottom = i;
832 0 : es->err_buffer[i] = 0;
833 : }
834 :
835 872 : if ((file != NULL) && (line != NULL)) {
836 0 : if (es->err_file[i] == NULL) {
837 0 : *file = "NA";
838 0 : if (line != NULL)
839 0 : *line = 0;
840 : } else {
841 0 : *file = es->err_file[i];
842 0 : if (line != NULL)
843 0 : *line = es->err_line[i];
844 : }
845 : }
846 :
847 872 : if (data == NULL) {
848 872 : if (inc) {
849 0 : err_clear_data(es, i);
850 : }
851 : } else {
852 0 : if (es->err_data[i] == NULL) {
853 0 : *data = "";
854 0 : if (flags != NULL)
855 0 : *flags = 0;
856 : } else {
857 0 : *data = es->err_data[i];
858 0 : if (flags != NULL)
859 0 : *flags = es->err_data_flags[i];
860 : }
861 : }
862 872 : return ret;
863 : }
864 :
865 0 : void ERR_error_string_n(unsigned long e, char *buf, size_t len)
866 : {
867 : char lsbuf[64], fsbuf[64], rsbuf[64];
868 : const char *ls, *fs, *rs;
869 : unsigned long l, f, r;
870 :
871 0 : l = ERR_GET_LIB(e);
872 0 : f = ERR_GET_FUNC(e);
873 0 : r = ERR_GET_REASON(e);
874 :
875 0 : ls = ERR_lib_error_string(e);
876 0 : fs = ERR_func_error_string(e);
877 0 : rs = ERR_reason_error_string(e);
878 :
879 0 : if (ls == NULL)
880 0 : BIO_snprintf(lsbuf, sizeof(lsbuf), "lib(%lu)", l);
881 0 : if (fs == NULL)
882 0 : BIO_snprintf(fsbuf, sizeof(fsbuf), "func(%lu)", f);
883 0 : if (rs == NULL)
884 0 : BIO_snprintf(rsbuf, sizeof(rsbuf), "reason(%lu)", r);
885 :
886 0 : BIO_snprintf(buf, len, "error:%08lX:%s:%s:%s", e, ls ? ls : lsbuf,
887 : fs ? fs : fsbuf, rs ? rs : rsbuf);
888 0 : if (strlen(buf) == len - 1) {
889 : /*
890 : * output may be truncated; make sure we always have 5
891 : * colon-separated fields, i.e. 4 colons ...
892 : */
893 : #define NUM_COLONS 4
894 0 : if (len > NUM_COLONS) { /* ... if possible */
895 : int i;
896 : char *s = buf;
897 :
898 0 : for (i = 0; i < NUM_COLONS; i++) {
899 0 : char *colon = strchr(s, ':');
900 0 : if (colon == NULL || colon > &buf[len - 1] - NUM_COLONS + i) {
901 : /*
902 : * set colon no. i at last possible position (buf[len-1]
903 : * is the terminating 0)
904 : */
905 0 : colon = &buf[len - 1] - NUM_COLONS + i;
906 0 : *colon = ':';
907 : }
908 0 : s = colon + 1;
909 : }
910 : }
911 : }
912 0 : }
913 :
914 : /* BAD for multi-threading: uses a local buffer if ret == NULL */
915 : /*
916 : * ERR_error_string_n should be used instead for ret != NULL as
917 : * ERR_error_string cannot know how large the buffer is
918 : */
919 0 : char *ERR_error_string(unsigned long e, char *ret)
920 : {
921 : static char buf[256];
922 :
923 0 : if (ret == NULL)
924 : ret = buf;
925 0 : ERR_error_string_n(e, ret, 256);
926 :
927 0 : return ret;
928 : }
929 :
930 0 : LHASH_OF(ERR_STRING_DATA) *ERR_get_string_table(void)
931 : {
932 0 : err_fns_check();
933 0 : return ERRFN(err_get) (0);
934 : }
935 :
936 0 : LHASH_OF(ERR_STATE) *ERR_get_err_state_table(void)
937 : {
938 0 : err_fns_check();
939 0 : return ERRFN(thread_get) (0);
940 : }
941 :
942 0 : void ERR_release_err_state_table(LHASH_OF(ERR_STATE) **hash)
943 : {
944 0 : err_fns_check();
945 0 : ERRFN(thread_release) (hash);
946 0 : }
947 :
948 0 : const char *ERR_lib_error_string(unsigned long e)
949 : {
950 : ERR_STRING_DATA d, *p;
951 : unsigned long l;
952 :
953 0 : err_fns_check();
954 0 : l = ERR_GET_LIB(e);
955 0 : d.error = ERR_PACK(l, 0, 0);
956 0 : p = ERRFN(err_get_item) (&d);
957 0 : return ((p == NULL) ? NULL : p->string);
958 : }
959 :
960 3388 : const char *ERR_func_error_string(unsigned long e)
961 : {
962 : ERR_STRING_DATA d, *p;
963 : unsigned long l, f;
964 :
965 3388 : err_fns_check();
966 3388 : l = ERR_GET_LIB(e);
967 3388 : f = ERR_GET_FUNC(e);
968 3388 : d.error = ERR_PACK(l, f, 0);
969 3388 : p = ERRFN(err_get_item) (&d);
970 3388 : return ((p == NULL) ? NULL : p->string);
971 : }
972 :
973 0 : const char *ERR_reason_error_string(unsigned long e)
974 : {
975 : ERR_STRING_DATA d, *p = NULL;
976 : unsigned long l, r;
977 :
978 0 : err_fns_check();
979 0 : l = ERR_GET_LIB(e);
980 0 : r = ERR_GET_REASON(e);
981 0 : d.error = ERR_PACK(l, 0, r);
982 0 : p = ERRFN(err_get_item) (&d);
983 0 : if (!p) {
984 0 : d.error = ERR_PACK(0, 0, r);
985 0 : p = ERRFN(err_get_item) (&d);
986 : }
987 0 : return ((p == NULL) ? NULL : p->string);
988 : }
989 :
990 0 : void ERR_remove_thread_state(const CRYPTO_THREADID *id)
991 : {
992 : ERR_STATE tmp;
993 :
994 0 : if (id)
995 0 : CRYPTO_THREADID_cpy(&tmp.tid, id);
996 : else
997 0 : CRYPTO_THREADID_current(&tmp.tid);
998 0 : err_fns_check();
999 : /*
1000 : * thread_del_item automatically destroys the LHASH if the number of
1001 : * items reaches zero.
1002 : */
1003 0 : ERRFN(thread_del_item) (&tmp);
1004 0 : }
1005 :
1006 : #ifndef OPENSSL_NO_DEPRECATED
1007 0 : void ERR_remove_state(unsigned long pid)
1008 : {
1009 0 : ERR_remove_thread_state(NULL);
1010 0 : }
1011 : #endif
1012 :
1013 21646 : ERR_STATE *ERR_get_state(void)
1014 : {
1015 : static ERR_STATE fallback;
1016 : ERR_STATE *ret, tmp, *tmpp = NULL;
1017 : int i;
1018 : CRYPTO_THREADID tid;
1019 :
1020 21646 : err_fns_check();
1021 21646 : CRYPTO_THREADID_current(&tid);
1022 21646 : CRYPTO_THREADID_cpy(&tmp.tid, &tid);
1023 21646 : ret = ERRFN(thread_get_item) (&tmp);
1024 :
1025 : /* ret == the error state, if NULL, make a new one */
1026 21647 : if (ret == NULL) {
1027 178 : ret = (ERR_STATE *)OPENSSL_malloc(sizeof(ERR_STATE));
1028 178 : if (ret == NULL)
1029 : return (&fallback);
1030 178 : CRYPTO_THREADID_cpy(&ret->tid, &tid);
1031 178 : ret->top = 0;
1032 178 : ret->bottom = 0;
1033 3026 : for (i = 0; i < ERR_NUM_ERRORS; i++) {
1034 2848 : ret->err_data[i] = NULL;
1035 2848 : ret->err_data_flags[i] = 0;
1036 : }
1037 178 : tmpp = ERRFN(thread_set_item) (ret);
1038 : /* To check if insertion failed, do a get. */
1039 178 : if (ERRFN(thread_get_item) (ret) != ret) {
1040 0 : ERR_STATE_free(ret); /* could not insert it */
1041 0 : return (&fallback);
1042 : }
1043 : /*
1044 : * If a race occured in this function and we came second, tmpp is the
1045 : * first one that we just replaced.
1046 : */
1047 178 : if (tmpp)
1048 0 : ERR_STATE_free(tmpp);
1049 : }
1050 21647 : return ret;
1051 : }
1052 :
1053 0 : int ERR_get_next_error_library(void)
1054 : {
1055 0 : err_fns_check();
1056 0 : return ERRFN(get_next_lib) ();
1057 : }
1058 :
1059 872 : void ERR_set_error_data(char *data, int flags)
1060 : {
1061 : ERR_STATE *es;
1062 : int i;
1063 :
1064 872 : es = ERR_get_state();
1065 :
1066 872 : i = es->top;
1067 872 : if (i == 0)
1068 : i = ERR_NUM_ERRORS - 1;
1069 :
1070 872 : err_clear_data(es, i);
1071 872 : es->err_data[i] = data;
1072 872 : es->err_data_flags[i] = flags;
1073 872 : }
1074 :
1075 872 : void ERR_add_error_data(int num, ...)
1076 : {
1077 : va_list args;
1078 872 : va_start(args, num);
1079 872 : ERR_add_error_vdata(num, args);
1080 872 : va_end(args);
1081 872 : }
1082 :
1083 872 : void ERR_add_error_vdata(int num, va_list args)
1084 : {
1085 : int i, n, s;
1086 : char *str, *p, *a;
1087 :
1088 : s = 80;
1089 872 : str = OPENSSL_malloc(s + 1);
1090 872 : if (str == NULL)
1091 : return;
1092 872 : str[0] = '\0';
1093 :
1094 : n = 0;
1095 2616 : for (i = 0; i < num; i++) {
1096 1744 : a = va_arg(args, char *);
1097 : /* ignore NULLs, thanks to Bob Beck <beck@obtuse.com> */
1098 1744 : if (a != NULL) {
1099 1744 : n += strlen(a);
1100 1744 : if (n > s) {
1101 0 : s = n + 20;
1102 0 : p = OPENSSL_realloc(str, s + 1);
1103 0 : if (p == NULL) {
1104 0 : OPENSSL_free(str);
1105 0 : return;
1106 : } else
1107 : str = p;
1108 : }
1109 1744 : BUF_strlcat(str, a, (size_t)s + 1);
1110 : }
1111 : }
1112 872 : ERR_set_error_data(str, ERR_TXT_MALLOCED | ERR_TXT_STRING);
1113 : }
1114 :
1115 0 : int ERR_set_mark(void)
1116 : {
1117 : ERR_STATE *es;
1118 :
1119 0 : es = ERR_get_state();
1120 :
1121 0 : if (es->bottom == es->top)
1122 : return 0;
1123 0 : es->err_flags[es->top] |= ERR_FLAG_MARK;
1124 0 : return 1;
1125 : }
1126 :
1127 0 : int ERR_pop_to_mark(void)
1128 : {
1129 : ERR_STATE *es;
1130 :
1131 0 : es = ERR_get_state();
1132 :
1133 0 : while (es->bottom != es->top
1134 0 : && (es->err_flags[es->top] & ERR_FLAG_MARK) == 0) {
1135 0 : err_clear(es, es->top);
1136 0 : es->top -= 1;
1137 0 : if (es->top == -1)
1138 0 : es->top = ERR_NUM_ERRORS - 1;
1139 : }
1140 :
1141 0 : if (es->bottom == es->top)
1142 : return 0;
1143 0 : es->err_flags[es->top] &= ~ERR_FLAG_MARK;
1144 0 : return 1;
1145 : }
|