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 = (short int)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 /* 427 * We have to truncate if there is no dynamic buffer and we have filled the 428 * static buffer. 429 */ 430 if (buffer == NULL) { 431 *truncated = (currlen > *maxlen - 1); 432 if (*truncated) 433 currlen = *maxlen - 1; 434 } 435 if(!doapr_outch(sbuffer, buffer, &currlen, maxlen, '\0')) 436 return 0; 437 *retlen = currlen - 1; 438 return 1; 439} 440 441static int 442fmtstr(char **sbuffer, 443 char **buffer, 444 size_t *currlen, 445 size_t *maxlen, const char *value, int flags, int min, int max) 446{ 447 int padlen; 448 size_t strln; 449 int cnt = 0; 450 451 if (value == 0) 452 value = "<NULL>"; 453 454 strln = strlen(value); 455 if (strln > INT_MAX) 456 strln = INT_MAX; 457 458 padlen = min - strln; 459 if (min < 0 || padlen < 0) 460 padlen = 0; 461 if (flags & DP_F_MINUS) 462 padlen = -padlen; 463 464 while ((padlen > 0) && (cnt < max)) { 465 if(!doapr_outch(sbuffer, buffer, currlen, maxlen, ' ')) 466 return 0; 467 --padlen; 468 ++cnt; 469 } 470 while (*value && (cnt < max)) { 471 if(!doapr_outch(sbuffer, buffer, currlen, maxlen, *value++)) 472 return 0; 473 ++cnt; 474 } 475 while ((padlen < 0) && (cnt < max)) { 476 if(!doapr_outch(sbuffer, buffer, currlen, maxlen, ' ')) 477 return 0; 478 ++padlen; 479 ++cnt; 480 } 481 return 1; 482} 483 484static int 485fmtint(char **sbuffer, 486 char **buffer, 487 size_t *currlen, 488 size_t *maxlen, LLONG value, int base, int min, int max, int flags) 489{ 490 int signvalue = 0; 491 const char *prefix = ""; 492 unsigned LLONG uvalue; 493 char convert[DECIMAL_SIZE(value) + 3]; 494 int place = 0; 495 int spadlen = 0; 496 int zpadlen = 0; 497 int caps = 0; 498 499 if (max < 0) 500 max = 0; 501 uvalue = value; 502 if (!(flags & DP_F_UNSIGNED)) { 503 if (value < 0) { 504 signvalue = '-'; 505 uvalue = 0 - (unsigned LLONG)value; 506 } else if (flags & DP_F_PLUS) 507 signvalue = '+'; 508 else if (flags & DP_F_SPACE) 509 signvalue = ' '; 510 } 511 if (flags & DP_F_NUM) { 512 if (base == 8) 513 prefix = "0"; 514 if (base == 16) 515 prefix = "0x"; 516 } 517 if (flags & DP_F_UP) 518 caps = 1; 519 do { 520 convert[place++] = (caps ? "0123456789ABCDEF" : "0123456789abcdef") 521 [uvalue % (unsigned)base]; 522 uvalue = (uvalue / (unsigned)base); 523 } while (uvalue && (place < (int)sizeof(convert))); 524 if (place == sizeof(convert)) 525 place--; 526 convert[place] = 0; 527 528 zpadlen = max - place; 529 spadlen = 530 min - OSSL_MAX(max, place) - (signvalue ? 1 : 0) - strlen(prefix); 531 if (zpadlen < 0) 532 zpadlen = 0; 533 if (spadlen < 0) 534 spadlen = 0; 535 if (flags & DP_F_ZERO) { 536 zpadlen = OSSL_MAX(zpadlen, spadlen); 537 spadlen = 0; 538 } 539 if (flags & DP_F_MINUS) 540 spadlen = -spadlen; 541 542 /* spaces */ 543 while (spadlen > 0) { 544 if(!doapr_outch(sbuffer, buffer, currlen, maxlen, ' ')) 545 return 0; 546 --spadlen; 547 } 548 549 /* sign */ 550 if (signvalue) 551 if(!doapr_outch(sbuffer, buffer, currlen, maxlen, signvalue)) 552 return 0; 553 554 /* prefix */ 555 while (*prefix) { 556 if(!doapr_outch(sbuffer, buffer, currlen, maxlen, *prefix)) 557 return 0; 558 prefix++; 559 } 560 561 /* zeros */ 562 if (zpadlen > 0) { 563 while (zpadlen > 0) { 564 if(!doapr_outch(sbuffer, buffer, currlen, maxlen, '0')) 565 return 0; 566 --zpadlen; 567 } 568 } 569 /* digits */ 570 while (place > 0) { 571 if (!doapr_outch(sbuffer, buffer, currlen, maxlen, convert[--place])) 572 return 0; 573 } 574 575 /* left justified spaces */ 576 while (spadlen < 0) { 577 if (!doapr_outch(sbuffer, buffer, currlen, maxlen, ' ')) 578 return 0; 579 ++spadlen; 580 } 581 return 1; 582} 583 584static LDOUBLE abs_val(LDOUBLE value) 585{ 586 LDOUBLE result = value; 587 if (value < 0) 588 result = -value; 589 return result; 590} 591 592static LDOUBLE pow_10(int in_exp) 593{ 594 LDOUBLE result = 1; 595 while (in_exp) { 596 result *= 10; 597 in_exp--; 598 } 599 return result; 600} 601 602static long roundv(LDOUBLE value) 603{ 604 long intpart; 605 intpart = (long)value; 606 value = value - intpart; 607 if (value >= 0.5) 608 intpart++; 609 return intpart; 610} 611 612static int 613fmtfp(char **sbuffer, 614 char **buffer, 615 size_t *currlen, 616 size_t *maxlen, LDOUBLE fvalue, int min, int max, int flags) 617{ 618 int signvalue = 0; 619 LDOUBLE ufvalue; 620 char iconvert[20]; 621 char fconvert[20]; 622 int iplace = 0; 623 int fplace = 0; 624 int padlen = 0; 625 int zpadlen = 0; 626 long intpart; 627 long fracpart; 628 long max10; 629 630 if (max < 0) 631 max = 6; 632 ufvalue = abs_val(fvalue); 633 if (fvalue < 0) 634 signvalue = '-'; 635 else if (flags & DP_F_PLUS) 636 signvalue = '+'; 637 else if (flags & DP_F_SPACE) 638 signvalue = ' '; 639 640 intpart = (long)ufvalue; 641 642 /* 643 * sorry, we only support 9 digits past the decimal because of our 644 * conversion method 645 */ 646 if (max > 9) 647 max = 9; 648 649 /* 650 * we "cheat" by converting the fractional part to integer by multiplying 651 * by a factor of 10 652 */ 653 max10 = roundv(pow_10(max)); 654 fracpart = roundv(pow_10(max) * (ufvalue - intpart)); 655 656 if (fracpart >= max10) { 657 intpart++; 658 fracpart -= max10; 659 } 660 661 /* convert integer part */ 662 do { 663 iconvert[iplace++] = "0123456789"[intpart % 10]; 664 intpart = (intpart / 10); 665 } while (intpart && (iplace < (int)sizeof(iconvert))); 666 if (iplace == sizeof(iconvert)) 667 iplace--; 668 iconvert[iplace] = 0; 669 670 /* convert fractional part */ 671 do { 672 fconvert[fplace++] = "0123456789"[fracpart % 10]; 673 fracpart = (fracpart / 10); 674 } while (fplace < max); 675 if (fplace == sizeof(fconvert)) 676 fplace--; 677 fconvert[fplace] = 0; 678 679 /* -1 for decimal point, another -1 if we are printing a sign */ 680 padlen = min - iplace - max - 1 - ((signvalue) ? 1 : 0); 681 zpadlen = max - fplace; 682 if (zpadlen < 0) 683 zpadlen = 0; 684 if (padlen < 0) 685 padlen = 0; 686 if (flags & DP_F_MINUS) 687 padlen = -padlen; 688 689 if ((flags & DP_F_ZERO) && (padlen > 0)) { 690 if (signvalue) { 691 if (!doapr_outch(sbuffer, buffer, currlen, maxlen, signvalue)) 692 return 0; 693 --padlen; 694 signvalue = 0; 695 } 696 while (padlen > 0) { 697 if (!doapr_outch(sbuffer, buffer, currlen, maxlen, '0')) 698 return 0; 699 --padlen; 700 } 701 } 702 while (padlen > 0) { 703 if (!doapr_outch(sbuffer, buffer, currlen, maxlen, ' ')) 704 return 0; 705 --padlen; 706 } 707 if (signvalue && !doapr_outch(sbuffer, buffer, currlen, maxlen, signvalue)) 708 return 0; 709 710 while (iplace > 0) { 711 if (!doapr_outch(sbuffer, buffer, currlen, maxlen, iconvert[--iplace])) 712 return 0; 713 } 714 715 /* 716 * Decimal point. This should probably use locale to find the correct 717 * char to print out. 718 */ 719 if (max > 0 || (flags & DP_F_NUM)) { 720 if (!doapr_outch(sbuffer, buffer, currlen, maxlen, '.')) 721 return 0; 722 723 while (fplace > 0) { 724 if(!doapr_outch(sbuffer, buffer, currlen, maxlen, 725 fconvert[--fplace])) 726 return 0; 727 } 728 } 729 while (zpadlen > 0) { 730 if (!doapr_outch(sbuffer, buffer, currlen, maxlen, '0')) 731 return 0; 732 --zpadlen; 733 } 734 735 while (padlen < 0) { 736 if (!doapr_outch(sbuffer, buffer, currlen, maxlen, ' ')) 737 return 0; 738 ++padlen; 739 } 740 return 1; 741} 742 743#define BUFFER_INC 1024 744 745static int 746doapr_outch(char **sbuffer, 747 char **buffer, size_t *currlen, size_t *maxlen, int c) 748{ 749 /* If we haven't at least one buffer, someone has doe a big booboo */ 750 assert(*sbuffer != NULL || buffer != NULL); 751 752 /* |currlen| must always be <= |*maxlen| */ 753 assert(*currlen <= *maxlen); 754 755 if (buffer && *currlen == *maxlen) { 756 if (*maxlen > INT_MAX - BUFFER_INC) 757 return 0; 758 759 *maxlen += BUFFER_INC; 760 if (*buffer == NULL) { 761 *buffer = OPENSSL_malloc(*maxlen); 762 if (*buffer == NULL) 763 return 0; 764 if (*currlen > 0) { 765 assert(*sbuffer != NULL); 766 memcpy(*buffer, *sbuffer, *currlen); 767 } 768 *sbuffer = NULL; 769 } else { 770 char *tmpbuf; 771 tmpbuf = OPENSSL_realloc(*buffer, *maxlen); 772 if (tmpbuf == NULL) 773 return 0; 774 *buffer = tmpbuf; 775 } 776 } 777 778 if (*currlen < *maxlen) { 779 if (*sbuffer) 780 (*sbuffer)[(*currlen)++] = (char)c; 781 else 782 (*buffer)[(*currlen)++] = (char)c; 783 } 784 785 return 1; 786} 787 788/***************************************************************************/ 789 790int BIO_printf(BIO *bio, const char *format, ...) 791{ 792 va_list args; 793 int ret; 794 795 va_start(args, format); 796 797 ret = BIO_vprintf(bio, format, args); 798 799 va_end(args); 800 return (ret); 801} 802 803int BIO_vprintf(BIO *bio, const char *format, va_list args) 804{ 805 int ret; 806 size_t retlen; 807 char hugebuf[1024 * 2]; /* Was previously 10k, which is unreasonable 808 * in small-stack environments, like threads 809 * or DOS programs. */ 810 char *hugebufp = hugebuf; 811 size_t hugebufsize = sizeof(hugebuf); 812 char *dynbuf = NULL; 813 int ignored; 814 815 dynbuf = NULL; 816 CRYPTO_push_info("doapr()"); 817 if (!_dopr(&hugebufp, &dynbuf, &hugebufsize, &retlen, &ignored, format, 818 args)) { 819 OPENSSL_free(dynbuf); 820 return -1; 821 } 822 if (dynbuf) { 823 ret = BIO_write(bio, dynbuf, (int)retlen); 824 OPENSSL_free(dynbuf); 825 } else { 826 ret = BIO_write(bio, hugebuf, (int)retlen); 827 } 828 CRYPTO_pop_info(); 829 return (ret); 830} 831 832/* 833 * As snprintf is not available everywhere, we provide our own 834 * implementation. This function has nothing to do with BIOs, but it's 835 * closely related to BIO_printf, and we need *some* name prefix ... (XXX the 836 * function should be renamed, but to what?) 837 */ 838int BIO_snprintf(char *buf, size_t n, const char *format, ...) 839{ 840 va_list args; 841 int ret; 842 843 va_start(args, format); 844 845 ret = BIO_vsnprintf(buf, n, format, args); 846 847 va_end(args); 848 return (ret); 849} 850 851int BIO_vsnprintf(char *buf, size_t n, const char *format, va_list args) 852{ 853 size_t retlen; 854 int truncated; 855 856 if(!_dopr(&buf, NULL, &n, &retlen, &truncated, format, args)) 857 return -1; 858 859 if (truncated) 860 /* 861 * In case of truncation, return -1 like traditional snprintf. 862 * (Current drafts for ISO/IEC 9899 say snprintf should return the 863 * number of characters that would have been written, had the buffer 864 * been large enough.) 865 */ 866 return -1; 867 else 868 return (retlen <= INT_MAX) ? (int)retlen : -1; 869} 870