From e5c84d5152c11a3dfa436041d3336a6f403baad8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bodo=20M=C3=B6ller?= Date: Fri, 14 Apr 2000 23:36:15 +0000 Subject: [PATCH] New function ERR_error_string_n. --- CHANGES | 6 ++ STATUS | 6 +- apps/errstr.c | 5 +- crypto/bio/b_print.c | 124 +++++++++++++++++++------------- crypto/bio/bio.h | 3 +- crypto/err/err.c | 62 +++++++++++----- crypto/err/err.h | 1 + crypto/err/err_prn.c | 6 +- doc/crypto/ERR_error_string.pod | 12 +++- util/libeay.num | 2 + 10 files changed, 147 insertions(+), 80 deletions(-) diff --git a/CHANGES b/CHANGES index 698ac30004..4688929252 100644 --- a/CHANGES +++ b/CHANGES @@ -4,6 +4,12 @@ Changes between 0.9.5a and 0.9.6 [xx XXX 2000] + *) New function ERR_error_string_n(e, buf, len) which is like + ERR_error_string(e, buf), but writes at most 'len' bytes + including the 0 terminator. For ERR_error_string_n, 'buf' + may not be NULL. + [Damien Miller , Bodo Moeller] + *) CONF library reworked to become more general. A new CONF configuration file reader "class" is implemented as well as a new functions (NCONF_*, for "New CONF") to handle it. The now diff --git a/STATUS b/STATUS index 99f2aec4d2..410739c045 100644 --- a/STATUS +++ b/STATUS @@ -1,6 +1,6 @@ OpenSSL STATUS Last modified at - ______________ $Date: 2000/04/01 12:32:10 $ + ______________ $Date: 2000/04/14 23:35:50 $ DEVELOPMENT STATE @@ -89,10 +89,6 @@ use a key length decided by the size of the RSA encrypted key and expect RC2 to adapt). - o ERR_error_string(..., buf) does not know how large buf is, - there should be ERR_error_string_n(..., buf, bufsize) - or similar. - WISHES o diff --git a/apps/errstr.c b/apps/errstr.c index 4650379589..2c62046476 100644 --- a/apps/errstr.c +++ b/apps/errstr.c @@ -104,7 +104,10 @@ int MAIN(int argc, char **argv) for (i=1; i (1998, for Samba) * o Luke Mewburn (1999, for LukemFTP) * o Ralf S. Engelschall (1999, for Pth) + * o ... (for OpenSSL) */ #if HAVE_LONG_DOUBLE @@ -161,18 +121,17 @@ static void fmtint (void (*)(char **, size_t *, size_t *, int), char **, size_t *, size_t *, LLONG, int, int, int, int); static void fmtfp (void (*)(char **, size_t *, size_t *, int), char **, size_t *, size_t *, LDOUBLE, int, int, int); -#ifndef USE_ALLOCATING_PRINT static int dopr_isbig (size_t, size_t); static int dopr_copy (size_t); static void dopr_outch (char **, size_t *, size_t *, int); -#else +#ifdef USE_ALLOCATING_PRINT static int doapr_isbig (size_t, size_t); static int doapr_copy (size_t); static void doapr_outch (char **, size_t *, size_t *, int); #endif static void _dopr(void (*)(char **, size_t *, size_t *, int), int (*)(size_t, size_t), int (*)(size_t), - char **buffer, size_t *maxlen, size_t *retlen, + char **buffer, size_t *maxlen, size_t *retlen, int *truncated, const char *format, va_list args); /* format read states */ @@ -213,8 +172,9 @@ dopr( const char *format, va_list args) { + int ignored; _dopr(dopr_outch, dopr_isbig, dopr_copy, - &buffer, &maxlen, retlen, format, args); + &buffer, &maxlen, retlen, &ignored, format, args); } #else @@ -226,8 +186,9 @@ doapr( va_list args) { size_t dummy_maxlen = 0; + int ignored; _dopr(doapr_outch, doapr_isbig, doapr_copy, - buffer, &dummy_maxlen, retlen, format, args); + buffer, &dummy_maxlen, retlen, &ignored, format, args); } #endif @@ -239,6 +200,7 @@ _dopr( char **buffer, size_t *maxlen, size_t *retlen, + int *truncated, const char *format, va_list args) { @@ -374,7 +336,7 @@ _dopr( break; } fmtint(outch_fn, buffer, &currlen, maxlen, - value, 10, min, max, flags); + value, 10, min, max, flags); break; case 'X': flags |= DP_F_UP; @@ -409,7 +371,7 @@ _dopr( else fvalue = va_arg(args, double); fmtfp(outch_fn, buffer, &currlen, maxlen, - fvalue, min, max, flags); + fvalue, min, max, flags); break; case 'E': flags |= DP_F_UP; @@ -436,7 +398,7 @@ _dopr( if (max < 0) max = (*copy_fn)(*maxlen); fmtstr(outch_fn, buffer, &currlen, maxlen, strvalue, - flags, min, max); + flags, min, max); break; case 'p': value = (long)va_arg(args, void *); @@ -484,7 +446,8 @@ _dopr( break; } } - if (currlen >= *maxlen - 1) + *truncated = (currlen > *maxlen - 1); + if (*truncated) currlen = *maxlen - 1; (*buffer)[currlen] = '\0'; *retlen = currlen; @@ -842,3 +805,62 @@ doapr_outch( return; } #endif + +/***************************************************************************/ + +int BIO_printf (BIO *bio, const char *format, ...) + { + va_list args; + int ret; + size_t retlen; +#ifdef USE_ALLOCATING_PRINT + char *hugebuf; +#else + MS_STATIC char hugebuf[1024*2]; /* 10k in one chunk is the limit */ +#endif + + va_start(args, format); + +#ifndef USE_ALLOCATING_PRINT + hugebuf[0]='\0'; + dopr(hugebuf, sizeof(hugebuf), &retlen, format, args); +#else + hugebuf = NULL; + CRYPTO_push_info("doapr()"); + doapr(&hugebuf, &retlen, format, args); + if (hugebuf) + { +#endif + ret=BIO_write(bio, hugebuf, (int)retlen); + +#ifdef USE_ALLOCATING_PRINT + Free(hugebuf); + } + CRYPTO_pop_info(); +#endif + va_end(args); + return(ret); + } + +/* As snprintf is not available everywhere, we provide our own implementation. + * This function has nothing to do with BIOs, but it's closely related + * to BIO_printf, and we need *some* name prefix ... + * (XXX the function should be renamed, but to what?) */ +int BIO_snprintf(char *buf, size_t n, const char *format, ...) + { + va_list args; + size_t retlen; + int truncated; + + va_start(args, format); + _dopr(dopr_outch, dopr_isbig, dopr_copy, + &buf, &n, &retlen, &truncated, format, args); + if (truncated) + /* In case of truncation, return -1 like traditional snprintf. + * (Current drafts for ISO/IEC 9899 say snprintf should return + * the number of characters that would have been written, + * had the buffer been large enough.) */ + return -1; + else + return (retlen <= INT_MAX) ? retlen : -1; + } diff --git a/crypto/bio/bio.h b/crypto/bio/bio.h index ebdb18170b..dd3cc3f470 100644 --- a/crypto/bio/bio.h +++ b/crypto/bio/bio.h @@ -592,7 +592,8 @@ void BIO_copy_next_retry(BIO *b); long BIO_ghbn_ctrl(int cmd,int iarg,char *parg); -int BIO_printf(BIO *bio, ...); +int BIO_printf(BIO *bio, const char *format, ...); +int BIO_snprintf(char *buf, size_t n, const char *format, ...); /* BEGIN ERROR CODES */ /* The following lines are auto generated by the script mkerr.pl. Any changes diff --git a/crypto/err/err.c b/crypto/err/err.c index cbbd326f74..a0135579f0 100644 --- a/crypto/err/err.c +++ b/crypto/err/err.c @@ -118,6 +118,7 @@ #include #include #include +#include static LHASH *error_hash=NULL; @@ -477,13 +478,11 @@ static unsigned long get_error_values(int inc, const char **file, int *line, return(ret); } -/* BAD for multi-threaded, uses a local buffer if ret == NULL */ -char *ERR_error_string(unsigned long e, char *ret) +void ERR_error_string_n(unsigned long e, char *buf, size_t len) { - static char buf[256]; + char lsbuf[64], fsbuf[64], rsbuf[64]; const char *ls,*fs,*rs; unsigned long l,f,r; - int i; l=ERR_GET_LIB(e); f=ERR_GET_FUNC(e); @@ -493,21 +492,50 @@ char *ERR_error_string(unsigned long e, char *ret) fs=ERR_func_error_string(e); rs=ERR_reason_error_string(e); - if (ret == NULL) ret=buf; - - sprintf(&(ret[0]),"error:%08lX:",e); - i=strlen(ret); - if (ls == NULL) - sprintf(&(ret[i]),":lib(%lu) ",l); - else sprintf(&(ret[i]),"%s",ls); - i=strlen(ret); + if (ls == NULL) + BIO_snprintf(lsbuf, sizeof(lsbuf), "lib(%lu)", l); if (fs == NULL) - sprintf(&(ret[i]),":func(%lu) ",f); - else sprintf(&(ret[i]),":%s",fs); - i=strlen(ret); + BIO_snprintf(fsbuf, sizeof(fsbuf), "func(%lu)", f); if (rs == NULL) - sprintf(&(ret[i]),":reason(%lu)",r); - else sprintf(&(ret[i]),":%s",rs); + 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; + ERR_error_string_n(e, buf, 256); return(ret); } diff --git a/crypto/err/err.h b/crypto/err/err.h index 35c4d97b76..e3984bb7a4 100644 --- a/crypto/err/err.h +++ b/crypto/err/err.h @@ -233,6 +233,7 @@ unsigned long ERR_peek_error_line_data(const char **file,int *line, const char **data,int *flags); void ERR_clear_error(void ); char *ERR_error_string(unsigned long e,char *buf); +void ERR_error_string_n(unsigned long e, char *buf, size_t len); const char *ERR_lib_error_string(unsigned long e); const char *ERR_func_error_string(unsigned long e); const char *ERR_reason_error_string(unsigned long e); diff --git a/crypto/err/err_prn.c b/crypto/err/err_prn.c index 0999ff214b..6f60b016c3 100644 --- a/crypto/err/err_prn.c +++ b/crypto/err/err_prn.c @@ -76,7 +76,8 @@ void ERR_print_errors_fp(FILE *fp) es=CRYPTO_thread_id(); while ((l=ERR_get_error_line_data(&file,&line,&data,&flags)) != 0) { - fprintf(fp,"%lu:%s:%s:%d:%s\n",es,ERR_error_string(l,buf), + ERR_error_string_n(l, buf, sizeof buf); + fprintf(fp,"%lu:%s:%s:%d:%s\n",es,buf, file,line,(flags&ERR_TXT_STRING)?data:""); } } @@ -94,7 +95,8 @@ void ERR_print_errors(BIO *bp) es=CRYPTO_thread_id(); while ((l=ERR_get_error_line_data(&file,&line,&data,&flags)) != 0) { - sprintf(buf2,"%lu:%s:%s:%d:",es,ERR_error_string(l,buf), + ERR_error_string_n(l, buf, sizeof buf); + sprintf(buf2,"%lu:%s:%s:%d:",es,buf, file,line); BIO_write(bp,buf2,strlen(buf2)); if (flags & ERR_TXT_STRING) diff --git a/doc/crypto/ERR_error_string.pod b/doc/crypto/ERR_error_string.pod index 0d2417599c..3518033b5b 100644 --- a/doc/crypto/ERR_error_string.pod +++ b/doc/crypto/ERR_error_string.pod @@ -9,6 +9,7 @@ ERR_error_string - obtain human-readable error message #include char *ERR_error_string(unsigned long e, char *buf); + char *ERR_error_string_n(unsigned long e, char *buf, size_t len); const char *ERR_lib_error_string(unsigned long e); const char *ERR_func_error_string(unsigned long e); @@ -17,9 +18,13 @@ ERR_error_string - obtain human-readable error message =head1 DESCRIPTION ERR_error_string() generates a human-readable string representing the -error code B, and places it at B. B must be at least 120 -bytes long. If B is B, the error string is placed in a +error code I, and places it at I. I must be at least 120 +bytes long. If I is B, the error string is placed in a static buffer. +ERR_error_string_n() is a variant of ERR_error_string() that writes +at most I characters (including the terminating 0) +and truncates the resulting string if necessary. +For ERR_error_string_n(), I may not be B. The string will have the following format: @@ -45,7 +50,7 @@ all error codes currently in the queue. =head1 RETURN VALUES ERR_error_string() returns a pointer to a static buffer containing the -string if B, B otherwise. +string if I B<== NULL>, I otherwise. ERR_lib_error_string(), ERR_func_error_string() and ERR_reason_error_string() return the strings, and B if @@ -61,5 +66,6 @@ L =head1 HISTORY ERR_error_string() is available in all versions of SSLeay and OpenSSL. +ERR_error_string_n() was added in OpenSSL 0.9.6. =cut diff --git a/util/libeay.num b/util/libeay.num index cde9bf425c..781c63d3f3 100755 --- a/util/libeay.num +++ b/util/libeay.num @@ -2262,3 +2262,5 @@ NCONF_dump_bio 2287 CONF_dump_bio 2288 NCONF_free_data 2289 CONF_set_default_method 2290 +ERR_error_string_n 2291 +BIO_snprintf 2292 -- GitLab