1/* crypto/bio/b_print.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/* disable assert() unless BIO_DEBUG has been defined */ 60#ifndef BIO_DEBUG 61# ifndef NDEBUG 62# define NDEBUG 63# endif 64#endif 65 66/* 67 * Stolen from tjh's ssl/ssl_trc.c stuff. 68 */ 69 70#include <stdio.h> 71#include <string.h> 72#include <ctype.h> 73#include <assert.h> 74#include <limits.h> 75#include "cryptlib.h" 76#ifndef NO_SYS_TYPES_H 77# include <sys/types.h> 78#endif 79#include <openssl/bn.h> /* To get BN_LLONG properly defined */ 80#include <openssl/bio.h> 81 82#if defined(BN_LLONG) || defined(SIXTY_FOUR_BIT) 83# ifndef HAVE_LONG_LONG 84# define HAVE_LONG_LONG 1 85# endif 86#endif 87 88/***************************************************************************/ 89 90/* 91 * Copyright Patrick Powell 1995 92 * This code is based on code written by Patrick Powell <papowell@astart.com> 93 * It may be used for any purpose as long as this notice remains intact 94 * on all source code distributions. 95 */ 96 97/*- 98 * This code contains numerious changes and enhancements which were 99 * made by lots of contributors over the last years to Patrick Powell's 100 * original code: 101 * 102 * o Patrick Powell <papowell@astart.com> (1995) 103 * o Brandon Long <blong@fiction.net> (1996, for Mutt) 104 * o Thomas Roessler <roessler@guug.de> (1998, for Mutt) 105 * o Michael Elkins <me@cs.hmc.edu> (1998, for Mutt) 106 * o Andrew Tridgell <tridge@samba.org> (1998, for Samba) 107 * o Luke Mewburn <lukem@netbsd.org> (1999, for LukemFTP) 108 * o Ralf S. Engelschall <rse@engelschall.com> (1999, for Pth) 109 * o ... (for OpenSSL) 110 */ 111 112#ifdef HAVE_LONG_DOUBLE 113# define LDOUBLE long double 114#else 115# define LDOUBLE double 116#endif 117 118#ifdef HAVE_LONG_LONG 119# if defined(_WIN32) && !defined(__GNUC__) 120# define LLONG __int64 121# else 122# define LLONG long long 123# endif 124#else 125# define LLONG long 126#endif 127 128static int fmtstr(char **, char **, size_t *, size_t *, 129 const char *, int, int, int); 130static int fmtint(char **, char **, size_t *, size_t *, 131 LLONG, int, int, int, int); 132static int fmtfp(char **, char **, size_t *, size_t *, 133 LDOUBLE, int, int, int); 134static int doapr_outch(char **, char **, size_t *, size_t *, int); 135static int _dopr(char **sbuffer, char **buffer, 136 size_t *maxlen, size_t *retlen, int *truncated, 137 const char *format, va_list args); 138 139/* format read states */ 140#define DP_S_DEFAULT 0 141#define DP_S_FLAGS 1 142#define DP_S_MIN 2 143#define DP_S_DOT 3 144#define DP_S_MAX 4 145#define DP_S_MOD 5 146#define DP_S_CONV 6 147#define DP_S_DONE 7 148 149/* format flags - Bits */ 150#define DP_F_MINUS (1 << 0) 151#define DP_F_PLUS (1 << 1) 152#define DP_F_SPACE (1 << 2) 153#define DP_F_NUM (1 << 3) 154#define DP_F_ZERO (1 << 4) 155#define DP_F_UP (1 << 5) 156#define DP_F_UNSIGNED (1 << 6) 157 158/* conversion flags */ 159#define DP_C_SHORT 1 160#define DP_C_LONG 2 161#define DP_C_LDOUBLE 3 162#define DP_C_LLONG 4 163 164/* some handy macros */ 165#define char_to_int(p) (p - '0') 166#define OSSL_MAX(p,q) ((p >= q) ? p : q) 167 168static int 169_dopr(char **sbuffer, 170 char **buffer, 171 size_t *maxlen, 172 size_t *retlen, int *truncated, const char *format, va_list args) 173{ 174 char ch; 175 LLONG value; 176 LDOUBLE fvalue; 177 char *strvalue; 178 int min; 179 int max; 180 int state; 181 int flags; 182 int cflags; 183 size_t currlen; 184 185 state = DP_S_DEFAULT; 186 flags = currlen = cflags = min = 0; 187 max = -1; 188 ch = *format++; 189 190 while (state != DP_S_DONE) { 191 if (ch == '\0' || (buffer == NULL && currlen >= *maxlen)) 192 state = DP_S_DONE; 193 194 switch (state) { 195 case DP_S_DEFAULT: 196 if (ch == '%') 197 state = DP_S_FLAGS; 198 else 199 if(!doapr_outch(sbuffer, buffer, &currlen, maxlen, ch)) 200 return 0; 201 ch = *format++; 202 break; 203 case DP_S_FLAGS: 204 switch (ch) { 205 case '-': 206 flags |= DP_F_MINUS; 207 ch = *format++; 208 break; 209 case '+': 210 flags |= DP_F_PLUS; 211 ch = *format++; 212 break; 213 case ' ': 214 flags |= DP_F_SPACE; 215 ch = *format++; 216 break; 217 case '#': 218 flags |= DP_F_NUM; 219 ch = *format++; 220 break; 221 case '0': 222 flags |= DP_F_ZERO; 223 ch = *format++; 224 break; 225 default: 226 state = DP_S_MIN; 227 break; 228 } 229 break; 230 case DP_S_MIN: 231 if (isdigit((unsigned char)ch)) { 232 min = 10 * min + char_to_int(ch); 233 ch = *format++; 234 } else if (ch == '*') { 235 min = va_arg(args, int); 236 ch = *format++; 237 state = DP_S_DOT; 238 } else 239 state = DP_S_DOT; 240 break; 241 case DP_S_DOT: 242 if (ch == '.') { 243 state = DP_S_MAX; 244 ch = *format++; 245 } else 246 state = DP_S_MOD; 247 break; 248 case DP_S_MAX: 249 if (isdigit((unsigned char)ch)) { 250 if (max < 0) 251 max = 0; 252 max = 10 * max + char_to_int(ch); 253 ch = *format++; 254 } else if (ch == '*') { 255 max = va_arg(args, int); 256 ch = *format++; 257 state = DP_S_MOD; 258 } else 259 state = DP_S_MOD; 260 break; 261 case DP_S_MOD: 262 switch (ch) { 263 case 'h': 264 cflags = DP_C_SHORT; 265 ch = *format++; 266 break; 267 case 'l': 268 if (*format == 'l') { 269 cflags = DP_C_LLONG; 270 format++; 271 } else 272 cflags = DP_C_LONG; 273 ch = *format++; 274 break; 275 case 'q': 276 cflags = DP_C_LLONG; 277 ch = *format++; 278 break; 279 case 'L': 280 cflags = DP_C_LDOUBLE; 281 ch = *format++; 282 break; 283 default: 284 break; 285 } 286 state = DP_S_CONV; 287 break; 288 case DP_S_CONV: 289 switch (ch) { 290 case 'd': 291 case 'i': 292 switch (cflags) { 293 case DP_C_SHORT: 294 value = (short int)va_arg(args, int); 295 break; 296 case DP_C_LONG: 297 value = va_arg(args, long int); 298 break; 299 case DP_C_LLONG: 300 value = va_arg(args, LLONG); 301 break; 302 default: 303 value = va_arg(args, int); 304 break; 305 } 306 if (!fmtint(sbuffer, buffer, &currlen, maxlen, value, 10, min, 307 max, flags)) 308 return 0; 309 break; 310 case 'X': 311 flags |= DP_F_UP; 312 /* FALLTHROUGH */ 313 case 'x': 314 case 'o': 315 case 'u': 316 flags |= DP_F_UNSIGNED; 317 switch (cflags) { 318 case DP_C_SHORT: 319 value = (unsigned short int)va_arg(args, unsigned int); 320 break; 321 case DP_C_LONG: 322 value = (LLONG) va_arg(args, unsigned long int); 323 break; 324 case DP_C_LLONG: 325 value = va_arg(args, unsigned LLONG); 326 break; 327 default: 328 value = (LLONG) va_arg(args, unsigned int); 329 break; 330 } 331 if (!fmtint(sbuffer, buffer, &currlen, maxlen, value, 332 ch == 'o' ? 8 : (ch == 'u' ? 10 : 16), 333 min, max, flags)) 334 return 0; 335 break; 336 case 'f': 337 if (cflags == DP_C_LDOUBLE) 338 fvalue = va_arg(args, LDOUBLE); 339 else 340 fvalue = va_arg(args, double); 341 if (!fmtfp(sbuffer, buffer, &currlen, maxlen, fvalue, min, max, 342 flags)) 343 return 0; 344 break; 345 case 'E': 346 flags |= DP_F_UP; 347 case 'e': 348 if (cflags == DP_C_LDOUBLE) 349 fvalue = va_arg(args, LDOUBLE); 350 else 351 fvalue = va_arg(args, double); 352 break; 353 case 'G': 354 flags |= DP_F_UP; 355 case 'g': 356 if (cflags == DP_C_LDOUBLE) 357 fvalue = va_arg(args, LDOUBLE); 358 else 359 fvalue = va_arg(args, double); 360 break; 361 case 'c': 362 if(!doapr_outch(sbuffer, buffer, &currlen, maxlen, 363 va_arg(args, int))) 364 return 0; 365 break; 366 case 's': 367 strvalue = va_arg(args, char *); 368 if (max < 0) { 369 if (buffer) 370 max = INT_MAX; 371 else 372 max = *maxlen; 373 } 374 if (!fmtstr(sbuffer, buffer, &currlen, maxlen, strvalue, 375 flags, min, max)) 376 return 0; 377 break; 378 case 'p': 379 value = (long)va_arg(args, void *); 380 if (!fmtint(sbuffer, buffer, &currlen, maxlen, 381 value, 16, min, max, flags | DP_F_NUM)) 382 return 0; 383 break; 384 case 'n': /* XXX */ 385 if (cflags == DP_C_SHORT) { 386 short int *num; 387 num = va_arg(args, short int *); 388 *num = currlen; 389 } else if (cflags == DP_C_LONG) { /* XXX */ 390 long int *num; 391 num = va_arg(args, long int *); 392 *num = (long int)currlen; 393 } else if (cflags == DP_C_LLONG) { /* XXX */ 394 LLONG *num; 395 num = va_arg(args, LLONG *); 396 *num = (LLONG) currlen; 397 } else { 398 int *num; 399 num = va_arg(args, int *); 400 *num = currlen; 401 } 402 break; 403 case '%': 404 if(!doapr_outch(sbuffer, buffer, &currlen, maxlen, ch)) 405 return 0; 406 break; 407 case 'w': 408 /* not supported yet, treat as next char */ 409 ch = *format++; 410 break; 411 default: 412 /* unknown, skip */ 413 break; 414 } 415 ch = *format++; 416 state = DP_S_DEFAULT; 417 flags = cflags = min = 0; 418 max = -1; 419 break; 420 case DP_S_DONE: 421 break; 422 default: 423 break; 424 } 425 } 426 *truncated = (currlen > *maxlen - 1); 427 if (*truncated) 428 currlen = *maxlen - 1; 429 if(!doapr_outch(sbuffer, buffer, &currlen, maxlen, '\0')) 430 return 0; 431 *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