1 /* 2 * Copyright 1995-2020 The OpenSSL Project Authors. All Rights Reserved. 3 * 4 * Licensed under the OpenSSL license (the "License"). You may not use 5 * this file except in compliance with the License. You can obtain a copy 6 * in the file LICENSE in the source distribution or at 7 * https://www.openssl.org/source/license.html 8 */ 9 10 #include <stdio.h> 11 #include <string.h> 12 #include "internal/cryptlib.h" 13 #include "crypto/ctype.h" 14 #include "internal/numbers.h" 15 #include <openssl/bio.h> 16 17 /* 18 * Copyright Patrick Powell 1995 19 * This code is based on code written by Patrick Powell <papowell@astart.com> 20 * It may be used for any purpose as long as this notice remains intact 21 * on all source code distributions. 22 */ 23 24 #ifdef HAVE_LONG_DOUBLE 25 # define LDOUBLE long double 26 #else 27 # define LDOUBLE double 28 #endif 29 30 static int fmtstr(char **, char **, size_t *, size_t *, 31 const char *, int, int, int); 32 static int fmtint(char **, char **, size_t *, size_t *, 33 int64_t, int, int, int, int); 34 static int fmtfp(char **, char **, size_t *, size_t *, 35 LDOUBLE, int, int, int, int); 36 static int doapr_outch(char **, char **, size_t *, size_t *, int); 37 static int _dopr(char **sbuffer, char **buffer, 38 size_t *maxlen, size_t *retlen, int *truncated, 39 const char *format, va_list args); 40 41 /* format read states */ 42 #define DP_S_DEFAULT 0 43 #define DP_S_FLAGS 1 44 #define DP_S_MIN 2 45 #define DP_S_DOT 3 46 #define DP_S_MAX 4 47 #define DP_S_MOD 5 48 #define DP_S_CONV 6 49 #define DP_S_DONE 7 50 51 /* format flags - Bits */ 52 /* left-aligned padding */ 53 #define DP_F_MINUS (1 << 0) 54 /* print an explicit '+' for a value with positive sign */ 55 #define DP_F_PLUS (1 << 1) 56 /* print an explicit ' ' for a value with positive sign */ 57 #define DP_F_SPACE (1 << 2) 58 /* print 0/0x prefix for octal/hex and decimal point for floating point */ 59 #define DP_F_NUM (1 << 3) 60 /* print leading zeroes */ 61 #define DP_F_ZERO (1 << 4) 62 /* print HEX in UPPPERcase */ 63 #define DP_F_UP (1 << 5) 64 /* treat value as unsigned */ 65 #define DP_F_UNSIGNED (1 << 6) 66 67 /* conversion flags */ 68 #define DP_C_SHORT 1 69 #define DP_C_LONG 2 70 #define DP_C_LDOUBLE 3 71 #define DP_C_LLONG 4 72 #define DP_C_SIZE 5 73 74 /* Floating point formats */ 75 #define F_FORMAT 0 76 #define E_FORMAT 1 77 #define G_FORMAT 2 78 79 /* some handy macros */ 80 #define char_to_int(p) (p - '0') 81 #define OSSL_MAX(p,q) ((p >= q) ? p : q) 82 83 static int 84 _dopr(char **sbuffer, 85 char **buffer, 86 size_t *maxlen, 87 size_t *retlen, int *truncated, const char *format, va_list args) 88 { 89 char ch; 90 int64_t value; 91 LDOUBLE fvalue; 92 char *strvalue; 93 int min; 94 int max; 95 int state; 96 int flags; 97 int cflags; 98 size_t currlen; 99 100 state = DP_S_DEFAULT; 101 flags = currlen = cflags = min = 0; 102 max = -1; 103 ch = *format++; 104 105 while (state != DP_S_DONE) { 106 if (ch == '\0' || (buffer == NULL && currlen >= *maxlen)) 107 state = DP_S_DONE; 108 109 switch (state) { 110 case DP_S_DEFAULT: 111 if (ch == '%') 112 state = DP_S_FLAGS; 113 else 114 if (!doapr_outch(sbuffer, buffer, &currlen, maxlen, ch)) 115 return 0; 116 ch = *format++; 117 break; 118 case DP_S_FLAGS: 119 switch (ch) { 120 case '-': 121 flags |= DP_F_MINUS; 122 ch = *format++; 123 break; 124 case '+': 125 flags |= DP_F_PLUS; 126 ch = *format++; 127 break; 128 case ' ': 129 flags |= DP_F_SPACE; 130 ch = *format++; 131 break; 132 case '#': 133 flags |= DP_F_NUM; 134 ch = *format++; 135 break; 136 case '0': 137 flags |= DP_F_ZERO; visibilitymap_clear(Relation rel,BlockNumber heapBlk,Buffer buf,uint8 flags)138 ch = *format++; 139 break; 140 default: 141 state = DP_S_MIN; 142 break; 143 } 144 break; 145 case DP_S_MIN: 146 if (ossl_isdigit(ch)) { 147 min = 10 * min + char_to_int(ch); 148 ch = *format++; 149 } else if (ch == '*') { 150 min = va_arg(args, int); 151 ch = *format++; 152 state = DP_S_DOT; 153 } else 154 state = DP_S_DOT; 155 break; 156 case DP_S_DOT: 157 if (ch == '.') { 158 state = DP_S_MAX; 159 ch = *format++; 160 } else 161 state = DP_S_MOD; 162 break; 163 case DP_S_MAX: 164 if (ossl_isdigit(ch)) { 165 if (max < 0) 166 max = 0; 167 max = 10 * max + char_to_int(ch); 168 ch = *format++; 169 } else if (ch == '*') { 170 max = va_arg(args, int); 171 ch = *format++; 172 state = DP_S_MOD; 173 } else 174 state = DP_S_MOD; 175 break; 176 case DP_S_MOD: 177 switch (ch) { 178 case 'h': 179 cflags = DP_C_SHORT; 180 ch = *format++; 181 break; 182 case 'l': 183 if (*format == 'l') { 184 cflags = DP_C_LLONG; 185 format++; 186 } else 187 cflags = DP_C_LONG; 188 ch = *format++; visibilitymap_pin(Relation rel,BlockNumber heapBlk,Buffer * buf)189 break; 190 case 'q': 191 case 'j': 192 cflags = DP_C_LLONG; 193 ch = *format++; 194 break; 195 case 'L': 196 cflags = DP_C_LDOUBLE; 197 ch = *format++; 198 break; 199 case 'z': 200 cflags = DP_C_SIZE; 201 ch = *format++; 202 break; 203 default: 204 break; 205 } 206 state = DP_S_CONV; 207 break; 208 case DP_S_CONV: 209 switch (ch) { 210 case 'd': 211 case 'i': 212 switch (cflags) { visibilitymap_pin_ok(BlockNumber heapBlk,Buffer buf)213 case DP_C_SHORT: 214 value = (short int)va_arg(args, int); 215 break; 216 case DP_C_LONG: 217 value = va_arg(args, long int); 218 break; 219 case DP_C_LLONG: 220 value = va_arg(args, int64_t); 221 break; 222 case DP_C_SIZE: 223 value = va_arg(args, ossl_ssize_t); 224 break; 225 default: 226 value = va_arg(args, int); 227 break; 228 } 229 if (!fmtint(sbuffer, buffer, &currlen, maxlen, value, 10, min, 230 max, flags)) 231 return 0; 232 break; 233 case 'X': 234 flags |= DP_F_UP; 235 /* FALLTHROUGH */ 236 case 'x': 237 case 'o': 238 case 'u': 239 flags |= DP_F_UNSIGNED; 240 switch (cflags) { 241 case DP_C_SHORT: visibilitymap_set(Relation rel,BlockNumber heapBlk,Buffer heapBuf,XLogRecPtr recptr,Buffer vmBuf,TransactionId cutoff_xid,uint8 flags)242 value = (unsigned short int)va_arg(args, unsigned int); 243 break; 244 case DP_C_LONG: 245 value = va_arg(args, unsigned long int); 246 break; 247 case DP_C_LLONG: 248 value = va_arg(args, uint64_t); 249 break; 250 case DP_C_SIZE: 251 value = va_arg(args, size_t); 252 break; 253 default: 254 value = va_arg(args, unsigned int); 255 break; 256 } 257 if (!fmtint(sbuffer, buffer, &currlen, maxlen, value, 258 ch == 'o' ? 8 : (ch == 'u' ? 10 : 16), 259 min, max, flags)) 260 return 0; 261 break; 262 case 'f': 263 if (cflags == DP_C_LDOUBLE) 264 fvalue = va_arg(args, LDOUBLE); 265 else 266 fvalue = va_arg(args, double); 267 if (!fmtfp(sbuffer, buffer, &currlen, maxlen, fvalue, min, max, 268 flags, F_FORMAT)) 269 return 0; 270 break; 271 case 'E': 272 flags |= DP_F_UP; 273 /* fall thru */ 274 case 'e': 275 if (cflags == DP_C_LDOUBLE) 276 fvalue = va_arg(args, LDOUBLE); 277 else 278 fvalue = va_arg(args, double); 279 if (!fmtfp(sbuffer, buffer, &currlen, maxlen, fvalue, min, max, 280 flags, E_FORMAT)) 281 return 0; 282 break; 283 case 'G': 284 flags |= DP_F_UP; 285 /* fall thru */ 286 case 'g': 287 if (cflags == DP_C_LDOUBLE) 288 fvalue = va_arg(args, LDOUBLE); 289 else 290 fvalue = va_arg(args, double); 291 if (!fmtfp(sbuffer, buffer, &currlen, maxlen, fvalue, min, max, 292 flags, G_FORMAT)) 293 return 0; 294 break; 295 case 'c': 296 if (!doapr_outch(sbuffer, buffer, &currlen, maxlen, 297 va_arg(args, int))) 298 return 0; 299 break; 300 case 's': 301 strvalue = va_arg(args, char *); 302 if (max < 0) { 303 if (buffer) 304 max = INT_MAX; 305 else 306 max = *maxlen; 307 } 308 if (!fmtstr(sbuffer, buffer, &currlen, maxlen, strvalue, 309 flags, min, max)) 310 return 0; 311 break; 312 case 'p': 313 value = (size_t)va_arg(args, void *); 314 if (!fmtint(sbuffer, buffer, &currlen, maxlen, 315 value, 16, min, max, flags | DP_F_NUM)) 316 return 0; 317 break; 318 case 'n': 319 { 320 int *num; 321 num = va_arg(args, int *); 322 *num = currlen; 323 } 324 break; 325 case '%': 326 if (!doapr_outch(sbuffer, buffer, &currlen, maxlen, ch)) 327 return 0; 328 break; visibilitymap_get_status(Relation rel,BlockNumber heapBlk,Buffer * buf)329 case 'w': 330 /* not supported yet, treat as next char */ 331 ch = *format++; 332 break; 333 default: 334 /* unknown, skip */ 335 break; 336 } 337 ch = *format++; 338 state = DP_S_DEFAULT; 339 flags = cflags = min = 0; 340 max = -1; 341 break; 342 case DP_S_DONE: 343 break; 344 default: 345 break; 346 } 347 } 348 /* 349 * We have to truncate if there is no dynamic buffer and we have filled the 350 * static buffer. 351 */ 352 if (buffer == NULL) { 353 *truncated = (currlen > *maxlen - 1); 354 if (*truncated) 355 currlen = *maxlen - 1; 356 } 357 if (!doapr_outch(sbuffer, buffer, &currlen, maxlen, '\0')) 358 return 0; 359 *retlen = currlen - 1; 360 return 1; 361 } 362 363 static int 364 fmtstr(char **sbuffer, 365 char **buffer, 366 size_t *currlen, 367 size_t *maxlen, const char *value, int flags, int min, int max) 368 { 369 int padlen; 370 size_t strln; 371 int cnt = 0; 372 373 if (value == 0) 374 value = "<NULL>"; 375 376 strln = OPENSSL_strnlen(value, max < 0 ? SIZE_MAX : (size_t)max); visibilitymap_count(Relation rel,BlockNumber * all_visible,BlockNumber * all_frozen)377 378 padlen = min - strln; 379 if (min < 0 || padlen < 0) 380 padlen = 0; 381 if (max >= 0) { 382 /* 383 * Calculate the maximum output including padding. 384 * Make sure max doesn't overflow into negativity 385 */ 386 if (max < INT_MAX - padlen) 387 max += padlen; 388 else 389 max = INT_MAX; 390 } 391 if (flags & DP_F_MINUS) 392 padlen = -padlen; 393 394 while ((padlen > 0) && (max < 0 || cnt < max)) { 395 if (!doapr_outch(sbuffer, buffer, currlen, maxlen, ' ')) 396 return 0; 397 --padlen; 398 ++cnt; 399 } 400 while (strln > 0 && (max < 0 || cnt < max)) { 401 if (!doapr_outch(sbuffer, buffer, currlen, maxlen, *value++)) 402 return 0; 403 --strln; 404 ++cnt; 405 } 406 while ((padlen < 0) && (max < 0 || cnt < max)) { 407 if (!doapr_outch(sbuffer, buffer, currlen, maxlen, ' ')) 408 return 0; 409 ++padlen; 410 ++cnt; 411 } 412 return 1; 413 } 414 415 static int 416 fmtint(char **sbuffer, 417 char **buffer, 418 size_t *currlen, 419 size_t *maxlen, int64_t value, int base, int min, int max, int flags) 420 { 421 int signvalue = 0; 422 const char *prefix = ""; 423 uint64_t uvalue; 424 char convert[DECIMAL_SIZE(value) + 3]; 425 int place = 0; 426 int spadlen = 0; 427 int zpadlen = 0; 428 int caps = 0; 429 430 if (max < 0) 431 max = 0; 432 uvalue = value; 433 if (!(flags & DP_F_UNSIGNED)) { 434 if (value < 0) { 435 signvalue = '-'; 436 uvalue = 0 - (uint64_t)value; 437 } else if (flags & DP_F_PLUS) 438 signvalue = '+'; 439 else if (flags & DP_F_SPACE) 440 signvalue = ' '; 441 } visibilitymap_truncate(Relation rel,BlockNumber nheapblocks)442 if (flags & DP_F_NUM) { 443 if (base == 8) 444 prefix = "0"; 445 if (base == 16) 446 prefix = "0x"; 447 } 448 if (flags & DP_F_UP) 449 caps = 1; 450 do { 451 convert[place++] = (caps ? "0123456789ABCDEF" : "0123456789abcdef") 452 [uvalue % (unsigned)base]; 453 uvalue = (uvalue / (unsigned)base); 454 } while (uvalue && (place < (int)sizeof(convert))); 455 if (place == sizeof(convert)) 456 place--; 457 convert[place] = 0; 458 459 zpadlen = max - place; 460 spadlen = 461 min - OSSL_MAX(max, place) - (signvalue ? 1 : 0) - strlen(prefix); 462 if (zpadlen < 0) 463 zpadlen = 0; 464 if (spadlen < 0) 465 spadlen = 0; 466 if (flags & DP_F_ZERO) { 467 zpadlen = OSSL_MAX(zpadlen, spadlen); 468 spadlen = 0; 469 } 470 if (flags & DP_F_MINUS) 471 spadlen = -spadlen; 472 473 /* spaces */ 474 while (spadlen > 0) { 475 if (!doapr_outch(sbuffer, buffer, currlen, maxlen, ' ')) 476 return 0; 477 --spadlen; 478 } 479 480 /* sign */ 481 if (signvalue) 482 if (!doapr_outch(sbuffer, buffer, currlen, maxlen, signvalue)) 483 return 0; 484 485 /* prefix */ 486 while (*prefix) { 487 if (!doapr_outch(sbuffer, buffer, currlen, maxlen, *prefix)) 488 return 0; 489 prefix++; 490 } 491 492 /* zeros */ 493 if (zpadlen > 0) { 494 while (zpadlen > 0) { 495 if (!doapr_outch(sbuffer, buffer, currlen, maxlen, '0')) 496 return 0; 497 --zpadlen; 498 } 499 } 500 /* digits */ 501 while (place > 0) { 502 if (!doapr_outch(sbuffer, buffer, currlen, maxlen, convert[--place])) 503 return 0; 504 } 505 506 /* left justified spaces */ 507 while (spadlen < 0) { 508 if (!doapr_outch(sbuffer, buffer, currlen, maxlen, ' ')) 509 return 0; 510 ++spadlen; 511 } 512 return 1; 513 } 514 515 static LDOUBLE abs_val(LDOUBLE value) 516 { 517 LDOUBLE result = value; 518 if (value < 0) 519 result = -value; 520 return result; 521 } 522 523 static LDOUBLE pow_10(int in_exp) 524 { 525 LDOUBLE result = 1; 526 while (in_exp) { 527 result *= 10; 528 in_exp--; 529 } 530 return result; 531 } 532 533 static long roundv(LDOUBLE value) 534 { 535 long intpart; 536 intpart = (long)value; 537 value = value - intpart; 538 if (value >= 0.5) 539 intpart++; 540 return intpart; 541 } 542 543 static int 544 fmtfp(char **sbuffer, 545 char **buffer, 546 size_t *currlen, 547 size_t *maxlen, LDOUBLE fvalue, int min, int max, int flags, int style) 548 { 549 int signvalue = 0; 550 LDOUBLE ufvalue; 551 LDOUBLE tmpvalue; 552 char iconvert[20]; 553 char fconvert[20]; vm_readbuf(Relation rel,BlockNumber blkno,bool extend)554 char econvert[20]; 555 int iplace = 0; 556 int fplace = 0; 557 int eplace = 0; 558 int padlen = 0; 559 int zpadlen = 0; 560 long exp = 0; 561 unsigned long intpart; 562 unsigned long fracpart; 563 unsigned long max10; 564 int realstyle; 565 566 if (max < 0) 567 max = 6; 568 569 if (fvalue < 0) 570 signvalue = '-'; 571 else if (flags & DP_F_PLUS) 572 signvalue = '+'; 573 else if (flags & DP_F_SPACE) 574 signvalue = ' '; 575 576 /* 577 * G_FORMAT sometimes prints like E_FORMAT and sometimes like F_FORMAT 578 * depending on the number to be printed. Work out which one it is and use 579 * that from here on. 580 */ 581 if (style == G_FORMAT) { 582 if (fvalue == 0.0) { 583 realstyle = F_FORMAT; 584 } else if (fvalue < 0.0001) { 585 realstyle = E_FORMAT; 586 } else if ((max == 0 && fvalue >= 10) 587 || (max > 0 && fvalue >= pow_10(max))) { 588 realstyle = E_FORMAT; 589 } else { 590 realstyle = F_FORMAT; 591 } 592 } else { 593 realstyle = style; 594 } 595 596 if (style != F_FORMAT) { 597 tmpvalue = fvalue; 598 /* Calculate the exponent */ 599 if (fvalue != 0.0) { 600 while (tmpvalue < 1) { 601 tmpvalue *= 10; 602 exp--; 603 } 604 while (tmpvalue > 10) { 605 tmpvalue /= 10; 606 exp++; 607 } 608 } 609 if (style == G_FORMAT) { 610 /* 611 * In G_FORMAT the "precision" represents significant digits. We 612 * always have at least 1 significant digit. 613 */ 614 if (max == 0) 615 max = 1; 616 /* Now convert significant digits to decimal places */ 617 if (realstyle == F_FORMAT) { 618 max -= (exp + 1); 619 if (max < 0) { 620 /* 621 * Should not happen. If we're in F_FORMAT then exp < max? 622 */ 623 return 0; 624 } vm_extend(Relation rel,BlockNumber vm_nblocks)625 } else { 626 /* 627 * In E_FORMAT there is always one significant digit in front 628 * of the decimal point, so: 629 * significant digits == 1 + decimal places 630 */ 631 max--; 632 } 633 } 634 if (realstyle == E_FORMAT) 635 fvalue = tmpvalue; 636 } 637 ufvalue = abs_val(fvalue); 638 /* 639 * By subtracting 65535 (2^16-1) we cancel the low order 15 bits 640 * of ULONG_MAX to avoid using imprecise floating point values. 641 */ 642 if (ufvalue >= (double)(ULONG_MAX - 65535) + 65536.0) { 643 /* Number too big */ 644 return 0; 645 } 646 intpart = (unsigned long)ufvalue; 647 648 /* 649 * sorry, we only support 9 digits past the decimal because of our 650 * conversion method 651 */ 652 if (max > 9) 653 max = 9; 654 655 /* 656 * we "cheat" by converting the fractional part to integer by multiplying 657 * by a factor of 10 658 */ 659 max10 = roundv(pow_10(max)); 660 fracpart = roundv(pow_10(max) * (ufvalue - intpart)); 661 662 if (fracpart >= max10) { 663 intpart++; 664 fracpart -= max10; 665 } 666 667 /* convert integer part */ 668 do { 669 iconvert[iplace++] = "0123456789"[intpart % 10]; 670 intpart = (intpart / 10); 671 } while (intpart && (iplace < (int)sizeof(iconvert))); 672 if (iplace == sizeof(iconvert)) 673 iplace--; 674 iconvert[iplace] = 0; 675 676 /* convert fractional part */ 677 while (fplace < max) { 678 if (style == G_FORMAT && fplace == 0 && (fracpart % 10) == 0) { 679 /* We strip trailing zeros in G_FORMAT */ 680 max--; 681 fracpart = fracpart / 10; 682 if (fplace < max) 683 continue; 684 break; 685 } 686 fconvert[fplace++] = "0123456789"[fracpart % 10]; 687 fracpart = (fracpart / 10); 688 } 689 690 if (fplace == sizeof(fconvert)) 691 fplace--; 692 fconvert[fplace] = 0; 693 694 /* convert exponent part */ 695 if (realstyle == E_FORMAT) { 696 int tmpexp; 697 if (exp < 0) 698 tmpexp = -exp; 699 else 700 tmpexp = exp; 701 702 do { 703 econvert[eplace++] = "0123456789"[tmpexp % 10]; 704 tmpexp = (tmpexp / 10); 705 } while (tmpexp > 0 && eplace < (int)sizeof(econvert)); 706 /* Exponent is huge!! Too big to print */ 707 if (tmpexp > 0) 708 return 0; 709 /* Add a leading 0 for single digit exponents */ 710 if (eplace == 1) 711 econvert[eplace++] = '0'; 712 } 713 714 /* 715 * -1 for decimal point (if we have one, i.e. max > 0), 716 * another -1 if we are printing a sign 717 */ 718 padlen = min - iplace - max - (max > 0 ? 1 : 0) - ((signvalue) ? 1 : 0); 719 /* Take some off for exponent prefix "+e" and exponent */ 720 if (realstyle == E_FORMAT) 721 padlen -= 2 + eplace; 722 zpadlen = max - fplace; 723 if (zpadlen < 0) 724 zpadlen = 0; 725 if (padlen < 0) 726 padlen = 0; 727 if (flags & DP_F_MINUS) 728 padlen = -padlen; 729 730 if ((flags & DP_F_ZERO) && (padlen > 0)) { 731 if (signvalue) { 732 if (!doapr_outch(sbuffer, buffer, currlen, maxlen, signvalue)) 733 return 0; 734 --padlen; 735 signvalue = 0; 736 } 737 while (padlen > 0) { 738 if (!doapr_outch(sbuffer, buffer, currlen, maxlen, '0')) 739 return 0; 740 --padlen; 741 } 742 } 743 while (padlen > 0) { 744 if (!doapr_outch(sbuffer, buffer, currlen, maxlen, ' ')) 745 return 0; 746 --padlen; 747 } 748 if (signvalue && !doapr_outch(sbuffer, buffer, currlen, maxlen, signvalue)) 749 return 0; 750 751 while (iplace > 0) { 752 if (!doapr_outch(sbuffer, buffer, currlen, maxlen, iconvert[--iplace])) 753 return 0; 754 } 755 756 /* 757 * Decimal point. This should probably use locale to find the correct 758 * char to print out. 759 */ 760 if (max > 0 || (flags & DP_F_NUM)) { 761 if (!doapr_outch(sbuffer, buffer, currlen, maxlen, '.')) 762 return 0; 763 764 while (fplace > 0) { 765 if (!doapr_outch(sbuffer, buffer, currlen, maxlen, 766 fconvert[--fplace])) 767 return 0; 768 } 769 } 770 while (zpadlen > 0) { 771 if (!doapr_outch(sbuffer, buffer, currlen, maxlen, '0')) 772 return 0; 773 --zpadlen; 774 } 775 if (realstyle == E_FORMAT) { 776 char ech; 777 778 if ((flags & DP_F_UP) == 0) 779 ech = 'e'; 780 else 781 ech = 'E'; 782 if (!doapr_outch(sbuffer, buffer, currlen, maxlen, ech)) 783 return 0; 784 if (exp < 0) { 785 if (!doapr_outch(sbuffer, buffer, currlen, maxlen, '-')) 786 return 0; 787 } else { 788 if (!doapr_outch(sbuffer, buffer, currlen, maxlen, '+')) 789 return 0; 790 } 791 while (eplace > 0) { 792 if (!doapr_outch(sbuffer, buffer, currlen, maxlen, 793 econvert[--eplace])) 794 return 0; 795 } 796 } 797 798 while (padlen < 0) { 799 if (!doapr_outch(sbuffer, buffer, currlen, maxlen, ' ')) 800 return 0; 801 ++padlen; 802 } 803 return 1; 804 } 805 806 #define BUFFER_INC 1024 807 808 static int 809 doapr_outch(char **sbuffer, 810 char **buffer, size_t *currlen, size_t *maxlen, int c) 811 { 812 /* If we haven't at least one buffer, someone has done a big booboo */ 813 if (!ossl_assert(*sbuffer != NULL || buffer != NULL)) 814 return 0; 815 816 /* |currlen| must always be <= |*maxlen| */ 817 if (!ossl_assert(*currlen <= *maxlen)) 818 return 0; 819 820 if (buffer && *currlen == *maxlen) { 821 if (*maxlen > INT_MAX - BUFFER_INC) 822 return 0; 823 824 *maxlen += BUFFER_INC; 825 if (*buffer == NULL) { 826 if ((*buffer = OPENSSL_malloc(*maxlen)) == NULL) { 827 BIOerr(BIO_F_DOAPR_OUTCH, ERR_R_MALLOC_FAILURE); 828 return 0; 829 } 830 if (*currlen > 0) { 831 if (!ossl_assert(*sbuffer != NULL)) 832 return 0; 833 memcpy(*buffer, *sbuffer, *currlen); 834 } 835 *sbuffer = NULL; 836 } else { 837 char *tmpbuf; 838 tmpbuf = OPENSSL_realloc(*buffer, *maxlen); 839 if (tmpbuf == NULL) 840 return 0; 841 *buffer = tmpbuf; 842 } 843 } 844 845 if (*currlen < *maxlen) { 846 if (*sbuffer) 847 (*sbuffer)[(*currlen)++] = (char)c; 848 else 849 (*buffer)[(*currlen)++] = (char)c; 850 } 851 852 return 1; 853 } 854 855 /***************************************************************************/ 856 857 int BIO_printf(BIO *bio, const char *format, ...) 858 { 859 va_list args; 860 int ret; 861 862 va_start(args, format); 863 864 ret = BIO_vprintf(bio, format, args); 865 866 va_end(args); 867 return ret; 868 } 869 870 int BIO_vprintf(BIO *bio, const char *format, va_list args) 871 { 872 int ret; 873 size_t retlen; 874 char hugebuf[1024 * 2]; /* Was previously 10k, which is unreasonable 875 * in small-stack environments, like threads 876 * or DOS programs. */ 877 char *hugebufp = hugebuf; 878 size_t hugebufsize = sizeof(hugebuf); 879 char *dynbuf = NULL; 880 int ignored; 881 882 dynbuf = NULL; 883 if (!_dopr(&hugebufp, &dynbuf, &hugebufsize, &retlen, &ignored, format, 884 args)) { 885 OPENSSL_free(dynbuf); 886 return -1; 887 } 888 if (dynbuf) { 889 ret = BIO_write(bio, dynbuf, (int)retlen); 890 OPENSSL_free(dynbuf); 891 } else { 892 ret = BIO_write(bio, hugebuf, (int)retlen); 893 } 894 return ret; 895 } 896 897 /* 898 * As snprintf is not available everywhere, we provide our own 899 * implementation. This function has nothing to do with BIOs, but it's 900 * closely related to BIO_printf, and we need *some* name prefix ... (XXX the 901 * function should be renamed, but to what?) 902 */ 903 int BIO_snprintf(char *buf, size_t n, const char *format, ...) 904 { 905 va_list args; 906 int ret; 907 908 va_start(args, format); 909 910 ret = BIO_vsnprintf(buf, n, format, args); 911 912 va_end(args); 913 return ret; 914 } 915 916 int BIO_vsnprintf(char *buf, size_t n, const char *format, va_list args) 917 { 918 size_t retlen; 919 int truncated; 920 921 if (!_dopr(&buf, NULL, &n, &retlen, &truncated, format, args)) 922 return -1; 923 924 if (truncated) 925 /* 926 * In case of truncation, return -1 like traditional snprintf. 927 * (Current drafts for ISO/IEC 9899 say snprintf should return the 928 * number of characters that would have been written, had the buffer 929 * been large enough.) 930 */ 931 return -1; 932 else 933 return (retlen <= INT_MAX) ? (int)retlen : -1; 934 } 935