114113SN/A/* crypto/bio/b_print.c */ 214113SN/A/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) 314113SN/A * All rights reserved. 414113SN/A * 514113SN/A * This package is an SSL implementation written 614113SN/A * by Eric Young (eay@cryptsoft.com). 714113SN/A * The implementation was written so as to conform with Netscapes SSL. 814113SN/A * 914113SN/A * This library is free for commercial and non-commercial use as long as 1014113SN/A * the following conditions are aheared to. The following conditions 1114113SN/A * apply to all code found in this distribution, be it the RC4, RSA, 1214113SN/A * lhash, DES, etc., code; not just the SSL code. The SSL documentation 1314113SN/A * included with this distribution is covered by the same copyright terms 1414113SN/A * except that the holder is Tim Hudson (tjh@cryptsoft.com). 1514113SN/A * 1614113SN/A * Copyright remains Eric Young's, and as such any Copyright notices in 1714113SN/A * the code are not to be removed. 1814113SN/A * If this package is used in a product, Eric Young should be given attribution 1914113SN/A * as the author of the parts of the library used. 2014113SN/A * This can be in the form of a textual message at program startup or 2114113SN/A * in documentation (online or textual) provided with the package. 2214113SN/A * 2314113SN/A * Redistribution and use in source and binary forms, with or without 2415424Splevart * modification, are permitted provided that the following conditions 2514113SN/A * are met: 2614113SN/A * 1. Redistributions of source code must retain the copyright 2714113SN/A * notice, this list of conditions and the following disclaimer. 2814113SN/A * 2. Redistributions in binary form must reproduce the above copyright 2915424Splevart * notice, this list of conditions and the following disclaimer in the 3014113SN/A * documentation and/or other materials provided with the distribution. 3114113SN/A * 3. All advertising materials mentioning features or use of this software 3214113SN/A * must display the following acknowledgement: 3314113SN/A * "This product includes cryptographic software written by 3414113SN/A * Eric Young (eay@cryptsoft.com)" 3514113SN/A * The word 'cryptographic' can be left out if the rouines from the library 3614113SN/A * being used are not cryptographic related :-). 3714113SN/A * 4. If you include any Windows specific code (or a derivative thereof) from 3814113SN/A * the apps directory (application code) you must include an acknowledgement: 3914113SN/A * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" 4014113SN/A * 4114113SN/A * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND 4214113SN/A * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 4315424Splevart * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 4414113SN/A * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 4514113SN/A * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 4614113SN/A * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 4714113SN/A * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 4814113SN/A * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 4914113SN/A * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 5014113SN/A * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 5114113SN/A * SUCH DAMAGE. 5214113SN/A * 5314113SN/A * The licence and distribution terms for any publically available version or 5414113SN/A * derivative of this code cannot be changed. i.e. this code cannot simply be 5514113SN/A * copied and put under another distribution licence 5614113SN/A * [including the GNU Public Licence.] 5714113SN/A */ 5814113SN/A 5914113SN/A/* disable assert() unless BIO_DEBUG has been defined */ 6014113SN/A#ifndef BIO_DEBUG 6114113SN/A# ifndef NDEBUG 6214113SN/A# define NDEBUG 6314113SN/A# endif 6414113SN/A#endif 6514113SN/A 6614113SN/A/* 6714113SN/A * Stolen from tjh's ssl/ssl_trc.c stuff. 6814113SN/A */ 6914113SN/A 7014113SN/A#include <stdio.h> 7114113SN/A#include <string.h> 7214113SN/A#include <ctype.h> 7314113SN/A#include <assert.h> 7414113SN/A#include <limits.h> 7514113SN/A#include "cryptlib.h" 7614113SN/A#ifndef NO_SYS_TYPES_H 7714113SN/A# include <sys/types.h> 7814113SN/A#endif 7914113SN/A#include <openssl/bn.h> /* To get BN_LLONG properly defined */ 8014113SN/A#include <openssl/bio.h> 8114113SN/A 8214113SN/A#if defined(BN_LLONG) || defined(SIXTY_FOUR_BIT) 8314113SN/A# ifndef HAVE_LONG_LONG 8414113SN/A# define HAVE_LONG_LONG 1 8514113SN/A# endif 8614113SN/A#endif 8714113SN/A 8814113SN/A/***************************************************************************/ 8914113SN/A 9014113SN/A/* 9114113SN/A * Copyright Patrick Powell 1995 9214113SN/A * This code is based on code written by Patrick Powell <papowell@astart.com> 9314113SN/A * It may be used for any purpose as long as this notice remains intact 9414113SN/A * on all source code distributions. 9514113SN/A */ 9614113SN/A 9714113SN/A/*- 9814113SN/A * This code contains numerious changes and enhancements which were 9914113SN/A * made by lots of contributors over the last years to Patrick Powell's 10014113SN/A * original code: 10114113SN/A * 10214113SN/A * o Patrick Powell <papowell@astart.com> (1995) 10314113SN/A * o Brandon Long <blong@fiction.net> (1996, for Mutt) 10414113SN/A * o Thomas Roessler <roessler@guug.de> (1998, for Mutt) 10514113SN/A * o Michael Elkins <me@cs.hmc.edu> (1998, for Mutt) 10614113SN/A * o Andrew Tridgell <tridge@samba.org> (1998, for Samba) 10714113SN/A * o Luke Mewburn <lukem@netbsd.org> (1999, for LukemFTP) 10814113SN/A * o Ralf S. Engelschall <rse@engelschall.com> (1999, for Pth) 10914113SN/A * o ... (for OpenSSL) 11014113SN/A */ 11114113SN/A 11214113SN/A#ifdef HAVE_LONG_DOUBLE 11314113SN/A# define LDOUBLE long double 11414113SN/A#else 11514113SN/A# define LDOUBLE double 11614113SN/A#endif 11714113SN/A 11814113SN/A#ifdef HAVE_LONG_LONG 11914113SN/A# if defined(_WIN32) && !defined(__GNUC__) 12014113SN/A# define LLONG __int64 12114113SN/A# else 12214113SN/A# define LLONG long long 12314113SN/A# endif 12414113SN/A#else 12514113SN/A# define LLONG long 12614113SN/A#endif 12714113SN/A 12814113SN/Astatic int fmtstr(char **, char **, size_t *, size_t *, 12914113SN/A const char *, int, int, int); 13014113SN/Astatic int fmtint(char **, char **, size_t *, size_t *, 13114113SN/A LLONG, int, int, int, int); 13214113SN/Astatic int fmtfp(char **, char **, size_t *, size_t *, 13314113SN/A LDOUBLE, int, int, int); 13414113SN/Astatic int doapr_outch(char **, char **, size_t *, size_t *, int); 13514113SN/Astatic int _dopr(char **sbuffer, char **buffer, 13614113SN/A size_t *maxlen, size_t *retlen, int *truncated, 13714113SN/A const char *format, va_list args); 13814113SN/A 13914113SN/A/* format read states */ 14014113SN/A#define DP_S_DEFAULT 0 14114113SN/A#define DP_S_FLAGS 1 14214113SN/A#define DP_S_MIN 2 14314113SN/A#define DP_S_DOT 3 14414113SN/A#define DP_S_MAX 4 14514113SN/A#define DP_S_MOD 5 14614113SN/A#define DP_S_CONV 6 14714113SN/A#define DP_S_DONE 7 14814113SN/A 14914113SN/A/* format flags - Bits */ 15014113SN/A#define DP_F_MINUS (1 << 0) 15114113SN/A#define DP_F_PLUS (1 << 1) 15214113SN/A#define DP_F_SPACE (1 << 2) 15314113SN/A#define DP_F_NUM (1 << 3) 15414113SN/A#define DP_F_ZERO (1 << 4) 15514113SN/A#define DP_F_UP (1 << 5) 15614113SN/A#define DP_F_UNSIGNED (1 << 6) 15714113SN/A 15814113SN/A/* conversion flags */ 15914113SN/A#define DP_C_SHORT 1 16014113SN/A#define DP_C_LONG 2 16114113SN/A#define DP_C_LDOUBLE 3 16214113SN/A#define DP_C_LLONG 4 16314113SN/A 16414113SN/A/* some handy macros */ 16514113SN/A#define char_to_int(p) (p - '0') 16614113SN/A#define OSSL_MAX(p,q) ((p >= q) ? p : q) 16714113SN/A 16814113SN/Astatic int 16914113SN/A_dopr(char **sbuffer, 17014113SN/A char **buffer, 17114113SN/A size_t *maxlen, 17214113SN/A size_t *retlen, int *truncated, const char *format, va_list args) 17314113SN/A{ 17414113SN/A char ch; 17514113SN/A LLONG value; 17614113SN/A LDOUBLE fvalue; 17714113SN/A char *strvalue; 17814113SN/A int min; 17914113SN/A int max; 18014113SN/A int state; 18114113SN/A int flags; 18214113SN/A int cflags; 18314113SN/A size_t currlen; 18414113SN/A 18514113SN/A state = DP_S_DEFAULT; 18614113SN/A flags = currlen = cflags = min = 0; 18714113SN/A max = -1; 18814113SN/A ch = *format++; 18914113SN/A 19014113SN/A while (state != DP_S_DONE) { 19114113SN/A if (ch == '\0' || (buffer == NULL && currlen >= *maxlen)) 19214113SN/A state = DP_S_DONE; 19314113SN/A 19414113SN/A switch (state) { 19514113SN/A case DP_S_DEFAULT: 19614113SN/A if (ch == '%') 19714113SN/A state = DP_S_FLAGS; 19814113SN/A else 19914113SN/A if(!doapr_outch(sbuffer, buffer, &currlen, maxlen, ch)) 20014113SN/A return 0; 20114113SN/A ch = *format++; 20214113SN/A break; 20314113SN/A case DP_S_FLAGS: 20414113SN/A switch (ch) { 20514113SN/A case '-': 20614113SN/A flags |= DP_F_MINUS; 20714113SN/A ch = *format++; 20814113SN/A break; 20914113SN/A case '+': 21014113SN/A flags |= DP_F_PLUS; 21114113SN/A ch = *format++; 21214113SN/A break; 21314113SN/A case ' ': 21414113SN/A flags |= DP_F_SPACE; 21514113SN/A ch = *format++; 21614113SN/A break; 21714113SN/A case '#': 21814113SN/A flags |= DP_F_NUM; 21914113SN/A ch = *format++; 22014113SN/A break; 22114113SN/A case '0': 22214113SN/A flags |= DP_F_ZERO; 22314113SN/A ch = *format++; 22414113SN/A break; 22514113SN/A default: 22614113SN/A state = DP_S_MIN; 22714113SN/A break; 22814113SN/A } 22914113SN/A break; 23014113SN/A case DP_S_MIN: 23114113SN/A if (isdigit((unsigned char)ch)) { 23214113SN/A min = 10 * min + char_to_int(ch); 23314113SN/A ch = *format++; 23414113SN/A } else if (ch == '*') { 23514113SN/A min = va_arg(args, int); 23614113SN/A ch = *format++; 23714113SN/A state = DP_S_DOT; 23814113SN/A } else 23914113SN/A state = DP_S_DOT; 24014113SN/A break; 24114113SN/A case DP_S_DOT: 24214113SN/A if (ch == '.') { 24314113SN/A state = DP_S_MAX; 24414113SN/A ch = *format++; 24514113SN/A } else 24614113SN/A state = DP_S_MOD; 24714113SN/A break; 24814113SN/A case DP_S_MAX: 24914113SN/A if (isdigit((unsigned char)ch)) { 25014113SN/A if (max < 0) 25114113SN/A max = 0; 25214113SN/A max = 10 * max + char_to_int(ch); 25314113SN/A ch = *format++; 25414113SN/A } else if (ch == '*') { 25514113SN/A max = va_arg(args, int); 25614113SN/A ch = *format++; 25714113SN/A state = DP_S_MOD; 25814113SN/A } else 25914113SN/A state = DP_S_MOD; 26014113SN/A break; 26114113SN/A case DP_S_MOD: 26214113SN/A switch (ch) { 26314113SN/A case 'h': 26414113SN/A cflags = DP_C_SHORT; 26514113SN/A ch = *format++; 26614113SN/A break; 26714113SN/A case 'l': 26814113SN/A if (*format == 'l') { 26914113SN/A cflags = DP_C_LLONG; 27014113SN/A format++; 27114113SN/A } else 27214113SN/A cflags = DP_C_LONG; 27314113SN/A ch = *format++; 27414113SN/A break; 27514113SN/A case 'q': 27614113SN/A cflags = DP_C_LLONG; 27714113SN/A ch = *format++; 27814113SN/A break; 27914113SN/A case 'L': 28014113SN/A cflags = DP_C_LDOUBLE; 28114113SN/A ch = *format++; 28214113SN/A break; 28314113SN/A default: 28414113SN/A break; 28514113SN/A } 28614113SN/A state = DP_S_CONV; 28714113SN/A break; 28814113SN/A case DP_S_CONV: 28914113SN/A switch (ch) { 29014113SN/A case 'd': 29114113SN/A case 'i': 29214113SN/A switch (cflags) { 29314113SN/A case DP_C_SHORT: 29414113SN/A value = (short int)va_arg(args, int); 29514113SN/A break; 29614113SN/A case DP_C_LONG: 29714113SN/A value = va_arg(args, long int); 29814113SN/A break; 29914113SN/A case DP_C_LLONG: 30014113SN/A value = va_arg(args, LLONG); 30114113SN/A break; 30214113SN/A default: 30314113SN/A value = va_arg(args, int); 30414113SN/A break; 30514113SN/A } 30614113SN/A if (!fmtint(sbuffer, buffer, &currlen, maxlen, value, 10, min, 30714113SN/A max, flags)) 30814113SN/A return 0; 30914113SN/A break; 31014113SN/A case 'X': 31114113SN/A flags |= DP_F_UP; 31214113SN/A /* FALLTHROUGH */ 31314113SN/A case 'x': 31414113SN/A case 'o': 31514113SN/A case 'u': 31614113SN/A flags |= DP_F_UNSIGNED; 31714113SN/A switch (cflags) { 31814113SN/A case DP_C_SHORT: 31914113SN/A value = (unsigned short int)va_arg(args, unsigned int); 32014113SN/A break; 32114113SN/A case DP_C_LONG: 32214113SN/A value = (LLONG) va_arg(args, unsigned long int); 32314113SN/A break; 32414113SN/A case DP_C_LLONG: 32514113SN/A value = va_arg(args, unsigned LLONG); 32614113SN/A break; 32714113SN/A default: 32814113SN/A value = (LLONG) va_arg(args, unsigned int); 32914113SN/A break; 33014113SN/A } 33114113SN/A if (!fmtint(sbuffer, buffer, &currlen, maxlen, value, 33214113SN/A ch == 'o' ? 8 : (ch == 'u' ? 10 : 16), 33314113SN/A min, max, flags)) 33414113SN/A return 0; 33514113SN/A break; 33614113SN/A case 'f': 33714113SN/A if (cflags == DP_C_LDOUBLE) 33814113SN/A fvalue = va_arg(args, LDOUBLE); 33914113SN/A else 34014113SN/A fvalue = va_arg(args, double); 34114113SN/A if (!fmtfp(sbuffer, buffer, &currlen, maxlen, fvalue, min, max, 34214113SN/A flags)) 34314113SN/A return 0; 34414113SN/A break; 34514113SN/A case 'E': 34614113SN/A flags |= DP_F_UP; 34714113SN/A case 'e': 34814113SN/A if (cflags == DP_C_LDOUBLE) 34914113SN/A fvalue = va_arg(args, LDOUBLE); 35014113SN/A else 35114113SN/A fvalue = va_arg(args, double); 35214113SN/A break; 35314113SN/A case 'G': 35414113SN/A flags |= DP_F_UP; 35514113SN/A case 'g': 35614113SN/A if (cflags == DP_C_LDOUBLE) 35714113SN/A fvalue = va_arg(args, LDOUBLE); 35814113SN/A else 35914113SN/A fvalue = va_arg(args, double); 36014113SN/A break; 36114113SN/A case 'c': 36214113SN/A if(!doapr_outch(sbuffer, buffer, &currlen, maxlen, 36314113SN/A va_arg(args, int))) 36414113SN/A return 0; 36514113SN/A break; 36614113SN/A case 's': 36714113SN/A strvalue = va_arg(args, char *); 36814113SN/A if (max < 0) { 36914113SN/A if (buffer) 37014113SN/A max = INT_MAX; 37114113SN/A else 37214113SN/A max = *maxlen; 37314113SN/A } 37414113SN/A if (!fmtstr(sbuffer, buffer, &currlen, maxlen, strvalue, 37514113SN/A flags, min, max)) 37614113SN/A return 0; 37714113SN/A break; 37814113SN/A case 'p': 37914113SN/A value = (long)va_arg(args, void *); 38015424Splevart if (!fmtint(sbuffer, buffer, &currlen, maxlen, 38114113SN/A value, 16, min, max, flags | DP_F_NUM)) 38214113SN/A return 0; 38314113SN/A break; 38414113SN/A case 'n': /* XXX */ 38514113SN/A if (cflags == DP_C_SHORT) { 38614113SN/A short int *num; 38714113SN/A num = va_arg(args, short int *); 38814113SN/A *num = currlen; 38914113SN/A } else if (cflags == DP_C_LONG) { /* XXX */ 39014113SN/A long int *num; 39114113SN/A num = va_arg(args, long int *); 39214113SN/A *num = (long int)currlen; 39314113SN/A } else if (cflags == DP_C_LLONG) { /* XXX */ 39414113SN/A LLONG *num; 39514113SN/A num = va_arg(args, LLONG *); 39614113SN/A *num = (LLONG) currlen; 39714113SN/A } else { 39814113SN/A int *num; 39914113SN/A num = va_arg(args, int *); 40014113SN/A *num = currlen; 40114113SN/A } 40214113SN/A break; 40314113SN/A case '%': 40414113SN/A if(!doapr_outch(sbuffer, buffer, &currlen, maxlen, ch)) 40514113SN/A return 0; 40614113SN/A break; 40714113SN/A case 'w': 40814113SN/A /* not supported yet, treat as next char */ 40914113SN/A ch = *format++; 41014113SN/A break; 41114113SN/A default: 41214113SN/A /* unknown, skip */ 41314113SN/A break; 41414113SN/A } 41514113SN/A ch = *format++; 41614113SN/A state = DP_S_DEFAULT; 41714113SN/A flags = cflags = min = 0; 41814113SN/A max = -1; 41914113SN/A break; 42014113SN/A case DP_S_DONE: 42114113SN/A break; 42214113SN/A default: 42314113SN/A break; 42414113SN/A } 42514113SN/A } 42614113SN/A *truncated = (currlen > *maxlen - 1); 42714113SN/A if (*truncated) 42814113SN/A currlen = *maxlen - 1; 42914113SN/A if(!doapr_outch(sbuffer, buffer, &currlen, maxlen, '\0')) 43014113SN/A return 0; 43114113SN/A *retlen = currlen - 1; 432 return 1; 433} 434 435static int 436fmtstr(char **sbuffer, 437 char **buffer, 438 size_t *currlen, 439 size_t *maxlen, const char *value, int flags, int min, int max) 440{ 441 int padlen; 442 size_t strln; 443 int cnt = 0; 444 445 if (value == 0) 446 value = "<NULL>"; 447 448 strln = strlen(value); 449 if (strln > INT_MAX) 450 strln = INT_MAX; 451 452 padlen = min - strln; 453 if (min < 0 || padlen < 0) 454 padlen = 0; 455 if (flags & DP_F_MINUS) 456 padlen = -padlen; 457 458 while ((padlen > 0) && (cnt < max)) { 459 if(!doapr_outch(sbuffer, buffer, currlen, maxlen, ' ')) 460 return 0; 461 --padlen; 462 ++cnt; 463 } 464 while (*value && (cnt < max)) { 465 if(!doapr_outch(sbuffer, buffer, currlen, maxlen, *value++)) 466 return 0; 467 ++cnt; 468 } 469 while ((padlen < 0) && (cnt < max)) { 470 if(!doapr_outch(sbuffer, buffer, currlen, maxlen, ' ')) 471 return 0; 472 ++padlen; 473 ++cnt; 474 } 475 return 1; 476} 477 478static int 479fmtint(char **sbuffer, 480 char **buffer, 481 size_t *currlen, 482 size_t *maxlen, LLONG value, int base, int min, int max, int flags) 483{ 484 int signvalue = 0; 485 const char *prefix = ""; 486 unsigned LLONG uvalue; 487 char convert[DECIMAL_SIZE(value) + 3]; 488 int place = 0; 489 int spadlen = 0; 490 int zpadlen = 0; 491 int caps = 0; 492 493 if (max < 0) 494 max = 0; 495 uvalue = value; 496 if (!(flags & DP_F_UNSIGNED)) { 497 if (value < 0) { 498 signvalue = '-'; 499 uvalue = -value; 500 } else if (flags & DP_F_PLUS) 501 signvalue = '+'; 502 else if (flags & DP_F_SPACE) 503 signvalue = ' '; 504 } 505 if (flags & DP_F_NUM) { 506 if (base == 8) 507 prefix = "0"; 508 if (base == 16) 509 prefix = "0x"; 510 } 511 if (flags & DP_F_UP) 512 caps = 1; 513 do { 514 convert[place++] = (caps ? "0123456789ABCDEF" : "0123456789abcdef") 515 [uvalue % (unsigned)base]; 516 uvalue = (uvalue / (unsigned)base); 517 } while (uvalue && (place < (int)sizeof(convert))); 518 if (place == sizeof(convert)) 519 place--; 520 convert[place] = 0; 521 522 zpadlen = max - place; 523 spadlen = 524 min - OSSL_MAX(max, place) - (signvalue ? 1 : 0) - strlen(prefix); 525 if (zpadlen < 0) 526 zpadlen = 0; 527 if (spadlen < 0) 528 spadlen = 0; 529 if (flags & DP_F_ZERO) { 530 zpadlen = OSSL_MAX(zpadlen, spadlen); 531 spadlen = 0; 532 } 533 if (flags & DP_F_MINUS) 534 spadlen = -spadlen; 535 536 /* spaces */ 537 while (spadlen > 0) { 538 if(!doapr_outch(sbuffer, buffer, currlen, maxlen, ' ')) 539 return 0; 540 --spadlen; 541 } 542 543 /* sign */ 544 if (signvalue) 545 if(!doapr_outch(sbuffer, buffer, currlen, maxlen, signvalue)) 546 return 0; 547 548 /* prefix */ 549 while (*prefix) { 550 if(!doapr_outch(sbuffer, buffer, currlen, maxlen, *prefix)) 551 return 0; 552 prefix++; 553 } 554 555 /* zeros */ 556 if (zpadlen > 0) { 557 while (zpadlen > 0) { 558 if(!doapr_outch(sbuffer, buffer, currlen, maxlen, '0')) 559 return 0; 560 --zpadlen; 561 } 562 } 563 /* digits */ 564 while (place > 0) { 565 if (!doapr_outch(sbuffer, buffer, currlen, maxlen, convert[--place])) 566 return 0; 567 } 568 569 /* left justified spaces */ 570 while (spadlen < 0) { 571 if (!doapr_outch(sbuffer, buffer, currlen, maxlen, ' ')) 572 return 0; 573 ++spadlen; 574 } 575 return 1; 576} 577 578static LDOUBLE abs_val(LDOUBLE value) 579{ 580 LDOUBLE result = value; 581 if (value < 0) 582 result = -value; 583 return result; 584} 585 586static LDOUBLE pow_10(int in_exp) 587{ 588 LDOUBLE result = 1; 589 while (in_exp) { 590 result *= 10; 591 in_exp--; 592 } 593 return result; 594} 595 596static long roundv(LDOUBLE value) 597{ 598 long intpart; 599 intpart = (long)value; 600 value = value - intpart; 601 if (value >= 0.5) 602 intpart++; 603 return intpart; 604} 605 606static int 607fmtfp(char **sbuffer, 608 char **buffer, 609 size_t *currlen, 610 size_t *maxlen, LDOUBLE fvalue, int min, int max, int flags) 611{ 612 int signvalue = 0; 613 LDOUBLE ufvalue; 614 char iconvert[20]; 615 char fconvert[20]; 616 int iplace = 0; 617 int fplace = 0; 618 int padlen = 0; 619 int zpadlen = 0; 620 long intpart; 621 long fracpart; 622 long max10; 623 624 if (max < 0) 625 max = 6; 626 ufvalue = abs_val(fvalue); 627 if (fvalue < 0) 628 signvalue = '-'; 629 else if (flags & DP_F_PLUS) 630 signvalue = '+'; 631 else if (flags & DP_F_SPACE) 632 signvalue = ' '; 633 634 intpart = (long)ufvalue; 635 636 /* 637 * sorry, we only support 9 digits past the decimal because of our 638 * conversion method 639 */ 640 if (max > 9) 641 max = 9; 642 643 /* 644 * we "cheat" by converting the fractional part to integer by multiplying 645 * by a factor of 10 646 */ 647 max10 = roundv(pow_10(max)); 648 fracpart = roundv(pow_10(max) * (ufvalue - intpart)); 649 650 if (fracpart >= max10) { 651 intpart++; 652 fracpart -= max10; 653 } 654 655 /* convert integer part */ 656 do { 657 iconvert[iplace++] = "0123456789"[intpart % 10]; 658 intpart = (intpart / 10); 659 } while (intpart && (iplace < (int)sizeof(iconvert))); 660 if (iplace == sizeof iconvert) 661 iplace--; 662 iconvert[iplace] = 0; 663 664 /* convert fractional part */ 665 do { 666 fconvert[fplace++] = "0123456789"[fracpart % 10]; 667 fracpart = (fracpart / 10); 668 } while (fplace < max); 669 if (fplace == sizeof fconvert) 670 fplace--; 671 fconvert[fplace] = 0; 672 673 /* -1 for decimal point, another -1 if we are printing a sign */ 674 padlen = min - iplace - max - 1 - ((signvalue) ? 1 : 0); 675 zpadlen = max - fplace; 676 if (zpadlen < 0) 677 zpadlen = 0; 678 if (padlen < 0) 679 padlen = 0; 680 if (flags & DP_F_MINUS) 681 padlen = -padlen; 682 683 if ((flags & DP_F_ZERO) && (padlen > 0)) { 684 if (signvalue) { 685 if (!doapr_outch(sbuffer, buffer, currlen, maxlen, signvalue)) 686 return 0; 687 --padlen; 688 signvalue = 0; 689 } 690 while (padlen > 0) { 691 if (!doapr_outch(sbuffer, buffer, currlen, maxlen, '0')) 692 return 0; 693 --padlen; 694 } 695 } 696 while (padlen > 0) { 697 if (!doapr_outch(sbuffer, buffer, currlen, maxlen, ' ')) 698 return 0; 699 --padlen; 700 } 701 if (signvalue && !doapr_outch(sbuffer, buffer, currlen, maxlen, signvalue)) 702 return 0; 703 704 while (iplace > 0) { 705 if (!doapr_outch(sbuffer, buffer, currlen, maxlen, iconvert[--iplace])) 706 return 0; 707 } 708 709 /* 710 * Decimal point. This should probably use locale to find the correct 711 * char to print out. 712 */ 713 if (max > 0 || (flags & DP_F_NUM)) { 714 if (!doapr_outch(sbuffer, buffer, currlen, maxlen, '.')) 715 return 0; 716 717 while (fplace > 0) { 718 if(!doapr_outch(sbuffer, buffer, currlen, maxlen, 719 fconvert[--fplace])) 720 return 0; 721 } 722 } 723 while (zpadlen > 0) { 724 if (!doapr_outch(sbuffer, buffer, currlen, maxlen, '0')) 725 return 0; 726 --zpadlen; 727 } 728 729 while (padlen < 0) { 730 if (!doapr_outch(sbuffer, buffer, currlen, maxlen, ' ')) 731 return 0; 732 ++padlen; 733 } 734 return 1; 735} 736 737#define BUFFER_INC 1024 738 739static int 740doapr_outch(char **sbuffer, 741 char **buffer, size_t *currlen, size_t *maxlen, int c) 742{ 743 /* If we haven't at least one buffer, someone has doe a big booboo */ 744 assert(*sbuffer != NULL || buffer != NULL); 745 746 /* |currlen| must always be <= |*maxlen| */ 747 assert(*currlen <= *maxlen); 748 749 if (buffer && *currlen == *maxlen) { 750 if (*maxlen > INT_MAX - BUFFER_INC) 751 return 0; 752 753 *maxlen += BUFFER_INC; 754 if (*buffer == NULL) { 755 *buffer = OPENSSL_malloc(*maxlen); 756 if (*buffer == NULL) 757 return 0; 758 if (*currlen > 0) { 759 assert(*sbuffer != NULL); 760 memcpy(*buffer, *sbuffer, *currlen); 761 } 762 *sbuffer = NULL; 763 } else { 764 char *tmpbuf; 765 tmpbuf = OPENSSL_realloc(*buffer, *maxlen); 766 if (tmpbuf == NULL) 767 return 0; 768 *buffer = tmpbuf; 769 } 770 } 771 772 if (*currlen < *maxlen) { 773 if (*sbuffer) 774 (*sbuffer)[(*currlen)++] = (char)c; 775 else 776 (*buffer)[(*currlen)++] = (char)c; 777 } 778 779 return 1; 780} 781 782/***************************************************************************/ 783 784int BIO_printf(BIO *bio, const char *format, ...) 785{ 786 va_list args; 787 int ret; 788 789 va_start(args, format); 790 791 ret = BIO_vprintf(bio, format, args); 792 793 va_end(args); 794 return (ret); 795} 796 797int BIO_vprintf(BIO *bio, const char *format, va_list args) 798{ 799 int ret; 800 size_t retlen; 801 char hugebuf[1024 * 2]; /* Was previously 10k, which is unreasonable 802 * in small-stack environments, like threads 803 * or DOS programs. */ 804 char *hugebufp = hugebuf; 805 size_t hugebufsize = sizeof(hugebuf); 806 char *dynbuf = NULL; 807 int ignored; 808 809 dynbuf = NULL; 810 CRYPTO_push_info("doapr()"); 811 if (!_dopr(&hugebufp, &dynbuf, &hugebufsize, &retlen, &ignored, format, 812 args)) { 813 OPENSSL_free(dynbuf); 814 return -1; 815 } 816 if (dynbuf) { 817 ret = BIO_write(bio, dynbuf, (int)retlen); 818 OPENSSL_free(dynbuf); 819 } else { 820 ret = BIO_write(bio, hugebuf, (int)retlen); 821 } 822 CRYPTO_pop_info(); 823 return (ret); 824} 825 826/* 827 * As snprintf is not available everywhere, we provide our own 828 * implementation. This function has nothing to do with BIOs, but it's 829 * closely related to BIO_printf, and we need *some* name prefix ... (XXX the 830 * function should be renamed, but to what?) 831 */ 832int BIO_snprintf(char *buf, size_t n, const char *format, ...) 833{ 834 va_list args; 835 int ret; 836 837 va_start(args, format); 838 839 ret = BIO_vsnprintf(buf, n, format, args); 840 841 va_end(args); 842 return (ret); 843} 844 845int BIO_vsnprintf(char *buf, size_t n, const char *format, va_list args) 846{ 847 size_t retlen; 848 int truncated; 849 850 if(!_dopr(&buf, NULL, &n, &retlen, &truncated, format, args)) 851 return -1; 852 853 if (truncated) 854 /* 855 * In case of truncation, return -1 like traditional snprintf. 856 * (Current drafts for ISO/IEC 9899 say snprintf should return the 857 * number of characters that would have been written, had the buffer 858 * been large enough.) 859 */ 860 return -1; 861 else 862 return (retlen <= INT_MAX) ? (int)retlen : -1; 863} 864