1/* Licensed to the Apache Software Foundation (ASF) under one or more 2 * contributor license agreements. See the NOTICE file distributed with 3 * this work for additional information regarding copyright ownership. 4 * The ASF licenses this file to You under the Apache License, Version 2.0 5 * (the "License"); you may not use this file except in compliance with 6 * the License. You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17#include "apr.h" 18#include "apr_private.h" 19 20#include "apr_lib.h" 21#include "apr_strings.h" 22#include "apr_network_io.h" 23#include "apr_portable.h" 24#include "apr_errno.h" 25#include <math.h> 26#if APR_HAVE_CTYPE_H 27#include <ctype.h> 28#endif 29#if APR_HAVE_NETINET_IN_H 30#include <netinet/in.h> 31#endif 32#if APR_HAVE_SYS_SOCKET_H 33#include <sys/socket.h> 34#endif 35#if APR_HAVE_ARPA_INET_H 36#include <arpa/inet.h> 37#endif 38#if APR_HAVE_LIMITS_H 39#include <limits.h> 40#endif 41#if APR_HAVE_STRING_H 42#include <string.h> 43#endif 44 45typedef enum { 46 NO = 0, YES = 1 47} boolean_e; 48 49#ifndef FALSE 50#define FALSE 0 51#endif 52#ifndef TRUE 53#define TRUE 1 54#endif 55#define NUL '\0' 56 57static const char null_string[] = "(null)"; 58#define S_NULL ((char *)null_string) 59#define S_NULL_LEN 6 60 61#define FLOAT_DIGITS 6 62#define EXPONENT_LENGTH 10 63 64/* 65 * NUM_BUF_SIZE is the size of the buffer used for arithmetic conversions 66 * 67 * NOTICE: this is a magic number; do not decrease it 68 */ 69#define NUM_BUF_SIZE 512 70 71/* 72 * cvt - IEEE floating point formatting routines. 73 * Derived from UNIX V7, Copyright(C) Caldera International Inc. 74 */ 75 76/* 77 * apr_ecvt converts to decimal 78 * the number of digits is specified by ndigit 79 * decpt is set to the position of the decimal point 80 * sign is set to 0 for positive, 1 for negative 81 */ 82 83#define NDIG 80 84 85/* buf must have at least NDIG bytes */ 86static char *apr_cvt(double arg, int ndigits, int *decpt, int *sign, 87 int eflag, char *buf) 88{ 89 register int r2; 90 double fi, fj; 91 register char *p, *p1; 92 93 if (ndigits >= NDIG - 1) 94 ndigits = NDIG - 2; 95 r2 = 0; 96 *sign = 0; 97 p = &buf[0]; 98 if (arg < 0) { 99 *sign = 1; 100 arg = -arg; 101 } 102 arg = modf(arg, &fi); 103 p1 = &buf[NDIG]; 104 /* 105 * Do integer part 106 */ 107 if (fi != 0) { 108 p1 = &buf[NDIG]; 109 while (p1 > &buf[0] && fi != 0) { 110 fj = modf(fi / 10, &fi); 111 *--p1 = (int) ((fj + .03) * 10) + '0'; 112 r2++; 113 } 114 while (p1 < &buf[NDIG]) 115 *p++ = *p1++; 116 } 117 else if (arg > 0) { 118 while ((fj = arg * 10) < 1) { 119 arg = fj; 120 r2--; 121 } 122 } 123 p1 = &buf[ndigits]; 124 if (eflag == 0) 125 p1 += r2; 126 if (p1 < &buf[0]) { 127 *decpt = -ndigits; 128 buf[0] = '\0'; 129 return (buf); 130 } 131 *decpt = r2; 132 while (p <= p1 && p < &buf[NDIG]) { 133 arg *= 10; 134 arg = modf(arg, &fj); 135 *p++ = (int) fj + '0'; 136 } 137 if (p1 >= &buf[NDIG]) { 138 buf[NDIG - 1] = '\0'; 139 return (buf); 140 } 141 p = p1; 142 *p1 += 5; 143 while (*p1 > '9') { 144 *p1 = '0'; 145 if (p1 > buf) 146 ++ * --p1; 147 else { 148 *p1 = '1'; 149 (*decpt)++; 150 if (eflag == 0) { 151 if (p > buf) 152 *p = '0'; 153 p++; 154 } 155 } 156 } 157 *p = '\0'; 158 return (buf); 159} 160 161static char *apr_ecvt(double arg, int ndigits, int *decpt, int *sign, char *buf) 162{ 163 return (apr_cvt(arg, ndigits, decpt, sign, 1, buf)); 164} 165 166static char *apr_fcvt(double arg, int ndigits, int *decpt, int *sign, char *buf) 167{ 168 return (apr_cvt(arg, ndigits, decpt, sign, 0, buf)); 169} 170 171/* 172 * apr_gcvt - Floating output conversion to 173 * minimal length string 174 */ 175 176static char *apr_gcvt(double number, int ndigit, char *buf, boolean_e altform) 177{ 178 int sign, decpt; 179 register char *p1, *p2; 180 register int i; 181 char buf1[NDIG]; 182 183 p1 = apr_ecvt(number, ndigit, &decpt, &sign, buf1); 184 p2 = buf; 185 if (sign) 186 *p2++ = '-'; 187 for (i = ndigit - 1; i > 0 && p1[i] == '0'; i--) 188 ndigit--; 189 if ((decpt >= 0 && decpt - ndigit > 4) 190 || (decpt < 0 && decpt < -3)) { /* use E-style */ 191 decpt--; 192 *p2++ = *p1++; 193 *p2++ = '.'; 194 for (i = 1; i < ndigit; i++) 195 *p2++ = *p1++; 196 *p2++ = 'e'; 197 if (decpt < 0) { 198 decpt = -decpt; 199 *p2++ = '-'; 200 } 201 else 202 *p2++ = '+'; 203 if (decpt / 100 > 0) 204 *p2++ = decpt / 100 + '0'; 205 if (decpt / 10 > 0) 206 *p2++ = (decpt % 100) / 10 + '0'; 207 *p2++ = decpt % 10 + '0'; 208 } 209 else { 210 if (decpt <= 0) { 211 if (*p1 != '0') 212 *p2++ = '.'; 213 while (decpt < 0) { 214 decpt++; 215 *p2++ = '0'; 216 } 217 } 218 for (i = 1; i <= ndigit; i++) { 219 *p2++ = *p1++; 220 if (i == decpt) 221 *p2++ = '.'; 222 } 223 if (ndigit < decpt) { 224 while (ndigit++ < decpt) 225 *p2++ = '0'; 226 *p2++ = '.'; 227 } 228 } 229 if (p2[-1] == '.' && !altform) 230 p2--; 231 *p2 = '\0'; 232 return (buf); 233} 234 235/* 236 * The INS_CHAR macro inserts a character in the buffer and writes 237 * the buffer back to disk if necessary 238 * It uses the char pointers sp and bep: 239 * sp points to the next available character in the buffer 240 * bep points to the end-of-buffer+1 241 * While using this macro, note that the nextb pointer is NOT updated. 242 * 243 * NOTE: Evaluation of the c argument should not have any side-effects 244 */ 245#define INS_CHAR(c, sp, bep, cc) \ 246{ \ 247 if (sp) { \ 248 if (sp >= bep) { \ 249 vbuff->curpos = sp; \ 250 if (flush_func(vbuff)) \ 251 return -1; \ 252 sp = vbuff->curpos; \ 253 bep = vbuff->endpos; \ 254 } \ 255 *sp++ = (c); \ 256 } \ 257 cc++; \ 258} 259 260#define NUM(c) (c - '0') 261 262#define STR_TO_DEC(str, num) \ 263 num = NUM(*str++); \ 264 while (apr_isdigit(*str)) \ 265 { \ 266 num *= 10 ; \ 267 num += NUM(*str++); \ 268 } 269 270/* 271 * This macro does zero padding so that the precision 272 * requirement is satisfied. The padding is done by 273 * adding '0's to the left of the string that is going 274 * to be printed. We don't allow precision to be large 275 * enough that we continue past the start of s. 276 * 277 * NOTE: this makes use of the magic info that s is 278 * always based on num_buf with a size of NUM_BUF_SIZE. 279 */ 280#define FIX_PRECISION(adjust, precision, s, s_len) \ 281 if (adjust) { \ 282 apr_size_t p = (precision + 1 < NUM_BUF_SIZE) \ 283 ? precision : NUM_BUF_SIZE - 1; \ 284 while (s_len < p) \ 285 { \ 286 *--s = '0'; \ 287 s_len++; \ 288 } \ 289 } 290 291/* 292 * Macro that does padding. The padding is done by printing 293 * the character ch. 294 */ 295#define PAD(width, len, ch) \ 296do \ 297{ \ 298 INS_CHAR(ch, sp, bep, cc); \ 299 width--; \ 300} \ 301while (width > len) 302 303/* 304 * Prefix the character ch to the string str 305 * Increase length 306 * Set the has_prefix flag 307 */ 308#define PREFIX(str, length, ch) \ 309 *--str = ch; \ 310 length++; \ 311 has_prefix=YES; 312 313 314/* 315 * Convert num to its decimal format. 316 * Return value: 317 * - a pointer to a string containing the number (no sign) 318 * - len contains the length of the string 319 * - is_negative is set to TRUE or FALSE depending on the sign 320 * of the number (always set to FALSE if is_unsigned is TRUE) 321 * 322 * The caller provides a buffer for the string: that is the buf_end argument 323 * which is a pointer to the END of the buffer + 1 (i.e. if the buffer 324 * is declared as buf[ 100 ], buf_end should be &buf[ 100 ]) 325 * 326 * Note: we have 2 versions. One is used when we need to use quads 327 * (conv_10_quad), the other when we don't (conv_10). We're assuming the 328 * latter is faster. 329 */ 330static char *conv_10(register apr_int32_t num, register int is_unsigned, 331 register int *is_negative, char *buf_end, 332 register apr_size_t *len) 333{ 334 register char *p = buf_end; 335 register apr_uint32_t magnitude = num; 336 337 if (is_unsigned) { 338 *is_negative = FALSE; 339 } 340 else { 341 *is_negative = (num < 0); 342 343 /* 344 * On a 2's complement machine, negating the most negative integer 345 * results in a number that cannot be represented as a signed integer. 346 * Here is what we do to obtain the number's magnitude: 347 * a. add 1 to the number 348 * b. negate it (becomes positive) 349 * c. convert it to unsigned 350 * d. add 1 351 */ 352 if (*is_negative) { 353 apr_int32_t t = num + 1; 354 magnitude = ((apr_uint32_t) -t) + 1; 355 } 356 } 357 358 /* 359 * We use a do-while loop so that we write at least 1 digit 360 */ 361 do { 362 register apr_uint32_t new_magnitude = magnitude / 10; 363 364 *--p = (char) (magnitude - new_magnitude * 10 + '0'); 365 magnitude = new_magnitude; 366 } 367 while (magnitude); 368 369 *len = buf_end - p; 370 return (p); 371} 372 373static char *conv_10_quad(apr_int64_t num, register int is_unsigned, 374 register int *is_negative, char *buf_end, 375 register apr_size_t *len) 376{ 377 register char *p = buf_end; 378 apr_uint64_t magnitude = num; 379 380 /* 381 * We see if we can use the faster non-quad version by checking the 382 * number against the largest long value it can be. If <=, we 383 * punt to the quicker version. 384 */ 385 if ((magnitude <= APR_UINT32_MAX && is_unsigned) 386 || (num <= APR_INT32_MAX && num >= APR_INT32_MIN && !is_unsigned)) 387 return(conv_10((apr_int32_t)num, is_unsigned, is_negative, buf_end, len)); 388 389 if (is_unsigned) { 390 *is_negative = FALSE; 391 } 392 else { 393 *is_negative = (num < 0); 394 395 /* 396 * On a 2's complement machine, negating the most negative integer 397 * results in a number that cannot be represented as a signed integer. 398 * Here is what we do to obtain the number's magnitude: 399 * a. add 1 to the number 400 * b. negate it (becomes positive) 401 * c. convert it to unsigned 402 * d. add 1 403 */ 404 if (*is_negative) { 405 apr_int64_t t = num + 1; 406 magnitude = ((apr_uint64_t) -t) + 1; 407 } 408 } 409 410 /* 411 * We use a do-while loop so that we write at least 1 digit 412 */ 413 do { 414 apr_uint64_t new_magnitude = magnitude / 10; 415 416 *--p = (char) (magnitude - new_magnitude * 10 + '0'); 417 magnitude = new_magnitude; 418 } 419 while (magnitude); 420 421 *len = buf_end - p; 422 return (p); 423} 424 425static char *conv_in_addr(struct in_addr *ia, char *buf_end, apr_size_t *len) 426{ 427 unsigned addr = ntohl(ia->s_addr); 428 char *p = buf_end; 429 int is_negative; 430 apr_size_t sub_len; 431 432 p = conv_10((addr & 0x000000FF) , TRUE, &is_negative, p, &sub_len); 433 *--p = '.'; 434 p = conv_10((addr & 0x0000FF00) >> 8, TRUE, &is_negative, p, &sub_len); 435 *--p = '.'; 436 p = conv_10((addr & 0x00FF0000) >> 16, TRUE, &is_negative, p, &sub_len); 437 *--p = '.'; 438 p = conv_10((addr & 0xFF000000) >> 24, TRUE, &is_negative, p, &sub_len); 439 440 *len = buf_end - p; 441 return (p); 442} 443 444 445/* Must be passed a buffer of size NUM_BUF_SIZE where buf_end points 446 * to 1 byte past the end of the buffer. */ 447static char *conv_apr_sockaddr(apr_sockaddr_t *sa, char *buf_end, apr_size_t *len) 448{ 449 char *p = buf_end; 450 int is_negative; 451 apr_size_t sub_len; 452 char *ipaddr_str; 453 454 p = conv_10(sa->port, TRUE, &is_negative, p, &sub_len); 455 *--p = ':'; 456 ipaddr_str = buf_end - NUM_BUF_SIZE; 457 if (apr_sockaddr_ip_getbuf(ipaddr_str, sa->addr_str_len, sa)) { 458 /* Should only fail if the buffer is too small, which it 459 * should not be; but fail safe anyway: */ 460 *--p = '?'; 461 *len = buf_end - p; 462 return p; 463 } 464 sub_len = strlen(ipaddr_str); 465#if APR_HAVE_IPV6 466 if (sa->family == APR_INET6 && 467 !IN6_IS_ADDR_V4MAPPED(&sa->sa.sin6.sin6_addr)) { 468 *(p - 1) = ']'; 469 p -= sub_len + 2; 470 *p = '['; 471 memcpy(p + 1, ipaddr_str, sub_len); 472 } 473 else 474#endif 475 { 476 p -= sub_len; 477 memcpy(p, ipaddr_str, sub_len); 478 } 479 480 *len = buf_end - p; 481 return (p); 482} 483 484 485 486#if APR_HAS_THREADS 487static char *conv_os_thread_t(apr_os_thread_t *tid, char *buf_end, apr_size_t *len) 488{ 489 union { 490 apr_os_thread_t tid; 491 apr_uint64_t u64; 492 apr_uint32_t u32; 493 } u; 494 int is_negative; 495 496 u.tid = *tid; 497 switch(sizeof(u.tid)) { 498 case sizeof(apr_int32_t): 499 return conv_10(u.u32, TRUE, &is_negative, buf_end, len); 500 case sizeof(apr_int64_t): 501 return conv_10_quad(u.u64, TRUE, &is_negative, buf_end, len); 502 default: 503 /* not implemented; stick 0 in the buffer */ 504 return conv_10(0, TRUE, &is_negative, buf_end, len); 505 } 506} 507#endif 508 509 510 511/* 512 * Convert a floating point number to a string formats 'f', 'e' or 'E'. 513 * The result is placed in buf, and len denotes the length of the string 514 * The sign is returned in the is_negative argument (and is not placed 515 * in buf). 516 */ 517static char *conv_fp(register char format, register double num, 518 boolean_e add_dp, int precision, int *is_negative, 519 char *buf, apr_size_t *len) 520{ 521 register char *s = buf; 522 register char *p; 523 int decimal_point; 524 char buf1[NDIG]; 525 526 if (format == 'f') 527 p = apr_fcvt(num, precision, &decimal_point, is_negative, buf1); 528 else /* either e or E format */ 529 p = apr_ecvt(num, precision + 1, &decimal_point, is_negative, buf1); 530 531 /* 532 * Check for Infinity and NaN 533 */ 534 if (apr_isalpha(*p)) { 535 *len = strlen(p); 536 memcpy(buf, p, *len + 1); 537 *is_negative = FALSE; 538 return (buf); 539 } 540 541 if (format == 'f') { 542 if (decimal_point <= 0) { 543 *s++ = '0'; 544 if (precision > 0) { 545 *s++ = '.'; 546 while (decimal_point++ < 0) 547 *s++ = '0'; 548 } 549 else if (add_dp) 550 *s++ = '.'; 551 } 552 else { 553 while (decimal_point-- > 0) 554 *s++ = *p++; 555 if (precision > 0 || add_dp) 556 *s++ = '.'; 557 } 558 } 559 else { 560 *s++ = *p++; 561 if (precision > 0 || add_dp) 562 *s++ = '.'; 563 } 564 565 /* 566 * copy the rest of p, the NUL is NOT copied 567 */ 568 while (*p) 569 *s++ = *p++; 570 571 if (format != 'f') { 572 char temp[EXPONENT_LENGTH]; /* for exponent conversion */ 573 apr_size_t t_len; 574 int exponent_is_negative; 575 576 *s++ = format; /* either e or E */ 577 decimal_point--; 578 if (decimal_point != 0) { 579 p = conv_10((apr_int32_t) decimal_point, FALSE, &exponent_is_negative, 580 &temp[EXPONENT_LENGTH], &t_len); 581 *s++ = exponent_is_negative ? '-' : '+'; 582 583 /* 584 * Make sure the exponent has at least 2 digits 585 */ 586 if (t_len == 1) 587 *s++ = '0'; 588 while (t_len--) 589 *s++ = *p++; 590 } 591 else { 592 *s++ = '+'; 593 *s++ = '0'; 594 *s++ = '0'; 595 } 596 } 597 598 *len = s - buf; 599 return (buf); 600} 601 602 603/* 604 * Convert num to a base X number where X is a power of 2. nbits determines X. 605 * For example, if nbits is 3, we do base 8 conversion 606 * Return value: 607 * a pointer to a string containing the number 608 * 609 * The caller provides a buffer for the string: that is the buf_end argument 610 * which is a pointer to the END of the buffer + 1 (i.e. if the buffer 611 * is declared as buf[ 100 ], buf_end should be &buf[ 100 ]) 612 * 613 * As with conv_10, we have a faster version which is used when 614 * the number isn't quad size. 615 */ 616static char *conv_p2(register apr_uint32_t num, register int nbits, 617 char format, char *buf_end, register apr_size_t *len) 618{ 619 register int mask = (1 << nbits) - 1; 620 register char *p = buf_end; 621 static const char low_digits[] = "0123456789abcdef"; 622 static const char upper_digits[] = "0123456789ABCDEF"; 623 register const char *digits = (format == 'X') ? upper_digits : low_digits; 624 625 do { 626 *--p = digits[num & mask]; 627 num >>= nbits; 628 } 629 while (num); 630 631 *len = buf_end - p; 632 return (p); 633} 634 635static char *conv_p2_quad(apr_uint64_t num, register int nbits, 636 char format, char *buf_end, register apr_size_t *len) 637{ 638 register int mask = (1 << nbits) - 1; 639 register char *p = buf_end; 640 static const char low_digits[] = "0123456789abcdef"; 641 static const char upper_digits[] = "0123456789ABCDEF"; 642 register const char *digits = (format == 'X') ? upper_digits : low_digits; 643 644 if (num <= APR_UINT32_MAX) 645 return(conv_p2((apr_uint32_t)num, nbits, format, buf_end, len)); 646 647 do { 648 *--p = digits[num & mask]; 649 num >>= nbits; 650 } 651 while (num); 652 653 *len = buf_end - p; 654 return (p); 655} 656 657#if APR_HAS_THREADS 658static char *conv_os_thread_t_hex(apr_os_thread_t *tid, char *buf_end, apr_size_t *len) 659{ 660 union { 661 apr_os_thread_t tid; 662 apr_uint64_t u64; 663 apr_uint32_t u32; 664 } u; 665 int is_negative; 666 667 u.tid = *tid; 668 switch(sizeof(u.tid)) { 669 case sizeof(apr_int32_t): 670 return conv_p2(u.u32, 4, 'x', buf_end, len); 671 case sizeof(apr_int64_t): 672 return conv_p2_quad(u.u64, 4, 'x', buf_end, len); 673 default: 674 /* not implemented; stick 0 in the buffer */ 675 return conv_10(0, TRUE, &is_negative, buf_end, len); 676 } 677} 678#endif 679 680/* 681 * Do format conversion placing the output in buffer 682 */ 683APR_DECLARE(int) apr_vformatter(int (*flush_func)(apr_vformatter_buff_t *), 684 apr_vformatter_buff_t *vbuff, const char *fmt, va_list ap) 685{ 686 register char *sp; 687 register char *bep; 688 register int cc = 0; 689 register apr_size_t i; 690 691 register char *s = NULL; 692 char *q; 693 apr_size_t s_len = 0; 694 695 register apr_size_t min_width = 0; 696 apr_size_t precision = 0; 697 enum { 698 LEFT, RIGHT 699 } adjust; 700 char pad_char; 701 char prefix_char; 702 703 double fp_num; 704 apr_int64_t i_quad = 0; 705 apr_uint64_t ui_quad; 706 apr_int32_t i_num = 0; 707 apr_uint32_t ui_num = 0; 708 709 char num_buf[NUM_BUF_SIZE]; 710 char char_buf[2]; /* for printing %% and %<unknown> */ 711 712 enum var_type_enum { 713 IS_QUAD, IS_LONG, IS_SHORT, IS_INT 714 }; 715 enum var_type_enum var_type = IS_INT; 716 717 /* 718 * Flag variables 719 */ 720 boolean_e alternate_form; 721 boolean_e print_sign; 722 boolean_e print_blank; 723 boolean_e adjust_precision; 724 boolean_e adjust_width; 725 int is_negative; 726 727 sp = vbuff->curpos; 728 bep = vbuff->endpos; 729 730 while (*fmt) { 731 if (*fmt != '%') { 732 INS_CHAR(*fmt, sp, bep, cc); 733 } 734 else { 735 /* 736 * Default variable settings 737 */ 738 boolean_e print_something = YES; 739 adjust = RIGHT; 740 alternate_form = print_sign = print_blank = NO; 741 pad_char = ' '; 742 prefix_char = NUL; 743 744 fmt++; 745 746 /* 747 * Try to avoid checking for flags, width or precision 748 */ 749 if (!apr_islower(*fmt)) { 750 /* 751 * Recognize flags: -, #, BLANK, + 752 */ 753 for (;; fmt++) { 754 if (*fmt == '-') 755 adjust = LEFT; 756 else if (*fmt == '+') 757 print_sign = YES; 758 else if (*fmt == '#') 759 alternate_form = YES; 760 else if (*fmt == ' ') 761 print_blank = YES; 762 else if (*fmt == '0') 763 pad_char = '0'; 764 else 765 break; 766 } 767 768 /* 769 * Check if a width was specified 770 */ 771 if (apr_isdigit(*fmt)) { 772 STR_TO_DEC(fmt, min_width); 773 adjust_width = YES; 774 } 775 else if (*fmt == '*') { 776 int v = va_arg(ap, int); 777 fmt++; 778 adjust_width = YES; 779 if (v < 0) { 780 adjust = LEFT; 781 min_width = (apr_size_t)(-v); 782 } 783 else 784 min_width = (apr_size_t)v; 785 } 786 else 787 adjust_width = NO; 788 789 /* 790 * Check if a precision was specified 791 */ 792 if (*fmt == '.') { 793 adjust_precision = YES; 794 fmt++; 795 if (apr_isdigit(*fmt)) { 796 STR_TO_DEC(fmt, precision); 797 } 798 else if (*fmt == '*') { 799 int v = va_arg(ap, int); 800 fmt++; 801 precision = (v < 0) ? 0 : (apr_size_t)v; 802 } 803 else 804 precision = 0; 805 } 806 else 807 adjust_precision = NO; 808 } 809 else 810 adjust_precision = adjust_width = NO; 811 812 /* 813 * Modifier check. In same cases, APR_OFF_T_FMT can be 814 * "lld" and APR_INT64_T_FMT can be "ld" (that is, off_t is 815 * "larger" than int64). Check that case 1st. 816 * Note that if APR_OFF_T_FMT is "d", 817 * the first if condition is never true. If APR_INT64_T_FMT 818 * is "d' then the second if condition is never true. 819 */ 820 if ((sizeof(APR_OFF_T_FMT) > sizeof(APR_INT64_T_FMT)) && 821 ((sizeof(APR_OFF_T_FMT) == 4 && 822 fmt[0] == APR_OFF_T_FMT[0] && 823 fmt[1] == APR_OFF_T_FMT[1]) || 824 (sizeof(APR_OFF_T_FMT) == 3 && 825 fmt[0] == APR_OFF_T_FMT[0]) || 826 (sizeof(APR_OFF_T_FMT) > 4 && 827 strncmp(fmt, APR_OFF_T_FMT, 828 sizeof(APR_OFF_T_FMT) - 2) == 0))) { 829 /* Need to account for trailing 'd' and null in sizeof() */ 830 var_type = IS_QUAD; 831 fmt += (sizeof(APR_OFF_T_FMT) - 2); 832 } 833 else if ((sizeof(APR_INT64_T_FMT) == 4 && 834 fmt[0] == APR_INT64_T_FMT[0] && 835 fmt[1] == APR_INT64_T_FMT[1]) || 836 (sizeof(APR_INT64_T_FMT) == 3 && 837 fmt[0] == APR_INT64_T_FMT[0]) || 838 (sizeof(APR_INT64_T_FMT) > 4 && 839 strncmp(fmt, APR_INT64_T_FMT, 840 sizeof(APR_INT64_T_FMT) - 2) == 0)) { 841 /* Need to account for trailing 'd' and null in sizeof() */ 842 var_type = IS_QUAD; 843 fmt += (sizeof(APR_INT64_T_FMT) - 2); 844 } 845 else if (*fmt == 'q') { 846 var_type = IS_QUAD; 847 fmt++; 848 } 849 else if (*fmt == 'l') { 850 var_type = IS_LONG; 851 fmt++; 852 } 853 else if (*fmt == 'h') { 854 var_type = IS_SHORT; 855 fmt++; 856 } 857 else { 858 var_type = IS_INT; 859 } 860 861 /* 862 * Argument extraction and printing. 863 * First we determine the argument type. 864 * Then, we convert the argument to a string. 865 * On exit from the switch, s points to the string that 866 * must be printed, s_len has the length of the string 867 * The precision requirements, if any, are reflected in s_len. 868 * 869 * NOTE: pad_char may be set to '0' because of the 0 flag. 870 * It is reset to ' ' by non-numeric formats 871 */ 872 switch (*fmt) { 873 case 'u': 874 if (var_type == IS_QUAD) { 875 i_quad = va_arg(ap, apr_uint64_t); 876 s = conv_10_quad(i_quad, 1, &is_negative, 877 &num_buf[NUM_BUF_SIZE], &s_len); 878 } 879 else { 880 if (var_type == IS_LONG) 881 i_num = (apr_int32_t) va_arg(ap, apr_uint32_t); 882 else if (var_type == IS_SHORT) 883 i_num = (apr_int32_t) (unsigned short) va_arg(ap, unsigned int); 884 else 885 i_num = (apr_int32_t) va_arg(ap, unsigned int); 886 s = conv_10(i_num, 1, &is_negative, 887 &num_buf[NUM_BUF_SIZE], &s_len); 888 } 889 FIX_PRECISION(adjust_precision, precision, s, s_len); 890 break; 891 892 case 'd': 893 case 'i': 894 if (var_type == IS_QUAD) { 895 i_quad = va_arg(ap, apr_int64_t); 896 s = conv_10_quad(i_quad, 0, &is_negative, 897 &num_buf[NUM_BUF_SIZE], &s_len); 898 } 899 else { 900 if (var_type == IS_LONG) 901 i_num = va_arg(ap, apr_int32_t); 902 else if (var_type == IS_SHORT) 903 i_num = (short) va_arg(ap, int); 904 else 905 i_num = va_arg(ap, int); 906 s = conv_10(i_num, 0, &is_negative, 907 &num_buf[NUM_BUF_SIZE], &s_len); 908 } 909 FIX_PRECISION(adjust_precision, precision, s, s_len); 910 911 if (is_negative) 912 prefix_char = '-'; 913 else if (print_sign) 914 prefix_char = '+'; 915 else if (print_blank) 916 prefix_char = ' '; 917 break; 918 919 920 case 'o': 921 if (var_type == IS_QUAD) { 922 ui_quad = va_arg(ap, apr_uint64_t); 923 s = conv_p2_quad(ui_quad, 3, *fmt, 924 &num_buf[NUM_BUF_SIZE], &s_len); 925 } 926 else { 927 if (var_type == IS_LONG) 928 ui_num = va_arg(ap, apr_uint32_t); 929 else if (var_type == IS_SHORT) 930 ui_num = (unsigned short) va_arg(ap, unsigned int); 931 else 932 ui_num = va_arg(ap, unsigned int); 933 s = conv_p2(ui_num, 3, *fmt, 934 &num_buf[NUM_BUF_SIZE], &s_len); 935 } 936 FIX_PRECISION(adjust_precision, precision, s, s_len); 937 if (alternate_form && *s != '0') { 938 *--s = '0'; 939 s_len++; 940 } 941 break; 942 943 944 case 'x': 945 case 'X': 946 if (var_type == IS_QUAD) { 947 ui_quad = va_arg(ap, apr_uint64_t); 948 s = conv_p2_quad(ui_quad, 4, *fmt, 949 &num_buf[NUM_BUF_SIZE], &s_len); 950 } 951 else { 952 if (var_type == IS_LONG) 953 ui_num = va_arg(ap, apr_uint32_t); 954 else if (var_type == IS_SHORT) 955 ui_num = (unsigned short) va_arg(ap, unsigned int); 956 else 957 ui_num = va_arg(ap, unsigned int); 958 s = conv_p2(ui_num, 4, *fmt, 959 &num_buf[NUM_BUF_SIZE], &s_len); 960 } 961 FIX_PRECISION(adjust_precision, precision, s, s_len); 962 if (alternate_form && ui_num != 0) { 963 *--s = *fmt; /* 'x' or 'X' */ 964 *--s = '0'; 965 s_len += 2; 966 } 967 break; 968 969 970 case 's': 971 s = va_arg(ap, char *); 972 if (s != NULL) { 973 if (!adjust_precision) { 974 s_len = strlen(s); 975 } 976 else { 977 /* From the C library standard in section 7.9.6.1: 978 * ...if the precision is specified, no more then 979 * that many characters are written. If the 980 * precision is not specified or is greater 981 * than the size of the array, the array shall 982 * contain a null character. 983 * 984 * My reading is is precision is specified and 985 * is less then or equal to the size of the 986 * array, no null character is required. So 987 * we can't do a strlen. 988 * 989 * This figures out the length of the string 990 * up to the precision. Once it's long enough 991 * for the specified precision, we don't care 992 * anymore. 993 * 994 * NOTE: you must do the length comparison 995 * before the check for the null character. 996 * Otherwise, you'll check one beyond the 997 * last valid character. 998 */ 999 const char *walk; 1000 1001 for (walk = s, s_len = 0; 1002 (s_len < precision) && (*walk != '\0'); 1003 ++walk, ++s_len); 1004 } 1005 } 1006 else { 1007 s = S_NULL; 1008 s_len = S_NULL_LEN; 1009 } 1010 pad_char = ' '; 1011 break; 1012 1013 1014 case 'f': 1015 case 'e': 1016 case 'E': 1017 fp_num = va_arg(ap, double); 1018 /* 1019 * We use &num_buf[ 1 ], so that we have room for the sign 1020 */ 1021 s = NULL; 1022#ifdef HAVE_ISNAN 1023 if (isnan(fp_num)) { 1024 s = "nan"; 1025 s_len = 3; 1026 } 1027#endif 1028#ifdef HAVE_ISINF 1029 if (!s && isinf(fp_num)) { 1030 s = "inf"; 1031 s_len = 3; 1032 } 1033#endif 1034 if (!s) { 1035 s = conv_fp(*fmt, fp_num, alternate_form, 1036 (int)((adjust_precision == NO) ? FLOAT_DIGITS : precision), 1037 &is_negative, &num_buf[1], &s_len); 1038 if (is_negative) 1039 prefix_char = '-'; 1040 else if (print_sign) 1041 prefix_char = '+'; 1042 else if (print_blank) 1043 prefix_char = ' '; 1044 } 1045 break; 1046 1047 1048 case 'g': 1049 case 'G': 1050 if (adjust_precision == NO) 1051 precision = FLOAT_DIGITS; 1052 else if (precision == 0) 1053 precision = 1; 1054 /* 1055 * * We use &num_buf[ 1 ], so that we have room for the sign 1056 */ 1057 s = apr_gcvt(va_arg(ap, double), (int) precision, &num_buf[1], 1058 alternate_form); 1059 if (*s == '-') 1060 prefix_char = *s++; 1061 else if (print_sign) 1062 prefix_char = '+'; 1063 else if (print_blank) 1064 prefix_char = ' '; 1065 1066 s_len = strlen(s); 1067 1068 if (alternate_form && (q = strchr(s, '.')) == NULL) { 1069 s[s_len++] = '.'; 1070 s[s_len] = '\0'; /* delimit for following strchr() */ 1071 } 1072 if (*fmt == 'G' && (q = strchr(s, 'e')) != NULL) 1073 *q = 'E'; 1074 break; 1075 1076 1077 case 'c': 1078 char_buf[0] = (char) (va_arg(ap, int)); 1079 s = &char_buf[0]; 1080 s_len = 1; 1081 pad_char = ' '; 1082 break; 1083 1084 1085 case '%': 1086 char_buf[0] = '%'; 1087 s = &char_buf[0]; 1088 s_len = 1; 1089 pad_char = ' '; 1090 break; 1091 1092 1093 case 'n': 1094 if (var_type == IS_QUAD) 1095 *(va_arg(ap, apr_int64_t *)) = cc; 1096 else if (var_type == IS_LONG) 1097 *(va_arg(ap, long *)) = cc; 1098 else if (var_type == IS_SHORT) 1099 *(va_arg(ap, short *)) = cc; 1100 else 1101 *(va_arg(ap, int *)) = cc; 1102 print_something = NO; 1103 break; 1104 1105 /* 1106 * This is where we extend the printf format, with a second 1107 * type specifier 1108 */ 1109 case 'p': 1110 switch(*++fmt) { 1111 /* 1112 * If the pointer size is equal to or smaller than the size 1113 * of the largest unsigned int, we convert the pointer to a 1114 * hex number, otherwise we print "%p" to indicate that we 1115 * don't handle "%p". 1116 */ 1117 case 'p': 1118#if APR_SIZEOF_VOIDP == 8 1119 if (sizeof(void *) <= sizeof(apr_uint64_t)) { 1120 ui_quad = (apr_uint64_t) va_arg(ap, void *); 1121 s = conv_p2_quad(ui_quad, 4, 'x', 1122 &num_buf[NUM_BUF_SIZE], &s_len); 1123 } 1124#else 1125 if (sizeof(void *) <= sizeof(apr_uint32_t)) { 1126 ui_num = (apr_uint32_t) va_arg(ap, void *); 1127 s = conv_p2(ui_num, 4, 'x', 1128 &num_buf[NUM_BUF_SIZE], &s_len); 1129 } 1130#endif 1131 else { 1132 s = "%p"; 1133 s_len = 2; 1134 prefix_char = NUL; 1135 } 1136 pad_char = ' '; 1137 break; 1138 1139 /* print an apr_sockaddr_t as a.b.c.d:port */ 1140 case 'I': 1141 { 1142 apr_sockaddr_t *sa; 1143 1144 sa = va_arg(ap, apr_sockaddr_t *); 1145 if (sa != NULL) { 1146 s = conv_apr_sockaddr(sa, &num_buf[NUM_BUF_SIZE], &s_len); 1147 if (adjust_precision && precision < s_len) 1148 s_len = precision; 1149 } 1150 else { 1151 s = S_NULL; 1152 s_len = S_NULL_LEN; 1153 } 1154 pad_char = ' '; 1155 } 1156 break; 1157 1158 /* print a struct in_addr as a.b.c.d */ 1159 case 'A': 1160 { 1161 struct in_addr *ia; 1162 1163 ia = va_arg(ap, struct in_addr *); 1164 if (ia != NULL) { 1165 s = conv_in_addr(ia, &num_buf[NUM_BUF_SIZE], &s_len); 1166 if (adjust_precision && precision < s_len) 1167 s_len = precision; 1168 } 1169 else { 1170 s = S_NULL; 1171 s_len = S_NULL_LEN; 1172 } 1173 pad_char = ' '; 1174 } 1175 break; 1176 1177 /* print the error for an apr_status_t */ 1178 case 'm': 1179 { 1180 apr_status_t *mrv; 1181 1182 mrv = va_arg(ap, apr_status_t *); 1183 if (mrv != NULL) { 1184 s = apr_strerror(*mrv, num_buf, NUM_BUF_SIZE-1); 1185 s_len = strlen(s); 1186 } 1187 else { 1188 s = S_NULL; 1189 s_len = S_NULL_LEN; 1190 } 1191 pad_char = ' '; 1192 } 1193 break; 1194 1195 case 'T': 1196#if APR_HAS_THREADS 1197 { 1198 apr_os_thread_t *tid; 1199 1200 tid = va_arg(ap, apr_os_thread_t *); 1201 if (tid != NULL) { 1202 s = conv_os_thread_t(tid, &num_buf[NUM_BUF_SIZE], &s_len); 1203 if (adjust_precision && precision < s_len) 1204 s_len = precision; 1205 } 1206 else { 1207 s = S_NULL; 1208 s_len = S_NULL_LEN; 1209 } 1210 pad_char = ' '; 1211 } 1212#else 1213 char_buf[0] = '0'; 1214 s = &char_buf[0]; 1215 s_len = 1; 1216 pad_char = ' '; 1217#endif 1218 break; 1219 1220 case 't': 1221#if APR_HAS_THREADS 1222 { 1223 apr_os_thread_t *tid; 1224 1225 tid = va_arg(ap, apr_os_thread_t *); 1226 if (tid != NULL) { 1227 s = conv_os_thread_t_hex(tid, &num_buf[NUM_BUF_SIZE], &s_len); 1228 if (adjust_precision && precision < s_len) 1229 s_len = precision; 1230 } 1231 else { 1232 s = S_NULL; 1233 s_len = S_NULL_LEN; 1234 } 1235 pad_char = ' '; 1236 } 1237#else 1238 char_buf[0] = '0'; 1239 s = &char_buf[0]; 1240 s_len = 1; 1241 pad_char = ' '; 1242#endif 1243 break; 1244 1245 case 'B': 1246 case 'F': 1247 case 'S': 1248 { 1249 char buf[5]; 1250 apr_off_t size = 0; 1251 1252 if (*fmt == 'B') { 1253 apr_uint32_t *arg = va_arg(ap, apr_uint32_t *); 1254 size = (arg) ? *arg : 0; 1255 } 1256 else if (*fmt == 'F') { 1257 apr_off_t *arg = va_arg(ap, apr_off_t *); 1258 size = (arg) ? *arg : 0; 1259 } 1260 else { 1261 apr_size_t *arg = va_arg(ap, apr_size_t *); 1262 size = (arg) ? *arg : 0; 1263 } 1264 1265 s = apr_strfsize(size, buf); 1266 s_len = strlen(s); 1267 pad_char = ' '; 1268 } 1269 break; 1270 1271 case NUL: 1272 /* if %p ends the string, oh well ignore it */ 1273 continue; 1274 1275 default: 1276 s = "bogus %p"; 1277 s_len = 8; 1278 prefix_char = NUL; 1279 (void)va_arg(ap, void *); /* skip the bogus argument on the stack */ 1280 break; 1281 } 1282 break; 1283 1284 case NUL: 1285 /* 1286 * The last character of the format string was %. 1287 * We ignore it. 1288 */ 1289 continue; 1290 1291 1292 /* 1293 * The default case is for unrecognized %'s. 1294 * We print %<char> to help the user identify what 1295 * option is not understood. 1296 * This is also useful in case the user wants to pass 1297 * the output of format_converter to another function 1298 * that understands some other %<char> (like syslog). 1299 * Note that we can't point s inside fmt because the 1300 * unknown <char> could be preceded by width etc. 1301 */ 1302 default: 1303 char_buf[0] = '%'; 1304 char_buf[1] = *fmt; 1305 s = char_buf; 1306 s_len = 2; 1307 pad_char = ' '; 1308 break; 1309 } 1310 1311 if (prefix_char != NUL && s != S_NULL && s != char_buf) { 1312 *--s = prefix_char; 1313 s_len++; 1314 } 1315 1316 if (adjust_width && adjust == RIGHT && min_width > s_len) { 1317 if (pad_char == '0' && prefix_char != NUL) { 1318 INS_CHAR(*s, sp, bep, cc); 1319 s++; 1320 s_len--; 1321 min_width--; 1322 } 1323 PAD(min_width, s_len, pad_char); 1324 } 1325 1326 /* 1327 * Print the string s. 1328 */ 1329 if (print_something == YES) { 1330 for (i = s_len; i != 0; i--) { 1331 INS_CHAR(*s, sp, bep, cc); 1332 s++; 1333 } 1334 } 1335 1336 if (adjust_width && adjust == LEFT && min_width > s_len) 1337 PAD(min_width, s_len, pad_char); 1338 } 1339 fmt++; 1340 } 1341 vbuff->curpos = sp; 1342 1343 return cc; 1344} 1345 1346 1347static int snprintf_flush(apr_vformatter_buff_t *vbuff) 1348{ 1349 /* if the buffer fills we have to abort immediately, there is no way 1350 * to "flush" an apr_snprintf... there's nowhere to flush it to. 1351 */ 1352 return -1; 1353} 1354 1355 1356APR_DECLARE_NONSTD(int) apr_snprintf(char *buf, apr_size_t len, 1357 const char *format, ...) 1358{ 1359 int cc; 1360 va_list ap; 1361 apr_vformatter_buff_t vbuff; 1362 1363 if (len == 0) { 1364 /* NOTE: This is a special case; we just want to return the number 1365 * of chars that would be written (minus \0) if the buffer 1366 * size was infinite. We leverage the fact that INS_CHAR 1367 * just does actual inserts iff the buffer pointer is non-NULL. 1368 * In this case, we don't care what buf is; it can be NULL, since 1369 * we don't touch it at all. 1370 */ 1371 vbuff.curpos = NULL; 1372 vbuff.endpos = NULL; 1373 } else { 1374 /* save one byte for nul terminator */ 1375 vbuff.curpos = buf; 1376 vbuff.endpos = buf + len - 1; 1377 } 1378 va_start(ap, format); 1379 cc = apr_vformatter(snprintf_flush, &vbuff, format, ap); 1380 va_end(ap); 1381 if (len != 0) { 1382 *vbuff.curpos = '\0'; 1383 } 1384 return (cc == -1) ? (int)len - 1 : cc; 1385} 1386 1387 1388APR_DECLARE(int) apr_vsnprintf(char *buf, apr_size_t len, const char *format, 1389 va_list ap) 1390{ 1391 int cc; 1392 apr_vformatter_buff_t vbuff; 1393 1394 if (len == 0) { 1395 /* See above note */ 1396 vbuff.curpos = NULL; 1397 vbuff.endpos = NULL; 1398 } else { 1399 /* save one byte for nul terminator */ 1400 vbuff.curpos = buf; 1401 vbuff.endpos = buf + len - 1; 1402 } 1403 cc = apr_vformatter(snprintf_flush, &vbuff, format, ap); 1404 if (len != 0) { 1405 *vbuff.curpos = '\0'; 1406 } 1407 return (cc == -1) ? (int)len - 1 : cc; 1408} 1409