Branch data 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 : : #define OPENSSL_NO_FIPS_ERR
113 : :
114 : : #include <stdio.h>
115 : : #include <stdarg.h>
116 : : #include <string.h>
117 : : #include "cryptlib.h"
118 : : #include <openssl/lhash.h>
119 : : #include <openssl/crypto.h>
120 : : #include <openssl/buffer.h>
121 : : #include <openssl/bio.h>
122 : : #include <openssl/err.h>
123 : :
124 : : DECLARE_LHASH_OF(ERR_STRING_DATA);
125 : : DECLARE_LHASH_OF(ERR_STATE);
126 : :
127 : : static void err_load_strings(int lib, ERR_STRING_DATA *str);
128 : :
129 : : static void ERR_STATE_free(ERR_STATE *s);
130 : : #ifndef OPENSSL_NO_ERR
131 : : static ERR_STRING_DATA ERR_str_libraries[]=
132 : : {
133 : : {ERR_PACK(ERR_LIB_NONE,0,0) ,"unknown library"},
134 : : {ERR_PACK(ERR_LIB_SYS,0,0) ,"system library"},
135 : : {ERR_PACK(ERR_LIB_BN,0,0) ,"bignum routines"},
136 : : {ERR_PACK(ERR_LIB_RSA,0,0) ,"rsa routines"},
137 : : {ERR_PACK(ERR_LIB_DH,0,0) ,"Diffie-Hellman routines"},
138 : : {ERR_PACK(ERR_LIB_EVP,0,0) ,"digital envelope routines"},
139 : : {ERR_PACK(ERR_LIB_BUF,0,0) ,"memory buffer routines"},
140 : : {ERR_PACK(ERR_LIB_OBJ,0,0) ,"object identifier routines"},
141 : : {ERR_PACK(ERR_LIB_PEM,0,0) ,"PEM routines"},
142 : : {ERR_PACK(ERR_LIB_DSA,0,0) ,"dsa routines"},
143 : : {ERR_PACK(ERR_LIB_X509,0,0) ,"x509 certificate routines"},
144 : : {ERR_PACK(ERR_LIB_ASN1,0,0) ,"asn1 encoding routines"},
145 : : {ERR_PACK(ERR_LIB_CONF,0,0) ,"configuration file routines"},
146 : : {ERR_PACK(ERR_LIB_CRYPTO,0,0) ,"common libcrypto routines"},
147 : : {ERR_PACK(ERR_LIB_EC,0,0) ,"elliptic curve routines"},
148 : : {ERR_PACK(ERR_LIB_ECDSA,0,0) ,"ECDSA routines"},
149 : : {ERR_PACK(ERR_LIB_ECDH,0,0) ,"ECDH routines"},
150 : : {ERR_PACK(ERR_LIB_SSL,0,0) ,"SSL routines"},
151 : : {ERR_PACK(ERR_LIB_BIO,0,0) ,"BIO routines"},
152 : : {ERR_PACK(ERR_LIB_PKCS7,0,0) ,"PKCS7 routines"},
153 : : {ERR_PACK(ERR_LIB_X509V3,0,0) ,"X509 V3 routines"},
154 : : {ERR_PACK(ERR_LIB_PKCS12,0,0) ,"PKCS12 routines"},
155 : : {ERR_PACK(ERR_LIB_RAND,0,0) ,"random number generator"},
156 : : {ERR_PACK(ERR_LIB_DSO,0,0) ,"DSO support routines"},
157 : : {ERR_PACK(ERR_LIB_TS,0,0) ,"time stamp routines"},
158 : : {ERR_PACK(ERR_LIB_ENGINE,0,0) ,"engine routines"},
159 : : {ERR_PACK(ERR_LIB_OCSP,0,0) ,"OCSP routines"},
160 : : {ERR_PACK(ERR_LIB_FIPS,0,0) ,"FIPS routines"},
161 : : {ERR_PACK(ERR_LIB_CMS,0,0) ,"CMS routines"},
162 : : {ERR_PACK(ERR_LIB_HMAC,0,0) ,"HMAC routines"},
163 : : {0,NULL},
164 : : };
165 : :
166 : : static ERR_STRING_DATA ERR_str_functs[]=
167 : : {
168 : : {ERR_PACK(0,SYS_F_FOPEN,0), "fopen"},
169 : : {ERR_PACK(0,SYS_F_CONNECT,0), "connect"},
170 : : {ERR_PACK(0,SYS_F_GETSERVBYNAME,0), "getservbyname"},
171 : : {ERR_PACK(0,SYS_F_SOCKET,0), "socket"},
172 : : {ERR_PACK(0,SYS_F_IOCTLSOCKET,0), "ioctlsocket"},
173 : : {ERR_PACK(0,SYS_F_BIND,0), "bind"},
174 : : {ERR_PACK(0,SYS_F_LISTEN,0), "listen"},
175 : : {ERR_PACK(0,SYS_F_ACCEPT,0), "accept"},
176 : : #ifdef OPENSSL_SYS_WINDOWS
177 : : {ERR_PACK(0,SYS_F_WSASTARTUP,0), "WSAstartup"},
178 : : #endif
179 : : {ERR_PACK(0,SYS_F_OPENDIR,0), "opendir"},
180 : : {ERR_PACK(0,SYS_F_FREAD,0), "fread"},
181 : : {0,NULL},
182 : : };
183 : :
184 : : static ERR_STRING_DATA ERR_str_reasons[]=
185 : : {
186 : : {ERR_R_SYS_LIB ,"system lib"},
187 : : {ERR_R_BN_LIB ,"BN lib"},
188 : : {ERR_R_RSA_LIB ,"RSA lib"},
189 : : {ERR_R_DH_LIB ,"DH lib"},
190 : : {ERR_R_EVP_LIB ,"EVP lib"},
191 : : {ERR_R_BUF_LIB ,"BUF lib"},
192 : : {ERR_R_OBJ_LIB ,"OBJ lib"},
193 : : {ERR_R_PEM_LIB ,"PEM lib"},
194 : : {ERR_R_DSA_LIB ,"DSA lib"},
195 : : {ERR_R_X509_LIB ,"X509 lib"},
196 : : {ERR_R_ASN1_LIB ,"ASN1 lib"},
197 : : {ERR_R_CONF_LIB ,"CONF lib"},
198 : : {ERR_R_CRYPTO_LIB ,"CRYPTO lib"},
199 : : {ERR_R_EC_LIB ,"EC lib"},
200 : : {ERR_R_SSL_LIB ,"SSL lib"},
201 : : {ERR_R_BIO_LIB ,"BIO lib"},
202 : : {ERR_R_PKCS7_LIB ,"PKCS7 lib"},
203 : : {ERR_R_X509V3_LIB ,"X509V3 lib"},
204 : : {ERR_R_PKCS12_LIB ,"PKCS12 lib"},
205 : : {ERR_R_RAND_LIB ,"RAND lib"},
206 : : {ERR_R_DSO_LIB ,"DSO lib"},
207 : : {ERR_R_ENGINE_LIB ,"ENGINE lib"},
208 : : {ERR_R_OCSP_LIB ,"OCSP lib"},
209 : : {ERR_R_TS_LIB ,"TS lib"},
210 : : {ERR_R_ECDSA_LIB ,"ECDSA lib"},
211 : :
212 : : {ERR_R_NESTED_ASN1_ERROR ,"nested asn1 error"},
213 : : {ERR_R_BAD_ASN1_OBJECT_HEADER ,"bad asn1 object header"},
214 : : {ERR_R_BAD_GET_ASN1_OBJECT_CALL ,"bad get asn1 object call"},
215 : : {ERR_R_EXPECTING_AN_ASN1_SEQUENCE ,"expecting an asn1 sequence"},
216 : : {ERR_R_ASN1_LENGTH_MISMATCH ,"asn1 length mismatch"},
217 : : {ERR_R_MISSING_ASN1_EOS ,"missing asn1 eos"},
218 : :
219 : : {ERR_R_FATAL ,"fatal"},
220 : : {ERR_R_MALLOC_FAILURE ,"malloc failure"},
221 : : {ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED ,"called a function you should not call"},
222 : : {ERR_R_PASSED_NULL_PARAMETER ,"passed a null parameter"},
223 : : {ERR_R_INTERNAL_ERROR ,"internal error"},
224 : : {ERR_R_DISABLED ,"called a function that was disabled at compile-time"},
225 : :
226 : : {0,NULL},
227 : : };
228 : : #endif
229 : :
230 : :
231 : : /* Define the predeclared (but externally opaque) "ERR_FNS" type */
232 : : struct st_ERR_FNS
233 : : {
234 : : /* Works on the "error_hash" string table */
235 : : LHASH_OF(ERR_STRING_DATA) *(*cb_err_get)(int create);
236 : : void (*cb_err_del)(void);
237 : : ERR_STRING_DATA *(*cb_err_get_item)(const ERR_STRING_DATA *);
238 : : ERR_STRING_DATA *(*cb_err_set_item)(ERR_STRING_DATA *);
239 : : ERR_STRING_DATA *(*cb_err_del_item)(ERR_STRING_DATA *);
240 : : /* Works on the "thread_hash" error-state table */
241 : : LHASH_OF(ERR_STATE) *(*cb_thread_get)(int create);
242 : : void (*cb_thread_release)(LHASH_OF(ERR_STATE) **hash);
243 : : ERR_STATE *(*cb_thread_get_item)(const ERR_STATE *);
244 : : ERR_STATE *(*cb_thread_set_item)(ERR_STATE *);
245 : : void (*cb_thread_del_item)(const ERR_STATE *);
246 : : /* Returns the next available error "library" numbers */
247 : : int (*cb_get_next_lib)(void);
248 : : };
249 : :
250 : : /* Predeclarations of the "err_defaults" functions */
251 : : static LHASH_OF(ERR_STRING_DATA) *int_err_get(int create);
252 : : static void int_err_del(void);
253 : : static ERR_STRING_DATA *int_err_get_item(const ERR_STRING_DATA *);
254 : : static ERR_STRING_DATA *int_err_set_item(ERR_STRING_DATA *);
255 : : static ERR_STRING_DATA *int_err_del_item(ERR_STRING_DATA *);
256 : : static LHASH_OF(ERR_STATE) *int_thread_get(int create);
257 : : static void int_thread_release(LHASH_OF(ERR_STATE) **hash);
258 : : static ERR_STATE *int_thread_get_item(const ERR_STATE *);
259 : : static ERR_STATE *int_thread_set_item(ERR_STATE *);
260 : : static void int_thread_del_item(const ERR_STATE *);
261 : : static int int_err_get_next_lib(void);
262 : : /* The static ERR_FNS table using these defaults functions */
263 : : static const ERR_FNS err_defaults =
264 : : {
265 : : int_err_get,
266 : : int_err_del,
267 : : int_err_get_item,
268 : : int_err_set_item,
269 : : int_err_del_item,
270 : : int_thread_get,
271 : : int_thread_release,
272 : : int_thread_get_item,
273 : : int_thread_set_item,
274 : : int_thread_del_item,
275 : : int_err_get_next_lib
276 : : };
277 : :
278 : : /* The replacable table of ERR_FNS functions we use at run-time */
279 : : static const ERR_FNS *err_fns = NULL;
280 : :
281 : : /* Eg. rather than using "err_get()", use "ERRFN(err_get)()". */
282 : : #define ERRFN(a) err_fns->cb_##a
283 : :
284 : : /* The internal state used by "err_defaults" - as such, the setting, reading,
285 : : * creating, and deleting of this data should only be permitted via the
286 : : * "err_defaults" functions. This way, a linked module can completely defer all
287 : : * ERR state operation (together with requisite locking) to the implementations
288 : : * and state in the loading application. */
289 : : static LHASH_OF(ERR_STRING_DATA) *int_error_hash = NULL;
290 : : static LHASH_OF(ERR_STATE) *int_thread_hash = NULL;
291 : : static int int_thread_hash_references = 0;
292 : : static int int_err_library_number= ERR_LIB_USER;
293 : :
294 : : /* Internal function that checks whether "err_fns" is set and if not, sets it to
295 : : * the defaults. */
296 : 27189092 : static void err_fns_check(void)
297 : : {
298 [ + + ]: 27189092 : if (err_fns) return;
299 : :
300 : 1633 : CRYPTO_w_lock(CRYPTO_LOCK_ERR);
301 [ + - ]: 1633 : if (!err_fns)
302 : 1633 : err_fns = &err_defaults;
303 : 1633 : CRYPTO_w_unlock(CRYPTO_LOCK_ERR);
304 : : }
305 : :
306 : : /* API functions to get or set the underlying ERR functions. */
307 : :
308 : 0 : const ERR_FNS *ERR_get_implementation(void)
309 : : {
310 : 0 : err_fns_check();
311 : 0 : return err_fns;
312 : : }
313 : :
314 : 0 : int ERR_set_implementation(const ERR_FNS *fns)
315 : : {
316 : 0 : int ret = 0;
317 : :
318 : 0 : CRYPTO_w_lock(CRYPTO_LOCK_ERR);
319 : : /* It's too late if 'err_fns' is non-NULL. BTW: not much point setting
320 : : * an error is there?! */
321 [ # # ]: 0 : if (!err_fns)
322 : : {
323 : 0 : err_fns = fns;
324 : 0 : ret = 1;
325 : : }
326 : 0 : CRYPTO_w_unlock(CRYPTO_LOCK_ERR);
327 : 0 : return ret;
328 : : }
329 : :
330 : : /* These are the callbacks provided to "lh_new()" when creating the LHASH tables
331 : : * internal to the "err_defaults" implementation. */
332 : :
333 : : static unsigned long get_error_values(int inc,int top,const char **file,int *line,
334 : : const char **data,int *flags);
335 : :
336 : : /* The internal functions used in the "err_defaults" implementation */
337 : :
338 : 52365328 : static unsigned long err_string_data_hash(const ERR_STRING_DATA *a)
339 : : {
340 : : unsigned long ret,l;
341 : :
342 : 26182664 : l=a->error;
343 : 26182664 : ret=l^ERR_GET_LIB(l)^ERR_GET_FUNC(l);
344 : 26182664 : return(ret^ret%19*13);
345 : : }
346 : 52365328 : static IMPLEMENT_LHASH_HASH_FN(err_string_data, ERR_STRING_DATA)
347 : :
348 : 46910488 : static int err_string_data_cmp(const ERR_STRING_DATA *a,
349 : : const ERR_STRING_DATA *b)
350 : : {
351 : 23455244 : return (int)(a->error - b->error);
352 : : }
353 : 46910488 : static IMPLEMENT_LHASH_COMP_FN(err_string_data, ERR_STRING_DATA)
354 : :
355 : 26182665 : static LHASH_OF(ERR_STRING_DATA) *int_err_get(int create)
356 : : {
357 : 26182665 : LHASH_OF(ERR_STRING_DATA) *ret = NULL;
358 : :
359 : 26182665 : CRYPTO_w_lock(CRYPTO_LOCK_ERR);
360 [ + + ][ + + ]: 26182665 : if (!int_error_hash && create)
361 : : {
362 : 1628 : CRYPTO_push_info("int_err_get (err.c)");
363 : 1628 : int_error_hash = lh_ERR_STRING_DATA_new();
364 : 1628 : CRYPTO_pop_info();
365 : : }
366 [ + + ]: 26182665 : if (int_error_hash)
367 : 26182664 : ret = int_error_hash;
368 : 26182665 : CRYPTO_w_unlock(CRYPTO_LOCK_ERR);
369 : :
370 : 26182665 : return ret;
371 : : }
372 : :
373 : 1627 : static void int_err_del(void)
374 : : {
375 : 1627 : CRYPTO_w_lock(CRYPTO_LOCK_ERR);
376 [ + + ]: 1627 : if (int_error_hash)
377 : : {
378 : 1626 : lh_ERR_STRING_DATA_free(int_error_hash);
379 : 1626 : int_error_hash = NULL;
380 : : }
381 : 1627 : CRYPTO_w_unlock(CRYPTO_LOCK_ERR);
382 : 1627 : }
383 : :
384 : 51394 : static ERR_STRING_DATA *int_err_get_item(const ERR_STRING_DATA *d)
385 : : {
386 : : ERR_STRING_DATA *p;
387 : : LHASH_OF(ERR_STRING_DATA) *hash;
388 : :
389 : 51394 : err_fns_check();
390 : 51394 : hash = ERRFN(err_get)(0);
391 [ + + ]: 51394 : if (!hash)
392 : : return NULL;
393 : :
394 : 51393 : CRYPTO_r_lock(CRYPTO_LOCK_ERR);
395 : 51393 : p = lh_ERR_STRING_DATA_retrieve(hash, d);
396 : 51393 : CRYPTO_r_unlock(CRYPTO_LOCK_ERR);
397 : :
398 : 51393 : return p;
399 : : }
400 : :
401 : 26017859 : static ERR_STRING_DATA *int_err_set_item(ERR_STRING_DATA *d)
402 : : {
403 : : ERR_STRING_DATA *p;
404 : : LHASH_OF(ERR_STRING_DATA) *hash;
405 : :
406 : 26017859 : err_fns_check();
407 : 26017859 : hash = ERRFN(err_get)(1);
408 [ + - ]: 26017859 : if (!hash)
409 : : return NULL;
410 : :
411 : 26017859 : CRYPTO_w_lock(CRYPTO_LOCK_ERR);
412 : 26017859 : p = lh_ERR_STRING_DATA_insert(hash, d);
413 : 26017859 : CRYPTO_w_unlock(CRYPTO_LOCK_ERR);
414 : :
415 : 26017859 : return p;
416 : : }
417 : :
418 : 113412 : static ERR_STRING_DATA *int_err_del_item(ERR_STRING_DATA *d)
419 : : {
420 : : ERR_STRING_DATA *p;
421 : : LHASH_OF(ERR_STRING_DATA) *hash;
422 : :
423 : 113412 : err_fns_check();
424 : 113412 : hash = ERRFN(err_get)(0);
425 [ + - ]: 113412 : if (!hash)
426 : : return NULL;
427 : :
428 : 113412 : CRYPTO_w_lock(CRYPTO_LOCK_ERR);
429 : 113412 : p = lh_ERR_STRING_DATA_delete(hash, d);
430 : 113412 : CRYPTO_w_unlock(CRYPTO_LOCK_ERR);
431 : :
432 : 113412 : return p;
433 : : }
434 : :
435 : 418922 : static unsigned long err_state_hash(const ERR_STATE *a)
436 : : {
437 : 418922 : return CRYPTO_THREADID_hash(&a->tid) * 13;
438 : : }
439 : 837844 : static IMPLEMENT_LHASH_HASH_FN(err_state, ERR_STATE)
440 : :
441 : 417294 : static int err_state_cmp(const ERR_STATE *a, const ERR_STATE *b)
442 : : {
443 : 417294 : return CRYPTO_THREADID_cmp(&a->tid, &b->tid);
444 : : }
445 : 834588 : static IMPLEMENT_LHASH_COMP_FN(err_state, ERR_STATE)
446 : :
447 : 420555 : static LHASH_OF(ERR_STATE) *int_thread_get(int create)
448 : : {
449 : 420555 : LHASH_OF(ERR_STATE) *ret = NULL;
450 : :
451 : 420555 : CRYPTO_w_lock(CRYPTO_LOCK_ERR);
452 [ + + ][ + + ]: 420555 : if (!int_thread_hash && create)
453 : : {
454 : 1628 : CRYPTO_push_info("int_thread_get (err.c)");
455 : 1628 : int_thread_hash = lh_ERR_STATE_new();
456 : 1628 : CRYPTO_pop_info();
457 : : }
458 [ + + ]: 420555 : if (int_thread_hash)
459 : : {
460 : 418922 : int_thread_hash_references++;
461 : 418922 : ret = int_thread_hash;
462 : : }
463 : 420555 : CRYPTO_w_unlock(CRYPTO_LOCK_ERR);
464 : 420555 : return ret;
465 : : }
466 : :
467 : 418922 : static void int_thread_release(LHASH_OF(ERR_STATE) **hash)
468 : : {
469 : : int i;
470 : :
471 [ + - ][ + - ]: 418922 : if (hash == NULL || *hash == NULL)
472 : : return;
473 : :
474 : 418922 : i = CRYPTO_add(&int_thread_hash_references, -1, CRYPTO_LOCK_ERR);
475 : :
476 : : #ifdef REF_PRINT
477 : : fprintf(stderr,"%4d:%s\n",int_thread_hash_references,"ERR");
478 : : #endif
479 [ + - ]: 418922 : if (i > 0) return;
480 : : #ifdef REF_CHECK
481 : : if (i < 0)
482 : : {
483 : : fprintf(stderr,"int_thread_release, bad reference count\n");
484 : : abort(); /* ok */
485 : : }
486 : : #endif
487 : 418922 : *hash = NULL;
488 : : }
489 : :
490 : 417297 : static ERR_STATE *int_thread_get_item(const ERR_STATE *d)
491 : : {
492 : : ERR_STATE *p;
493 : : LHASH_OF(ERR_STATE) *hash;
494 : :
495 : 417297 : err_fns_check();
496 : 417297 : hash = ERRFN(thread_get)(0);
497 [ + + ]: 417297 : if (!hash)
498 : : return NULL;
499 : :
500 : 415669 : CRYPTO_r_lock(CRYPTO_LOCK_ERR);
501 : 415669 : p = lh_ERR_STATE_retrieve(hash, d);
502 : 415669 : CRYPTO_r_unlock(CRYPTO_LOCK_ERR);
503 : :
504 : 415669 : ERRFN(thread_release)(&hash);
505 : 415669 : return p;
506 : : }
507 : :
508 : 1628 : static ERR_STATE *int_thread_set_item(ERR_STATE *d)
509 : : {
510 : : ERR_STATE *p;
511 : : LHASH_OF(ERR_STATE) *hash;
512 : :
513 : 1628 : err_fns_check();
514 : 1628 : hash = ERRFN(thread_get)(1);
515 [ + - ]: 1628 : if (!hash)
516 : : return NULL;
517 : :
518 : 1628 : CRYPTO_w_lock(CRYPTO_LOCK_ERR);
519 : 1628 : p = lh_ERR_STATE_insert(hash, d);
520 : 1628 : CRYPTO_w_unlock(CRYPTO_LOCK_ERR);
521 : :
522 : 1628 : ERRFN(thread_release)(&hash);
523 : 1628 : return p;
524 : : }
525 : :
526 : 1630 : static void int_thread_del_item(const ERR_STATE *d)
527 : : {
528 : : ERR_STATE *p;
529 : : LHASH_OF(ERR_STATE) *hash;
530 : :
531 : 1630 : err_fns_check();
532 : 1630 : hash = ERRFN(thread_get)(0);
533 [ + + ]: 1630 : if (!hash)
534 : 5 : return;
535 : :
536 : 1625 : CRYPTO_w_lock(CRYPTO_LOCK_ERR);
537 : 1625 : p = lh_ERR_STATE_delete(hash, d);
538 : : /* make sure we don't leak memory */
539 [ + - ]: 1625 : if (int_thread_hash_references == 1
540 [ + - ][ + - ]: 1625 : && int_thread_hash && lh_ERR_STATE_num_items(int_thread_hash) == 0)
541 : : {
542 : 1625 : lh_ERR_STATE_free(int_thread_hash);
543 : 1625 : int_thread_hash = NULL;
544 : : }
545 : 1625 : CRYPTO_w_unlock(CRYPTO_LOCK_ERR);
546 : :
547 : 1625 : ERRFN(thread_release)(&hash);
548 [ + - ]: 1625 : if (p)
549 : 1625 : ERR_STATE_free(p);
550 : : }
551 : :
552 : 6552 : static int int_err_get_next_lib(void)
553 : : {
554 : : int ret;
555 : :
556 : 6552 : CRYPTO_w_lock(CRYPTO_LOCK_ERR);
557 : 6552 : ret = int_err_library_number++;
558 : 6552 : CRYPTO_w_unlock(CRYPTO_LOCK_ERR);
559 : :
560 : 6552 : return ret;
561 : : }
562 : :
563 : :
564 : : #ifndef OPENSSL_NO_ERR
565 : : #define NUM_SYS_STR_REASONS 127
566 : : #define LEN_SYS_STR_REASON 32
567 : :
568 : : static ERR_STRING_DATA SYS_str_reasons[NUM_SYS_STR_REASONS + 1];
569 : : /* SYS_str_reasons is filled with copies of strerror() results at
570 : : * initialization.
571 : : * 'errno' values up to 127 should cover all usual errors,
572 : : * others will be displayed numerically by ERR_error_string.
573 : : * It is crucial that we have something for each reason code
574 : : * that occurs in ERR_str_reasons, or bogus reason strings
575 : : * will be returned for SYSerr(), which always gets an errno
576 : : * value and never one of those 'standard' reason codes. */
577 : :
578 : 109025 : static void build_SYS_str_reasons(void)
579 : : {
580 : : /* OPENSSL_malloc cannot be used here, use static storage instead */
581 : : static char strerror_tab[NUM_SYS_STR_REASONS][LEN_SYS_STR_REASON];
582 : : int i;
583 : : static int init = 1;
584 : :
585 : 109025 : CRYPTO_r_lock(CRYPTO_LOCK_ERR);
586 [ + + ]: 109025 : if (!init)
587 : : {
588 : 107397 : CRYPTO_r_unlock(CRYPTO_LOCK_ERR);
589 : 107397 : return;
590 : : }
591 : :
592 : 1628 : CRYPTO_r_unlock(CRYPTO_LOCK_ERR);
593 : 1628 : CRYPTO_w_lock(CRYPTO_LOCK_ERR);
594 [ + - ]: 1628 : if (!init)
595 : : {
596 : 0 : CRYPTO_w_unlock(CRYPTO_LOCK_ERR);
597 : 0 : return;
598 : : }
599 : :
600 [ + + ]: 208384 : for (i = 1; i <= NUM_SYS_STR_REASONS; i++)
601 : : {
602 : 206756 : ERR_STRING_DATA *str = &SYS_str_reasons[i - 1];
603 : :
604 : 206756 : str->error = (unsigned long)i;
605 [ + - ]: 206756 : if (str->string == NULL)
606 : : {
607 : 206756 : char (*dest)[LEN_SYS_STR_REASON] = &(strerror_tab[i - 1]);
608 : 206756 : char *src = strerror(i);
609 [ + - ]: 206756 : if (src != NULL)
610 : : {
611 : : strncpy(*dest, src, sizeof *dest);
612 : 206756 : (*dest)[sizeof *dest - 1] = '\0';
613 : 206756 : str->string = *dest;
614 : : }
615 : : }
616 [ - + ]: 206756 : if (str->string == NULL)
617 : 0 : str->string = "unknown";
618 : : }
619 : :
620 : : /* Now we still have SYS_str_reasons[NUM_SYS_STR_REASONS] = {0, NULL},
621 : : * as required by ERR_load_strings. */
622 : :
623 : 1628 : init = 0;
624 : :
625 : 1628 : CRYPTO_w_unlock(CRYPTO_LOCK_ERR);
626 : : }
627 : : #endif
628 : :
629 : : #define err_clear_data(p,i) \
630 : : do { \
631 : : if (((p)->err_data[i] != NULL) && \
632 : : (p)->err_data_flags[i] & ERR_TXT_MALLOCED) \
633 : : { \
634 : : OPENSSL_free((p)->err_data[i]); \
635 : : (p)->err_data[i]=NULL; \
636 : : } \
637 : : (p)->err_data_flags[i]=0; \
638 : : } while(0)
639 : :
640 : : #define err_clear(p,i) \
641 : : do { \
642 : : (p)->err_flags[i]=0; \
643 : : (p)->err_buffer[i]=0; \
644 : : err_clear_data(p,i); \
645 : : (p)->err_file[i]=NULL; \
646 : : (p)->err_line[i]= -1; \
647 : : } while(0)
648 : :
649 : 1625 : static void ERR_STATE_free(ERR_STATE *s)
650 : : {
651 : : int i;
652 : :
653 [ + - ]: 1625 : if (s == NULL)
654 : 1625 : return;
655 : :
656 [ + + ]: 27625 : for (i=0; i<ERR_NUM_ERRORS; i++)
657 : : {
658 [ + + ][ + - ]: 26000 : err_clear_data(s,i);
659 : : }
660 : 1625 : OPENSSL_free(s);
661 : : }
662 : :
663 : 109025 : void ERR_load_ERR_strings(void)
664 : : {
665 : 109025 : err_fns_check();
666 : : #ifndef OPENSSL_NO_ERR
667 : 109025 : err_load_strings(0,ERR_str_libraries);
668 : 109025 : err_load_strings(0,ERR_str_reasons);
669 : 109025 : err_load_strings(ERR_LIB_SYS,ERR_str_functs);
670 : 109025 : build_SYS_str_reasons();
671 : 109025 : err_load_strings(ERR_LIB_SYS,SYS_str_reasons);
672 : : #endif
673 : 109025 : }
674 : :
675 : 543272 : static void err_load_strings(int lib, ERR_STRING_DATA *str)
676 : : {
677 [ + + ]: 26561131 : while (str->error)
678 : : {
679 [ + + ]: 26017859 : if (lib)
680 : 15100953 : str->error|=ERR_PACK(lib,0,0);
681 : 26017859 : ERRFN(err_set_item)(str);
682 : 26017859 : str++;
683 : : }
684 : 543272 : }
685 : :
686 : 107172 : void ERR_load_strings(int lib, ERR_STRING_DATA *str)
687 : : {
688 : 107172 : ERR_load_ERR_strings();
689 : 107172 : err_load_strings(lib, str);
690 : 107172 : }
691 : :
692 : 15994 : void ERR_unload_strings(int lib, ERR_STRING_DATA *str)
693 : : {
694 [ + + ]: 129406 : while (str->error)
695 : : {
696 [ + + ]: 113412 : if (lib)
697 : 109050 : str->error|=ERR_PACK(lib,0,0);
698 : 113412 : ERRFN(err_del_item)(str);
699 : 113412 : str++;
700 : : }
701 : 15994 : }
702 : :
703 : 1627 : void ERR_free_strings(void)
704 : : {
705 : 1627 : err_fns_check();
706 : 1627 : ERRFN(err_del)();
707 : 1627 : }
708 : :
709 : : /********************************************************/
710 : :
711 : 140418 : void ERR_put_error(int lib, int func, int reason, const char *file,
712 : : int line)
713 : : {
714 : : ERR_STATE *es;
715 : :
716 : : #ifdef _OSD_POSIX
717 : : /* In the BS2000-OSD POSIX subsystem, the compiler generates
718 : : * path names in the form "*POSIX(/etc/passwd)".
719 : : * This dirty hack strips them to something sensible.
720 : : * @@@ We shouldn't modify a const string, though.
721 : : */
722 : : if (strncmp(file,"*POSIX(", sizeof("*POSIX(")-1) == 0) {
723 : : char *end;
724 : :
725 : : /* Skip the "*POSIX(" prefix */
726 : : file += sizeof("*POSIX(")-1;
727 : : end = &file[strlen(file)-1];
728 : : if (*end == ')')
729 : : *end = '\0';
730 : : /* Optional: use the basename of the path only. */
731 : : if ((end = strrchr(file, '/')) != NULL)
732 : : file = &end[1];
733 : : }
734 : : #endif
735 : 140418 : es=ERR_get_state();
736 : :
737 : 140418 : es->top=(es->top+1)%ERR_NUM_ERRORS;
738 [ + + ]: 140418 : if (es->top == es->bottom)
739 : 125641 : es->bottom=(es->bottom+1)%ERR_NUM_ERRORS;
740 : 140418 : es->err_flags[es->top]=0;
741 : 140418 : es->err_buffer[es->top]=ERR_PACK(lib,func,reason);
742 : 140418 : es->err_file[es->top]=file;
743 : 140418 : es->err_line[es->top]=line;
744 [ + + ][ + - ]: 140418 : err_clear_data(es,es->top);
745 : 140418 : }
746 : :
747 : 89408 : void ERR_clear_error(void)
748 : : {
749 : : int i;
750 : : ERR_STATE *es;
751 : :
752 : 89408 : es=ERR_get_state();
753 : :
754 [ + + ]: 1519936 : for (i=0; i<ERR_NUM_ERRORS; i++)
755 : : {
756 [ + + ][ + - ]: 1430528 : err_clear(es,i);
757 : : }
758 : 89408 : es->top=es->bottom=0;
759 : 89408 : }
760 : :
761 : :
762 : 0 : unsigned long ERR_get_error(void)
763 : 0 : { return(get_error_values(1,0,NULL,NULL,NULL,NULL)); }
764 : :
765 : 0 : unsigned long ERR_get_error_line(const char **file,
766 : : int *line)
767 : 0 : { return(get_error_values(1,0,file,line,NULL,NULL)); }
768 : :
769 : 1997 : unsigned long ERR_get_error_line_data(const char **file, int *line,
770 : : const char **data, int *flags)
771 : 1997 : { return(get_error_values(1,0,file,line,data,flags)); }
772 : :
773 : :
774 : 87234 : unsigned long ERR_peek_error(void)
775 : 87234 : { return(get_error_values(0,0,NULL,NULL,NULL,NULL)); }
776 : :
777 : 0 : unsigned long ERR_peek_error_line(const char **file, int *line)
778 : 0 : { return(get_error_values(0,0,file,line,NULL,NULL)); }
779 : :
780 : 0 : unsigned long ERR_peek_error_line_data(const char **file, int *line,
781 : : const char **data, int *flags)
782 : 0 : { return(get_error_values(0,0,file,line,data,flags)); }
783 : :
784 : :
785 : 652 : unsigned long ERR_peek_last_error(void)
786 : 652 : { return(get_error_values(0,1,NULL,NULL,NULL,NULL)); }
787 : :
788 : 0 : unsigned long ERR_peek_last_error_line(const char **file, int *line)
789 : 0 : { return(get_error_values(0,1,file,line,NULL,NULL)); }
790 : :
791 : 0 : unsigned long ERR_peek_last_error_line_data(const char **file, int *line,
792 : : const char **data, int *flags)
793 : 0 : { return(get_error_values(0,1,file,line,data,flags)); }
794 : :
795 : :
796 : 89883 : static unsigned long get_error_values(int inc, int top, const char **file, int *line,
797 : : const char **data, int *flags)
798 : : {
799 : 89883 : int i=0;
800 : : ERR_STATE *es;
801 : : unsigned long ret;
802 : :
803 : 89883 : es=ERR_get_state();
804 : :
805 [ - + ]: 89883 : if (inc && top)
806 : : {
807 [ # # ]: 0 : if (file) *file = "";
808 [ # # ]: 0 : if (line) *line = 0;
809 [ # # ]: 0 : if (data) *data = "";
810 [ # # ]: 0 : if (flags) *flags = 0;
811 : :
812 : : return ERR_R_INTERNAL_ERROR;
813 : : }
814 : :
815 [ + + ]: 89883 : if (es->bottom == es->top) return 0;
816 [ + + ]: 1155 : if (top)
817 : : i=es->top; /* last error */
818 : : else
819 : 503 : i=(es->bottom+1)%ERR_NUM_ERRORS; /* first error */
820 : :
821 : 1155 : ret=es->err_buffer[i];
822 [ + + ]: 1155 : if (inc)
823 : : {
824 : 130 : es->bottom=i;
825 : 130 : es->err_buffer[i]=0;
826 : : }
827 : :
828 [ + + ]: 1155 : if ((file != NULL) && (line != NULL))
829 : : {
830 [ - + ]: 130 : if (es->err_file[i] == NULL)
831 : : {
832 : 0 : *file="NA";
833 [ # # ]: 0 : if (line != NULL) *line=0;
834 : : }
835 : : else
836 : : {
837 : 130 : *file=es->err_file[i];
838 [ + - ]: 130 : if (line != NULL) *line=es->err_line[i];
839 : : }
840 : : }
841 : :
842 [ + + ]: 1155 : if (data == NULL)
843 : : {
844 [ - + ]: 1025 : if (inc)
845 : : {
846 [ # # ][ # # ]: 0 : err_clear_data(es, i);
847 : : }
848 : : }
849 : : else
850 : : {
851 [ + + ]: 130 : if (es->err_data[i] == NULL)
852 : : {
853 : 121 : *data="";
854 [ + - ]: 121 : if (flags != NULL) *flags=0;
855 : : }
856 : : else
857 : : {
858 : 9 : *data=es->err_data[i];
859 [ + - ]: 9 : if (flags != NULL) *flags=es->err_data_flags[i];
860 : : }
861 : : }
862 : 1155 : return ret;
863 : : }
864 : :
865 : 130 : 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 : 130 : l=ERR_GET_LIB(e);
872 : 130 : f=ERR_GET_FUNC(e);
873 : 130 : r=ERR_GET_REASON(e);
874 : :
875 : 130 : ls=ERR_lib_error_string(e);
876 : 130 : fs=ERR_func_error_string(e);
877 : 130 : rs=ERR_reason_error_string(e);
878 : :
879 [ - + ]: 130 : if (ls == NULL)
880 : 0 : BIO_snprintf(lsbuf, sizeof(lsbuf), "lib(%lu)", l);
881 [ - + ]: 130 : if (fs == NULL)
882 : 0 : BIO_snprintf(fsbuf, sizeof(fsbuf), "func(%lu)", f);
883 [ - + ]: 130 : if (rs == NULL)
884 : 0 : BIO_snprintf(rsbuf, sizeof(rsbuf), "reason(%lu)", r);
885 : :
886 [ + - ][ + - ]: 130 : BIO_snprintf(buf, len,"error:%08lX:%s:%s:%s", e, ls?ls:lsbuf,
[ + - ]
887 : : fs?fs:fsbuf, rs?rs:rsbuf);
888 [ - + ]: 130 : 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 : : #define NUM_COLONS 4
893 [ # # ]: 0 : if (len > NUM_COLONS) /* ... if possible */
894 : : {
895 : : int i;
896 : : char *s = buf;
897 : :
898 [ # # ]: 0 : for (i = 0; i < NUM_COLONS; i++)
899 : : {
900 : 0 : char *colon = strchr(s, ':');
901 [ # # ][ # # ]: 0 : if (colon == NULL || colon > &buf[len-1] - NUM_COLONS + i)
902 : : {
903 : : /* set colon no. i at last possible position
904 : : * (buf[len-1] is the terminating 0)*/
905 : 0 : colon = &buf[len-1] - NUM_COLONS + i;
906 : 0 : *colon = ':';
907 : : }
908 : 0 : s = colon + 1;
909 : : }
910 : : }
911 : : }
912 : 130 : }
913 : :
914 : : /* BAD for multi-threading: uses a local buffer if ret == NULL */
915 : : /* ERR_error_string_n should be used instead for ret != NULL
916 : : * as ERR_error_string cannot know how large the buffer is */
917 : 0 : char *ERR_error_string(unsigned long e, char *ret)
918 : : {
919 : : static char buf[256];
920 : :
921 [ # # ]: 0 : if (ret == NULL) ret=buf;
922 : 0 : ERR_error_string_n(e, ret, 256);
923 : :
924 : 0 : return ret;
925 : : }
926 : :
927 : 0 : LHASH_OF(ERR_STRING_DATA) *ERR_get_string_table(void)
928 : : {
929 : 0 : err_fns_check();
930 : 0 : return ERRFN(err_get)(0);
931 : : }
932 : :
933 : 0 : LHASH_OF(ERR_STATE) *ERR_get_err_state_table(void)
934 : : {
935 : 0 : err_fns_check();
936 : 0 : return ERRFN(thread_get)(0);
937 : : }
938 : :
939 : 0 : void ERR_release_err_state_table(LHASH_OF(ERR_STATE) **hash)
940 : : {
941 : 0 : err_fns_check();
942 : 0 : ERRFN(thread_release)(hash);
943 : 0 : }
944 : :
945 : 130 : const char *ERR_lib_error_string(unsigned long e)
946 : : {
947 : : ERR_STRING_DATA d,*p;
948 : : unsigned long l;
949 : :
950 : 130 : err_fns_check();
951 : 130 : l=ERR_GET_LIB(e);
952 : 130 : d.error=ERR_PACK(l,0,0);
953 : 130 : p=ERRFN(err_get_item)(&d);
954 [ + - ]: 130 : return((p == NULL)?NULL:p->string);
955 : : }
956 : :
957 : 51109 : const char *ERR_func_error_string(unsigned long e)
958 : : {
959 : : ERR_STRING_DATA d,*p;
960 : : unsigned long l,f;
961 : :
962 : 51109 : err_fns_check();
963 : 51109 : l=ERR_GET_LIB(e);
964 : 51109 : f=ERR_GET_FUNC(e);
965 : 51109 : d.error=ERR_PACK(l,f,0);
966 : 51109 : p=ERRFN(err_get_item)(&d);
967 [ + + ]: 51109 : return((p == NULL)?NULL:p->string);
968 : : }
969 : :
970 : 130 : const char *ERR_reason_error_string(unsigned long e)
971 : : {
972 : 130 : ERR_STRING_DATA d,*p=NULL;
973 : : unsigned long l,r;
974 : :
975 : 130 : err_fns_check();
976 : 130 : l=ERR_GET_LIB(e);
977 : 130 : r=ERR_GET_REASON(e);
978 : 130 : d.error=ERR_PACK(l,0,r);
979 : 130 : p=ERRFN(err_get_item)(&d);
980 [ + + ]: 130 : if (!p)
981 : : {
982 : 25 : d.error=ERR_PACK(0,0,r);
983 : 25 : p=ERRFN(err_get_item)(&d);
984 : : }
985 [ + - ]: 130 : return((p == NULL)?NULL:p->string);
986 : : }
987 : :
988 : 1630 : void ERR_remove_thread_state(const CRYPTO_THREADID *id)
989 : : {
990 : : ERR_STATE tmp;
991 : :
992 [ - + ]: 1630 : if (id)
993 : 0 : CRYPTO_THREADID_cpy(&tmp.tid, id);
994 : : else
995 : 1630 : CRYPTO_THREADID_current(&tmp.tid);
996 : 1630 : err_fns_check();
997 : : /* thread_del_item automatically destroys the LHASH if the number of
998 : : * items reaches zero. */
999 : 1630 : ERRFN(thread_del_item)(&tmp);
1000 : 1630 : }
1001 : :
1002 : : #ifndef OPENSSL_NO_DEPRECATED
1003 : 0 : void ERR_remove_state(unsigned long pid)
1004 : : {
1005 : 0 : ERR_remove_thread_state(NULL);
1006 : 0 : }
1007 : : #endif
1008 : :
1009 : 415669 : ERR_STATE *ERR_get_state(void)
1010 : : {
1011 : : static ERR_STATE fallback;
1012 : 415669 : ERR_STATE *ret,tmp,*tmpp=NULL;
1013 : : int i;
1014 : : CRYPTO_THREADID tid;
1015 : :
1016 : 415669 : err_fns_check();
1017 : 415669 : CRYPTO_THREADID_current(&tid);
1018 : 415669 : CRYPTO_THREADID_cpy(&tmp.tid, &tid);
1019 : 415669 : ret=ERRFN(thread_get_item)(&tmp);
1020 : :
1021 : : /* ret == the error state, if NULL, make a new one */
1022 [ + + ]: 415669 : if (ret == NULL)
1023 : : {
1024 : 1628 : ret=(ERR_STATE *)OPENSSL_malloc(sizeof(ERR_STATE));
1025 [ + - ]: 1628 : if (ret == NULL) return(&fallback);
1026 : 1628 : CRYPTO_THREADID_cpy(&ret->tid, &tid);
1027 : 1628 : ret->top=0;
1028 : 1628 : ret->bottom=0;
1029 [ + + ]: 27676 : for (i=0; i<ERR_NUM_ERRORS; i++)
1030 : : {
1031 : 26048 : ret->err_data[i]=NULL;
1032 : 26048 : ret->err_data_flags[i]=0;
1033 : : }
1034 : 1628 : tmpp = ERRFN(thread_set_item)(ret);
1035 : : /* To check if insertion failed, do a get. */
1036 [ - + ]: 1628 : if (ERRFN(thread_get_item)(ret) != ret)
1037 : : {
1038 : 0 : ERR_STATE_free(ret); /* could not insert it */
1039 : 0 : return(&fallback);
1040 : : }
1041 : : /* If a race occurred in this function and we came second, tmpp
1042 : : * is the first one that we just replaced. */
1043 [ - + ]: 1628 : if (tmpp)
1044 : 0 : ERR_STATE_free(tmpp);
1045 : : }
1046 : 415669 : return ret;
1047 : : }
1048 : :
1049 : 6552 : int ERR_get_next_error_library(void)
1050 : : {
1051 : 6552 : err_fns_check();
1052 : 6552 : return ERRFN(get_next_lib)();
1053 : : }
1054 : :
1055 : 4774 : void ERR_set_error_data(char *data, int flags)
1056 : : {
1057 : : ERR_STATE *es;
1058 : : int i;
1059 : :
1060 : 4774 : es=ERR_get_state();
1061 : :
1062 : 4774 : i=es->top;
1063 [ + + ]: 4774 : if (i == 0)
1064 : 281 : i=ERR_NUM_ERRORS-1;
1065 : :
1066 [ - + ][ # # ]: 4774 : err_clear_data(es,i);
1067 : 4774 : es->err_data[i]=data;
1068 : 4774 : es->err_data_flags[i]=flags;
1069 : 4774 : }
1070 : :
1071 : 4774 : void ERR_add_error_data(int num, ...)
1072 : : {
1073 : : va_list args;
1074 : 4774 : va_start(args, num);
1075 : 4774 : ERR_add_error_vdata(num, args);
1076 : 4774 : va_end(args);
1077 : 4774 : }
1078 : :
1079 : 4774 : void ERR_add_error_vdata(int num, va_list args)
1080 : : {
1081 : : int i,n,s;
1082 : : char *str,*p,*a;
1083 : :
1084 : 4774 : s=80;
1085 : 4774 : str=OPENSSL_malloc(s+1);
1086 [ + - ]: 4774 : if (str == NULL) return;
1087 : 4774 : str[0]='\0';
1088 : :
1089 : 4774 : n=0;
1090 [ + + ]: 24271 : for (i=0; i<num; i++)
1091 : : {
1092 [ + - ]: 19497 : a=va_arg(args, char*);
1093 : : /* ignore NULLs, thanks to Bob Beck <beck@obtuse.com> */
1094 [ + + ]: 19497 : if (a != NULL)
1095 : : {
1096 : 18781 : n+=strlen(a);
1097 [ + + ]: 18781 : if (n > s)
1098 : : {
1099 : 3154 : s=n+20;
1100 : 3154 : p=OPENSSL_realloc(str,s+1);
1101 [ - + ]: 3154 : if (p == NULL)
1102 : : {
1103 : 0 : OPENSSL_free(str);
1104 : 0 : return;
1105 : : }
1106 : : else
1107 : : str=p;
1108 : : }
1109 : 18781 : BUF_strlcat(str,a,(size_t)s+1);
1110 : : }
1111 : : }
1112 : 4774 : ERR_set_error_data(str,ERR_TXT_MALLOCED|ERR_TXT_STRING);
1113 : : }
1114 : :
1115 : 45593 : int ERR_set_mark(void)
1116 : : {
1117 : : ERR_STATE *es;
1118 : :
1119 : 45593 : es=ERR_get_state();
1120 : :
1121 [ + + ]: 45593 : if (es->bottom == es->top) return 0;
1122 : 779 : es->err_flags[es->top]|=ERR_FLAG_MARK;
1123 : 779 : return 1;
1124 : : }
1125 : :
1126 : 45593 : int ERR_pop_to_mark(void)
1127 : : {
1128 : : ERR_STATE *es;
1129 : :
1130 : 45593 : es=ERR_get_state();
1131 : :
1132 [ + + ]: 98425 : while(es->bottom != es->top
1133 [ + + ]: 8018 : && (es->err_flags[es->top] & ERR_FLAG_MARK) == 0)
1134 : : {
1135 [ + + ][ + - ]: 7239 : err_clear(es,es->top);
1136 : 7239 : es->top-=1;
1137 [ + + ]: 52832 : if (es->top == -1) es->top=ERR_NUM_ERRORS-1;
1138 : : }
1139 : :
1140 [ + + ]: 45593 : if (es->bottom == es->top) return 0;
1141 : 779 : es->err_flags[es->top]&=~ERR_FLAG_MARK;
1142 : 779 : return 1;
1143 : : }
|