1/* vsprintf with automatic memory allocation. 2 Copyright (C) 1999, 2002-2005 Free Software Foundation, Inc. 3 4 This program is free software; you can redistribute it and/or modify 5 it under the terms of the GNU General Public License as published by 6 the Free Software Foundation; either version 2, or (at your option) 7 any later version. 8 9 This program is distributed in the hope that it will be useful, 10 but WITHOUT ANY WARRANTY; without even the implied warranty of 11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 GNU General Public License for more details. 13 14 You should have received a copy of the GNU General Public License along 15 with this program; if not, write to the Free Software Foundation, 16 Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ 17#include <sys/cdefs.h> 18__RCSID("$NetBSD: vasnprintf.c,v 1.4 2016/05/17 14:00:09 christos Exp $"); 19 20 21/* Tell glibc's <stdio.h> to provide a prototype for snprintf(). 22 This must come before <config.h> because <config.h> may include 23 <features.h>, and once <features.h> has been included, it's too late. */ 24#ifndef _GNU_SOURCE 25# define _GNU_SOURCE 1 26#endif 27 28#ifdef HAVE_CONFIG_H 29# include <config.h> 30#endif 31#ifdef __SSP__ 32#undef HAVE_ALLOCA 33#endif 34#ifndef __NetBSD__ 35#ifndef IN_LIBINTL 36# include <alloca.h> 37#endif 38#endif 39 40/* Specification. */ 41#if WIDE_CHAR_VERSION 42# include "vasnwprintf.h" 43#else 44# include "vasnprintf.h" 45#endif 46 47#include <stdio.h> /* snprintf(), sprintf() */ 48#include <stdlib.h> /* abort(), malloc(), realloc(), free() */ 49#include <string.h> /* memcpy(), strlen() */ 50#include <errno.h> /* errno */ 51#include <limits.h> /* CHAR_BIT, INT_MAX */ 52#include <float.h> /* DBL_MAX_EXP, LDBL_MAX_EXP */ 53#if WIDE_CHAR_VERSION 54# include "wprintf-parse.h" 55#else 56# include "printf-parse.h" 57#endif 58 59/* Checked size_t computations. */ 60#include "xsize.h" 61 62/* Some systems, like OSF/1 4.0 and Woe32, don't have EOVERFLOW. */ 63#ifndef EOVERFLOW 64# define EOVERFLOW E2BIG 65#endif 66 67#ifdef HAVE_WCHAR_T 68# ifdef HAVE_WCSLEN 69# define local_wcslen wcslen 70# else 71 /* Solaris 2.5.1 has wcslen() in a separate library libw.so. To avoid 72 a dependency towards this library, here is a local substitute. 73 Define this substitute only once, even if this file is included 74 twice in the same compilation unit. */ 75# ifndef local_wcslen_defined 76# define local_wcslen_defined 1 77static size_t 78local_wcslen (const wchar_t *s) 79{ 80 const wchar_t *ptr; 81 82 for (ptr = s; *ptr != (wchar_t) 0; ptr++) 83 ; 84 return ptr - s; 85} 86# endif 87# endif 88#endif 89 90#if WIDE_CHAR_VERSION 91# define VASNPRINTF vasnwprintf 92# define CHAR_T wchar_t 93# define DIRECTIVE wchar_t_directive 94# define DIRECTIVES wchar_t_directives 95# define PRINTF_PARSE wprintf_parse 96# define USE_SNPRINTF 1 97# if HAVE_DECL__SNWPRINTF 98 /* On Windows, the function swprintf() has a different signature than 99 on Unix; we use the _snwprintf() function instead. */ 100# define SNPRINTF _snwprintf 101# else 102 /* Unix. */ 103# define SNPRINTF swprintf 104# endif 105#else 106# define VASNPRINTF vasnprintf 107# define CHAR_T char 108# define DIRECTIVE char_directive 109# define DIRECTIVES char_directives 110# define PRINTF_PARSE printf_parse 111# define USE_SNPRINTF (HAVE_DECL__SNPRINTF || HAVE_SNPRINTF) 112# if HAVE_DECL__SNPRINTF 113 /* Windows. */ 114# define SNPRINTF _snprintf 115# else 116 /* Unix. */ 117# define SNPRINTF snprintf 118# endif 119#endif 120 121CHAR_T * 122VASNPRINTF (CHAR_T *resultbuf, size_t *lengthp, const CHAR_T *format, va_list args) 123{ 124 DIRECTIVES d; 125 arguments a; 126 127 if (PRINTF_PARSE (format, &d, &a) < 0) 128 { 129 errno = EINVAL; 130 return NULL; 131 } 132 133#define CLEANUP() \ 134 free (d.dir); \ 135 if (a.arg) \ 136 free (a.arg); 137 138 if (printf_fetchargs (args, &a) < 0) 139 { 140 CLEANUP (); 141 errno = EINVAL; 142 return NULL; 143 } 144 145 { 146 size_t buf_neededlength; 147 CHAR_T *buf; 148 CHAR_T *buf_malloced; 149 const CHAR_T *cp; 150 size_t i; 151 DIRECTIVE *dp; 152 /* Output string accumulator. */ 153 CHAR_T *result; 154 size_t allocated; 155 size_t length; 156 157 /* Allocate a small buffer that will hold a directive passed to 158 sprintf or snprintf. */ 159 buf_neededlength = 160 xsum4 (7, d.max_width_length, d.max_precision_length, 6); 161#if HAVE_ALLOCA 162 if (buf_neededlength < 4000 / sizeof (CHAR_T)) 163 { 164 buf = (CHAR_T *) alloca (buf_neededlength * sizeof (CHAR_T)); 165 buf_malloced = NULL; 166 } 167 else 168#endif 169 { 170 size_t buf_memsize = xtimes (buf_neededlength, sizeof (CHAR_T)); 171 if (size_overflow_p (buf_memsize)) 172 goto out_of_memory_1; 173 buf = (CHAR_T *) malloc (buf_memsize); 174 if (buf == NULL) 175 goto out_of_memory_1; 176 buf_malloced = buf; 177 } 178 179 if (resultbuf != NULL) 180 { 181 result = resultbuf; 182 allocated = *lengthp; 183 } 184 else 185 { 186 result = NULL; 187 allocated = 0; 188 } 189 length = 0; 190 /* Invariants: 191 result is either == resultbuf or == NULL or malloc-allocated. 192 If length > 0, then result != NULL. */ 193 194 /* Ensures that allocated >= needed. Aborts through a jump to 195 out_of_memory if needed is SIZE_MAX or otherwise too big. */ 196#define ENSURE_ALLOCATION(needed) \ 197 if ((needed) > allocated) \ 198 { \ 199 size_t memory_size; \ 200 CHAR_T *memory; \ 201 \ 202 allocated = (allocated > 0 ? xtimes (allocated, 2) : 12); \ 203 if ((needed) > allocated) \ 204 allocated = (needed); \ 205 memory_size = xtimes (allocated, sizeof (CHAR_T)); \ 206 if (size_overflow_p (memory_size)) \ 207 goto out_of_memory; \ 208 if (result == resultbuf || result == NULL) \ 209 memory = (CHAR_T *) malloc (memory_size); \ 210 else \ 211 memory = (CHAR_T *) realloc (result, memory_size); \ 212 if (memory == NULL) \ 213 goto out_of_memory; \ 214 if (result == resultbuf && length > 0) \ 215 memcpy (memory, result, length * sizeof (CHAR_T)); \ 216 result = memory; \ 217 } 218 219 for (cp = format, i = 0, dp = &d.dir[0]; ; cp = dp->dir_end, i++, dp++) 220 { 221 if (cp != dp->dir_start) 222 { 223 size_t n = dp->dir_start - cp; 224 size_t augmented_length = xsum (length, n); 225 226 ENSURE_ALLOCATION (augmented_length); 227 memcpy (result + length, cp, n * sizeof (CHAR_T)); 228 length = augmented_length; 229 } 230 if (i == d.count) 231 break; 232 233 /* Execute a single directive. */ 234 if (dp->conversion == '%') 235 { 236 size_t augmented_length; 237 238 if (!(dp->arg_index == ARG_NONE)) 239 abort (); 240 augmented_length = xsum (length, 1); 241 ENSURE_ALLOCATION (augmented_length); 242 result[length] = '%'; 243 length = augmented_length; 244 } 245 else 246 { 247 if (!(dp->arg_index != ARG_NONE)) 248 abort (); 249 250 if (dp->conversion == 'n') 251 { 252 switch (a.arg[dp->arg_index].type) 253 { 254 case TYPE_COUNT_SCHAR_POINTER: 255 *a.arg[dp->arg_index].a.a_count_schar_pointer = length; 256 break; 257 case TYPE_COUNT_SHORT_POINTER: 258 *a.arg[dp->arg_index].a.a_count_short_pointer = length; 259 break; 260 case TYPE_COUNT_INT_POINTER: 261 *a.arg[dp->arg_index].a.a_count_int_pointer = length; 262 break; 263 case TYPE_COUNT_LONGINT_POINTER: 264 *a.arg[dp->arg_index].a.a_count_longint_pointer = length; 265 break; 266#ifdef HAVE_LONG_LONG 267 case TYPE_COUNT_LONGLONGINT_POINTER: 268 *a.arg[dp->arg_index].a.a_count_longlongint_pointer = length; 269 break; 270#endif 271 default: 272 abort (); 273 } 274 } 275 else 276 { 277 arg_type type = a.arg[dp->arg_index].type; 278 CHAR_T *p; 279 unsigned int prefix_count; 280 int prefixes[2]; 281#if !USE_SNPRINTF 282 size_t tmp_length; 283 CHAR_T tmpbuf[700]; 284 CHAR_T *tmp; 285 286 /* Allocate a temporary buffer of sufficient size for calling 287 sprintf. */ 288 { 289 size_t width; 290 size_t precision; 291 292 width = 0; 293 if (dp->width_start != dp->width_end) 294 { 295 if (dp->width_arg_index != ARG_NONE) 296 { 297 int arg; 298 299 if (!(a.arg[dp->width_arg_index].type == TYPE_INT)) 300 abort (); 301 arg = a.arg[dp->width_arg_index].a.a_int; 302 width = (arg < 0 ? (unsigned int) (-arg) : arg); 303 } 304 else 305 { 306 const CHAR_T *digitp = dp->width_start; 307 308 do 309 width = xsum (xtimes (width, 10), *digitp++ - '0'); 310 while (digitp != dp->width_end); 311 } 312 } 313 314 precision = 6; 315 if (dp->precision_start != dp->precision_end) 316 { 317 if (dp->precision_arg_index != ARG_NONE) 318 { 319 int arg; 320 321 if (!(a.arg[dp->precision_arg_index].type == TYPE_INT)) 322 abort (); 323 arg = a.arg[dp->precision_arg_index].a.a_int; 324 precision = (arg < 0 ? 0 : arg); 325 } 326 else 327 { 328 const CHAR_T *digitp = dp->precision_start + 1; 329 330 precision = 0; 331 while (digitp != dp->precision_end) 332 precision = xsum (xtimes (precision, 10), *digitp++ - '0'); 333 } 334 } 335 336 switch (dp->conversion) 337 { 338 339 case 'd': case 'i': case 'u': 340# ifdef HAVE_LONG_LONG 341 if (type == TYPE_LONGLONGINT || type == TYPE_ULONGLONGINT) 342 tmp_length = 343 (unsigned int) (sizeof (unsigned long long) * CHAR_BIT 344 * 0.30103 /* binary -> decimal */ 345 * 2 /* estimate for FLAG_GROUP */ 346 ) 347 + 1 /* turn floor into ceil */ 348 + 1; /* account for leading sign */ 349 else 350# endif 351 if (type == TYPE_LONGINT || type == TYPE_ULONGINT) 352 tmp_length = 353 (unsigned int) (sizeof (unsigned long) * CHAR_BIT 354 * 0.30103 /* binary -> decimal */ 355 * 2 /* estimate for FLAG_GROUP */ 356 ) 357 + 1 /* turn floor into ceil */ 358 + 1; /* account for leading sign */ 359 else 360 tmp_length = 361 (unsigned int) (sizeof (unsigned int) * CHAR_BIT 362 * 0.30103 /* binary -> decimal */ 363 * 2 /* estimate for FLAG_GROUP */ 364 ) 365 + 1 /* turn floor into ceil */ 366 + 1; /* account for leading sign */ 367 break; 368 369 case 'o': 370# ifdef HAVE_LONG_LONG 371 if (type == TYPE_LONGLONGINT || type == TYPE_ULONGLONGINT) 372 tmp_length = 373 (unsigned int) (sizeof (unsigned long long) * CHAR_BIT 374 * 0.333334 /* binary -> octal */ 375 ) 376 + 1 /* turn floor into ceil */ 377 + 1; /* account for leading sign */ 378 else 379# endif 380 if (type == TYPE_LONGINT || type == TYPE_ULONGINT) 381 tmp_length = 382 (unsigned int) (sizeof (unsigned long) * CHAR_BIT 383 * 0.333334 /* binary -> octal */ 384 ) 385 + 1 /* turn floor into ceil */ 386 + 1; /* account for leading sign */ 387 else 388 tmp_length = 389 (unsigned int) (sizeof (unsigned int) * CHAR_BIT 390 * 0.333334 /* binary -> octal */ 391 ) 392 + 1 /* turn floor into ceil */ 393 + 1; /* account for leading sign */ 394 break; 395 396 case 'x': case 'X': 397# ifdef HAVE_LONG_LONG 398 if (type == TYPE_LONGLONGINT || type == TYPE_ULONGLONGINT) 399 tmp_length = 400 (unsigned int) (sizeof (unsigned long long) * CHAR_BIT 401 * 0.25 /* binary -> hexadecimal */ 402 ) 403 + 1 /* turn floor into ceil */ 404 + 2; /* account for leading sign or alternate form */ 405 else 406# endif 407 if (type == TYPE_LONGINT || type == TYPE_ULONGINT) 408 tmp_length = 409 (unsigned int) (sizeof (unsigned long) * CHAR_BIT 410 * 0.25 /* binary -> hexadecimal */ 411 ) 412 + 1 /* turn floor into ceil */ 413 + 2; /* account for leading sign or alternate form */ 414 else 415 tmp_length = 416 (unsigned int) (sizeof (unsigned int) * CHAR_BIT 417 * 0.25 /* binary -> hexadecimal */ 418 ) 419 + 1 /* turn floor into ceil */ 420 + 2; /* account for leading sign or alternate form */ 421 break; 422 423 case 'f': case 'F': 424# ifdef HAVE_LONG_DOUBLE 425 if (type == TYPE_LONGDOUBLE) 426 tmp_length = 427 (unsigned int) (LDBL_MAX_EXP 428 * 0.30103 /* binary -> decimal */ 429 * 2 /* estimate for FLAG_GROUP */ 430 ) 431 + 1 /* turn floor into ceil */ 432 + 10; /* sign, decimal point etc. */ 433 else 434# endif 435 tmp_length = 436 (unsigned int) (DBL_MAX_EXP 437 * 0.30103 /* binary -> decimal */ 438 * 2 /* estimate for FLAG_GROUP */ 439 ) 440 + 1 /* turn floor into ceil */ 441 + 10; /* sign, decimal point etc. */ 442 tmp_length = xsum (tmp_length, precision); 443 break; 444 445 case 'e': case 'E': case 'g': case 'G': 446 case 'a': case 'A': 447 tmp_length = 448 12; /* sign, decimal point, exponent etc. */ 449 tmp_length = xsum (tmp_length, precision); 450 break; 451 452 case 'c': 453# if defined HAVE_WINT_T && !WIDE_CHAR_VERSION 454 if (type == TYPE_WIDE_CHAR) 455 tmp_length = MB_CUR_MAX; 456 else 457# endif 458 tmp_length = 1; 459 break; 460 461 case 's': 462# ifdef HAVE_WCHAR_T 463 if (type == TYPE_WIDE_STRING) 464 { 465 tmp_length = 466 local_wcslen (a.arg[dp->arg_index].a.a_wide_string); 467 468# if !WIDE_CHAR_VERSION 469 tmp_length = xtimes (tmp_length, MB_CUR_MAX); 470# endif 471 } 472 else 473# endif 474 tmp_length = strlen (a.arg[dp->arg_index].a.a_string); 475 break; 476 477 case 'p': 478 tmp_length = 479 (unsigned int) (sizeof (void *) * CHAR_BIT 480 * 0.25 /* binary -> hexadecimal */ 481 ) 482 + 1 /* turn floor into ceil */ 483 + 2; /* account for leading 0x */ 484 break; 485 486 default: 487 abort (); 488 } 489 490 if (tmp_length < width) 491 tmp_length = width; 492 493 tmp_length = xsum (tmp_length, 1); /* account for trailing NUL */ 494 } 495 496 if (tmp_length <= sizeof (tmpbuf) / sizeof (CHAR_T)) 497 tmp = tmpbuf; 498 else 499 { 500 size_t tmp_memsize = xtimes (tmp_length, sizeof (CHAR_T)); 501 502 if (size_overflow_p (tmp_memsize)) 503 /* Overflow, would lead to out of memory. */ 504 goto out_of_memory; 505 tmp = (CHAR_T *) malloc (tmp_memsize); 506 if (tmp == NULL) 507 /* Out of memory. */ 508 goto out_of_memory; 509 } 510#endif 511 512 /* Construct the format string for calling snprintf or 513 sprintf. */ 514 p = buf; 515 *p++ = '%'; 516 if (dp->flags & FLAG_GROUP) 517 *p++ = '\''; 518 if (dp->flags & FLAG_LEFT) 519 *p++ = '-'; 520 if (dp->flags & FLAG_SHOWSIGN) 521 *p++ = '+'; 522 if (dp->flags & FLAG_SPACE) 523 *p++ = ' '; 524 if (dp->flags & FLAG_ALT) 525 *p++ = '#'; 526 if (dp->flags & FLAG_ZERO) 527 *p++ = '0'; 528 if (dp->width_start != dp->width_end) 529 { 530 size_t n = dp->width_end - dp->width_start; 531 memcpy (p, dp->width_start, n * sizeof (CHAR_T)); 532 p += n; 533 } 534 if (dp->precision_start != dp->precision_end) 535 { 536 size_t n = dp->precision_end - dp->precision_start; 537 memcpy (p, dp->precision_start, n * sizeof (CHAR_T)); 538 p += n; 539 } 540 541 switch (type) 542 { 543#ifdef HAVE_LONG_LONG 544 case TYPE_LONGLONGINT: 545 case TYPE_ULONGLONGINT: 546 *p++ = 'l'; 547 /*FALLTHROUGH*/ 548#endif 549 case TYPE_LONGINT: 550 case TYPE_ULONGINT: 551#ifdef HAVE_WINT_T 552 case TYPE_WIDE_CHAR: 553#endif 554#ifdef HAVE_WCHAR_T 555 case TYPE_WIDE_STRING: 556#endif 557 *p++ = 'l'; 558 break; 559#ifdef HAVE_LONG_DOUBLE 560 case TYPE_LONGDOUBLE: 561 *p++ = 'L'; 562 break; 563#endif 564 default: 565 break; 566 } 567 *p = dp->conversion; 568 p[1] = '\0'; 569 570 /* Construct the arguments for calling snprintf or sprintf. */ 571 prefix_count = 0; 572 if (dp->width_arg_index != ARG_NONE) 573 { 574 if (!(a.arg[dp->width_arg_index].type == TYPE_INT)) 575 abort (); 576 prefixes[prefix_count++] = a.arg[dp->width_arg_index].a.a_int; 577 } 578 if (dp->precision_arg_index != ARG_NONE) 579 { 580 if (!(a.arg[dp->precision_arg_index].type == TYPE_INT)) 581 abort (); 582 prefixes[prefix_count++] = a.arg[dp->precision_arg_index].a.a_int; 583 } 584 585#if USE_SNPRINTF 586 /* Prepare checking whether snprintf returns the count 587 via %n. */ 588 ENSURE_ALLOCATION (xsum (length, 1)); 589 result[length] = '\0'; 590#endif 591 592 for (;;) 593 { 594 size_t maxlen; 595 int count; 596 597 maxlen = allocated - length; 598 count = -1; 599 600#if USE_SNPRINTF 601# define SNPRINTF_BUF(arg) \ 602 switch (prefix_count) \ 603 { \ 604 case 0: \ 605 count = SNPRINTF (result + length, maxlen, buf, \ 606 arg); \ 607 break; \ 608 case 1: \ 609 count = SNPRINTF (result + length, maxlen, buf, \ 610 prefixes[0], arg); \ 611 break; \ 612 case 2: \ 613 count = SNPRINTF (result + length, maxlen, buf, \ 614 prefixes[0], prefixes[1], arg); \ 615 break; \ 616 default: \ 617 abort (); \ 618 } 619#else 620# define SNPRINTF_BUF(arg) \ 621 switch (prefix_count) \ 622 { \ 623 case 0: \ 624 count = sprintf (tmp, buf, arg); \ 625 break; \ 626 case 1: \ 627 count = sprintf (tmp, buf, prefixes[0], arg); \ 628 break; \ 629 case 2: \ 630 count = sprintf (tmp, buf, prefixes[0], prefixes[1],\ 631 arg); \ 632 break; \ 633 default: \ 634 abort (); \ 635 } 636#endif 637 638 switch (type) 639 { 640 case TYPE_SCHAR: 641 { 642 int arg = a.arg[dp->arg_index].a.a_schar; 643 SNPRINTF_BUF (arg); 644 } 645 break; 646 case TYPE_UCHAR: 647 { 648 unsigned int arg = a.arg[dp->arg_index].a.a_uchar; 649 SNPRINTF_BUF (arg); 650 } 651 break; 652 case TYPE_SHORT: 653 { 654 int arg = a.arg[dp->arg_index].a.a_short; 655 SNPRINTF_BUF (arg); 656 } 657 break; 658 case TYPE_USHORT: 659 { 660 unsigned int arg = a.arg[dp->arg_index].a.a_ushort; 661 SNPRINTF_BUF (arg); 662 } 663 break; 664 case TYPE_INT: 665 { 666 int arg = a.arg[dp->arg_index].a.a_int; 667 SNPRINTF_BUF (arg); 668 } 669 break; 670 case TYPE_UINT: 671 { 672 unsigned int arg = a.arg[dp->arg_index].a.a_uint; 673 SNPRINTF_BUF (arg); 674 } 675 break; 676 case TYPE_LONGINT: 677 { 678 long int arg = a.arg[dp->arg_index].a.a_longint; 679 SNPRINTF_BUF (arg); 680 } 681 break; 682 case TYPE_ULONGINT: 683 { 684 unsigned long int arg = a.arg[dp->arg_index].a.a_ulongint; 685 SNPRINTF_BUF (arg); 686 } 687 break; 688#ifdef HAVE_LONG_LONG 689 case TYPE_LONGLONGINT: 690 { 691 long long int arg = a.arg[dp->arg_index].a.a_longlongint; 692 SNPRINTF_BUF (arg); 693 } 694 break; 695 case TYPE_ULONGLONGINT: 696 { 697 unsigned long long int arg = a.arg[dp->arg_index].a.a_ulonglongint; 698 SNPRINTF_BUF (arg); 699 } 700 break; 701#endif 702 case TYPE_DOUBLE: 703 { 704 double arg = a.arg[dp->arg_index].a.a_double; 705 SNPRINTF_BUF (arg); 706 } 707 break; 708#ifdef HAVE_LONG_DOUBLE 709 case TYPE_LONGDOUBLE: 710 { 711 long double arg = a.arg[dp->arg_index].a.a_longdouble; 712 SNPRINTF_BUF (arg); 713 } 714 break; 715#endif 716 case TYPE_CHAR: 717 { 718 int arg = a.arg[dp->arg_index].a.a_char; 719 SNPRINTF_BUF (arg); 720 } 721 break; 722#ifdef HAVE_WINT_T 723 case TYPE_WIDE_CHAR: 724 { 725 wint_t arg = a.arg[dp->arg_index].a.a_wide_char; 726 SNPRINTF_BUF (arg); 727 } 728 break; 729#endif 730 case TYPE_STRING: 731 { 732 const char *arg = a.arg[dp->arg_index].a.a_string; 733 SNPRINTF_BUF (arg); 734 } 735 break; 736#ifdef HAVE_WCHAR_T 737 case TYPE_WIDE_STRING: 738 { 739 const wchar_t *arg = a.arg[dp->arg_index].a.a_wide_string; 740 SNPRINTF_BUF (arg); 741 } 742 break; 743#endif 744 case TYPE_POINTER: 745 { 746 void *arg = a.arg[dp->arg_index].a.a_pointer; 747 SNPRINTF_BUF (arg); 748 } 749 break; 750 default: 751 abort (); 752 } 753 754#if USE_SNPRINTF 755 /* Portability: Not all implementations of snprintf() 756 are ISO C 99 compliant. Determine the number of 757 bytes that snprintf() has produced or would have 758 produced. */ 759 if (count >= 0) 760 { 761 /* Verify that snprintf() has NUL-terminated its 762 result. */ 763 if (count < maxlen && result[length + count] != '\0') 764 abort (); 765 } 766#endif 767 768 /* Attempt to handle failure. */ 769 if (count < 0) 770 { 771 if (!(result == resultbuf || result == NULL)) 772 free (result); 773 if (buf_malloced != NULL) 774 free (buf_malloced); 775 CLEANUP (); 776 errno = EINVAL; 777 return NULL; 778 } 779 780#if !USE_SNPRINTF 781 if (count >= tmp_length) 782 /* tmp_length was incorrectly calculated - fix the 783 code above! */ 784 abort (); 785#endif 786 787 /* Make room for the result. */ 788 if (count >= maxlen) 789 { 790 /* Need at least count bytes. But allocate 791 proportionally, to avoid looping eternally if 792 snprintf() reports a too small count. */ 793 size_t n = 794 xmax (xsum (length, count), xtimes (allocated, 2)); 795 796 ENSURE_ALLOCATION (n); 797#if USE_SNPRINTF 798 continue; 799#endif 800 } 801 802#if USE_SNPRINTF 803 /* The snprintf() result did fit. */ 804#else 805 /* Append the sprintf() result. */ 806 memcpy (result + length, tmp, count * sizeof (CHAR_T)); 807 if (tmp != tmpbuf) 808 free (tmp); 809#endif 810 811 length += count; 812 break; 813 } 814 } 815 } 816 } 817 818 /* Add the final NUL. */ 819 ENSURE_ALLOCATION (xsum (length, 1)); 820 result[length] = '\0'; 821 822 if (result != resultbuf && length + 1 < allocated) 823 { 824 /* Shrink the allocated memory if possible. */ 825 CHAR_T *memory; 826 827 memory = (CHAR_T *) realloc (result, (length + 1) * sizeof (CHAR_T)); 828 if (memory != NULL) 829 result = memory; 830 } 831 832 if (buf_malloced != NULL) 833 free (buf_malloced); 834 CLEANUP (); 835 *lengthp = length; 836 if (length > INT_MAX) 837 goto length_overflow; 838 return result; 839 840 length_overflow: 841 /* We could produce such a big string, but its length doesn't fit into 842 an 'int'. POSIX says that snprintf() fails with errno = EOVERFLOW in 843 this case. */ 844 if (result != resultbuf) 845 free (result); 846 errno = EOVERFLOW; 847 return NULL; 848 849 out_of_memory: 850 if (!(result == resultbuf || result == NULL)) 851 free (result); 852 if (buf_malloced != NULL) 853 free (buf_malloced); 854 out_of_memory_1: 855 CLEANUP (); 856 errno = ENOMEM; 857 return NULL; 858 } 859} 860 861#undef SNPRINTF 862#undef USE_SNPRINTF 863#undef PRINTF_PARSE 864#undef DIRECTIVES 865#undef DIRECTIVE 866#undef CHAR_T 867#undef VASNPRINTF 868