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 
45 typedef 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 
57 static 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 */
apr_cvt(double arg,int ndigits,int * decpt,int * sign,int eflag,char * buf)86 static 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     /*
104      * Do integer part
105      */
106     if (fi != 0) {
107         p1 = &buf[NDIG];
108         while (p1 > &buf[0] && fi != 0) {
109             fj = modf(fi / 10, &fi);
110             *--p1 = (int) ((fj + .03) * 10) + '0';
111             r2++;
112         }
113         while (p1 < &buf[NDIG])
114             *p++ = *p1++;
115     }
116     else if (arg > 0) {
117         while ((fj = arg * 10) < 1) {
118             arg = fj;
119             r2--;
120         }
121     }
122     p1 = &buf[ndigits];
123     if (eflag == 0)
124         p1 += r2;
125     if (p1 < &buf[0]) {
126         *decpt = -ndigits;
127         buf[0] = '\0';
128         return (buf);
129     }
130     *decpt = r2;
131     while (p <= p1 && p < &buf[NDIG]) {
132         arg *= 10;
133         arg = modf(arg, &fj);
134         *p++ = (int) fj + '0';
135     }
136     if (p1 >= &buf[NDIG]) {
137         buf[NDIG - 1] = '\0';
138         return (buf);
139     }
140     p = p1;
141     *p1 += 5;
142     while (*p1 > '9') {
143         *p1 = '0';
144         if (p1 > buf)
145             ++ * --p1;
146         else {
147             *p1 = '1';
148             (*decpt)++;
149             if (eflag == 0) {
150                 if (p > buf)
151                     *p = '0';
152                 p++;
153             }
154         }
155     }
156     *p = '\0';
157     return (buf);
158 }
159 
apr_ecvt(double arg,int ndigits,int * decpt,int * sign,char * buf)160 static char *apr_ecvt(double arg, int ndigits, int *decpt, int *sign, char *buf)
161 {
162     return (apr_cvt(arg, ndigits, decpt, sign, 1, buf));
163 }
164 
apr_fcvt(double arg,int ndigits,int * decpt,int * sign,char * buf)165 static char *apr_fcvt(double arg, int ndigits, int *decpt, int *sign, char *buf)
166 {
167     return (apr_cvt(arg, ndigits, decpt, sign, 0, buf));
168 }
169 
170 /*
171  * apr_gcvt  - Floating output conversion to
172  * minimal length string
173  */
174 
apr_gcvt(double number,int ndigit,char * buf,boolean_e altform)175 static char *apr_gcvt(double number, int ndigit, char *buf, boolean_e altform)
176 {
177     int sign, decpt;
178     register char *p1, *p2;
179     register int i;
180     char buf1[NDIG];
181 
182     p1 = apr_ecvt(number, ndigit, &decpt, &sign, buf1);
183     p2 = buf;
184     if (sign)
185         *p2++ = '-';
186     for (i = ndigit - 1; i > 0 && p1[i] == '0'; i--)
187         ndigit--;
188     if ((decpt >= 0 && decpt - ndigit > 4)
189         || (decpt < 0 && decpt < -3)) {                /* use E-style */
190         decpt--;
191         *p2++ = *p1++;
192         *p2++ = '.';
193         for (i = 1; i < ndigit; i++)
194             *p2++ = *p1++;
195         *p2++ = 'e';
196         if (decpt < 0) {
197             decpt = -decpt;
198             *p2++ = '-';
199         }
200         else
201             *p2++ = '+';
202         if (decpt / 100 > 0)
203             *p2++ = decpt / 100 + '0';
204         if (decpt / 10 > 0)
205             *p2++ = (decpt % 100) / 10 + '0';
206         *p2++ = decpt % 10 + '0';
207     }
208     else {
209         if (decpt <= 0) {
210             if (*p1 != '0')
211                 *p2++ = '.';
212             while (decpt < 0) {
213                 decpt++;
214                 *p2++ = '0';
215             }
216         }
217         for (i = 1; i <= ndigit; i++) {
218             *p2++ = *p1++;
219             if (i == decpt)
220                 *p2++ = '.';
221         }
222         if (ndigit < decpt) {
223             while (ndigit++ < decpt)
224                 *p2++ = '0';
225             *p2++ = '.';
226         }
227     }
228     if (p2[-1] == '.' && !altform)
229         p2--;
230     *p2 = '\0';
231     return (buf);
232 }
233 
234 /*
235  * The INS_CHAR macro inserts a character in the buffer and writes
236  * the buffer back to disk if necessary
237  * It uses the char pointers sp and bep:
238  *      sp points to the next available character in the buffer
239  *      bep points to the end-of-buffer+1
240  * While using this macro, note that the nextb pointer is NOT updated.
241  *
242  * NOTE: Evaluation of the c argument should not have any side-effects
243  */
244 #define INS_CHAR(c, sp, bep, cc)                    \
245 {                                                   \
246     if (sp) {                                       \
247         if (sp >= bep) {                            \
248             vbuff->curpos = sp;                     \
249             if (flush_func(vbuff))                  \
250                 return -1;                          \
251             sp = vbuff->curpos;                     \
252             bep = vbuff->endpos;                    \
253         }                                           \
254         *sp++ = (c);                                \
255     }                                               \
256     cc++;                                           \
257 }
258 
259 #define NUM(c) (c - '0')
260 
261 #define STR_TO_DEC(str, num)                        \
262     num = NUM(*str++);                              \
263     while (apr_isdigit(*str))                       \
264     {                                               \
265         num *= 10 ;                                 \
266         num += NUM(*str++);                         \
267     }
268 
269 /*
270  * This macro does zero padding so that the precision
271  * requirement is satisfied. The padding is done by
272  * adding '0's to the left of the string that is going
273  * to be printed. We don't allow precision to be large
274  * enough that we continue past the start of s.
275  *
276  * NOTE: this makes use of the magic info that s is
277  * always based on num_buf with a size of NUM_BUF_SIZE.
278  */
279 #define FIX_PRECISION(adjust, precision, s, s_len)  \
280     if (adjust) {                                   \
281         apr_size_t p = (precision + 1 < NUM_BUF_SIZE) \
282                      ? precision : NUM_BUF_SIZE - 1;  \
283         while (s_len < p)                           \
284         {                                           \
285             *--s = '0';                             \
286             s_len++;                                \
287         }                                           \
288     }
289 
290 /*
291  * Macro that does padding. The padding is done by printing
292  * the character ch.
293  */
294 #define PAD(width, len, ch)                         \
295 do                                                  \
296 {                                                   \
297     INS_CHAR(ch, sp, bep, cc);                      \
298     width--;                                        \
299 }                                                   \
300 while (width > len)
301 
302 /*
303  * Prefix the character ch to the string str
304  * Increase length
305  * Set the has_prefix flag
306  */
307 #define PREFIX(str, length, ch)                     \
308     *--str = ch;                                    \
309     length++;                                       \
310     has_prefix=YES;
311 
312 
313 /*
314  * Convert num to its decimal format.
315  * Return value:
316  *   - a pointer to a string containing the number (no sign)
317  *   - len contains the length of the string
318  *   - is_negative is set to TRUE or FALSE depending on the sign
319  *     of the number (always set to FALSE if is_unsigned is TRUE)
320  *
321  * The caller provides a buffer for the string: that is the buf_end argument
322  * which is a pointer to the END of the buffer + 1 (i.e. if the buffer
323  * is declared as buf[ 100 ], buf_end should be &buf[ 100 ])
324  *
325  * Note: we have 2 versions. One is used when we need to use quads
326  * (conv_10_quad), the other when we don't (conv_10). We're assuming the
327  * latter is faster.
328  */
conv_10(register apr_int32_t num,register int is_unsigned,register int * is_negative,char * buf_end,register apr_size_t * len)329 static char *conv_10(register apr_int32_t num, register int is_unsigned,
330                      register int *is_negative, char *buf_end,
331                      register apr_size_t *len)
332 {
333     register char *p = buf_end;
334     register apr_uint32_t magnitude = num;
335 
336     if (is_unsigned) {
337         *is_negative = FALSE;
338     }
339     else {
340         *is_negative = (num < 0);
341 
342         /*
343          * On a 2's complement machine, negating the most negative integer
344          * results in a number that cannot be represented as a signed integer.
345          * Here is what we do to obtain the number's magnitude:
346          *      a. add 1 to the number
347          *      b. negate it (becomes positive)
348          *      c. convert it to unsigned
349          *      d. add 1
350          */
351         if (*is_negative) {
352             apr_int32_t t = num + 1;
353             magnitude = ((apr_uint32_t) -t) + 1;
354         }
355     }
356 
357     /*
358      * We use a do-while loop so that we write at least 1 digit
359      */
360     do {
361         register apr_uint32_t new_magnitude = magnitude / 10;
362 
363         *--p = (char) (magnitude - new_magnitude * 10 + '0');
364         magnitude = new_magnitude;
365     }
366     while (magnitude);
367 
368     *len = buf_end - p;
369     return (p);
370 }
371 
conv_10_quad(apr_int64_t num,register int is_unsigned,register int * is_negative,char * buf_end,register apr_size_t * len)372 static char *conv_10_quad(apr_int64_t num, register int is_unsigned,
373                      register int *is_negative, char *buf_end,
374                      register apr_size_t *len)
375 {
376     register char *p = buf_end;
377     apr_uint64_t magnitude = num;
378 
379     /*
380      * We see if we can use the faster non-quad version by checking the
381      * number against the largest long value it can be. If <=, we
382      * punt to the quicker version.
383      */
384     if ((magnitude <= APR_UINT32_MAX && is_unsigned)
385         || (num <= APR_INT32_MAX && num >= APR_INT32_MIN && !is_unsigned))
386             return(conv_10((apr_int32_t)num, is_unsigned, is_negative, buf_end, len));
387 
388     if (is_unsigned) {
389         *is_negative = FALSE;
390     }
391     else {
392         *is_negative = (num < 0);
393 
394         /*
395          * On a 2's complement machine, negating the most negative integer
396          * results in a number that cannot be represented as a signed integer.
397          * Here is what we do to obtain the number's magnitude:
398          *      a. add 1 to the number
399          *      b. negate it (becomes positive)
400          *      c. convert it to unsigned
401          *      d. add 1
402          */
403         if (*is_negative) {
404             apr_int64_t t = num + 1;
405             magnitude = ((apr_uint64_t) -t) + 1;
406         }
407     }
408 
409     /*
410      * We use a do-while loop so that we write at least 1 digit
411      */
412     do {
413         apr_uint64_t new_magnitude = magnitude / 10;
414 
415         *--p = (char) (magnitude - new_magnitude * 10 + '0');
416         magnitude = new_magnitude;
417     }
418     while (magnitude);
419 
420     *len = buf_end - p;
421     return (p);
422 }
423 
conv_in_addr(struct in_addr * ia,char * buf_end,apr_size_t * len)424 static char *conv_in_addr(struct in_addr *ia, char *buf_end, apr_size_t *len)
425 {
426     unsigned addr = ntohl(ia->s_addr);
427     char *p = buf_end;
428     int is_negative;
429     apr_size_t sub_len;
430 
431     p = conv_10((addr & 0x000000FF)      , TRUE, &is_negative, p, &sub_len);
432     *--p = '.';
433     p = conv_10((addr & 0x0000FF00) >>  8, TRUE, &is_negative, p, &sub_len);
434     *--p = '.';
435     p = conv_10((addr & 0x00FF0000) >> 16, TRUE, &is_negative, p, &sub_len);
436     *--p = '.';
437     p = conv_10((addr & 0xFF000000) >> 24, TRUE, &is_negative, p, &sub_len);
438 
439     *len = buf_end - p;
440     return (p);
441 }
442 
443 
444 /* Must be passed a buffer of size NUM_BUF_SIZE where buf_end points
445  * to 1 byte past the end of the buffer. */
conv_apr_sockaddr(apr_sockaddr_t * sa,char * buf_end,apr_size_t * len)446 static char *conv_apr_sockaddr(apr_sockaddr_t *sa, char *buf_end, apr_size_t *len)
447 {
448     char *p = buf_end;
449     int is_negative;
450     apr_size_t sub_len;
451     char *ipaddr_str;
452 
453     p = conv_10(sa->port, TRUE, &is_negative, p, &sub_len);
454     *--p = ':';
455     ipaddr_str = buf_end - NUM_BUF_SIZE;
456     if (apr_sockaddr_ip_getbuf(ipaddr_str, sa->addr_str_len, sa)) {
457         /* Should only fail if the buffer is too small, which it
458          * should not be; but fail safe anyway: */
459         *--p = '?';
460         *len = buf_end - p;
461         return p;
462     }
463     sub_len = strlen(ipaddr_str);
464 #if APR_HAVE_IPV6
465     if (sa->family == APR_INET6 &&
466         !IN6_IS_ADDR_V4MAPPED(&sa->sa.sin6.sin6_addr)) {
467         *(p - 1) = ']';
468         p -= sub_len + 2;
469         *p = '[';
470         memcpy(p + 1, ipaddr_str, sub_len);
471     }
472     else
473 #endif
474     {
475         p -= sub_len;
476         memcpy(p, ipaddr_str, sub_len);
477     }
478 
479     *len = buf_end - p;
480     return (p);
481 }
482 
483 
484 
485 #if APR_HAS_THREADS
conv_os_thread_t(apr_os_thread_t * tid,char * buf_end,apr_size_t * len)486 static char *conv_os_thread_t(apr_os_thread_t *tid, char *buf_end, apr_size_t *len)
487 {
488     union {
489         apr_os_thread_t tid;
490         apr_uint64_t u64;
491         apr_uint32_t u32;
492     } u;
493     int is_negative;
494 
495     u.tid = *tid;
496     switch(sizeof(u.tid)) {
497     case sizeof(apr_int32_t):
498         return conv_10(u.u32, TRUE, &is_negative, buf_end, len);
499     case sizeof(apr_int64_t):
500         return conv_10_quad(u.u64, TRUE, &is_negative, buf_end, len);
501     default:
502         /* not implemented; stick 0 in the buffer */
503         return conv_10(0, TRUE, &is_negative, buf_end, len);
504     }
505 }
506 #endif
507 
508 
509 
510 /*
511  * Convert a floating point number to a string formats 'f', 'e' or 'E'.
512  * The result is placed in buf, and len denotes the length of the string
513  * The sign is returned in the is_negative argument (and is not placed
514  * in buf).
515  */
conv_fp(register char format,register double num,boolean_e add_dp,int precision,int * is_negative,char * buf,apr_size_t * len)516 static char *conv_fp(register char format, register double num,
517     boolean_e add_dp, int precision, int *is_negative,
518     char *buf, apr_size_t *len)
519 {
520     register char *s = buf;
521     register char *p;
522     int decimal_point;
523     char buf1[NDIG];
524 
525     if (format == 'f')
526         p = apr_fcvt(num, precision, &decimal_point, is_negative, buf1);
527     else /* either e or E format */
528         p = apr_ecvt(num, precision + 1, &decimal_point, is_negative, buf1);
529 
530     /*
531      * Check for Infinity and NaN
532      */
533     if (apr_isalpha(*p)) {
534         *len = strlen(p);
535         memcpy(buf, p, *len + 1);
536         *is_negative = FALSE;
537         return (buf);
538     }
539 
540     if (format == 'f') {
541         if (decimal_point <= 0) {
542             *s++ = '0';
543             if (precision > 0) {
544                 *s++ = '.';
545                 while (decimal_point++ < 0)
546                     *s++ = '0';
547             }
548             else if (add_dp)
549                 *s++ = '.';
550         }
551         else {
552             while (decimal_point-- > 0)
553                 *s++ = *p++;
554             if (precision > 0 || add_dp)
555                 *s++ = '.';
556         }
557     }
558     else {
559         *s++ = *p++;
560         if (precision > 0 || add_dp)
561             *s++ = '.';
562     }
563 
564     /*
565      * copy the rest of p, the NUL is NOT copied
566      */
567     while (*p)
568         *s++ = *p++;
569 
570     if (format != 'f') {
571         char temp[EXPONENT_LENGTH];        /* for exponent conversion */
572         apr_size_t t_len;
573         int exponent_is_negative;
574 
575         *s++ = format;                /* either e or E */
576         decimal_point--;
577         if (decimal_point != 0) {
578             p = conv_10((apr_int32_t) decimal_point, FALSE, &exponent_is_negative,
579                         &temp[EXPONENT_LENGTH], &t_len);
580             *s++ = exponent_is_negative ? '-' : '+';
581 
582             /*
583              * Make sure the exponent has at least 2 digits
584              */
585             if (t_len == 1)
586                 *s++ = '0';
587             while (t_len--)
588                 *s++ = *p++;
589         }
590         else {
591             *s++ = '+';
592             *s++ = '0';
593             *s++ = '0';
594         }
595     }
596 
597     *len = s - buf;
598     return (buf);
599 }
600 
601 
602 /*
603  * Convert num to a base X number where X is a power of 2. nbits determines X.
604  * For example, if nbits is 3, we do base 8 conversion
605  * Return value:
606  *      a pointer to a string containing the number
607  *
608  * The caller provides a buffer for the string: that is the buf_end argument
609  * which is a pointer to the END of the buffer + 1 (i.e. if the buffer
610  * is declared as buf[ 100 ], buf_end should be &buf[ 100 ])
611  *
612  * As with conv_10, we have a faster version which is used when
613  * the number isn't quad size.
614  */
conv_p2(register apr_uint32_t num,register int nbits,char format,char * buf_end,register apr_size_t * len)615 static char *conv_p2(register apr_uint32_t num, register int nbits,
616                      char format, char *buf_end, register apr_size_t *len)
617 {
618     register int mask = (1 << nbits) - 1;
619     register char *p = buf_end;
620     static const char low_digits[] = "0123456789abcdef";
621     static const char upper_digits[] = "0123456789ABCDEF";
622     register const char *digits = (format == 'X') ? upper_digits : low_digits;
623 
624     do {
625         *--p = digits[num & mask];
626         num >>= nbits;
627     }
628     while (num);
629 
630     *len = buf_end - p;
631     return (p);
632 }
633 
conv_p2_quad(apr_uint64_t num,register int nbits,char format,char * buf_end,register apr_size_t * len)634 static char *conv_p2_quad(apr_uint64_t num, register int nbits,
635                      char format, char *buf_end, register apr_size_t *len)
636 {
637     register int mask = (1 << nbits) - 1;
638     register char *p = buf_end;
639     static const char low_digits[] = "0123456789abcdef";
640     static const char upper_digits[] = "0123456789ABCDEF";
641     register const char *digits = (format == 'X') ? upper_digits : low_digits;
642 
643     if (num <= APR_UINT32_MAX)
644         return(conv_p2((apr_uint32_t)num, nbits, format, buf_end, len));
645 
646     do {
647         *--p = digits[num & mask];
648         num >>= nbits;
649     }
650     while (num);
651 
652     *len = buf_end - p;
653     return (p);
654 }
655 
656 #if APR_HAS_THREADS
conv_os_thread_t_hex(apr_os_thread_t * tid,char * buf_end,apr_size_t * len)657 static char *conv_os_thread_t_hex(apr_os_thread_t *tid, char *buf_end, apr_size_t *len)
658 {
659     union {
660         apr_os_thread_t tid;
661         apr_uint64_t u64;
662         apr_uint32_t u32;
663     } u;
664     int is_negative;
665 
666     u.tid = *tid;
667     switch(sizeof(u.tid)) {
668     case sizeof(apr_int32_t):
669         return conv_p2(u.u32, 4, 'x', buf_end, len);
670     case sizeof(apr_int64_t):
671         return conv_p2_quad(u.u64, 4, 'x', buf_end, len);
672     default:
673         /* not implemented; stick 0 in the buffer */
674         return conv_10(0, TRUE, &is_negative, buf_end, len);
675     }
676 }
677 #endif
678 
679 /*
680  * Do format conversion placing the output in buffer
681  */
apr_vformatter(int (* flush_func)(apr_vformatter_buff_t *),apr_vformatter_buff_t * vbuff,const char * fmt,va_list ap)682 APR_DECLARE(int) apr_vformatter(int (*flush_func)(apr_vformatter_buff_t *),
683     apr_vformatter_buff_t *vbuff, const char *fmt, va_list ap)
684 {
685     register char *sp;
686     register char *bep;
687     register int cc = 0;
688     register apr_size_t i;
689 
690     register char *s = NULL;
691     char *q;
692     apr_size_t s_len = 0;
693 
694     register apr_size_t min_width = 0;
695     apr_size_t precision = 0;
696     enum {
697         LEFT, RIGHT
698     } adjust;
699     char pad_char;
700     char prefix_char;
701 
702     double fp_num;
703     apr_int64_t i_quad = 0;
704     apr_uint64_t ui_quad;
705     apr_int32_t i_num = 0;
706     apr_uint32_t ui_num = 0;
707 
708     char num_buf[NUM_BUF_SIZE];
709     char char_buf[2];                /* for printing %% and %<unknown> */
710     char buf[5];                     /* for printing %B, %F, and %S */
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                     apr_off_t size = 0;
1250 
1251                     if (*fmt == 'B') {
1252                         apr_uint32_t *arg = va_arg(ap, apr_uint32_t *);
1253                         size = (arg) ? *arg : 0;
1254                     }
1255                     else if (*fmt == 'F') {
1256                         apr_off_t *arg = va_arg(ap, apr_off_t *);
1257                         size = (arg) ? *arg : 0;
1258                     }
1259                     else {
1260                         apr_size_t *arg = va_arg(ap, apr_size_t *);
1261                         size = (arg) ? *arg : 0;
1262                     }
1263 
1264                     s = apr_strfsize(size, buf);
1265                     s_len = strlen(s);
1266                     pad_char = ' ';
1267                 }
1268                 break;
1269 
1270                 case NUL:
1271                     /* if %p ends the string, oh well ignore it */
1272                     continue;
1273 
1274                 default:
1275                     s = "bogus %p";
1276                     s_len = 8;
1277                     prefix_char = NUL;
1278                     (void)va_arg(ap, void *); /* skip the bogus argument on the stack */
1279                     break;
1280                 }
1281                 break;
1282 
1283             case NUL:
1284                 /*
1285                  * The last character of the format string was %.
1286                  * We ignore it.
1287                  */
1288                 continue;
1289 
1290 
1291                 /*
1292                  * The default case is for unrecognized %'s.
1293                  * We print %<char> to help the user identify what
1294                  * option is not understood.
1295                  * This is also useful in case the user wants to pass
1296                  * the output of format_converter to another function
1297                  * that understands some other %<char> (like syslog).
1298                  * Note that we can't point s inside fmt because the
1299                  * unknown <char> could be preceded by width etc.
1300                  */
1301             default:
1302                 char_buf[0] = '%';
1303                 char_buf[1] = *fmt;
1304                 s = char_buf;
1305                 s_len = 2;
1306                 pad_char = ' ';
1307                 break;
1308             }
1309 
1310             if (prefix_char != NUL && s != S_NULL && s != char_buf) {
1311                 *--s = prefix_char;
1312                 s_len++;
1313             }
1314 
1315             if (adjust_width && adjust == RIGHT && min_width > s_len) {
1316                 if (pad_char == '0' && prefix_char != NUL) {
1317                     INS_CHAR(*s, sp, bep, cc);
1318                     s++;
1319                     s_len--;
1320                     min_width--;
1321                 }
1322                 PAD(min_width, s_len, pad_char);
1323             }
1324 
1325             /*
1326              * Print the string s.
1327              */
1328             if (print_something == YES) {
1329                 for (i = s_len; i != 0; i--) {
1330                     INS_CHAR(*s, sp, bep, cc);
1331                     s++;
1332                 }
1333             }
1334 
1335             if (adjust_width && adjust == LEFT && min_width > s_len)
1336                 PAD(min_width, s_len, pad_char);
1337         }
1338         fmt++;
1339     }
1340     vbuff->curpos = sp;
1341 
1342     return cc;
1343 }
1344 
1345 
snprintf_flush(apr_vformatter_buff_t * vbuff)1346 static int snprintf_flush(apr_vformatter_buff_t *vbuff)
1347 {
1348     /* if the buffer fills we have to abort immediately, there is no way
1349      * to "flush" an apr_snprintf... there's nowhere to flush it to.
1350      */
1351     return -1;
1352 }
1353 
1354 
apr_snprintf(char * buf,apr_size_t len,const char * format,...)1355 APR_DECLARE_NONSTD(int) apr_snprintf(char *buf, apr_size_t len,
1356                                      const char *format, ...)
1357 {
1358     int cc;
1359     va_list ap;
1360     apr_vformatter_buff_t vbuff;
1361 
1362     if (len == 0) {
1363         /* NOTE: This is a special case; we just want to return the number
1364          * of chars that would be written (minus \0) if the buffer
1365          * size was infinite. We leverage the fact that INS_CHAR
1366          * just does actual inserts iff the buffer pointer is non-NULL.
1367          * In this case, we don't care what buf is; it can be NULL, since
1368          * we don't touch it at all.
1369          */
1370         vbuff.curpos = NULL;
1371         vbuff.endpos = NULL;
1372     } else {
1373         /* save one byte for nul terminator */
1374         vbuff.curpos = buf;
1375         vbuff.endpos = buf + len - 1;
1376     }
1377     va_start(ap, format);
1378     cc = apr_vformatter(snprintf_flush, &vbuff, format, ap);
1379     va_end(ap);
1380     if (len != 0) {
1381         *vbuff.curpos = '\0';
1382     }
1383     return (cc == -1) ? (int)len - 1 : cc;
1384 }
1385 
1386 
apr_vsnprintf(char * buf,apr_size_t len,const char * format,va_list ap)1387 APR_DECLARE(int) apr_vsnprintf(char *buf, apr_size_t len, const char *format,
1388                                va_list ap)
1389 {
1390     int cc;
1391     apr_vformatter_buff_t vbuff;
1392 
1393     if (len == 0) {
1394         /* See above note */
1395         vbuff.curpos = NULL;
1396         vbuff.endpos = NULL;
1397     } else {
1398         /* save one byte for nul terminator */
1399         vbuff.curpos = buf;
1400         vbuff.endpos = buf + len - 1;
1401     }
1402     cc = apr_vformatter(snprintf_flush, &vbuff, format, ap);
1403     if (len != 0) {
1404         *vbuff.curpos = '\0';
1405     }
1406     return (cc == -1) ? (int)len - 1 : cc;
1407 }
1408