vasprintf.c revision 191736
1/* 2 * Copyright (c) Ian F. Darwin 1986-1995. 3 * Software written by Ian F. Darwin and others; 4 * maintained 1995-present by Christos Zoulas and others. 5 * 6 * Redistribution and use in source and binary forms, with or without 7 * modification, are permitted provided that the following conditions 8 * are met: 9 * 1. Redistributions of source code must retain the above copyright 10 * notice immediately at the beginning of the file, without modification, 11 * this list of conditions, and the following disclaimer. 12 * 2. Redistributions in binary form must reproduce the above copyright 13 * notice, this list of conditions and the following disclaimer in the 14 * documentation and/or other materials provided with the distribution. 15 * 16 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 17 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 18 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 19 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR 20 * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 21 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 22 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 23 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 24 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 25 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 26 * SUCH DAMAGE. 27 */ 28/*########################################################################### 29 # # 30 # vasprintf # 31 # # 32 # Copyright (c) 2002-2005 David TAILLANDIER # 33 # # 34 ###########################################################################*/ 35 36/* 37 38This software is distributed under the "modified BSD licence". 39 40This software is also released with GNU license (GPL) in another file (same 41source-code, only license differ). 42 43 44 45Redistribution and use in source and binary forms, with or without 46modification, are permitted provided that the following conditions are met: 47 48Redistributions of source code must retain the above copyright notice, this 49list of conditions and the following disclaimer. Redistributions in binary 50form must reproduce the above copyright notice, this list of conditions and 51the following disclaimer in the documentation and/or other materials 52provided with the distribution. The name of the author may not be used to 53endorse or promote products derived from this software without specific 54prior written permission. 55 56THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED 57WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 58MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO 59EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 60SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 61PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; 62OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 63WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR 64OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF 65ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 66 67==================== 68 69Hacked from xnprintf version of 26th February 2005 to provide only 70vasprintf by Reuben Thomas <rrt@sc3d.org>. 71 72==================== 73 74 75'printf' function family use the following format string: 76 77%[flag][width][.prec][modifier]type 78 79%% is the escape sequence to print a '%' 80% followed by an unknown format will print the characters without 81trying to do any interpretation 82 83flag: none + - # (blank) 84width: n 0n * 85prec: none .0 .n .* 86modifier: F N L h l ll ('F' and 'N' are ms-dos/16-bit specific) 87type: d i o u x X f e g E G c s p n 88 89 90The function needs to allocate memory to store the full text before to 91actually writting it. i.e if you want to fnprintf() 1000 characters, the 92functions will allocate 1000 bytes. 93This behaviour can be modified: you have to customise the code to flush the 94internal buffer (writing to screen or file) when it reach a given size. Then 95the buffer can have a shorter length. But what? If you really need to write 96HUGE string, don't use printf! 97During the process, some other memory is allocated (1024 bytes minimum) 98to handle the output of partial sprintf() calls. If you have only 10000 bytes 99free in memory, you *may* not be able to nprintf() a 8000 bytes-long text. 100 101note: if a buffer overflow occurs, exit() is called. This situation should 102never appear ... but if you want to be *really* sure, you have to modify the 103code to handle those situations (only one place to modify). 104A buffer overflow can only occur if your sprintf() do strange things or when 105you use strange formats. 106 107*/ 108#include "file.h" 109 110#ifndef lint 111FILE_RCSID("@(#)$File: vasprintf.c,v 1.7 2009/02/03 20:27:52 christos Exp $") 112#endif /* lint */ 113 114#include <assert.h> 115#include <string.h> 116#include <stdlib.h> 117#include <stdarg.h> 118#include <ctype.h> 119#ifdef HAVE_LIMITS_H 120#include <limits.h> 121#endif 122 123#define ALLOC_CHUNK 2048 124#define ALLOC_SECURITY_MARGIN 1024 /* big value because some platforms have very big 'G' exponent */ 125#if ALLOC_CHUNK < ALLOC_SECURITY_MARGIN 126# error !!! ALLOC_CHUNK < ALLOC_SECURITY_MARGIN !!! 127#endif 128/* note: to have some interest, ALLOC_CHUNK should be much greater than ALLOC_SECURITY_MARGIN */ 129 130/* 131 * To save a lot of push/pop, every variable are stored into this 132 * structure, which is passed among nearly every sub-functions. 133 */ 134typedef struct { 135 const char * src_string; /* current position into intput string */ 136 char * buffer_base; /* output buffer */ 137 char * dest_string; /* current position into output string */ 138 size_t buffer_len; /* length of output buffer */ 139 size_t real_len; /* real current length of output text */ 140 size_t pseudo_len; /* total length of output text if it were not limited in size */ 141 size_t maxlen; 142 va_list vargs; /* pointer to current position into vargs */ 143 char * sprintf_string; 144 FILE * fprintf_file; 145} xprintf_struct; 146 147/* 148 * Realloc buffer if needed 149 * Return value: 0 = ok 150 * EOF = not enought memory 151 */ 152static int realloc_buff(xprintf_struct *s, size_t len) 153{ 154 char * ptr; 155 156 if (len + ALLOC_SECURITY_MARGIN + s->real_len > s->buffer_len) { 157 len += s->real_len + ALLOC_CHUNK; 158 ptr = (char *)realloc((void *)(s->buffer_base), len); 159 if (ptr == NULL) { 160 s->buffer_base = NULL; 161 return EOF; 162 } 163 164 s->dest_string = ptr + (size_t)(s->dest_string - s->buffer_base); 165 s->buffer_base = ptr; 166 s->buffer_len = len; 167 168 (s->buffer_base)[s->buffer_len - 1] = 1; /* overflow marker */ 169 } 170 171 return 0; 172} 173 174/* 175 * Prints 'usual' characters up to next '%' 176 * or up to end of text 177 */ 178static int usual_char(xprintf_struct * s) 179{ 180 size_t len; 181 182 len = strcspn(s->src_string, "%"); /* reachs the next '%' or end of input string */ 183 /* note: 'len' is never 0 because the presence of '%' */ 184 /* or end-of-line is checked in the calling function */ 185 186 if (realloc_buff(s,len) == EOF) 187 return EOF; 188 189 memcpy(s->dest_string, s->src_string, len); 190 s->src_string += len; 191 s->dest_string += len; 192 s->real_len += len; 193 s->pseudo_len += len; 194 195 return 0; 196} 197 198/* 199 * Return value: 0 = ok 200 * EOF = error 201 */ 202static int print_it(xprintf_struct *s, size_t approx_len, 203 const char *format_string, ...) 204{ 205 va_list varg; 206 int vsprintf_len; 207 size_t len; 208 209 if (realloc_buff(s,approx_len) == EOF) 210 return EOF; 211 212 va_start(varg, format_string); 213 vsprintf_len = vsprintf(s->dest_string, format_string, varg); 214 va_end(varg); 215 216 /* Check for overflow */ 217 assert((s->buffer_base)[s->buffer_len - 1] == 1); 218 219 if (vsprintf_len == EOF) /* must be done *after* overflow-check */ 220 return EOF; 221 222 s->pseudo_len += vsprintf_len; 223 len = strlen(s->dest_string); 224 s->real_len += len; 225 s->dest_string += len; 226 227 return 0; 228} 229 230/* 231 * Prints a string (%s) 232 * We need special handling because: 233 * a: the length of the string is unknown 234 * b: when .prec is used, we must not access any extra byte of the 235 * string (of course, if the original sprintf() does... what the 236 * hell, not my problem) 237 * 238 * Return value: 0 = ok 239 * EOF = error 240 */ 241static int type_s(xprintf_struct *s, int width, int prec, 242 const char *format_string, const char *arg_string) 243{ 244 size_t string_len; 245 246 if (arg_string == NULL) 247 return print_it(s, (size_t)6, "(null)", 0); 248 249 /* hand-made strlen() whitch stops when 'prec' is reached. */ 250 /* if 'prec' is -1 then it is never reached. */ 251 string_len = 0; 252 while (arg_string[string_len] != 0 && (size_t)prec != string_len) 253 string_len++; 254 255 if (width != -1 && string_len < (size_t)width) 256 string_len = (size_t)width; 257 258 return print_it(s, string_len, format_string, arg_string); 259} 260 261/* 262 * Read a serie of digits. Stop when non-digit is found. 263 * Return value: the value read (between 0 and 32767). 264 * Note: no checks are made against overflow. If the string contain a big 265 * number, then the return value won't be what we want (but, in this case, 266 * the programmer don't know whatr he wants, then no problem). 267 */ 268static int getint(const char **string) 269{ 270 int i = 0; 271 272 while (isdigit((unsigned char)**string) != 0) { 273 i = i * 10 + (**string - '0'); 274 (*string)++; 275 } 276 277 if (i < 0 || i > 32767) 278 i = 32767; /* if we have i==-10 this is not because the number is */ 279 /* negative; this is because the number is big */ 280 return i; 281} 282 283/* 284 * Read a part of the format string. A part is 'usual characters' (ie "blabla") 285 * or '%%' escape sequence (to print a single '%') or any combination of 286 * format specifier (ie "%i" or "%10.2d"). 287 * After the current part is managed, the function returns to caller with 288 * everything ready to manage the following part. 289 * The caller must ensure than the string is not empty, i.e. the first byte 290 * is not zero. 291 * 292 * Return value: 0 = ok 293 * EOF = error 294 */ 295static int dispatch(xprintf_struct *s) 296{ 297 const char *initial_ptr; 298 char format_string[24]; /* max length may be something like "% +-#032768.32768Ld" */ 299 char *format_ptr; 300 int flag_plus, flag_minus, flag_space, flag_sharp, flag_zero; 301 int width, prec, modifier, approx_width; 302 char type; 303 /* most of those variables are here to rewrite the format string */ 304 305#define SRCTXT (s->src_string) 306#define DESTTXT (s->dest_string) 307 308 /* incoherent format string. Characters after the '%' will be printed with the next call */ 309#define INCOHERENT() do {SRCTXT=initial_ptr; return 0;} while (0) /* do/while to avoid */ 310#define INCOHERENT_TEST() do {if(*SRCTXT==0) INCOHERENT();} while (0) /* a null statement */ 311 312 /* 'normal' text */ 313 if (*SRCTXT != '%') 314 return usual_char(s); 315 316 /* we then have a '%' */ 317 SRCTXT++; 318 /* don't check for end-of-string ; this is done later */ 319 320 /* '%%' escape sequence */ 321 if (*SRCTXT == '%') { 322 if (realloc_buff(s, (size_t)1) == EOF) /* because we can have "%%%%%%%%..." */ 323 return EOF; 324 *DESTTXT = '%'; 325 DESTTXT++; 326 SRCTXT++; 327 (s->real_len)++; 328 (s->pseudo_len)++; 329 return 0; 330 } 331 332 /* '%' managing */ 333 initial_ptr = SRCTXT; /* save current pointer in case of incorrect */ 334 /* 'decoding'. Points just after the '%' so the '%' */ 335 /* won't be printed in any case, as required. */ 336 337 /* flag */ 338 flag_plus = flag_minus = flag_space = flag_sharp = flag_zero = 0; 339 340 for (;; SRCTXT++) { 341 if (*SRCTXT == ' ') 342 flag_space = 1; 343 else if (*SRCTXT == '+') 344 flag_plus = 1; 345 else if (*SRCTXT == '-') 346 flag_minus = 1; 347 else if (*SRCTXT == '#') 348 flag_sharp = 1; 349 else if (*SRCTXT == '0') 350 flag_zero = 1; 351 else 352 break; 353 } 354 355 INCOHERENT_TEST(); /* here is the first test for end of string */ 356 357 /* width */ 358 if (*SRCTXT == '*') { /* width given by next argument */ 359 SRCTXT++; 360 width = va_arg(s->vargs, int); 361 if ((size_t)width > 0x3fffU) /* 'size_t' to check against negative values too */ 362 width = 0x3fff; 363 } else if (isdigit((unsigned char)*SRCTXT)) /* width given as ASCII number */ 364 width = getint(&SRCTXT); 365 else 366 width = -1; /* no width specified */ 367 368 INCOHERENT_TEST(); 369 370 /* .prec */ 371 if (*SRCTXT == '.') { 372 SRCTXT++; 373 if (*SRCTXT == '*') { /* .prec given by next argument */ 374 SRCTXT++; 375 prec = va_arg(s->vargs, int); 376 if ((size_t)prec >= 0x3fffU) /* 'size_t' to check against negative values too */ 377 prec = 0x3fff; 378 } else { /* .prec given as ASCII number */ 379 if (isdigit((unsigned char)*SRCTXT) == 0) 380 INCOHERENT(); 381 prec = getint(&SRCTXT); 382 } 383 INCOHERENT_TEST(); 384 } else 385 prec = -1; /* no .prec specified */ 386 387 /* modifier */ 388 if (*SRCTXT == 'L' || *SRCTXT == 'h' || *SRCTXT == 'l') { 389 modifier = *SRCTXT; 390 SRCTXT++; 391 if (modifier=='l' && *SRCTXT=='l') { 392 SRCTXT++; 393 modifier = 'L'; /* 'll' == 'L' long long == long double */ 394 } /* only for compatibility ; not portable */ 395 INCOHERENT_TEST(); 396 } else 397 modifier = -1; /* no modifier specified */ 398 399 /* type */ 400 type = *SRCTXT; 401 if (strchr("diouxXfegEGcspn",type) == NULL) 402 INCOHERENT(); /* unknown type */ 403 SRCTXT++; 404 405 /* rewrite format-string */ 406 format_string[0] = '%'; 407 format_ptr = &(format_string[1]); 408 409 if (flag_plus) { 410 *format_ptr = '+'; 411 format_ptr++; 412 } 413 if (flag_minus) { 414 *format_ptr = '-'; 415 format_ptr++; 416 } 417 if (flag_space) { 418 *format_ptr = ' '; 419 format_ptr++; 420 } 421 if (flag_sharp) { 422 *format_ptr = '#'; 423 format_ptr++; 424 } 425 if (flag_zero) { 426 *format_ptr = '0'; 427 format_ptr++; 428 } /* '0' *must* be the last one */ 429 430 if (width != -1) { 431 sprintf(format_ptr, "%i", width); 432 format_ptr += strlen(format_ptr); 433 } 434 435 if (prec != -1) { 436 *format_ptr = '.'; 437 format_ptr++; 438 sprintf(format_ptr, "%i", prec); 439 format_ptr += strlen(format_ptr); 440 } 441 442 if (modifier != -1) { 443 if (modifier == 'L' && strchr("diouxX",type) != NULL) { 444 *format_ptr = 'l'; 445 format_ptr++; 446 *format_ptr = 'l'; 447 format_ptr++; 448 } else { 449 *format_ptr = modifier; 450 format_ptr++; 451 } 452 } 453 454 *format_ptr = type; 455 format_ptr++; 456 *format_ptr = 0; 457 458 /* vague approximation of minimal length if width or prec are specified */ 459 approx_width = width + prec; 460 if (approx_width < 0) /* because width == -1 and/or prec == -1 */ 461 approx_width = 0; 462 463 switch (type) { 464 /* int */ 465 case 'd': 466 case 'i': 467 case 'o': 468 case 'u': 469 case 'x': 470 case 'X': 471 switch (modifier) { 472 case -1 : 473 return print_it(s, (size_t)approx_width, format_string, va_arg(s->vargs, int)); 474 case 'L': 475 return print_it(s, (size_t)approx_width, format_string, va_arg(s->vargs, long long int)); 476 case 'l': 477 return print_it(s, (size_t)approx_width, format_string, va_arg(s->vargs, long int)); 478 case 'h': 479 return print_it(s, (size_t)approx_width, format_string, va_arg(s->vargs, int)); 480 /* 'int' instead of 'short int' because default promotion is 'int' */ 481 default: 482 INCOHERENT(); 483 } 484 485 /* char */ 486 case 'c': 487 if (modifier != -1) 488 INCOHERENT(); 489 return print_it(s, (size_t)approx_width, format_string, va_arg(s->vargs, int)); 490 /* 'int' instead of 'char' because default promotion is 'int' */ 491 492 /* math */ 493 case 'e': 494 case 'f': 495 case 'g': 496 case 'E': 497 case 'G': 498 switch (modifier) { 499 case -1 : /* because of default promotion, no modifier means 'l' */ 500 case 'l': 501 return print_it(s, (size_t)approx_width, format_string, va_arg(s->vargs, double)); 502 case 'L': 503 return print_it(s, (size_t)approx_width, format_string, va_arg(s->vargs, long double)); 504 default: 505 INCOHERENT(); 506 } 507 508 /* string */ 509 case 's': 510 return type_s(s, width, prec, format_string, va_arg(s->vargs, const char*)); 511 512 /* pointer */ 513 case 'p': 514 if (modifier == -1) 515 return print_it(s, (size_t)approx_width, format_string, va_arg(s->vargs, void *)); 516 INCOHERENT(); 517 518 /* store */ 519 case 'n': 520 if (modifier == -1) { 521 int * p; 522 p = va_arg(s->vargs, int *); 523 if (p != NULL) { 524 *p = s->pseudo_len; 525 return 0; 526 } 527 return EOF; 528 } 529 INCOHERENT(); 530 531 } /* switch */ 532 533 INCOHERENT(); /* unknown type */ 534 535#undef INCOHERENT 536#undef INCOHERENT_TEST 537#undef SRCTXT 538#undef DESTTXT 539} 540 541/* 542 * Return value: number of *virtually* written characters 543 * EOF = error 544 */ 545static int core(xprintf_struct *s) 546{ 547 size_t len, save_len; 548 char *dummy_base; 549 550 /* basic checks */ 551 if ((int)(s->maxlen) <= 0) /* 'int' to check against some conversion */ 552 return EOF; /* error for example if value is (int)-10 */ 553 s->maxlen--; /* because initial maxlen counts final 0 */ 554 /* note: now 'maxlen' _can_ be zero */ 555 556 if (s->src_string == NULL) 557 s->src_string = "(null)"; 558 559 /* struct init and memory allocation */ 560 s->buffer_base = NULL; 561 s->buffer_len = 0; 562 s->real_len = 0; 563 s->pseudo_len = 0; 564 if (realloc_buff(s, (size_t)0) == EOF) 565 return EOF; 566 s->dest_string = s->buffer_base; 567 568 /* process source string */ 569 for (;;) { 570 /* up to end of source string */ 571 if (*(s->src_string) == 0) { 572 *(s->dest_string) = 0; /* final 0 */ 573 len = s->real_len + 1; 574 break; 575 } 576 577 if (dispatch(s) == EOF) 578 goto free_EOF; 579 580 /* up to end of dest string */ 581 if (s->real_len >= s->maxlen) { 582 (s->buffer_base)[s->maxlen] = 0; /* final 0 */ 583 len = s->maxlen + 1; 584 break; 585 } 586 } 587 588 /* for (v)asnprintf */ 589 dummy_base = s->buffer_base; 590 save_len = 0; /* just to avoid a compiler warning */ 591 592 dummy_base = s->buffer_base + s->real_len; 593 save_len = s->real_len; 594 595 /* process the remaining of source string to compute 'pseudo_len'. We 596 * overwrite again and again, starting at 'dummy_base' because we don't 597 * need the text, only char count. */ 598 while(*(s->src_string) != 0) { /* up to end of source string */ 599 s->real_len = 0; 600 s->dest_string = dummy_base; 601 if (dispatch(s) == EOF) 602 goto free_EOF; 603 } 604 605 s->buffer_base = (char *)realloc((void *)(s->buffer_base), save_len + 1); 606 if (s->buffer_base == NULL) 607 return EOF; /* should rarely happen because we shrink the buffer */ 608 return s->pseudo_len; 609 610 free_EOF: 611 if (s->buffer_base != NULL) 612 free(s->buffer_base); 613 return EOF; 614} 615 616int vasprintf(char **ptr, const char *format_string, va_list vargs) 617{ 618 xprintf_struct s; 619 int retval; 620 621 s.src_string = format_string; 622#ifdef va_copy 623 va_copy (s.vargs, vargs); 624#else 625#ifdef __va_copy 626 __va_copy (s.vargs, vargs); 627#else 628 memcpy (&s.vargs, vargs, sizeof (va_list)); 629#endif /* __va_copy */ 630#endif /* va_copy */ 631 s.maxlen = (size_t)INT_MAX; 632 633 retval = core(&s); 634 va_end(s.vargs); 635 if (retval == EOF) { 636 *ptr = NULL; 637 return EOF; 638 } 639 640 *ptr = s.buffer_base; 641 return retval; 642} 643