1 /* estream-printf.c - Versatile mostly C-99 compliant printf formatting
2  * Copyright (C) 2007, 2008, 2009, 2010, 2012, 2014 g10 Code GmbH
3  *
4  * This file is part of Libestream.
5  *
6  * Libestream is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU Lesser General Public License as
8  * published by the Free Software Foundation; either version 2.1 of
9  * the License, or (at your option) any later version.
10  *
11  * Libestream is distributed in the hope that it will be useful, but
12  * WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14  * Lesser General Public License for more details.
15  *
16  * You should have received a copy of the GNU Lesser General Public
17  * License along with Libestream; if not, see <https://www.gnu.org/licenses/>.
18  *
19  * ALTERNATIVELY, Libestream may be distributed under the terms of the
20  * following license, in which case the provisions of this license are
21  * required INSTEAD OF the GNU General Public License. If you wish to
22  * allow use of your version of this file only under the terms of the
23  * GNU General Public License, and not to allow others to use your
24  * version of this file under the terms of the following license,
25  * indicate your decision by deleting this paragraph and the license
26  * below.
27  *
28  * Redistribution and use in source and binary forms, with or without
29  * modification, are permitted provided that the following conditions
30  * are met:
31  * 1. Redistributions of source code must retain the above copyright
32  *    notice, and the entire permission notice in its entirety,
33  *    including the disclaimer of warranties.
34  * 2. Redistributions in binary form must reproduce the above copyright
35  *    notice, this list of conditions and the following disclaimer in the
36  *    documentation and/or other materials provided with the distribution.
37  * 3. The name of the author may not be used to endorse or promote
38  *    products derived from this software without specific prior
39  *    written permission.
40  *
41  * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
42  * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
43  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
44  * DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
45  * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
46  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
47  * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
48  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
49  * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
50  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
51  * OF THE POSSIBILITY OF SUCH DAMAGE.
52  */
53 
54 /*  Required autoconf tests:
55 
56     AC_TYPE_LONG_LONG_INT            defines HAVE_LONG_LONG_INT
57     AC_TYPE_LONG_DOUBLE              defines HAVE_LONG_DOUBLE
58     AC_TYPE_INTMAX_T                 defines HAVE_INTMAX_T
59     AC_TYPE_UINTMAX_T                defines HAVE_UINTMAX_T
60     AC_CHECK_TYPES([ptrdiff_t])      defines HAVE_PTRDIFF_T
61     AC_CHECK_SIZEOF([unsigned long]) defines SIZEOF_UNSIGNED_LONG
62     AC_CHECK_SIZEOF([void *])        defines SIZEOF_VOID_P
63                                              HAVE_LANGINFO_THOUSEP
64 
65     Note that the file estream.m4 provides the autoconf macro
66     ESTREAM_PRINTF_INIT which runs all required checks.
67     See estream-printf.h for ways to tune this code.
68 
69   Missing stuff:  wchar and wint_t
70                   thousep in pr_float.
71 
72 */
73 
74 #ifdef HAVE_CONFIG_H
75 # include <config.h>
76 #endif
77 
78 #if defined(_WIN32) && !defined(HAVE_W32_SYSTEM)
79 # define HAVE_W32_SYSTEM 1
80 # if defined(__MINGW32CE__) && !defined (HAVE_W32CE_SYSTEM)
81 #  define HAVE_W32CE_SYSTEM
82 # endif
83 #endif
84 
85 #include <stdio.h>
86 #include <stdlib.h>
87 #include <string.h>
88 #include <unistd.h>
89 #include <stdarg.h>
90 #include <errno.h>
91 #include <stddef.h>
92 #if defined(HAVE_INTMAX_T) || defined(HAVE_UINTMAX_T)
93 # ifdef HAVE_STDINT_H
94 #  include <stdint.h>
95 # endif
96 #endif
97 #ifdef HAVE_LANGINFO_THOUSEP
98 #include <langinfo.h>
99 #endif
100 #ifdef HAVE_W32CE_SYSTEM
101 #include <gpg-error.h>  /* ERRNO replacement.  */
102 #endif
103 #ifdef _ESTREAM_PRINTF_EXTRA_INCLUDE
104 # include _ESTREAM_PRINTF_EXTRA_INCLUDE
105 #endif
106 #include "estream-printf.h"
107 
108 /* #define DEBUG 1 */
109 
110 
111 /* Allow redefinition of asprintf used realloc function.  */
112 #if defined(_ESTREAM_PRINTF_REALLOC)
113 #define my_printf_realloc(a,b) _ESTREAM_PRINTF_REALLOC((a),(b))
114 #else
115 #define my_printf_realloc(a,b) fixed_realloc((a),(b))
116 #endif
117 
118 /* A wrapper to set ERRNO.  */
119 #ifdef HAVE_W32CE_SYSTEM
120 # define _set_errno(a)  gpg_err_set_errno ((a))
121 #else
122 # define _set_errno(a)  do { errno = (a); } while (0)
123 #endif
124 
125 
126 /* Calculate array dimension.  */
127 #ifndef DIM
128 #define DIM(array) (sizeof (array) / sizeof (*array))
129 #endif
130 
131 
132 /* We allow for that many args without requiring malloced memory. */
133 #define DEFAULT_MAX_ARGSPECS  5
134 
135 /* We allow for that many values without requiring malloced memory. */
136 #define DEFAULT_MAX_VALUES  8
137 
138 /* We allocate this many new array argspec elements each time.  */
139 #define ARGSPECS_BUMP_VALUE   10
140 
141 /* Special values for the field width and the precision.  */
142 #define NO_FIELD_VALUE   (-1)
143 #define STAR_FIELD_VALUE (-2)
144 
145 /* Bit valuues used for the conversion flags. */
146 #define FLAG_GROUPING   1
147 #define FLAG_LEFT_JUST  2
148 #define FLAG_PLUS_SIGN  4
149 #define FLAG_SPACE_PLUS 8
150 #define FLAG_ALT_CONV   16
151 #define FLAG_ZERO_PAD   32
152 
153 /* Constants used the length modifiers.  */
154 typedef enum
155   {
156     LENMOD_NONE = 0,
157     LENMOD_CHAR,     /* "hh" */
158     LENMOD_SHORT,    /* "h"  */
159     LENMOD_LONG,     /* "l"  */
160     LENMOD_LONGLONG, /* "ll" */
161     LENMOD_INTMAX,   /* "j"  */
162     LENMOD_SIZET,    /* "z"  */
163     LENMOD_PTRDIFF,  /* "t"  */
164     LENMOD_LONGDBL   /* "L"  */
165   } lenmod_t;
166 
167 /* All the conversion specifiers.  */
168 typedef enum
169   {
170     CONSPEC_UNKNOWN = 0,
171     CONSPEC_DECIMAL,
172     CONSPEC_OCTAL,
173     CONSPEC_UNSIGNED,
174     CONSPEC_HEX,
175     CONSPEC_HEX_UP,
176     CONSPEC_FLOAT,
177     CONSPEC_FLOAT_UP,
178     CONSPEC_EXP,
179     CONSPEC_EXP_UP,
180     CONSPEC_F_OR_G,
181     CONSPEC_F_OR_G_UP,
182     CONSPEC_HEX_EXP,
183     CONSPEC_HEX_EXP_UP,
184     CONSPEC_CHAR,
185     CONSPEC_STRING,
186     CONSPEC_POINTER,
187     CONSPEC_STRERROR,
188     CONSPEC_BYTES_SO_FAR
189   } conspec_t;
190 
191 
192 /* Constants describing all the suppoorted types.  Note that we list
193    all the types we know about even if certain types are not available
194    on this system. */
195 typedef enum
196   {
197     VALTYPE_UNSUPPORTED = 0,  /* Artificial type for error detection.  */
198     VALTYPE_CHAR,
199     VALTYPE_SCHAR,
200     VALTYPE_UCHAR,
201     VALTYPE_SHORT,
202     VALTYPE_USHORT,
203     VALTYPE_INT,
204     VALTYPE_UINT,
205     VALTYPE_LONG,
206     VALTYPE_ULONG,
207     VALTYPE_LONGLONG,
208     VALTYPE_ULONGLONG,
209     VALTYPE_DOUBLE,
210     VALTYPE_LONGDOUBLE,
211     VALTYPE_STRING,
212     VALTYPE_INTMAX,
213     VALTYPE_UINTMAX,
214     VALTYPE_SIZE,
215     VALTYPE_PTRDIFF,
216     VALTYPE_POINTER,
217     VALTYPE_CHAR_PTR,
218     VALTYPE_SCHAR_PTR,
219     VALTYPE_SHORT_PTR,
220     VALTYPE_INT_PTR,
221     VALTYPE_LONG_PTR,
222     VALTYPE_LONGLONG_PTR,
223     VALTYPE_INTMAX_PTR,
224     VALTYPE_SIZE_PTR,
225     VALTYPE_PTRDIFF_PTR
226   } valtype_t;
227 
228 
229 /* A union used to store the actual values. */
230 typedef union
231 {
232   char a_char;
233   signed char a_schar;
234   unsigned char a_uchar;
235   short a_short;
236   unsigned short a_ushort;
237   int a_int;
238   unsigned int a_uint;
239   long int a_long;
240   unsigned long int a_ulong;
241 #ifdef HAVE_LONG_LONG_INT
242   long long int a_longlong;
243   unsigned long long int a_ulonglong;
244 #endif
245   double a_double;
246 #ifdef HAVE_LONG_DOUBLE
247   long double a_longdouble;
248 #endif
249   const char *a_string;
250 #ifdef HAVE_INTMAX_T
251   intmax_t a_intmax;
252 #endif
253 #ifdef HAVE_UINTMAX_T
254   intmax_t a_uintmax;
255 #endif
256   size_t a_size;
257 #ifdef HAVE_PTRDIFF_T
258   ptrdiff_t a_ptrdiff;
259 #endif
260   void *a_void_ptr;
261   char *a_char_ptr;
262   signed char *a_schar_ptr;
263   short *a_short_ptr;
264   int  *a_int_ptr;
265   long *a_long_ptr;
266 #ifdef HAVE_LONG_LONG_INT
267   long long int *a_longlong_ptr;
268 #endif
269 #ifdef HAVE_INTMAX_T
270   intmax_t *a_intmax_ptr;
271 #endif
272   size_t *a_size_ptr;
273 #ifdef HAVE_PTRDIFF_T
274   ptrdiff_t *a_ptrdiff_ptr;
275 #endif
276 } value_t;
277 
278 /* An object used to keep track of a format option and arguments. */
279 struct argspec_s
280 {
281   size_t length;       /* The length of these args including the percent.  */
282   unsigned int flags;  /* The conversion flags (bits defined by FLAG_foo).  */
283   int width;           /* The field width.  */
284   int precision;       /* The precision.  */
285   lenmod_t lenmod;     /* The length modifier.  */
286   conspec_t conspec;   /* The conversion specifier.  */
287   int arg_pos;         /* The position of the argument.  This one may
288                           be -1 to indicate that no value is expected
289                           (e.g. for "%m").  */
290   int width_pos;       /* The position of the argument for a field
291                           width star's value. 0 for not used.  */
292   int precision_pos;   /* The position of the argument for the a
293                           precision star's value.  0 for not used. */
294   valtype_t vt;        /* The type of the corresponding argument.  */
295 };
296 typedef struct argspec_s *argspec_t;
297 
298 /* An object to build up a table of values and their types.  */
299 struct valueitem_s
300 {
301   valtype_t vt;  /* The type of the value.  */
302   value_t value; /* The value.  */
303 };
304 typedef struct valueitem_s *valueitem_t;
305 
306 
307 /* Not all systems have a C-90 compliant realloc.  To cope with this
308    we use this simple wrapper. */
309 #ifndef _ESTREAM_PRINTF_REALLOC
310 static void *
fixed_realloc(void * a,size_t n)311 fixed_realloc (void *a, size_t n)
312 {
313   if (!a)
314     return malloc (n);
315 
316   if (!n)
317     {
318       free (a);
319       return NULL;
320     }
321 
322   return realloc (a, n);
323 }
324 #endif /*!_ESTREAM_PRINTF_REALLOC*/
325 
326 
327 #ifdef DEBUG
328 static void
dump_argspecs(argspec_t arg,size_t argcount)329 dump_argspecs (argspec_t arg, size_t argcount)
330 {
331   int idx;
332 
333   for (idx=0; argcount; argcount--, arg++, idx++)
334     fprintf (stderr,
335              "%2d: len=%u flags=%u width=%d prec=%d mod=%d "
336              "con=%d vt=%d pos=%d-%d-%d\n",
337              idx,
338              (unsigned int)arg->length,
339              arg->flags,
340              arg->width,
341              arg->precision,
342              arg->lenmod,
343              arg->conspec,
344              arg->vt,
345              arg->arg_pos,
346              arg->width_pos,
347              arg->precision_pos);
348 }
349 #endif /*DEBUG*/
350 
351 
352 /* Set the vt field for ARG.  */
353 static void
compute_type(argspec_t arg)354 compute_type (argspec_t arg)
355 {
356   switch (arg->conspec)
357     {
358     case CONSPEC_UNKNOWN:
359       arg->vt = VALTYPE_UNSUPPORTED;
360       break;
361 
362     case CONSPEC_DECIMAL:
363       switch (arg->lenmod)
364         {
365         case LENMOD_CHAR: arg->vt = VALTYPE_SCHAR; break;
366         case LENMOD_SHORT: arg->vt = VALTYPE_SHORT; break;
367         case LENMOD_LONG: arg->vt = VALTYPE_LONG; break;
368         case LENMOD_LONGLONG: arg->vt = VALTYPE_LONGLONG; break;
369         case LENMOD_INTMAX: arg->vt = VALTYPE_INTMAX; break;
370         case LENMOD_SIZET: arg->vt = VALTYPE_SIZE; break;
371         case LENMOD_PTRDIFF: arg->vt = VALTYPE_PTRDIFF; break;
372         default: arg->vt = VALTYPE_INT; break;
373         }
374       break;
375 
376     case CONSPEC_OCTAL:
377     case CONSPEC_UNSIGNED:
378     case CONSPEC_HEX:
379     case CONSPEC_HEX_UP:
380       switch (arg->lenmod)
381         {
382         case LENMOD_CHAR: arg->vt = VALTYPE_UCHAR; break;
383         case LENMOD_SHORT: arg->vt = VALTYPE_USHORT; break;
384         case LENMOD_LONG: arg->vt = VALTYPE_ULONG; break;
385         case LENMOD_LONGLONG: arg->vt = VALTYPE_ULONGLONG; break;
386         case LENMOD_INTMAX: arg->vt = VALTYPE_UINTMAX; break;
387         case LENMOD_SIZET: arg->vt = VALTYPE_SIZE; break;
388         case LENMOD_PTRDIFF: arg->vt = VALTYPE_PTRDIFF; break;
389         default: arg->vt = VALTYPE_UINT; break;
390         }
391       break;
392 
393     case CONSPEC_FLOAT:
394     case CONSPEC_FLOAT_UP:
395     case CONSPEC_EXP:
396     case CONSPEC_EXP_UP:
397     case CONSPEC_F_OR_G:
398     case CONSPEC_F_OR_G_UP:
399     case CONSPEC_HEX_EXP:
400     case CONSPEC_HEX_EXP_UP:
401       switch (arg->lenmod)
402         {
403         case LENMOD_LONGDBL: arg->vt = VALTYPE_LONGDOUBLE; break;
404         case LENMOD_LONG: arg->vt = VALTYPE_DOUBLE; break;
405         default: arg->vt = VALTYPE_DOUBLE; break;
406         }
407       break;
408 
409     case CONSPEC_CHAR:
410       arg->vt = VALTYPE_INT;
411       break;
412 
413     case CONSPEC_STRING:
414       arg->vt = VALTYPE_STRING;
415       break;
416 
417     case CONSPEC_POINTER:
418       arg->vt = VALTYPE_POINTER;
419       break;
420 
421     case CONSPEC_STRERROR:
422       arg->vt = VALTYPE_STRING;
423       break;
424 
425     case CONSPEC_BYTES_SO_FAR:
426       switch (arg->lenmod)
427         {
428         case LENMOD_CHAR: arg->vt = VALTYPE_SCHAR_PTR; break;
429         case LENMOD_SHORT: arg->vt = VALTYPE_SHORT_PTR; break;
430         case LENMOD_LONG: arg->vt = VALTYPE_LONG_PTR; break;
431         case LENMOD_LONGLONG: arg->vt = VALTYPE_LONGLONG_PTR; break;
432         case LENMOD_INTMAX: arg->vt = VALTYPE_INTMAX_PTR; break;
433         case LENMOD_SIZET: arg->vt = VALTYPE_SIZE_PTR; break;
434         case LENMOD_PTRDIFF: arg->vt = VALTYPE_PTRDIFF_PTR; break;
435         default: arg->vt = VALTYPE_INT_PTR; break;
436         }
437       break;
438 
439     }
440 }
441 
442 
443 
444 /* Parse the FORMAT string and populate the specification array stored
445    at the address ARGSPECS_ADDR.  The caller has provided enough space
446    to store up to MAX_ARGSPECS in that buffer.  The function may
447    however ignore the provided buffer and malloc a larger one.  On
448    success the address of that larger buffer will be stored at
449    ARGSPECS_ADDR.  The actual number of specifications will be
450    returned at R_ARGSPECS_COUNT. */
451 static int
parse_format(const char * format,argspec_t * argspecs_addr,size_t max_argspecs,size_t * r_argspecs_count)452 parse_format (const char *format,
453               argspec_t *argspecs_addr, size_t max_argspecs,
454               size_t *r_argspecs_count)
455 {
456   const char *s;
457   argspec_t argspecs = *argspecs_addr;
458   argspec_t arg;
459   size_t argcount = 0;
460 
461   if (!format)
462     goto leave_einval;
463 
464   for (; *format; format++)
465     {
466       unsigned int flags;
467       int width, precision;
468       lenmod_t lenmod;
469       conspec_t conspec;
470       int arg_pos, width_pos, precision_pos;
471 
472       if (*format != '%')
473         continue;
474       s = ++format;
475       if (!*s)
476         goto leave_einval;
477       if (*s == '%')
478         continue; /* Just a quoted percent.  */
479 
480       /* First check whether there is a positional argument.  */
481       arg_pos = 0; /* No positional argument given.  */
482       if (*s >= '1' && *s <= '9')
483         {
484           const char *save_s = s;
485 
486           arg_pos = (*s++ - '0');
487           for (; *s >= '0' && *s <= '9'; s++)
488             arg_pos = 10*arg_pos + (*s - '0');
489           if (arg_pos < 0)
490             goto leave_einval; /* Overflow during conversion.  */
491           if (*s == '$')
492             s++;
493           else
494             {
495               arg_pos = 0;
496               s = save_s;
497             }
498         }
499 
500       /* Parse the flags.  */
501       flags = 0;
502       for ( ; *s; s++)
503         {
504           switch (*s)
505             {
506             case '\'': flags |= FLAG_GROUPING; break;
507             case '-': flags |= FLAG_LEFT_JUST; break;
508             case '+': flags |= FLAG_PLUS_SIGN; break;
509             case ' ': flags |= FLAG_SPACE_PLUS; break;
510             case '#': flags |= FLAG_ALT_CONV; break;
511             case '0': flags |= FLAG_ZERO_PAD; break;
512             default:
513               goto flags_parsed;
514             }
515         }
516     flags_parsed:
517 
518       /* Parse the field width.  */
519       width_pos = 0;
520       if (*s == '*')
521         {
522           width = STAR_FIELD_VALUE;
523           s++;
524           /* If we have a positional argument, another one might also
525              be used to give the position of the star's value. */
526           if (arg_pos && *s >= '1' && *s <= '9')
527             {
528               width_pos = (*s++ - '0');
529               for (; *s >= '0' && *s <= '9'; s++)
530                 width_pos = 10*width_pos + (*s - '0');
531               if (width_pos < 1)
532                 goto leave_einval; /* Overflow during conversion.  */
533               if (*s != '$')
534                 goto leave_einval; /* Not followed by $.  */
535               s++;
536             }
537         }
538       else if ( *s >= '0' && *s <= '9')
539         {
540           width = (*s++ - '0');
541           for (; *s >= '0' && *s <= '9'; s++)
542             {
543               if (!width && *s == '0')
544                 goto leave_einval; /* Leading zeroes are not allowed.
545                                       Fixme: check what other
546                                       implementations do. */
547               width = 10*width + (*s - '0');
548             }
549           if (width < 0)
550             goto leave_einval; /* Overflow during conversion.  */
551         }
552       else
553         width = NO_FIELD_VALUE;
554 
555       /* Parse the precision.  */
556       precision_pos = 0;
557       precision = NO_FIELD_VALUE;
558       if (*s == '.')
559         {
560           int ignore_value = (s[1] == '-');
561 
562           s++;
563           if (*s == '*')
564             {
565               precision = STAR_FIELD_VALUE;
566               s++;
567               /* If we have a positional argument, another one might also
568                  be used to give the position of the star's value. */
569               if (arg_pos && *s >= '1' && *s <= '9')
570                 {
571                   precision_pos = (*s++ - '0');
572                   for (; *s >= '0' && *s <= '9'; s++)
573                     precision_pos = 10*precision_pos + (*s - '0');
574                   if (precision_pos < 1)
575                     goto leave_einval; /* Overflow during conversion.  */
576                   if (*s != '$')
577                     goto leave_einval; /* Not followed by $.  */
578                   s++;
579                 }
580             }
581           else if ( *s >= '0' && *s <= '9')
582             {
583               precision = (*s++ - '0');
584               for (; *s >= '0' && *s <= '9'; s++)
585                 {
586                   if (!precision && *s == '0')
587                     goto leave_einval; /* Leading zeroes are not allowed.
588                                           Fixme: check what other
589                                           implementations do. */
590                   precision = 10*precision + (*s - '0');
591                 }
592               if (precision < 0)
593                 goto leave_einval; /* Overflow during conversion.  */
594             }
595           else
596             precision = 0;
597           if (ignore_value)
598             precision = NO_FIELD_VALUE;
599         }
600 
601       /* Parse the length modifiers.  */
602       switch (*s)
603         {
604         case 'h':
605           if (s[1] == 'h')
606             {
607               lenmod = LENMOD_CHAR;
608               s++;
609             }
610           else
611             lenmod = LENMOD_SHORT;
612           s++;
613           break;
614         case 'l':
615           if (s[1] == 'l')
616             {
617               lenmod = LENMOD_LONGLONG;
618               s++;
619             }
620           else
621             lenmod = LENMOD_LONG;
622           s++;
623           break;
624         case 'j': lenmod = LENMOD_INTMAX; s++; break;
625         case 'z': lenmod = LENMOD_SIZET; s++; break;
626         case 't': lenmod = LENMOD_PTRDIFF; s++; break;
627         case 'L': lenmod = LENMOD_LONGDBL; s++; break;
628         default:  lenmod = LENMOD_NONE; break;
629         }
630 
631       /* Parse the conversion specifier.  */
632       switch (*s)
633         {
634         case 'd':
635         case 'i': conspec = CONSPEC_DECIMAL; break;
636         case 'o': conspec = CONSPEC_OCTAL; break;
637         case 'u': conspec = CONSPEC_UNSIGNED; break;
638         case 'x': conspec = CONSPEC_HEX; break;
639         case 'X': conspec = CONSPEC_HEX_UP; break;
640         case 'f': conspec = CONSPEC_FLOAT; break;
641         case 'F': conspec = CONSPEC_FLOAT_UP; break;
642         case 'e': conspec = CONSPEC_EXP; break;
643         case 'E': conspec = CONSPEC_EXP_UP; break;
644         case 'g': conspec = CONSPEC_F_OR_G; break;
645         case 'G': conspec = CONSPEC_F_OR_G_UP; break;
646         case 'a': conspec = CONSPEC_HEX_EXP; break;
647         case 'A': conspec = CONSPEC_HEX_EXP_UP; break;
648         case 'c': conspec = CONSPEC_CHAR; break;
649         case 's': conspec = CONSPEC_STRING; break;
650         case 'p': conspec = CONSPEC_POINTER; break;
651         case 'n': conspec = CONSPEC_BYTES_SO_FAR; break;
652         case 'C': conspec = CONSPEC_CHAR; lenmod = LENMOD_LONG; break;
653         case 'S': conspec = CONSPEC_STRING; lenmod = LENMOD_LONG; break;
654         case 'm': conspec = CONSPEC_STRERROR; arg_pos = -1; break;
655         default: conspec = CONSPEC_UNKNOWN;
656         }
657 
658       /* Save the args. */
659       if (argcount >= max_argspecs)
660         {
661           /* We either need to allocate a new array instead of the
662              caller provided one or realloc the array.  Instead of
663              using realloc we allocate a new one and release the
664              original one then. */
665           size_t n, newmax;
666           argspec_t newarg;
667 
668           newmax = max_argspecs + ARGSPECS_BUMP_VALUE;
669           if (newmax <= max_argspecs)
670             goto leave_einval;  /* Too many arguments. */
671           newarg = calloc (newmax, sizeof *newarg);
672           if (!newarg)
673             goto leave;
674           for (n=0; n < argcount; n++)
675             newarg[n] = argspecs[n];
676           if (argspecs != *argspecs_addr)
677             free (argspecs);
678           argspecs = newarg;
679           max_argspecs = newmax;
680         }
681 
682       arg = argspecs + argcount;
683       arg->length = s - format + 2;
684       arg->flags = flags;
685       arg->width = width;
686       arg->precision = precision;
687       arg->lenmod = lenmod;
688       arg->conspec = conspec;
689       arg->arg_pos = arg_pos;
690       arg->width_pos = width_pos;
691       arg->precision_pos = precision_pos;
692       compute_type (arg);
693       argcount++;
694       format = s;
695     }
696 
697   *argspecs_addr = argspecs;
698   *r_argspecs_count = argcount;
699   return 0; /* Success.  */
700 
701  leave_einval:
702   _set_errno (EINVAL);
703  leave:
704   if (argspecs != *argspecs_addr)
705     free (argspecs);
706   *argspecs_addr = NULL;
707   return -1;
708 }
709 
710 
711 /* This function reads all the values as specified by VALUETABLE into
712    VALUETABLE.  The values are expected in VAARGS.  The function
713    returns -1 if a specified type is not supported. */
714 static int
read_values(valueitem_t valuetable,size_t valuetable_len,va_list vaargs)715 read_values (valueitem_t valuetable, size_t valuetable_len, va_list vaargs)
716 {
717   int validx;
718 
719   for (validx=0; validx < valuetable_len; validx++)
720     {
721       value_t *value = &valuetable[validx].value;
722       valtype_t vt = valuetable[validx].vt;
723 
724       switch (vt)
725         {
726         case VALTYPE_CHAR: value->a_char = va_arg (vaargs, int); break;
727         case VALTYPE_CHAR_PTR:
728           value->a_char_ptr = va_arg (vaargs, char *);
729           break;
730         case VALTYPE_SCHAR: value->a_schar = va_arg (vaargs, int); break;
731         case VALTYPE_SCHAR_PTR:
732           value->a_schar_ptr = va_arg (vaargs, signed char *);
733           break;
734         case VALTYPE_UCHAR: value->a_uchar = va_arg (vaargs, int); break;
735         case VALTYPE_SHORT: value->a_short = va_arg (vaargs, int); break;
736         case VALTYPE_USHORT: value->a_ushort = va_arg (vaargs, int); break;
737         case VALTYPE_SHORT_PTR:
738           value->a_short_ptr = va_arg (vaargs, short *);
739           break;
740         case VALTYPE_INT:
741           value->a_int = va_arg (vaargs, int);
742           break;
743         case VALTYPE_INT_PTR:
744           value->a_int_ptr = va_arg (vaargs, int *);
745           break;
746         case VALTYPE_UINT:
747           value->a_uint = va_arg (vaargs, unsigned int);
748           break;
749         case VALTYPE_LONG:
750           value->a_long = va_arg (vaargs, long);
751           break;
752         case VALTYPE_ULONG:
753           value->a_ulong = va_arg (vaargs, unsigned long);
754           break;
755         case VALTYPE_LONG_PTR:
756           value->a_long_ptr = va_arg (vaargs, long *);
757           break;
758 #ifdef HAVE_LONG_LONG_INT
759         case VALTYPE_LONGLONG:
760           value->a_longlong = va_arg (vaargs, long long int);
761           break;
762         case VALTYPE_ULONGLONG:
763           value->a_ulonglong = va_arg (vaargs, unsigned long long int);
764           break;
765         case VALTYPE_LONGLONG_PTR:
766           value->a_longlong_ptr = va_arg (vaargs, long long *);
767           break;
768 #endif
769         case VALTYPE_DOUBLE:
770           value->a_double = va_arg (vaargs, double);
771           break;
772 #ifdef HAVE_LONG_DOUBLE
773         case VALTYPE_LONGDOUBLE:
774           value->a_longdouble = va_arg (vaargs, long double);
775           break;
776 #endif
777         case VALTYPE_STRING:
778           value->a_string = va_arg (vaargs, const char *);
779           break;
780         case VALTYPE_POINTER:
781           value->a_void_ptr = va_arg (vaargs, void *);
782           break;
783 #ifdef HAVE_INTMAX_T
784         case VALTYPE_INTMAX:
785           value->a_intmax = va_arg (vaargs, intmax_t);
786           break;
787         case VALTYPE_INTMAX_PTR:
788           value->a_intmax_ptr = va_arg (vaargs, intmax_t *);
789           break;
790 #endif
791 #ifdef HAVE_UINTMAX_T
792         case VALTYPE_UINTMAX:
793           value->a_uintmax = va_arg (vaargs, uintmax_t);
794           break;
795 #endif
796         case VALTYPE_SIZE:
797           value->a_size = va_arg (vaargs, size_t);
798           break;
799         case VALTYPE_SIZE_PTR:
800           value->a_size_ptr = va_arg (vaargs, size_t *);
801           break;
802 #ifdef HAVE_PTRDIFF_T
803         case VALTYPE_PTRDIFF:
804           value->a_ptrdiff = va_arg (vaargs, ptrdiff_t);
805           break;
806         case VALTYPE_PTRDIFF_PTR:
807           value->a_ptrdiff_ptr = va_arg (vaargs, ptrdiff_t *);
808           break;
809 #endif
810         default: /* Unsupported type.  */
811           return -1;
812         }
813     }
814   return 0;
815 }
816 
817 
818 
819 /* Output COUNT padding characters PADCHAR and update NBYTES by the
820    number of bytes actually written.  */
821 static int
pad_out(estream_printf_out_t outfnc,void * outfncarg,int padchar,int count,size_t * nbytes)822 pad_out (estream_printf_out_t outfnc, void *outfncarg,
823          int padchar, int count, size_t *nbytes)
824 {
825   char buf[32];
826   size_t n;
827   int rc;
828 
829   while (count > 0)
830     {
831       n = (count <= sizeof buf)? count : sizeof buf;
832       memset (buf, padchar, n);
833       rc = outfnc (outfncarg, buf, n);
834       if (rc)
835         return rc;
836       *nbytes += n;
837       count -= n;
838     }
839 
840   return 0;
841 }
842 
843 
844 /* "d,i,o,u,x,X" formatting.  OUTFNC and OUTFNCARG describes the
845    output routine, ARG gives the argument description and VALUE the
846    actual value (its type is available through arg->vt).  */
847 static int
pr_integer(estream_printf_out_t outfnc,void * outfncarg,argspec_t arg,value_t value,size_t * nbytes)848 pr_integer (estream_printf_out_t outfnc, void *outfncarg,
849             argspec_t arg, value_t value, size_t *nbytes)
850 {
851   int rc;
852 #ifdef HAVE_LONG_LONG_INT
853   unsigned long long aulong;
854 #else
855   unsigned long aulong;
856 #endif
857   char numbuf[100];
858   char *p, *pend;
859   size_t n;
860   char signchar = 0;
861   int n_prec;  /* Number of extra precision digits required.  */
862   int n_extra; /* Extra number of prefix or sign characters.  */
863 
864   if (arg->conspec == CONSPEC_DECIMAL)
865     {
866 #ifdef HAVE_LONG_LONG_INT
867       long long along;
868 #else
869       long along;
870 #endif
871 
872       switch (arg->vt)
873         {
874         case VALTYPE_SHORT: along = value.a_short; break;
875         case VALTYPE_INT: along = value.a_int; break;
876         case VALTYPE_LONG: along = value.a_long; break;
877 #ifdef HAVE_LONG_LONG_INT
878         case VALTYPE_LONGLONG: along = value.a_longlong; break;
879         case VALTYPE_SIZE: along = value.a_size; break;
880 # ifdef HAVE_INTMAX_T
881         case VALTYPE_INTMAX: along = value.a_intmax; break;
882 # endif
883 # ifdef HAVE_PTRDIFF_T
884         case VALTYPE_PTRDIFF: along = value.a_ptrdiff; break;
885 # endif
886 #endif /*HAVE_LONG_LONG_INT*/
887         default:
888           return -1;
889         }
890       if (along < 0)
891         {
892           aulong = -along;
893           signchar = '-';
894         }
895       else
896         aulong = along;
897     }
898   else
899     {
900       switch (arg->vt)
901         {
902         case VALTYPE_USHORT: aulong = value.a_ushort; break;
903         case VALTYPE_UINT: aulong = value.a_uint; break;
904         case VALTYPE_ULONG: aulong = value.a_ulong; break;
905 #ifdef HAVE_LONG_LONG_INT
906         case VALTYPE_ULONGLONG: aulong = value.a_ulonglong; break;
907         case VALTYPE_SIZE: aulong = value.a_size; break;
908 # ifdef HAVE_UINTMAX_T
909         case VALTYPE_UINTMAX: aulong = value.a_uintmax; break;
910 # endif
911 # ifdef HAVE_PTRDIFF_T
912         case VALTYPE_PTRDIFF: aulong = value.a_ptrdiff; break;
913 # endif
914 #endif /*HAVE_LONG_LONG_INT*/
915         default:
916           return -1;
917         }
918     }
919 
920   if (signchar == '-')
921     ;
922   else if ((arg->flags & FLAG_PLUS_SIGN))
923     signchar = '+';
924   else if ((arg->flags & FLAG_SPACE_PLUS))
925     signchar = ' ';
926 
927   n_extra = !!signchar;
928 
929   /* We build the string up backwards.  */
930   p = pend = numbuf + DIM(numbuf);
931   if ((!aulong && !arg->precision))
932     ;
933   else if (arg->conspec == CONSPEC_DECIMAL
934            || arg->conspec == CONSPEC_UNSIGNED)
935     {
936       int grouping = -1;
937       const char * grouping_string =
938 #ifdef HAVE_LANGINFO_THOUSEP
939         nl_langinfo(THOUSEP);
940 #else
941         "'";
942 #endif
943 
944       do
945         {
946           if ((arg->flags & FLAG_GROUPING)
947               && (++grouping == 3) && *grouping_string)
948             {
949               *--p = *grouping_string;
950               grouping = 0;
951             }
952           *--p = '0' + (aulong % 10);
953           aulong /= 10;
954         }
955       while (aulong);
956     }
957   else if (arg->conspec == CONSPEC_OCTAL)
958     {
959       do
960         {
961           *--p = '0' + (aulong % 8);
962           aulong /= 8;
963         }
964       while (aulong);
965       if ((arg->flags & FLAG_ALT_CONV) && *p != '0')
966         *--p = '0';
967     }
968   else /* HEX or HEXUP */
969     {
970       const char *digits = ((arg->conspec == CONSPEC_HEX)
971                             ? "0123456789abcdef" : "0123456789ABCDEF");
972       do
973         {
974           *--p = digits[(aulong % 16)];
975           aulong /= 16;
976         }
977       while (aulong);
978       if ((arg->flags & FLAG_ALT_CONV))
979         n_extra += 2;
980     }
981 
982   n = pend - p;
983 
984   if ((arg->flags & FLAG_ZERO_PAD)
985       && arg->precision == NO_FIELD_VALUE && !(arg->flags & FLAG_LEFT_JUST)
986       && n && arg->width - n_extra > n )
987     n_prec = arg->width - n_extra - n;
988   else if (arg->precision > 0 && arg->precision > n)
989     n_prec = arg->precision - n;
990   else
991     n_prec = 0;
992 
993   if (!(arg->flags & FLAG_LEFT_JUST)
994       && arg->width >= 0 && arg->width - n_extra > n
995       && arg->width - n_extra - n >= n_prec )
996     {
997       rc = pad_out (outfnc, outfncarg, ' ',
998                     arg->width - n_extra - n - n_prec, nbytes);
999       if (rc)
1000         return rc;
1001     }
1002 
1003   if (signchar)
1004     {
1005       rc = outfnc (outfncarg, &signchar, 1);
1006       if (rc)
1007         return rc;
1008       *nbytes += 1;
1009     }
1010 
1011   if ((arg->flags & FLAG_ALT_CONV)
1012       && (arg->conspec == CONSPEC_HEX || arg->conspec == CONSPEC_HEX_UP))
1013     {
1014       rc = outfnc (outfncarg, arg->conspec == CONSPEC_HEX? "0x": "0X", 2);
1015       if (rc)
1016         return rc;
1017       *nbytes += 2;
1018     }
1019 
1020   if (n_prec)
1021     {
1022       rc = pad_out (outfnc, outfncarg, '0', n_prec, nbytes);
1023       if (rc)
1024         return rc;
1025     }
1026 
1027   rc = outfnc (outfncarg, p, pend - p);
1028   if (rc)
1029     return rc;
1030   *nbytes += pend - p;
1031 
1032   if ((arg->flags & FLAG_LEFT_JUST)
1033       && arg->width >= 0 && arg->width - n_extra - n_prec > n)
1034     {
1035       rc = pad_out (outfnc, outfncarg, ' ',
1036                     arg->width - n_extra - n_prec - n, nbytes);
1037       if (rc)
1038         return rc;
1039     }
1040 
1041   return 0;
1042 }
1043 
1044 
1045 /* "e,E,f,F,g,G,a,A" formatting.  OUTFNC and OUTFNCARG describes the
1046    output routine, ARG gives the argument description and VALUE the
1047    actual value (its type is available through arg->vt).  For
1048    portability reasons sprintf is used for the actual formatting.
1049    This is useful because sprint is the only standard function to
1050    convert a floating number into its ascii representation.  To avoid
1051    using malloc we just pass the precision to sprintf and do the final
1052    formatting with our own code.  */
1053 static int
pr_float(estream_printf_out_t outfnc,void * outfncarg,argspec_t arg,value_t value,size_t * nbytes)1054 pr_float (estream_printf_out_t outfnc, void *outfncarg,
1055           argspec_t arg, value_t value, size_t *nbytes)
1056 {
1057   int rc;
1058 #ifdef HAVE_LONG_DOUBLE
1059   long double adblfloat = 0; /* Just to please gcc.  */
1060   int use_dbl = 0;
1061 #endif
1062   double afloat;
1063   char numbuf[350];
1064   char formatstr[20];
1065   char *p, *pend;
1066   size_t n;
1067   char signchar = 0;
1068   int n_extra;  /* Extra number of prefix or sign characters.  */
1069 
1070   switch (arg->vt)
1071     {
1072     case VALTYPE_DOUBLE: afloat = value.a_double; break;
1073 #ifdef HAVE_LONG_DOUBLE
1074     case VALTYPE_LONGDOUBLE:
1075       afloat = 0;  /* Just to please gcc.  */
1076       adblfloat = value.a_longdouble;
1077       use_dbl=1; break;
1078 #endif
1079     default:
1080       return -1;
1081     }
1082 
1083   /* We build the string using sprint.  */
1084   p = formatstr + sizeof formatstr;
1085   *--p = 0;
1086   switch (arg->conspec)
1087     {
1088     case CONSPEC_FLOAT:      *--p = 'f'; break;
1089     case CONSPEC_FLOAT_UP:   *--p = 'F'; break;
1090     case CONSPEC_EXP:        *--p = 'e'; break;
1091     case CONSPEC_EXP_UP:     *--p = 'E'; break;
1092     case CONSPEC_F_OR_G:     *--p = 'g'; break;
1093     case CONSPEC_F_OR_G_UP:  *--p = 'G'; break;
1094     case CONSPEC_HEX_EXP:    *--p = 'a'; break;
1095     case CONSPEC_HEX_EXP_UP: *--p = 'A'; break;
1096     default:
1097       return -1; /* Actually a bug.  */
1098     }
1099 #ifdef HAVE_LONG_DOUBLE
1100   if (use_dbl)
1101     *--p = 'L';
1102 #endif
1103   if (arg->precision != NO_FIELD_VALUE)
1104     {
1105       /* Limit it to a meaningful value so that even a stupid sprintf
1106          won't overflow our buffer.  */
1107       n = arg->precision <= 100? arg->precision : 100;
1108       do
1109         {
1110           *--p = '0' + (n % 10);
1111           n /= 10;
1112         }
1113       while (n);
1114       *--p = '.';
1115     }
1116   if ((arg->flags & FLAG_ALT_CONV))
1117     *--p = '#';
1118   *--p = '%';
1119 #ifdef HAVE_LONG_DOUBLE
1120   if (use_dbl)
1121     sprintf (numbuf, p, adblfloat);
1122   else
1123 #endif /*HAVE_LONG_DOUBLE*/
1124     sprintf (numbuf, p, afloat);
1125   p = numbuf;
1126   n = strlen (numbuf);
1127   pend = p + n;
1128 
1129   if (*p =='-')
1130     {
1131       signchar = '-';
1132       p++;
1133       n--;
1134     }
1135   else if ((arg->flags & FLAG_PLUS_SIGN))
1136     signchar = '+';
1137   else if ((arg->flags & FLAG_SPACE_PLUS))
1138     signchar = ' ';
1139 
1140   n_extra = !!signchar;
1141 
1142   if (!(arg->flags & FLAG_LEFT_JUST)
1143       && arg->width >= 0 && arg->width - n_extra > n)
1144     {
1145       rc = pad_out (outfnc, outfncarg, ' ', arg->width - n_extra - n, nbytes);
1146       if (rc)
1147         return rc;
1148     }
1149 
1150   if (signchar)
1151     {
1152       rc = outfnc (outfncarg, &signchar, 1);
1153       if (rc)
1154         return rc;
1155       *nbytes += 1;
1156     }
1157 
1158   rc = outfnc (outfncarg, p, pend - p);
1159   if (rc)
1160     return rc;
1161   *nbytes += pend - p;
1162 
1163   if ((arg->flags & FLAG_LEFT_JUST)
1164       && arg->width >= 0 && arg->width - n_extra > n)
1165     {
1166       rc = pad_out (outfnc, outfncarg, ' ', arg->width - n_extra - n, nbytes);
1167       if (rc)
1168         return rc;
1169     }
1170 
1171   return 0;
1172 }
1173 
1174 
1175 /* "c" formatting.  */
1176 static int
pr_char(estream_printf_out_t outfnc,void * outfncarg,argspec_t arg,value_t value,size_t * nbytes)1177 pr_char (estream_printf_out_t outfnc, void *outfncarg,
1178             argspec_t arg, value_t value, size_t *nbytes)
1179 {
1180   int rc;
1181   char buf[1];
1182 
1183   if (arg->vt != VALTYPE_INT)
1184     return -1;
1185   buf[0] = (unsigned int)value.a_int;
1186   rc = outfnc (outfncarg, buf, 1);
1187   if(rc)
1188     return rc;
1189   *nbytes += 1;
1190 
1191   return 0;
1192 }
1193 
1194 
1195 /* "s" formatting.  */
1196 static int
pr_string(estream_printf_out_t outfnc,void * outfncarg,argspec_t arg,value_t value,size_t * nbytes,gpgrt_string_filter_t sf,void * sfvalue,int string_no)1197 pr_string (estream_printf_out_t outfnc, void *outfncarg,
1198            argspec_t arg, value_t value, size_t *nbytes,
1199            gpgrt_string_filter_t sf, void *sfvalue, int string_no)
1200 {
1201   int rc;
1202   size_t n;
1203   const char *string, *s;
1204 
1205   if (arg->vt != VALTYPE_STRING)
1206     return -1;
1207   if (sf)
1208     string = sf (value.a_string, string_no, sfvalue);
1209   else
1210     string = value.a_string;
1211 
1212   if (!string)
1213     string = "(null)";
1214   if (arg->precision >= 0)
1215     {
1216       /* Test for nul after N so that we can pass a non-nul terminated
1217          string.  */
1218       for (n=0,s=string; n < arg->precision && *s; s++)
1219         n++;
1220     }
1221   else
1222     n = strlen (string);
1223 
1224   if (!(arg->flags & FLAG_LEFT_JUST)
1225       && arg->width >= 0 && arg->width > n )
1226     {
1227       rc = pad_out (outfnc, outfncarg, ' ', arg->width - n, nbytes);
1228       if (rc)
1229         goto leave;
1230     }
1231 
1232   rc = outfnc (outfncarg, string, n);
1233   if (rc)
1234     goto leave;
1235   *nbytes += n;
1236 
1237   if ((arg->flags & FLAG_LEFT_JUST)
1238       && arg->width >= 0 && arg->width > n)
1239     {
1240       rc = pad_out (outfnc, outfncarg, ' ', arg->width - n, nbytes);
1241       if (rc)
1242         goto leave;
1243     }
1244 
1245   rc = 0;
1246 
1247  leave:
1248   if (sf) /* Tell the filter to release resources.  */
1249     sf (value.a_string, -1, sfvalue);
1250 
1251   return rc;
1252 }
1253 
1254 
1255 /* "p" formatting.  */
1256 static int
pr_pointer(estream_printf_out_t outfnc,void * outfncarg,argspec_t arg,value_t value,size_t * nbytes)1257 pr_pointer (estream_printf_out_t outfnc, void *outfncarg,
1258             argspec_t arg, value_t value, size_t *nbytes)
1259 {
1260   int rc;
1261 #if defined(HAVE_LONG_LONG_INT) && (SIZEOF_UNSIGNED_LONG < SIZEOF_VOID_P)
1262   unsigned long long aulong;
1263 #else
1264   unsigned long aulong;
1265 #endif
1266   char numbuf[100];
1267   char *p, *pend;
1268 
1269   if (arg->vt != VALTYPE_POINTER)
1270     return -1;
1271   /* We assume that a pointer can be converted to an unsigned long.
1272      That is not correct for a 64 bit Windows, but then we assume that
1273      long long is supported and usable for storing a pointer.  */
1274 #if defined(HAVE_LONG_LONG_INT) && (SIZEOF_UNSIGNED_LONG < SIZEOF_VOID_P)
1275   aulong = (unsigned long long)value.a_void_ptr;
1276 #else
1277   aulong = (unsigned long)value.a_void_ptr;
1278 #endif
1279 
1280   p = pend = numbuf + DIM(numbuf);
1281   do
1282     {
1283       *--p = "0123456789abcdefx"[(aulong % 16)];
1284       aulong /= 16;
1285     }
1286   while (aulong);
1287   while ((pend-p) < 2*sizeof (aulong))
1288     *--p = '0';
1289   *--p = 'x';
1290   *--p = '0';
1291 
1292   rc = outfnc (outfncarg, p, pend - p);
1293   if (rc)
1294     return rc;
1295   *nbytes += pend - p;
1296 
1297   return 0;
1298 }
1299 
1300 /* "n" pesudo format operation.  */
1301 static int
pr_bytes_so_far(estream_printf_out_t outfnc,void * outfncarg,argspec_t arg,value_t value,size_t * nbytes)1302 pr_bytes_so_far (estream_printf_out_t outfnc, void *outfncarg,
1303                  argspec_t arg, value_t value, size_t *nbytes)
1304 {
1305   (void)outfnc;
1306   (void)outfncarg;
1307 
1308   switch (arg->vt)
1309     {
1310     case VALTYPE_SCHAR_PTR:
1311       *value.a_schar_ptr = (signed char)(unsigned int)(*nbytes);
1312       break;
1313     case VALTYPE_SHORT_PTR:
1314       *value.a_short_ptr = (short)(unsigned int)(*nbytes);
1315       break;
1316     case VALTYPE_LONG_PTR:
1317       *value.a_long_ptr = (long)(*nbytes);
1318       break;
1319 #ifdef HAVE_LONG_LONG_INT
1320     case VALTYPE_LONGLONG_PTR:
1321       *value.a_longlong_ptr = (long long)(*nbytes);
1322       break;
1323 #endif
1324 #ifdef HAVE_INTMAX_T
1325     case VALTYPE_INTMAX_PTR:
1326       *value.a_intmax_ptr = (intmax_t)(*nbytes);
1327       break;
1328 #endif
1329     case VALTYPE_SIZE_PTR:
1330       *value.a_size_ptr = (*nbytes);
1331       break;
1332 #ifdef HAVE_PTRDIFF_T
1333     case VALTYPE_PTRDIFF_PTR:
1334       *value.a_ptrdiff_ptr = (ptrdiff_t)(*nbytes);
1335       break;
1336 #endif
1337     case VALTYPE_INT_PTR:
1338       *value.a_int_ptr = (int)(*nbytes);
1339       break;
1340     default:
1341       return -1; /* An unsupported type has been used.  */
1342     }
1343 
1344   return 0;
1345 }
1346 
1347 
1348 
1349 /* Run the actual formatting.  OUTFNC and OUTFNCARG are the output
1350  * functions.  FORMAT is format string ARGSPECS is the parsed format
1351  * string, ARGSPECS_LEN the number of items in ARGSPECS.
1352  * STRING_FILTER is an optional function to filter string (%s) args;
1353  * it is called with the original string and the count of already
1354  * processed %s arguments.  Its return value will be used instead of
1355  * the original string.  VALUETABLE holds the values and may be
1356  * directly addressed using the position arguments given by ARGSPECS.
1357  * MYERRNO is used for the "%m" conversion. NBYTES well be updated to
1358  * reflect the number of bytes send to the output function. */
1359 static int
do_format(estream_printf_out_t outfnc,void * outfncarg,gpgrt_string_filter_t sf,void * sfvalue,const char * format,argspec_t argspecs,size_t argspecs_len,valueitem_t valuetable,int myerrno,size_t * nbytes)1360 do_format (estream_printf_out_t outfnc, void *outfncarg,
1361            gpgrt_string_filter_t sf, void *sfvalue,
1362            const char *format, argspec_t argspecs, size_t argspecs_len,
1363            valueitem_t valuetable, int myerrno, size_t *nbytes)
1364 {
1365   int rc = 0;
1366   const char *s;
1367   argspec_t arg = argspecs;
1368   int argidx = 0; /* Only used for assertion.  */
1369   size_t n;
1370   value_t value;
1371   int string_no = 0;  /* Number of processed "%s" args.  */
1372 
1373   s = format;
1374   while ( *s )
1375     {
1376       if (*s != '%')
1377         {
1378           s++;
1379           continue;
1380         }
1381       if (s != format)
1382         {
1383           rc = outfnc (outfncarg, format, (n=s-format));
1384           if (rc)
1385             return rc;
1386           *nbytes += n;
1387         }
1388       if (s[1] == '%')
1389         {
1390           /* Note that this code ignores one trailing percent escape -
1391              this is however okay as the args parser must have
1392              detected this already.  */
1393           rc = outfnc (outfncarg, s, 1);
1394           if (rc)
1395             return rc;
1396           *nbytes += 1;
1397           s += 2;
1398           format = s;
1399           continue;
1400         }
1401 
1402       /* Save the next start.  */
1403       s += arg->length;
1404       format = s;
1405 
1406       gpgrt_assert (argidx < argspecs_len);
1407       argidx++;
1408 
1409       /* Apply indirect field width and precision values.  */
1410       if (arg->width == STAR_FIELD_VALUE)
1411         {
1412           gpgrt_assert (valuetable[arg->width_pos-1].vt == VALTYPE_INT);
1413           arg->width = valuetable[arg->width_pos-1].value.a_int;
1414           if (arg->width < 0)
1415             {
1416               arg->width = -arg->width;
1417               arg->flags |= FLAG_LEFT_JUST;
1418             }
1419         }
1420       if (arg->precision == STAR_FIELD_VALUE)
1421         {
1422           gpgrt_assert (valuetable[arg->precision_pos-1].vt == VALTYPE_INT);
1423           arg->precision = valuetable[arg->precision_pos-1].value.a_int;
1424           if (arg->precision < 0)
1425             arg->precision = NO_FIELD_VALUE;
1426         }
1427 
1428       if (arg->arg_pos == -1 && arg->conspec == CONSPEC_STRERROR)
1429         value.a_string = strerror (myerrno);
1430       else
1431         {
1432           gpgrt_assert (arg->vt == valuetable[arg->arg_pos-1].vt);
1433           value = valuetable[arg->arg_pos-1].value;
1434         }
1435 
1436       switch (arg->conspec)
1437         {
1438         case CONSPEC_UNKNOWN: gpgrt_assert (!"bug"); break;
1439 
1440         case CONSPEC_DECIMAL:
1441         case CONSPEC_UNSIGNED:
1442         case CONSPEC_OCTAL:
1443         case CONSPEC_HEX:
1444         case CONSPEC_HEX_UP:
1445           rc = pr_integer (outfnc, outfncarg, arg, value, nbytes);
1446           break;
1447         case CONSPEC_FLOAT:
1448         case CONSPEC_FLOAT_UP:
1449         case CONSPEC_EXP:
1450         case CONSPEC_EXP_UP:
1451         case CONSPEC_F_OR_G:
1452         case CONSPEC_F_OR_G_UP:
1453         case CONSPEC_HEX_EXP:
1454         case CONSPEC_HEX_EXP_UP:
1455           rc = pr_float (outfnc, outfncarg, arg, value, nbytes);
1456           break;
1457         case CONSPEC_CHAR:
1458           rc = pr_char (outfnc, outfncarg, arg, value, nbytes);
1459           break;
1460         case CONSPEC_STRING:
1461           rc = pr_string (outfnc, outfncarg, arg, value, nbytes,
1462                           sf, sfvalue, string_no++);
1463           break;
1464         case CONSPEC_STRERROR:
1465           rc = pr_string (outfnc, outfncarg, arg, value, nbytes,
1466                           NULL, NULL, 0);
1467           break;
1468         case CONSPEC_POINTER:
1469           rc = pr_pointer (outfnc, outfncarg, arg, value, nbytes);
1470           break;
1471         case CONSPEC_BYTES_SO_FAR:
1472           rc = pr_bytes_so_far (outfnc, outfncarg, arg, value, nbytes);
1473           break;
1474         }
1475       if (rc)
1476         return rc;
1477       arg++;
1478     }
1479 
1480   /* Print out any trailing stuff. */
1481   n = s - format;
1482   rc = n? outfnc (outfncarg, format, n) : 0;
1483   if (!rc)
1484     *nbytes += n;
1485 
1486   return rc;
1487 }
1488 
1489 
1490 
1491 
1492 /* The versatile printf formatting routine.  It expects a callback
1493    function OUTFNC and an opaque argument OUTFNCARG used for actual
1494    output of the formatted stuff.  FORMAT is the format specification
1495    and VAARGS a variable argumemt list matching the arguments of
1496    FORMAT.  */
1497 int
_gpgrt_estream_format(estream_printf_out_t outfnc,void * outfncarg,gpgrt_string_filter_t sf,void * sfvalue,const char * format,va_list vaargs)1498 _gpgrt_estream_format (estream_printf_out_t outfnc,
1499                        void *outfncarg,
1500                        gpgrt_string_filter_t sf, void *sfvalue,
1501                        const char *format, va_list vaargs)
1502 {
1503   /* Buffer to hold the argspecs and a pointer to it.*/
1504   struct argspec_s argspecs_buffer[DEFAULT_MAX_ARGSPECS];
1505   argspec_t argspecs = argspecs_buffer;
1506   size_t argspecs_len;  /* Number of specifications in ARGSPECS.  */
1507 
1508   /* Buffer to hold the description for the values.  */
1509   struct valueitem_s valuetable_buffer[DEFAULT_MAX_VALUES];
1510   valueitem_t valuetable = valuetable_buffer;
1511 
1512   int rc;        /* Return code. */
1513   size_t argidx; /* Used to index the argspecs array.  */
1514   size_t validx; /* Used to index the valuetable.  */
1515   int max_pos;   /* Highest argument position.  */
1516 
1517   size_t nbytes = 0; /* Keep track of the number of bytes passed to
1518                         the output function.  */
1519 
1520   int myerrno = errno; /* Save the errno for use with "%m". */
1521 
1522 
1523   /* Parse the arguments to come up with descriptive list.  We can't
1524      do this on the fly because we need to support positional
1525      arguments. */
1526   rc = parse_format (format, &argspecs, DIM(argspecs_buffer), &argspecs_len);
1527   if (rc)
1528     goto leave;
1529 
1530   /* Check that all ARG_POS fields are set.  */
1531   for (argidx=0,max_pos=0; argidx < argspecs_len; argidx++)
1532     {
1533       if (argspecs[argidx].arg_pos != -1
1534           && argspecs[argidx].arg_pos > max_pos)
1535         max_pos = argspecs[argidx].arg_pos;
1536       if (argspecs[argidx].width_pos > max_pos)
1537         max_pos = argspecs[argidx].width_pos;
1538       if (argspecs[argidx].precision_pos > max_pos)
1539         max_pos = argspecs[argidx].precision_pos;
1540     }
1541   if (!max_pos)
1542     {
1543       /* Fill in all the positions.  */
1544       for (argidx=0; argidx < argspecs_len; argidx++)
1545         {
1546           if (argspecs[argidx].width == STAR_FIELD_VALUE)
1547             argspecs[argidx].width_pos = ++max_pos;
1548           if (argspecs[argidx].precision == STAR_FIELD_VALUE)
1549             argspecs[argidx].precision_pos = ++max_pos;
1550           if (argspecs[argidx].arg_pos != -1 )
1551             argspecs[argidx].arg_pos = ++max_pos;
1552         }
1553     }
1554   else
1555     {
1556       /* Check that they are all filled.   More test are done later.  */
1557       for (argidx=0; argidx < argspecs_len; argidx++)
1558         {
1559           if (!argspecs[argidx].arg_pos
1560               || (argspecs[argidx].width == STAR_FIELD_VALUE
1561                   && !argspecs[argidx].width_pos)
1562               || (argspecs[argidx].precision == STAR_FIELD_VALUE
1563                   && !argspecs[argidx].precision_pos))
1564             goto leave_einval;
1565         }
1566     }
1567   /* Check that there is no overflow in max_pos and that it has a
1568      reasonable length.  There may never be more elements than the
1569      number of characters in FORMAT.  */
1570   if (max_pos < 0 || max_pos >= strlen (format))
1571     goto leave_einval;
1572 
1573 #ifdef DEBUG
1574     dump_argspecs (argspecs, argspecs_len);
1575 #endif
1576 
1577   /* Allocate a table to hold the values.  If it is small enough we
1578      use a stack allocated buffer.  */
1579   if (max_pos > DIM(valuetable_buffer))
1580     {
1581       valuetable = calloc (max_pos, sizeof *valuetable);
1582       if (!valuetable)
1583         goto leave_error;
1584     }
1585   else
1586     {
1587       for (validx=0; validx < DIM(valuetable_buffer); validx++)
1588         {
1589           valuetable[validx].vt = VALTYPE_UNSUPPORTED;
1590           memset (&valuetable[validx].value, 0,
1591                   sizeof valuetable[validx].value);
1592         }
1593     }
1594   for (argidx=0; argidx < argspecs_len; argidx++)
1595     {
1596       if (argspecs[argidx].arg_pos != - 1)
1597         {
1598           validx = argspecs[argidx].arg_pos - 1;
1599           if (valuetable[validx].vt)
1600             goto leave_einval; /* Already defined. */
1601           valuetable[validx].vt = argspecs[argidx].vt;
1602         }
1603       if (argspecs[argidx].width == STAR_FIELD_VALUE)
1604         {
1605           validx = argspecs[argidx].width_pos - 1;
1606           if (valuetable[validx].vt)
1607             goto leave_einval; /* Already defined.  */
1608           valuetable[validx].vt = VALTYPE_INT;
1609         }
1610       if (argspecs[argidx].precision == STAR_FIELD_VALUE)
1611         {
1612           validx = argspecs[argidx].precision_pos - 1;
1613           if (valuetable[validx].vt)
1614             goto leave_einval; /* Already defined.  */
1615           valuetable[validx].vt = VALTYPE_INT;
1616         }
1617     }
1618 
1619   /* Read all the arguments.  This will error out for unsupported
1620      types and for not given positional arguments. */
1621   rc = read_values (valuetable, max_pos, vaargs);
1622   if (rc)
1623     goto leave_einval;
1624 
1625 /*   for (validx=0; validx < max_pos; validx++) */
1626 /*     fprintf (stderr, "%2d: vt=%d\n", validx, valuetable[validx].vt); */
1627 
1628   /* Everything has been collected, go ahead with the formatting.  */
1629   rc = do_format (outfnc, outfncarg, sf, sfvalue, format,
1630                   argspecs, argspecs_len, valuetable, myerrno, &nbytes);
1631 
1632   goto leave;
1633 
1634  leave_einval:
1635   _set_errno (EINVAL);
1636  leave_error:
1637   rc = -1;
1638  leave:
1639   if (valuetable != valuetable_buffer)
1640     free (valuetable);
1641   if (argspecs != argspecs_buffer)
1642     free (argspecs);
1643   return rc;
1644 }
1645 
1646 
1647 
1648 
1649 /* A simple output handler utilizing stdio.  */
1650 static int
plain_stdio_out(void * outfncarg,const char * buf,size_t buflen)1651 plain_stdio_out (void *outfncarg, const char *buf, size_t buflen)
1652 {
1653   FILE *fp = (FILE*)outfncarg;
1654 
1655   if ( fwrite (buf, buflen, 1, fp) != 1 )
1656     return -1;
1657   return 0;
1658 }
1659 
1660 
1661 /* A replacement for printf.  */
1662 int
_gpgrt_estream_printf(const char * format,...)1663 _gpgrt_estream_printf (const char *format, ...)
1664 {
1665   int rc;
1666   va_list arg_ptr;
1667 
1668   va_start (arg_ptr, format);
1669   rc = _gpgrt_estream_format (plain_stdio_out, stderr, NULL, NULL,
1670                               format, arg_ptr);
1671   va_end (arg_ptr);
1672 
1673   return rc;
1674 }
1675 
1676 /* A replacement for fprintf.  */
1677 int
_gpgrt_estream_fprintf(FILE * fp,const char * format,...)1678 _gpgrt_estream_fprintf (FILE *fp, const char *format, ...)
1679 {
1680   int rc;
1681   va_list arg_ptr;
1682 
1683   va_start (arg_ptr, format);
1684   rc = _gpgrt_estream_format (plain_stdio_out, fp, NULL, NULL,
1685                               format, arg_ptr);
1686   va_end (arg_ptr);
1687 
1688   return rc;
1689 }
1690 
1691 /* A replacement for vfprintf.  */
1692 int
_gpgrt_estream_vfprintf(FILE * fp,const char * format,va_list arg_ptr)1693 _gpgrt_estream_vfprintf (FILE *fp, const char *format, va_list arg_ptr)
1694 {
1695   return _gpgrt_estream_format (plain_stdio_out, fp, NULL, NULL,
1696                                 format, arg_ptr);
1697 }
1698 
1699 
1700 
1701 /* Communication object used between estream_snprintf and
1702    fixed_buffer_out.  */
1703 struct fixed_buffer_parm_s
1704 {
1705   size_t size;    /* Size of the buffer.  */
1706   size_t count;   /* Number of bytes requested for output.  */
1707   size_t used;    /* Used size of the buffer.  */
1708   char *buffer;   /* Provided buffer.  */
1709 };
1710 
1711 /* A simple malloced buffer output handler.  */
1712 static int
fixed_buffer_out(void * outfncarg,const char * buf,size_t buflen)1713 fixed_buffer_out (void *outfncarg, const char *buf, size_t buflen)
1714 {
1715   struct fixed_buffer_parm_s *parm = outfncarg;
1716 
1717   parm->count += buflen;
1718 
1719   if (!parm->buffer)
1720     ;
1721   else if (parm->used + buflen < parm->size)
1722     {
1723       /* Handle the common case that everything fits into the buffer
1724          separately.  */
1725       memcpy (parm->buffer + parm->used, buf, buflen);
1726       parm->used += buflen;
1727     }
1728   else
1729     {
1730       /* The slow version of above.  */
1731       for ( ;buflen && parm->used < parm->size; buflen--)
1732         parm->buffer[parm->used++] = *buf++;
1733     }
1734 
1735   return 0;
1736 }
1737 
1738 
1739 /* A replacement for vsnprintf. */
1740 int
_gpgrt_estream_vsnprintf(char * buf,size_t bufsize,const char * format,va_list arg_ptr)1741 _gpgrt_estream_vsnprintf (char *buf, size_t bufsize,
1742                    const char *format, va_list arg_ptr)
1743 {
1744   struct fixed_buffer_parm_s parm;
1745   int rc;
1746 
1747   parm.size = bufsize;
1748   parm.count = 0;
1749   parm.used = 0;
1750   parm.buffer = bufsize?buf:NULL;
1751   rc = _gpgrt_estream_format (fixed_buffer_out, &parm, NULL, NULL,
1752                               format, arg_ptr);
1753   if (!rc)
1754     rc = fixed_buffer_out (&parm, "", 1); /* Print terminating Nul.  */
1755   if (rc == -1)
1756     return -1;
1757   if (bufsize && buf && parm.size && parm.count >= parm.size)
1758     buf[parm.size-1] = 0;
1759 
1760   parm.count--; /* Do not count the trailing nul.  */
1761   return (int)parm.count; /* Return number of bytes which would have
1762                              been written.  */
1763 }
1764 
1765 /* A replacement for snprintf.  */
1766 int
_gpgrt_estream_snprintf(char * buf,size_t bufsize,const char * format,...)1767 _gpgrt_estream_snprintf (char *buf, size_t bufsize, const char *format, ...)
1768 {
1769   int rc;
1770   va_list arg_ptr;
1771 
1772   va_start (arg_ptr, format);
1773   rc = _gpgrt_estream_vsnprintf (buf, bufsize, format, arg_ptr);
1774   va_end (arg_ptr);
1775 
1776   return rc;
1777 }
1778 
1779 
1780 
1781 /* Communication object used between estream_asprintf and
1782    dynamic_buffer_out.  */
1783 struct dynamic_buffer_parm_s
1784 {
1785   int error_flag; /* Internal helper.  */
1786   size_t alloced; /* Allocated size of the buffer.  */
1787   size_t used;    /* Used size of the buffer.  */
1788   char *buffer;   /* Malloced buffer.  */
1789 };
1790 
1791 /* A simple malloced buffer output handler.  */
1792 static int
dynamic_buffer_out(void * outfncarg,const char * buf,size_t buflen)1793 dynamic_buffer_out (void *outfncarg, const char *buf, size_t buflen)
1794 {
1795   struct dynamic_buffer_parm_s *parm = outfncarg;
1796 
1797   if (parm->error_flag)
1798     {
1799       /* Just in case some formatting routine did not checked for an
1800          error. */
1801       _set_errno (parm->error_flag);
1802       return -1;
1803     }
1804 
1805   if (parm->used + buflen >= parm->alloced)
1806     {
1807       char *p;
1808 
1809       parm->alloced += buflen + 512;
1810       p = my_printf_realloc (parm->buffer, parm->alloced);
1811       if (!p)
1812         {
1813           parm->error_flag = errno ? errno : ENOMEM;
1814           /* Wipe out what we already accumulated.  This is useful in
1815              case sensitive data is formatted.  */
1816           memset (parm->buffer, 0, parm->used);
1817           return -1;
1818         }
1819       parm->buffer = p;
1820     }
1821   memcpy (parm->buffer + parm->used, buf, buflen);
1822   parm->used += buflen;
1823 
1824   return 0;
1825 }
1826 
1827 
1828 /* A replacement for vasprintf.  As with the BSD version of vasprintf
1829    -1 will be returned on error and NULL stored at BUFP.  On success
1830    the number of bytes printed will be returned. */
1831 int
_gpgrt_estream_vasprintf(char ** bufp,const char * format,va_list arg_ptr)1832 _gpgrt_estream_vasprintf (char **bufp, const char *format, va_list arg_ptr)
1833 {
1834   struct dynamic_buffer_parm_s parm;
1835   int rc;
1836 
1837   parm.error_flag = 0;
1838   parm.alloced = 512;
1839   parm.used = 0;
1840   parm.buffer = my_printf_realloc (NULL, parm.alloced);
1841   if (!parm.buffer)
1842     {
1843       *bufp = NULL;
1844       return -1;
1845     }
1846 
1847   rc = _gpgrt_estream_format (dynamic_buffer_out, &parm, NULL, NULL,
1848                               format, arg_ptr);
1849   if (!rc)
1850     rc = dynamic_buffer_out (&parm, "", 1); /* Print terminating Nul.  */
1851   /* Fixme: Should we shrink the resulting buffer?  */
1852   if (rc != -1 && parm.error_flag)
1853     {
1854       rc = -1;
1855       _set_errno (parm.error_flag);
1856     }
1857   if (rc == -1)
1858     {
1859       memset (parm.buffer, 0, parm.used);
1860       if (parm.buffer)
1861         my_printf_realloc (parm.buffer, 0);
1862       *bufp = NULL;
1863       return -1;
1864     }
1865   gpgrt_assert (parm.used);   /* We have at least the terminating Nul.  */
1866   *bufp = parm.buffer;
1867   return parm.used - 1; /* Do not include that Nul. */
1868 }
1869 
1870 /* A replacement for asprintf.  As with the BSD of asprintf version -1
1871    will be returned on error and NULL stored at BUFP.  On success the
1872    number of bytes printed will be returned. */
1873 int
_gpgrt_estream_asprintf(char ** bufp,const char * format,...)1874 _gpgrt_estream_asprintf (char **bufp, const char *format, ...)
1875 {
1876   int rc;
1877   va_list arg_ptr;
1878 
1879   va_start (arg_ptr, format);
1880   rc = _gpgrt_estream_vasprintf (bufp, format, arg_ptr);
1881   va_end (arg_ptr);
1882 
1883   return rc;
1884 }
1885 
1886 /* A variant of asprintf.  The function returns the allocated buffer
1887    or NULL on error; ERRNO is set in the error case.  The caller
1888    should use es_free to release the buffer.  This function actually
1889    belongs into estream-printf but we put it here as a convenience
1890    and because es_free is required anyway.  */
1891 char *
_gpgrt_estream_bsprintf(const char * format,...)1892 _gpgrt_estream_bsprintf (const char *format, ...)
1893 {
1894   int rc;
1895   va_list ap;
1896   char *buf;
1897 
1898   va_start (ap, format);
1899   rc = _gpgrt_estream_vasprintf (&buf, format, ap);
1900   va_end (ap);
1901   if (rc < 0)
1902     return NULL;
1903   return buf;
1904 }
1905